diff --git a/ALGO_RESEARCH.md b/ALGO_RESEARCH.md deleted file mode 100644 index b32b9d4..0000000 --- a/ALGO_RESEARCH.md +++ /dev/null @@ -1,105 +0,0 @@ -In order to implement a new algo in a pool you need three things - 1) the C code to do the actual hashing - which I convert into a native node addon - 2) the max difficulty (diff1) of the coin used to check if shares/blocks are valid - 3) the share multiplier (2^16 for example) to determine the hashrate of a miner/entire pool - - -Most coins have diff1 in format like (~uint256(0) >> 20) -I believe you can determine the hashrate multiplier by subtracting the 20 used in bitshift from the number 32 -so it would be 2^12 for this one. or for (~uint256(0) >> 16) it would be 2^(32 - 16) - -so really for every algo you simple need the bitshift on a zero value uint256. - - -I believe these are the true diff1 values that should be used on pools for each algo - sha256d: 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff - scrypt: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - scrypt-jane: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - scrypt-n: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - x11: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - quark: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - shavite: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - keccak: 0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - fugue: 0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - blake: 0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - hefty1: 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - bcrypt: 0x00f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - -To see how I generated these diff1 values see https://github.com/zone117x/node-stratum-pool/blob/master/diff1.js - - - -So remember how that list to add a new algo had 3 items, well the maxcoin devs very unforutentely did something -that added a fourth step: - Step 4) Determine which parts of how work-generation / share-processing / creating-blocks work were arbitrarily - changed and implement them.... - - -Maxcoin devs, it seems, did not simply implement keccek in the way that litecoin devs implemented scrypt. -Or how the darkcoin devs implements x11, or how the quarkcoin devs implemented quark. The maxcoin devs -decided to change several parts of how the the currency works - so that instead of simply changing the block -hashing from sha256d to keccak, you have to change a few other parts of the block creation/submission progress. -I believe there is actually at least one coin that implemented keccak hashing normally - copperlark coin. -Too bad its source and binaries are only on some sketchy russian site and neither will compile/run on my -system.. Anyway, it looks like several coin devs forked this maxcoin and switched out keccak with -a different algo. This group of max-tainted algos I believe to be: keccak, fugue, blake. -There may be more, and there may be coins that implemented those algos the regular way instead of the maxcoin -way. So.. for each of these max-tainted algos we may have to implement, for example, blake and blake-max, or -keccak and keccak-max. - - - -One of my goals is to create a single native node.js addon that has all the hashing functions. So many of them -share the same C code. Also it appears that some coins slightly tweak the way an algo is used which renders -the currernt native node addon for that algo useless unless modified. Seems much better to have one big native -node addon with all the hashing algos, and each configurable for the needs of different coins. It would make -the process of adding a new algo much more simple as well. - - - - -hefty1 -https://github.com/heavycoin/heavycoin/blob/master/src/main.cpp#L40 -00000000ffff0000000000000000000000000000000000000000000000000000 -https://github.com/heavycoin/heavycoin-hash-python - - -keccak -https://github.com/Max-Coin/maxcoin/blob/master/src/main.cpp#L42 -https://github.com/wecoin/wecoin/blob/master/src/main.cpp#L44 -https://github.com/phusion/node-sha3 -https://github.com/GalleonBank/galleon - -blake -https://github.com/BlueDragon747/Blakecoin/blob/master/src/main.cpp#L38 -https://github.com/BlueDragon747/Blakecoin_Python_POW_Module - - -bcrypt -https://github.com/TaojingCoin-pd/Taojingcoin/blob/master/src/main.cpp#L35 -https://github.com/TaojingCoin-pd/Taojingcoin/blob/master/src/bcrypt.cpp -https://github.com/TaojingCoin-pd/Taojingcoin/blob/master/src/bcrypt.h - - -scrypt-n -https://github.com/vertcoin/vertcoin/blob/master-0.8/src/main.cpp#L35 -https://github.com/scr34m/vertcoin_scrypt -https://github.com/ahmedbodi/stratum-mining/tree/NScrypt - - -max -https://github.com/Prydie/maxcoin-hash-python -https://github.com/ahmedbodi/stratum-mining-maxcoin - - -fugue -https://github.com/fuguecoin/fuguecoin/blob/master/src/main.cpp#L40 -https://github.com/fuguecoin/fuguecoin - - -SHAvite-3 -https://github.com/inkcoin/inkcoin-project/blob/master/src/main.cpp#L38 -https://github.com/inkcoin/inkcoin-project/blob/f729f1070eb6222832f34fbf087b1aea16522962/src/hashblock.h -https://github.com/inkcoin/inkcoin-project -http://www.cs.technion.ac.il/~orrd/SHAvite-3/ -https://bitcointalk.org/index.php?topic=481516.0 diff --git a/README.md b/README.md index 7514414..3ff4330 100644 --- a/README.md +++ b/README.md @@ -50,13 +50,12 @@ May be working (needs additional testing): * ? *Blake* (Blakecoin [BLC]) * ? *Fugue* (Fuguecoin [FC]) * ? *Skein* (Skeincoin [SKC]) -* ? *Groestl* (Groestlcoin [GRS], Myriadcoin [MYR) +* ? *Groestl* (Groestlcoin [GRS], Myriadcoin [MYR]) +* ? *Qubit* (Qubitcoin [Q2C], Myriadcoin [MYR]) +* ? *Hefty1* (Heavycoin [HVC]) +* ? *SHAvite-3* (INKcoin [INK]) + -Under development: -* ✗ *Qubit* (Qubitcoin [Q2C], Myriadcoin [MYR]) -* ✗ *Hefty1* (Heavycoin [HVC]) -* ✗ *SHAvite-3* (INKcoin [INK]) -* ✗ *Bcrypt* (Taojingcoin [TJC]) Requirements @@ -79,11 +78,14 @@ npm update Create the configuration for your coin: +Possible options for `algorithm`: *sha256, scrypt, scrypt-jane, scrypt-n, quark, x11, keccak, blake, +skein, groestl, fugue, shavite3, hefty1, or qubit*. + ```javascript var myCoin = { "name": "Dogecoin", "symbol": "DOGE", - "algorithm": "scrypt", //or "sha256", "scrypt-jane", "scrypt-n", "quark", "x11" + "algorithm": "scrypt", "txMessages": false, //or true (not required, defaults to false) }; ``` diff --git a/diff1.js b/diff1.js deleted file mode 100644 index 3ad9197..0000000 --- a/diff1.js +++ /dev/null @@ -1,388 +0,0 @@ -var readline = require('readline'); - -var bignum = require('bignum'); - -/* - - Typically coins give us nBits (diff1) in the inconvenient form of: - CBigNum bnProofOfWorkLimit(~uint256(0) >> 24); - nBits = bnProofOfWorkLimit.GetCompact(); - The reason they had to do that was because in the compact nBit form there wasn't enough - precision for the harder to mine algos (speculation). - - - So far this script can get the hex representation of the diff1 using either the - bitwise-rightShift integer, or using the 8 character hex representation of nBits. - However, I'm not able to convert that to the compact format (nbits) yet. - - - Values from coin sources: - - fuguecoin [fugue] (~uint256(0) >> 24) - https://github.com/fuguecoin/fuguecoin/blob/master/src/main.cpp#L40 - - heavycoin [hefty1] (~uint256(0) >> 16) - https://github.com/heavycoin/heavycoin/blob/master/src/main.cpp#L40 - - maxcoin [keccak] (~uint256(0) >> 24) - https://github.com/Max-Coin/maxcoin/blob/master/src/main.cpp#L42 - - galleon [keccak] (~uint256(0) >> 20) - https://github.com/GalleonBank/galleon/blob/master/src/main.cpp#L51 - - cryptometh [keccak] (~uint256(0) >> 24) - https://github.com/cryptometh/cryptometh/blob/master/src/main.cpp#L43 - - 365coin [keccak] (~uint256(0) >> 24) - https://github.com/365-Coin/365coin/blob/master/src/main.cpp#L42 - - slothcoin [keccak] (~uint256(0) >> 24) - https://github.com/thimod/Slothcoin/blob/master/src/main.cpp#L40 - - blakecoin [blake] (~uint256(0) >> 24) - https://github.com/BlueDragon747/Blakecoin/blob/master/src/main.cpp#L38 - - quarkcoin [quark] (~uint256(0) >> 20) - https://github.com/MaxGuevara/quark/blob/master/src/main.cpp#L39 - - taojingcoin [bcrypt] (~uint256(0) >> 11) - https://github.com/TaojingCoin-pd/Taojingcoin/blob/master/src/main.cpp#L35 - - darkcoin [x11] (~uint256(0) >> 20) - https://github.com/evan82/darkcoin/blob/master/src/main.cpp#L36 - - hirocoin [x11] 0x1e0ffff0 - https://github.com/HiroSatou/Hirocoin/blob/ea99705ba60ea9b69c738c1853d41ce75d05eb25/src/main.cpp#L2873 - - inkcoin [shavite] (~uint256(0) >> 20) - https://github.com/inkcoin/inkcoin-project/blob/master/src/main.cpp#L38 - - litecoin [scrypt] (~uint256(0) >> 20) - https://github.com/litecoin-project/litecoin/blob/master-0.8/src/main.cpp#L35 - - yacoin [scrypt-jane] (~uint256(0) >> 20) - https://github.com/yacoin/yacoin/blob/master/src/main.cpp#L36 - - ultracoin [scrypt-jane] (~uint256(0) >> 20) - https://github.com/ziggy909/ultracoin/blob/master/src/main.cpp#L39 - - vertcoin [scrypt-n] (~uint256(0) >> 20) - https://github.com/vertcoin/vertcoin/blob/master-0.8/src/main.cpp#L35 - - skiencoin [skein] (~uint256(0) >> 20) - https://github.com/skeincoin/skeincoin/blob/master/src/chainparams.cpp#L33 - - nigeriacoin [skein] (~uint256(0) >> 20) - https://github.com/nigeriacoin/nigeriacoin/blob/master/src/chainparams.cpp#L35 - - bitcoin [sha256d] 0x1d00ffff - https://github.com/bitcoin/bitcoin/blob/b8d9058a4d1ce28eefa65aa3339bcc52b3c014e9/src/chainparams.cpp#L136 - btc just gave use the value in compact format of 0x1d00ffff, but its bitshift is (~uint256(0) >> 32) - - */ - - -console.log('\n\n===== Diff1 Calculator ===== \n'); - -console.log('Get the diff1 value from either nBits such as 0x1d00ffff or from bitwise-right-shift value such ' + - 'as "20" from "uint256(0) >> 20" in source codes for various daemons.\n\n'); - -console.log('To get the most accurate diff1 to use for your pool, use the bitwise shift value (option 1). The value ' + - 'is found in the coin source, typically in main.cpp and looks like "static CBigNum bnProofOfWorkLimit(~uint256(0) >> 20);"\n\n'); - -var args = process.argv.slice(2); -var testing = args[0] == 'test'; - -var rl = readline.createInterface({ - input: process.stdin, - output: process.stdout -}); - -var methods = { - bitshift: 'Bitshift', - nbits: 'nBits' -}; - -function startAsking() { - rl.question('\nWhat are you converting from:' + - '\n\t[1] Bitshift Value (example: 20)' + - '\n\t[2] nBits Hex (example: 0x1d00ffff)' + - '\n1 or 2?: ', function (answer) { - switch (answer) { - case '1': - askBitshift(); - break; - case '2': - askBitsConvert(); - break; - default: - console.log("Answer 1 or 2..."); - startAsking(); - break; - } - }); -} - -function askBitshift(){ - console.log('\nEnter the right bitshift integer, for example with "uint256(0) >> 24", enter in the number 24'); - rl.question('Number: ', function (answer) { - - var shiftRight; - try { - shiftRight = parseInt(answer); - } - catch(e) { - console.error('Must enter an integer...'); - console.error(e); - startAsking(); - } - if (shiftRight) { - DisplayResult(methods.bitshift, ShiftMax256Right(shiftRight), answer); - startAsking(); - } - - }); -} - -function askBitsConvert(){ - console.log('\n(Note that this will always give truncated results as diff1 precision is ' + - 'lost when compacting to nBits. Enter the 8 character nBit hex code, for example ' + - 'with BTC its 0x1d00ffff so enter 1d00ffff\n'); - rl.question('Hex code: ', function (answer) { - - if (answer.length !== 8){ - console.log('Must be an 8 character hex string'); - startAsking(); - return; - } - - var bitsBuffer; - try{ - bitsBuffer = new Buffer(answer, 'hex'); - } - catch(e){ - console.error('Must be valid hex..'); - console.error(e); - } - - if (bitsBuffer){ - DisplayResult(methods.nbits, ConvertBitsToHex(answer), answer); - startAsking(); - } - - }); -} - - -function ShiftMax256Right (shiftRight){ - - var arr256 = Array.apply(null, new Array(256)).map(Number.prototype.valueOf, 1); - - var arrLeft = Array.apply(null, new Array(shiftRight)).map(Number.prototype.valueOf, 0); - - var preShift = arrLeft.concat(arr256); - - var trimmed = preShift.slice(0, 256); - - var octets = []; - - for (var i = 0; i < 32; i++){ - octets[i] = 0; - var bits = trimmed.slice(i * 8, i * 8 + 8); - for (var f = 0; f < bits.length; f++){ - var multiplier = Math.pow(2, f); - octets[i] += bits[f] * multiplier; - } - } - - var buff = new Buffer(octets); - var hexString = buff.toString('hex'); - - return hexString; - -} - - -function ConvertBitsToHex(hexString){ - - var bitsBuff = new Buffer(hexString, 'hex'); - - var numBytes = bitsBuff.readUInt8(0); - var bigBits = bignum.fromBuffer(bitsBuff.slice(1)); - var target = bigBits.mul( - bignum(2).pow( - bignum(8).mul( - numBytes - 3 - ) - ) - ); - - var resultBuff = target.toBuffer(); - var buff256 = new Buffer(32); - buff256.fill(0); - resultBuff.copy(buff256, buff256.length - resultBuff.length); - - var hexResult = buff256.toString('hex'); - - return hexResult; -} - - -function BufferToCompact(hexString){ - - var startingBuff = new Buffer(hexString, 'hex'); - var bigNum = bignum.fromBuffer(startingBuff); - var buff = bigNum.toBuffer(); - - buff = buff.readUInt8(0) > 0x7f ? Buffer.concat([new Buffer([0x00]), buff]) : buff; - - buff = Buffer.concat([new Buffer([buff.length]), buff]); - var compact = buff.slice(0, 4); - return compact.toString('hex'); - -} - - -function DisplayResult(method, hexString, input){ - - var details = GetResultDetails(hexString); - - var logMessages = ['\nConversion results for ' + method + ' on ' + input]; - - for (var detail in details){ - logMessages.push(detail + ':\t0x' + details[detail]); - } - - var message = logMessages.join('\n\t\t'); - - console.log(message); - - if (method === methods.bitshift) - console.log('Use Difficulty 1 for your pool.'); -} - -function GetResultDetails(hex){ - var compactHex = BufferToCompact(hex); - - var lostPrecision = ConvertBitsToHex(compactHex); - - return details = { - 'As Compact': compactHex, - 'Difficulty 1': hex, - 'Truncated': lostPrecision - }; -}; - -//tests to see if an nbit value evaluates to the same truncated diff1 as a bitshift value -//also returns the diff1 that should be used for pools -function TestEquality(testName, bitshiftValue, nBitsValue){ - - var t1 = ShiftMax256Right(bitshiftValue); - var t2 = ConvertBitsToHex(nBitsValue); - - var t1Details = GetResultDetails(t1); - var t2Details = GetResultDetails(t2); - if (bignum(t1Details.Truncated, 16).eq(bignum(t2Details.Truncated, 16))){ - //console.log('Test successful for ' + testName + ', truncated values are equal for bitwise ' + bitshiftValue + ' and nBits of ' + nBitsValue); - } - else{ - DisplayResult(methods.bitshift, t1, bitshiftValue); - DisplayResult(methods.nbits, t2, nBitsValue); - console.log('Test failed for ' + testName + ', truncated values are different for bitwise ' + bitshiftValue + ' and nBits of ' + nBitsValue); - } - - return t1Details['Difficulty 1']; -} - - -if (!testing) - startAsking(); -else { - - var algos = { - sha256d: { - shift: 32, - nBits: '1d00ffff' - }, - scrypt: { - shift: 20, - nBits: '1f00f0ff' - }, - 'scrypt-jane': { - shift: 20, - nBits: '1f00f0ff' - }, - 'scrypt-n': { - shift: 20, - nBits: '1f00f0ff' - }, - x11: { - shift: 20, - nBits: '1f00f0ff' - }, - quark: { - shift: 20, - nBits: '1f00f0ff' - }, - skein: { - shift: 20, - nBits: '1f00f0ff' - }, - keccak: { - shift: 24, - nBits: '1e00ffff' - }, - hefty1: { - shift: 16, - nBits: '1f00ffff' - }, - bcrypt: { - shift: 11, - nBits: '2000f8ff' - }, - fugue: { - shift: 24, - nBits: '1e00ffff' - }, - blake: { - shift: 24, - nBits: '1e00ffff' - }, - shavite: { - shift: 20, - nBits: '1f00f0ff' - } - }; - - var diffLogLines = []; - - for (var algo in algos){ - - - var whitespace = new Array(15 - algo.length).join(' '); - - var diff1 = TestEquality(algo, algos[algo].shift, algos[algo].nBits); - diffLogLines.push(algo + ':' + whitespace + '0x' + diff1); - } - - console.log('Pools should use these difficulties:\n' + diffLogLines.join('\n')); - -} - -/* -Test Output: - Pools should use these difficulties: - sha256d: 0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff - scrypt: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - scrypt-jane: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - scrypt-n: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - x11: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - quark: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - keccak: 0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - hefty1: 0x0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - bcrypt: 0x00f8ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - fugue: 0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - blake: 0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - shavite: 0x0000f0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff - - */ \ No newline at end of file diff --git a/lib/algoProperties.js b/lib/algoProperties.js index af2ac0c..254cea3 100644 --- a/lib/algoProperties.js +++ b/lib/algoProperties.js @@ -96,7 +96,6 @@ var algos = module.exports = global.algos = { } }, skein: { - multiplier: Math.pow(2, 8), hash: function(){ return function(){ return multiHashing.skein.apply(this, arguments); @@ -104,7 +103,6 @@ var algos = module.exports = global.algos = { } }, groestl: { - multiplier: Math.pow(2, 8), hash: function(){ return function(){ return multiHashing.groestl.apply(this, arguments); @@ -112,34 +110,30 @@ var algos = module.exports = global.algos = { } }, fugue: { - multiplier: Math.pow(2, 8), hash: function(){ return function(){ return multiHashing.fugue.apply(this, arguments); } } }, - shavite: { - shift: 20, + shavite3: { hash: function(){ return function(){ - + return multiHashing.shavite3.apply(this, arguments); } } }, hefty1: { - shift: 16, hash: function(){ return function(){ - + return multiHashing.hefty1.apply(this, arguments); } } }, - bcrypt: { - shift: 11, + qubit: { hash: function(){ return function(){ - return multiHashing.bcrypt.apply(this, arguments); + return multiHashing.qubit.apply(this, arguments); } } }