From f7e50e3435e66ce17644424c9b88fa3b85b50f73 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Tue, 6 Dec 2016 17:37:35 -0800 Subject: [PATCH] tx: pass coins into scripting system. --- lib/primitives/mtx.js | 153 ++++++++++++-------------------------- lib/primitives/tx.js | 34 +++++---- lib/script/script.js | 26 +++---- lib/wallet/txdb.js | 12 +-- lib/workers/jobs.js | 14 ++-- lib/workers/packets.js | 66 +++++++--------- lib/workers/workerpool.js | 10 ++- test/mempool-test.js | 10 +-- test/script-test.js | 3 +- test/tx-test.js | 5 +- 10 files changed, 137 insertions(+), 196 deletions(-) diff --git a/lib/primitives/mtx.js b/lib/primitives/mtx.js index d9ccb114..349a9aa8 100644 --- a/lib/primitives/mtx.js +++ b/lib/primitives/mtx.js @@ -217,19 +217,17 @@ MTX.prototype.addOutput = function addOutput(options, value) { * Build input script (or witness) templates (with * OP_0 in place of signatures). * @param {Number} index - Input index. + * @param {Coin|Output} coin * @param {KeyRing} ring * @returns {Boolean} Whether the script was able to be built. */ -MTX.prototype.scriptInput = function scriptInput(index, ring) { +MTX.prototype.scriptInput = function scriptInput(index, coin, ring) { var input = this.inputs[index]; var prev, redeem; assert(input, 'Input does not exist.'); - - // We should have previous outputs by now. - if (!input.coin) - return false; + assert(coin, 'No coin passed.'); // Don't bother with any below calculation // if the output is already templated. @@ -239,7 +237,7 @@ MTX.prototype.scriptInput = function scriptInput(index, ring) { } // Get the previous output's script - prev = input.coin.script; + prev = coin.script; // This is easily the hardest part about // building a transaction with segwit: @@ -402,33 +400,32 @@ MTX.prototype.scriptVector = function scriptVector(prev, vector, ring) { * @returns {Promise} */ -MTX.prototype.signInputAsync = function signInputAsync(index, ring, type) { - return workerPool.signInput(this, index, ring, type); +MTX.prototype.signInputAsync = function signInputAsync(index, coin, ring, type) { + return workerPool.signInput(this, index, coin, ring, type); }; /** * Sign an input. * @param {Number} index - Index of input being signed. + * @param {Coin|Output} coin * @param {KeyRing} ring - Private key. * @param {SighashType} type * @returns {Boolean} Whether the input was able to be signed. */ -MTX.prototype.signInput = function signInput(index, ring, type) { +MTX.prototype.signInput = function signInput(index, coin, ring, type) { var input = this.inputs[index]; var version = 0; var redeem = false; var key = ring.privateKey; - var prev, vector, sig, result; + var prev, value, vector, sig, result; assert(input, 'Input does not exist.'); - - // We should have previous outputs by now. - if (!input.coin) - return false; + assert(coin, 'No coin passed.'); // Get the previous output's script - prev = input.coin.script; + prev = coin.script; + value = coin.value; vector = input.script; // Grab regular p2sh redeem script. @@ -460,7 +457,7 @@ MTX.prototype.signInput = function signInput(index, ring, type) { } // Create our signature. - sig = this.signature(index, prev, key, type, version); + sig = this.signature(index, prev, value, key, type, version); if (redeem) { redeem = vector.pop(); @@ -618,88 +615,19 @@ MTX.prototype.signVector = function signVector(prev, vector, sig, ring) { return false; }; -/** - * Combine and sort multisig signatures for script. - * Mimics bitcoind's behavior. - * @param {Number} index - * @param {Script} prev - * @param {Witness|Script} vector - * @param {Number} version - * @param {Buffer} data - * @return {Boolean} - */ - -MTX.prototype.combine = function combine(index, prev, vector, version, data) { - var m = prev.getSmall(0); - var sigs = []; - var map = {}; - var result = false; - var i, j, sig, type, msg, key, pub, res; - - if (data) - sigs.push(data); - - for (i = 1; i < vector.length; i++) { - sig = vector.get(i); - if (Script.isSignature(sig)) - sigs.push(sig); - } - - for (i = 0; i < sigs.length; i++) { - sig = sigs[i]; - type = sig[sig.length - 1]; - - msg = this.signatureHash(index, prev, type, version); - - for (j = 1; j < prev.length - 2; j++) { - key = prev.get(j); - pub = key.toString('hex'); - - if (map[pub]) - continue; - - res = Script.checksig(msg, sig, key); - - if (res) { - map[pub] = sig; - if (util.equal(sig, data)) - result = true; - break; - } - } - } - - vector.clear(); - vector.push(opcodes.OP_0); - - for (i = 1; i < prev.length - 2; i++) { - key = prev.get(i); - pub = key.toString('hex'); - sig = map[pub]; - if (sig) - vector.push(sig); - } - - while (vector.length - 1 < m) - vector.push(opcodes.OP_0); - - vector.compile(); - - return result; -}; - /** * Create a signature suitable for inserting into scriptSigs/witnesses. * @param {Number} index - Index of input being signed. * @param {Script} prev - Previous output script or redeem script * (in the case of witnesspubkeyhash, this should be the generated * p2pkh script). + * @param {Amount} value - Previous output value. * @param {SighashType} type * @param {Number} version - Sighash version (0=legacy, 1=segwit). * @returns {Buffer} Signature in DER format. */ -MTX.prototype.signature = function signature(index, prev, key, type, version) { +MTX.prototype.signature = function signature(index, prev, value, key, type, version) { var hash; if (type == null) @@ -710,7 +638,7 @@ MTX.prototype.signature = function signature(index, prev, key, type, version) { // Get the hash of the current tx, minus the other // inputs, plus the sighash type. - hash = this.signatureHash(index, prev, type, version); + hash = this.signatureHash(index, prev, value, type, version); // Sign the transaction with our one input return Script.sign(hash, key, type); @@ -722,10 +650,19 @@ MTX.prototype.signature = function signature(index, prev, key, type, version) { */ MTX.prototype.isSigned = function isSigned() { - for (var i = 0; i < this.inputs.length; i++) { - if (!this.isInputSigned(i)) + var i, input, coin; + + for (i = 0; i < this.inputs.length; i++) { + input = this.inputs[i]; + coin = input.coin; + + if (!coin) + return false; + + if (!this.isInputSigned(i, coin)) return false; } + return true; }; @@ -735,19 +672,15 @@ MTX.prototype.isSigned = function isSigned() { * @returns {Boolean} */ -MTX.prototype.isInputSigned = function isInputSigned(index) { +MTX.prototype.isInputSigned = function isInputSigned(index, coin) { var input = this.inputs[index]; var prev, vector, redeem, result; assert(input, 'Input does not exist.'); - - // We can't check for signatures unless - // we have the previous output. - if (!input.coin) - return false; + assert(coin, 'No coin passed.'); // Get the prevout's script - prev = input.coin.script; + prev = coin.script; // Script length, needed for multisig vector = input.script; @@ -839,7 +772,7 @@ MTX.prototype.isVectorSigned = function isVectorSigned(prev, vector) { MTX.prototype.template = function template(ring) { var total = 0; - var i; + var i, input, coin; if (Array.isArray(ring)) { for (i = 0; i < ring.length; i++) @@ -848,11 +781,17 @@ MTX.prototype.template = function template(ring) { } for (i = 0; i < this.inputs.length; i++) { - if (!ring.ownInput(this, i)) + input = this.inputs[i]; + coin = input.coin; + + if (!coin) + continue; + + if (!ring.ownOutput(coin)) continue; // Build script for input - if (!this.scriptInput(i, ring)) + if (!this.scriptInput(i, coin, ring)) continue; total++; @@ -871,7 +810,7 @@ MTX.prototype.template = function template(ring) { MTX.prototype.sign = function sign(ring, type) { var total = 0; - var i; + var i, input, coin; if (Array.isArray(ring)) { for (i = 0; i < ring.length; i++) @@ -882,15 +821,21 @@ MTX.prototype.sign = function sign(ring, type) { assert(ring.privateKey, 'No private key available.'); for (i = 0; i < this.inputs.length; i++) { - if (!ring.ownInput(this, i)) + input = this.inputs[i]; + coin = input.coin; + + if (!coin) + continue; + + if (!ring.ownOutput(coin)) continue; // Build script for input - if (!this.scriptInput(i, ring)) + if (!this.scriptInput(i, coin, ring)) continue; // Sign input - if (!this.signInput(i, ring, type)) + if (!this.signInput(i, coin, ring, type)) continue; total++; diff --git a/lib/primitives/tx.js b/lib/primitives/tx.js index 71f871c0..722a40e7 100644 --- a/lib/primitives/tx.js +++ b/lib/primitives/tx.js @@ -460,12 +460,13 @@ TX.prototype.hasWitness = function hasWitness() { * @returns {Buffer} Signature hash. */ -TX.prototype.signatureHash = function signatureHash(index, prev, type, version) { +TX.prototype.signatureHash = function signatureHash(index, prev, value, type, version) { if (typeof type === 'string') type = constants.hashType[type.toUpperCase()]; assert(index >= 0 && index < this.inputs.length); assert(prev instanceof Script); + assert(typeof value === 'number'); // Traditional sighashing if (version === 0) @@ -473,7 +474,7 @@ TX.prototype.signatureHash = function signatureHash(index, prev, type, version) // Segwit sighashing if (version === 1) - return this.signatureHashV1(index, prev, type); + return this.signatureHashV1(index, prev, value, type); assert(false, 'Unknown sighash version.'); }; @@ -599,7 +600,7 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) { * @returns {Buffer} */ -TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) { +TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, value, type) { var i, bw, input, output, prevouts, sequences, outputs; if (!(type & constants.hashType.ANYONECANPAY)) { @@ -678,7 +679,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) { bw.writeHash(input.prevout.hash); bw.writeU32(input.prevout.index); bw.writeVarBytes(prev.toRaw()); - bw.write64(input.coin.value); + bw.write64(value); bw.writeU32(input.sequence); bw.writeBytes(outputs); bw.writeU32(this.locktime); @@ -694,7 +695,7 @@ TX.prototype.signatureHashV1 = function signatureHashV1(index, prev, type) { */ TX.prototype.verify = function verify(flags) { - var i; + var i, input, coin; if (this.inputs.length === 0) return false; @@ -703,7 +704,13 @@ TX.prototype.verify = function verify(flags) { return true; for (i = 0; i < this.inputs.length; i++) { - if (!this.verifyInput(i, flags)) + input = this.inputs[i]; + coin = input.coin; + + if (!coin) + return false; + + if (!this.verifyInput(i, coin, flags)) return false; } @@ -714,25 +721,25 @@ TX.prototype.verify = function verify(flags) { * Verify a transaction input. * @param {Number} index - Index of output being * verified. + * @param {Coin|Output} coin - Previous output. * @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS] * @returns {Boolean} Whether the input is valid. */ -TX.prototype.verifyInput = function verifyInput(index, flags) { +TX.prototype.verifyInput = function verifyInput(index, coin, flags) { var input = this.inputs[index]; assert(input, 'Input does not exist.'); - - if (!input.coin) - return false; + assert(coin, 'No coin passed.'); try { Script.verify( input.script, input.witness, - input.coin.script, + coin.script, this, index, + coin.value, flags ); } catch (e) { @@ -766,14 +773,15 @@ TX.prototype.verifyAsync = co(function* verifyAsync(flags) { * Verify a transaction input asynchronously. * @param {Number} index - Index of output being * verified. + * @param {Coin|Output} coin - Previous output. * @param {VerifyFlags} [flags=STANDARD_VERIFY_FLAGS] * @returns {Boolean} Whether the input is valid. */ -TX.prototype.verifyInputAsync = co(function* verifyInputAsync(index, flags) { +TX.prototype.verifyInputAsync = co(function* verifyInputAsync(index, coin, flags) { var input = this.inputs[index]; assert(input, 'Input does not exist.'); - return yield workerPool.verifyInput(this, index, flags); + return yield workerPool.verifyInput(this, index, coin, flags); }); /** diff --git a/lib/script/script.js b/lib/script/script.js index 4f469183..a5097eb8 100644 --- a/lib/script/script.js +++ b/lib/script/script.js @@ -309,7 +309,7 @@ Script.prototype.removeSeparators = function removeSeparators() { * @returns {Boolean} Whether the execution was successful. */ -Script.prototype.execute = function execute(stack, flags, tx, index, version) { +Script.prototype.execute = function execute(stack, flags, tx, index, value, version) { var ip = 0; var lastSep = 0; var opCount = 0; @@ -997,7 +997,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) { if (sig.length > 0) { type = sig[sig.length - 1]; - hash = tx.signatureHash(index, subscript, type, version); + hash = tx.signatureHash(index, subscript, value, type, version); res = Script.checksig(hash, sig, key, flags); } @@ -1076,7 +1076,7 @@ Script.prototype.execute = function execute(stack, flags, tx, index, version) { if (sig.length > 0) { type = sig[sig.length - 1]; - hash = tx.signatureHash(index, subscript, type, version); + hash = tx.signatureHash(index, subscript, value, type, version); if (Script.checksig(hash, sig, key, flags)) { isig++; @@ -3091,7 +3091,7 @@ Script.getSmall = function getSmall(op) { * @throws {ScriptError} */ -Script.verify = function verify(input, witness, output, tx, i, flags) { +Script.verify = function verify(input, witness, output, tx, i, value, flags) { var stack, copy, raw, redeem, hadWitness; if (flags == null) @@ -3106,14 +3106,14 @@ Script.verify = function verify(input, witness, output, tx, i, flags) { stack = new Stack(); // Execute the input script - input.execute(stack, flags, tx, i, 0); + input.execute(stack, flags, tx, i, value, 0); // Copy the stack for P2SH if (flags & constants.flags.VERIFY_P2SH) copy = stack.clone(); // Execute the previous output script. - output.execute(stack, flags, tx, i, 0); + output.execute(stack, flags, tx, i, value, 0); // Verify the stack values. if (stack.length === 0 || !Script.bool(stack.top(-1))) @@ -3127,7 +3127,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) { throw new ScriptError('WITNESS_MALLEATED'); // Verify the program in the output script. - Script.verifyProgram(witness, output, flags, tx, i); + Script.verifyProgram(witness, output, flags, tx, i, value); // Force a cleanstack stack.length = 1; @@ -3151,7 +3151,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) { redeem = new Script(raw); // Execute the redeem script. - redeem.execute(stack, flags, tx, i, 0); + redeem.execute(stack, flags, tx, i, value, 0); // Verify the the stack values. if (stack.length === 0 || !Script.bool(stack.top(-1))) @@ -3165,7 +3165,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) { throw new ScriptError('WITNESS_MALLEATED_P2SH'); // Verify the program in the redeem script. - Script.verifyProgram(witness, redeem, flags, tx, i); + Script.verifyProgram(witness, redeem, flags, tx, i, value); // Force a cleanstack. stack.length = 1; @@ -3202,7 +3202,7 @@ Script.verify = function verify(input, witness, output, tx, i, flags) { * @throws {ScriptError} */ -Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) { +Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i, value) { var program = output.toProgram(); var stack = witness.toStack(); var j, witnessScript, redeem; @@ -3252,7 +3252,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) { } // Verify the redeem script. - redeem.execute(stack, flags, tx, i, 1); + redeem.execute(stack, flags, tx, i, value, 1); // Verify the stack values. if (stack.length !== 1 || !Script.bool(stack.top(-1))) @@ -3273,7 +3273,7 @@ Script.verifyProgram = function verifyProgram(witness, output, flags, tx, i) { * @throws {ScriptError} */ -Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i) { +Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i, value) { var mastRoot = new BufferWriter(); var scriptRoot = new BufferWriter(); var scripts = new BufferWriter(); @@ -3388,7 +3388,7 @@ Script.verifyMast = function verifyMast(program, stack, output, flags, tx, i) { } output = new Script(scripts.render()); - output.execute(stack, flags, tx, i, 1); + output.execute(stack, flags, tx, i, value, 1); if (stack.length !== 0) throw new ScriptError('EVAL_FALSE'); diff --git a/lib/wallet/txdb.js b/lib/wallet/txdb.js index 16c97252..6fb0cc17 100644 --- a/lib/wallet/txdb.js +++ b/lib/wallet/txdb.js @@ -346,8 +346,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx, block) { if (coin) { if (this.options.verify && tx.height === -1) { - input.coin = coin; - if (!(yield tx.verifyInputAsync(i, flags))) + if (!(yield tx.verifyInputAsync(i, coin, flags))) return false; } @@ -366,8 +365,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx, block) { // of it. if (coin) { if (this.options.verify && tx.height === -1) { - input.coin = coin; - if (!(yield tx.verifyInputAsync(i, flags))) + if (!(yield tx.verifyInputAsync(i, coin, flags))) return false; } continue; @@ -480,10 +478,8 @@ TXDB.prototype.resolveOutputs = co(function* resolveOutputs(tx, block, resolved) assert(input.prevout.index === i); // We can finally verify this input. - if (this.options.verify && orphan.tx.height === -1) { - input.coin = coin; - valid = yield orphan.tx.verifyInputAsync(orphan.index, flags); - } + if (this.options.verify && orphan.tx.height === -1) + valid = yield orphan.tx.verifyInputAsync(orphan.index, coin, flags); // If it's valid and fully resolved, // we can resolve _its_ outputs. diff --git a/lib/workers/jobs.js b/lib/workers/jobs.js index e8d79891..7f708b27 100644 --- a/lib/workers/jobs.js +++ b/lib/workers/jobs.js @@ -48,11 +48,11 @@ jobs._execute = function execute(p) { case packets.types.VERIFY: return jobs.verify(p.tx, p.flags); case packets.types.VERIFYINPUT: - return jobs.verifyInput(p.tx, p.index, p.flags); + return jobs.verifyInput(p.tx, p.index, p.coin, p.flags); case packets.types.SIGN: return jobs.sign(p.tx, p.rings, p.type); case packets.types.SIGNINPUT: - return jobs.signInput(p.tx, p.index, p.rings, p.type); + return jobs.signInput(p.tx, p.index, p.coin, p.ring, p.type); case packets.types.ECVERIFY: return jobs.ecVerify(p.msg, p.sig, p.key); case packets.types.ECSIGN: @@ -84,12 +84,13 @@ jobs.verify = function verify(tx, flags) { * @see TX#verifyInput * @param {TX} tx * @param {Number} index + * @param {Output} coin * @param {VerifyFlags} flags * @returns {Boolean} */ -jobs.verifyInput = function verifyInput(tx, index, flags) { - var result = tx.verifyInput(index, flags); +jobs.verifyInput = function verifyInput(tx, index, coin, flags) { + var result = tx.verifyInput(index, coin, flags); return new packets.VerifyInputResultPacket(result); }; @@ -111,12 +112,13 @@ jobs.sign = function sign(tx, ring, type) { * @see MTX#signInput * @param {MTX} tx * @param {Number} index + * @param {Output} coin * @param {KeyRing} ring * @param {SighashType} type */ -jobs.signInput = function signInput(tx, index, ring, type) { - var result = tx.signInput(tx, index, ring, type); +jobs.signInput = function signInput(tx, index, coin, ring, type) { + var result = tx.signInput(tx, index, coin, ring, type); return packets.SignInputResultPacket.fromTX(tx, index, result); }; diff --git a/lib/workers/packets.js b/lib/workers/packets.js index b69ed3a0..a5fb53d7 100644 --- a/lib/workers/packets.js +++ b/lib/workers/packets.js @@ -12,6 +12,7 @@ var BufferReader = require('../utils/reader'); var Script = require('../script/script'); var Witness = require('../script/witness'); var Coin = require('../primitives/coin'); +var Output = require('../primitives/output'); /* * Constants @@ -233,7 +234,7 @@ function SignPacket(tx, rings, type) { Packet.call(this); this.tx = tx || null; this.rings = rings || []; - this.type = type != null ? type : null; + this.type = type != null ? type : 1; } util.inherits(SignPacket, Packet); @@ -252,7 +253,7 @@ SignPacket.prototype.toWriter = function toWriter(bw) { ring.toWriter(bw); } - bw.write8(this.type != null ? this.type : -1); + bw.writeU8(this.type); }; SignPacket.fromRaw = function fromRaw(MTX, KeyRing, data) { @@ -269,10 +270,7 @@ SignPacket.fromRaw = function fromRaw(MTX, KeyRing, data) { packet.rings.push(ring); } - packet.type = br.read8(); - - if (packet.type === -1) - packet.type = null; + packet.type = br.readU8(); return packet; }; @@ -355,10 +353,11 @@ SignResultPacket.fromRaw = function fromRaw(data) { * @constructor */ -function VerifyInputPacket(tx, index, flags) { +function VerifyInputPacket(tx, index, coin, flags) { Packet.call(this); this.tx = tx || null; this.index = index; + this.coin = coin || null; this.flags = flags != null ? flags : null; } @@ -367,8 +366,10 @@ util.inherits(VerifyInputPacket, Packet); VerifyInputPacket.prototype.cmd = packetTypes.VERIFYINPUT; VerifyInputPacket.prototype.toWriter = function toWriter(bw) { - frameTX(this.tx, bw); + this.tx.toWriter(bw); bw.writeVarint(this.index); + bw.writeVarint(this.coin.value); + this.coin.script.toWriter(bw); bw.write32(this.flags != null ? this.flags : -1); }; @@ -376,8 +377,13 @@ VerifyInputPacket.fromRaw = function fromRaw(TX, data) { var br = new BufferReader(data, true); var packet = new VerifyInputPacket(); - packet.tx = parseTX(TX, br); + packet.tx = TX.fromReader(br); packet.index = br.readVarint(); + + packet.coin = new Output(); + packet.coin.value = br.readVarint(); + packet.coin.script.fromReader(br); + packet.flags = br.read32(); if (packet.flags === -1) @@ -416,12 +422,13 @@ VerifyInputResultPacket.fromRaw = function fromRaw(data) { * @constructor */ -function SignInputPacket(tx, index, ring, type) { +function SignInputPacket(tx, index, coin, ring, type) { Packet.call(this); this.tx = tx || null; this.index = index; + this.coin = coin || null; this.ring = ring || null; - this.type = type != null ? type : null; + this.type = type != null ? type : 1; } util.inherits(SignInputPacket, Packet); @@ -429,48 +436,27 @@ util.inherits(SignInputPacket, Packet); SignInputPacket.prototype.cmd = packetTypes.SIGNINPUT; SignInputPacket.prototype.toWriter = function toWriter(bw) { - var input = this.tx.inputs[this.index]; - - assert(input); - assert(input.coin); - this.tx.toWriter(bw); bw.writeVarint(this.index); - - bw.writeVarint(input.coin.value); - input.coin.script.toWriter(bw); - + bw.writeVarint(this.coin.value); + this.coin.script.toWriter(bw); this.ring.toWriter(bw); - - bw.write8(this.type != null ? this.type : -1); + bw.writeU8(this.type); }; SignInputPacket.fromRaw = function fromRaw(MTX, KeyRing, data) { var br = new BufferReader(data, true); var packet = new SignInputPacket(); - var coin = new Coin(); - var input; - packet.tx = parseTX(MTX, br); + packet.tx = MTX.fromReader(br); packet.index = br.readVarint(); - coin.value = br.readVarint(); - coin.script.fromReader(br); + packet.coin = new Output(); + packet.coin.value = br.readVarint(); + packet.coin.script.fromReader(br); packet.ring = KeyRing.fromReader(br); - - packet.type = br.read8(); - - if (packet.type === -1) - packet.type = null; - - input = packet.tx.inputs[packet.index]; - assert(input); - - coin.hash = input.prevout.hash; - coin.index = input.prevout.index; - - input.coin = coin; + packet.type = br.readU8(); return packet; }; diff --git a/lib/workers/workerpool.js b/lib/workers/workerpool.js index 6faaccec..f8ee44dd 100644 --- a/lib/workers/workerpool.js +++ b/lib/workers/workerpool.js @@ -297,12 +297,13 @@ WorkerPool.prototype.sign = co(function* sign(tx, ring, type) { * Execute the tx input verification job (default timeout). * @param {TX} tx * @param {Number} index + * @param {Coin|Output} coin * @param {VerifyFlags} flags * @returns {Promise} - Returns Boolean. */ -WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, flags) { - var packet = new packets.VerifyInputPacket(tx, index, flags); +WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, coin, flags) { + var packet = new packets.VerifyInputPacket(tx, index, coin, flags); var result = yield this.execute(packet, -1); return result.value; }); @@ -311,13 +312,14 @@ WorkerPool.prototype.verifyInput = co(function* verifyInput(tx, index, flags) { * Execute the tx input signing job (default timeout). * @param {MTX} tx * @param {Number} index + * @param {Coin|Output} coin * @param {KeyRing} ring * @param {SighashType} type * @returns {Promise} */ -WorkerPool.prototype.signInput = co(function* signInput(tx, index, ring, type) { - var packet = new packets.SignInputPacket(tx, index, ring, type); +WorkerPool.prototype.signInput = co(function* signInput(tx, index, coin, ring, type) { + var packet = new packets.SignInputPacket(tx, index, coin, ring, type); var result = yield this.execute(packet, -1); result.inject(tx); return result.value; diff --git a/test/mempool-test.js b/test/mempool-test.js index c442592d..924b5c2e 100644 --- a/test/mempool-test.js +++ b/test/mempool-test.js @@ -81,7 +81,7 @@ describe('Mempool', function() { prev = new bcoin.script([kp.publicKey, opcodes.OP_CHECKSIG]); t1.addInput(dummy(prev)); - sig = t1.signature(0, prev, kp.privateKey, 'all', 0); + sig = t1.signature(0, prev, t1.inputs[0].coin.value, kp.privateKey, 'all', 0); t1.inputs[0].script = new bcoin.script([sig]); // balance: 51000 @@ -192,7 +192,7 @@ describe('Mempool', function() { chain.tip.height = 200; - sig = tx.signature(0, prev, kp.privateKey, 'all', 0); + sig = tx.signature(0, prev, tx.inputs[0].coin.value, kp.privateKey, 'all', 0); tx.inputs[0].script = new bcoin.script([sig]), tx = tx.toTX(); @@ -217,7 +217,7 @@ describe('Mempool', function() { tx.setLocktime(200); chain.tip.height = 200 - 1; - sig = tx.signature(0, prev, kp.privateKey, 'all', 0); + sig = tx.signature(0, prev, tx.inputs[0].coin.value, kp.privateKey, 'all', 0); tx.inputs[0].script = new bcoin.script([sig]), tx = tx.toTX(); @@ -250,7 +250,7 @@ describe('Mempool', function() { prevs = bcoin.script.fromPubkeyhash(kp.getKeyHash()); - sig = tx.signature(0, prevs, kp.privateKey, 'all', 1); + sig = tx.signature(0, prevs, tx.inputs[0].coin.value, kp.privateKey, 'all', 1); sig[sig.length - 1] = 0; tx.inputs[0].witness = new bcoin.witness([sig, kp.publicKey]); tx = tx.toTX(); @@ -279,7 +279,7 @@ describe('Mempool', function() { tx.addInput(dummy(prev, prevHash)); - sig = tx.signature(0, prev, kp.privateKey, 'all', 0); + sig = tx.signature(0, prev, tx.inputs[0].coin.value, kp.privateKey, 'all', 0); tx.inputs[0].script = new bcoin.script([sig]); tx.inputs[0].witness.push(new Buffer(0)); tx = tx.toTX(); diff --git a/test/script-test.js b/test/script-test.js index b1fec413..cc0ab744 100644 --- a/test/script-test.js +++ b/test/script-test.js @@ -371,8 +371,9 @@ describe('Script', function() { delete output._address; } var err, res; + var value = tx.inputs[0].coin.value; try { - res = Script.verify(input, witness, output, tx, 0, flags); + res = Script.verify(input, witness, output, tx, 0, value, flags); } catch (e) { err = e; } diff --git a/test/tx-test.js b/test/tx-test.js index 3d405346..79596dea 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -141,8 +141,9 @@ describe('TX', function() { }); it('should verify high S value with only DERSIG enabled' + suffix, function() { + var coin = tx4.inputs[0].coin; clearCache(tx4, nocache); - assert(tx4.verifyInput(0, constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG)); + assert(tx4.verifyInput(0, coin, constants.flags.VERIFY_P2SH | constants.flags.VERIFY_DERSIG)); }); it('should verify the coolest tx ever sent' + suffix, function() { @@ -297,7 +298,7 @@ describe('TX', function() { hexType = '0' + hexType; it('should get signature hash of ' + data[4] + ' (' + hexType + ')' + suffix, function() { var subscript = script.getSubscript(0).removeSeparators(); - var hash = tx.signatureHash(index, subscript, type, 0).toString('hex'); + var hash = tx.signatureHash(index, subscript, 0, type, 0).toString('hex'); assert.equal(hash, expected); }); });