diff --git a/lib/bcoin/miner.js b/lib/bcoin/miner.js index e899443b..cd329dec 100644 --- a/lib/bcoin/miner.js +++ b/lib/bcoin/miner.js @@ -220,7 +220,7 @@ Miner.prototype.createBlock = function createBlock(tx) { bcoin.script.array(this.last.height + 1), // extraNonce - incremented when // the nonce overflows. - new Buffer([]), + 0, // Add a nonce to ensure we don't // collide with a previous coinbase // of ours. This isn't really diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 8c438061..aaf1d7ba 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -41,7 +41,7 @@ script.decode = function decode(s) { // Special case: this is an empty array // because it can be seen as an empty pushdata. if (b === 0x00) { - opcodes.push(new Buffer([])); + opcodes.push(0); continue; } @@ -445,6 +445,11 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { continue; } + if (o === 0) { + stack.push(new Buffer([])); + continue; + } + if (o >= 1 && o <= 16) { stack.push(new Buffer([o])); continue; @@ -465,7 +470,7 @@ script.execute = function execute(data, stack, tx, index, flags, recurse) { break; } case '1negate': { - stack.push(new Buffer([0x80, 0xff])); + stack.push(new Buffer([0xff])); break; } case 'if': @@ -1121,7 +1126,7 @@ script.num = function num(value, useNum, minimaldata) { if (utils.isNegZero(value, 'le')) { value = new bn(0, 'le'); } else { - value = new bn(value, 'le').notn(64).addn(1).neg(); + value = new bn(value, 'le').notn(value.length * 8).addn(1).neg(); } } else { value = new bn(value, 'le'); @@ -1153,7 +1158,7 @@ script.array = function(value) { if (value.cmpn(0) === 0) value = new bn(0); else - value = value.neg().notn(64).addn(1); + value = value.neg().notn(value.byteLength() * 8).subn(1); } if (value.cmpn(0) === 0) @@ -1370,15 +1375,18 @@ script.getInputData = function getData(s, prev) { // we really only need the signatures. if (output.type === 'pubkey') { if (s.length >= 1) - output.signatures = [s[0]]; + output.signatures = [s[0] === 0 ? new Buffer([]) : s[0]]; } else if (output.type === 'pubkeyhash') { if (s.length >= 2) { - output.signatures = [s[0]]; + output.signatures = [s[0] === 0 ? new Buffer([]) : s[0]]; output.keys = [s[1]]; } } else if (output.type === 'multisig') { - if (s.length >= 2) - output.signatures = s.slice(1); + if (s.length >= 2) { + output.signatures = s.slice(1).map(function(sig) { + return sig === 0 ? new Buffer([]) : sig; + }); + } } else if (output.type === 'scripthash') { // Scripthash is the only case where // we get more data from the input @@ -1420,6 +1428,8 @@ script._getInputData = function _getInputData(s, type) { if (type === 'pubkey') { sig = s[0]; + if (sig === 0) + sig = new Buffer([]); return { type: 'pubkey', side: 'input', @@ -1430,6 +1440,8 @@ script._getInputData = function _getInputData(s, type) { if (type === 'pubkeyhash') { sig = s[0]; + if (sig === 0) + sig = new Buffer([]); key = s[1]; hash = bcoin.address.hash160(key); address = bcoin.address.toAddress(hash, 'pubkeyhash'); @@ -1445,7 +1457,9 @@ script._getInputData = function _getInputData(s, type) { } if (type === 'multisig') { - sig = s.slice(1); + sig = s.slice(1).map(function(sig) { + return sig === 0 ? new Buffer([]) : sig; + }); return { type: 'multisig', side: 'input', @@ -2333,7 +2347,7 @@ script.isPushOnly = function isPushOnly(s) { var i, op; for (i = 0; i < s.length; i++) { op = s[i]; - if (Buffer.isBuffer(op) || op === '1negate' || (op >= 1 && op <= 16)) + if (Buffer.isBuffer(op) || op === '1negate' || (op >= 0 && op <= 16)) continue; return false; } diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 75dad79c..6df99985 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -270,7 +270,7 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Already has a script template (at least) if (input.script.length) return true; - input.script = [new Buffer([])]; + input.script = [0]; } else if (bcoin.script.isPubkeyhash(s)) { // P2PKH if (!utils.isEqual(s[2], bcoin.address.hash160(publicKey))) @@ -278,7 +278,7 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Already has a script template (at least) if (input.script.length) return true; - input.script = [new Buffer([]), publicKey]; + input.script = [0, publicKey]; } else if (bcoin.script.isMultisig(s)) { // Multisig for (i = 0; i < s.length; i++) { @@ -296,14 +296,14 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Technically we should create m signature slots, // but we create n signature slots so we can order // the signatures properly. - input.script = [new Buffer([])]; + input.script = [0]; // Grab `n` value (number of keys). n = s[s.length - 2]; // Fill script with `n` signature slots. for (i = 0; i < n; i++) - input.script[i + 1] = new Buffer([]); + input.script[i + 1] = 0; } else { for (i = 0; i < s.length; i++) { if (utils.isEqual(s[i], publicKey)) @@ -322,11 +322,11 @@ TX.prototype.scriptInput = function scriptInput(index, publicKey, redeem) { // Also, only allow nonstandard types for // scripthash. if (redeem) { - input.script = [new Buffer([])]; + input.script = [0]; // Fill script with `n` signature slots. for (i = 0; i < s.length; i++) { if (bcoin.script.isKey(s[i])) - input.script.push(new Buffer([])); + input.script.push(0); } } } @@ -420,12 +420,8 @@ TX.prototype.signInput = function signInput(index, key, type) { if (bcoin.script.isPubkey(s)) { // P2PK - // Something is wrong. Abort. - if (!Buffer.isBuffer(input.script[0])) - return false; - // Already signed. - if (input.script[0].length) + if (bcoin.script.isSignature(input.script[0])) return true; // Make sure the pubkey is ours. @@ -440,12 +436,8 @@ TX.prototype.signInput = function signInput(index, key, type) { if (bcoin.script.isPubkeyhash(s)) { // P2PKH - // Something is wrong. Abort. - if (!Buffer.isBuffer(input.script[0])) - return false; - // Already signed. - if (input.script[0].length) + if (bcoin.script.isSignature(input.script[0])) return true; // Make sure the pubkey hash is ours. @@ -507,7 +499,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // or by `m`. Add some signature slots for // us to use. while (len - 1 < n) { - input.script.splice(len, 0, new Buffer([])); + input.script.splice(len, 0, 0); len++; } @@ -533,7 +525,7 @@ TX.prototype.signInput = function signInput(index, key, type) { // and increment the total number of // signatures. if (ki < len && signatures < m) { - if (bcoin.script.isDummy(input.script[ki])) { + if (input.script[ki] === 0) { input.script[ki] = signature; signatures++; } @@ -543,7 +535,7 @@ TX.prototype.signInput = function signInput(index, key, type) { if (signatures >= m) { // Remove empty slots left over. for (i = len - 1; i >= 1; i--) { - if (bcoin.script.isDummy(input.script[i])) { + if (input.script[i] === 0) { input.script.splice(i, 1); len--; } diff --git a/lib/bcoin/utils.js b/lib/bcoin/utils.js index 084337db..e0a89fcb 100644 --- a/lib/bcoin/utils.js +++ b/lib/bcoin/utils.js @@ -326,6 +326,9 @@ utils.binaryInsert = binaryInsert; utils.isEqual = function isEqual(a, b) { var i = 0; + if (!a || !b) + return false; + if (a.length !== b.length) return false; @@ -1252,7 +1255,7 @@ utils.write64 = function write64(dst, num, off) { if (num.cmpn(0) === 0) num = new bn(0); else - num = num.neg().notn(64).addn(1); + num = num.neg().notn(64).subn(1); } if (num.bitLength() > 64) @@ -1282,7 +1285,7 @@ utils.write64BE = function write64BE(dst, num, off) { if (num.cmpn(0) === 0) num = new bn(0); else - num = num.neg().notn(64).addn(1); + num = num.neg().notn(64).subn(1); } if (num.bitLength() > 64) diff --git a/test/script-test.js b/test/script-test.js index 008edc57..7239af4e 100644 --- a/test/script-test.js +++ b/test/script-test.js @@ -24,7 +24,7 @@ describe('Script', function() { }); it('should encode/decode numbers', function() { - var script = [ [], 1, 2, 16 ]; + var script = [ 0, 1, 2, 16 ]; var encoded = bcoin.script.encode(script); assert.deepEqual(encoded, [ 0, 0x51, 0x52, 0x60 ]); var decoded = bcoin.script.decode(encoded);