From 2f446286047557f8ac9356c068bf55797ace5f73 Mon Sep 17 00:00:00 2001 From: Daniel Cousens <github@dcousens.com> Date: Thu, 29 May 2014 01:20:13 +1000 Subject: [PATCH] Transaction: refactor hashForSignature Adds asserts to ensure only valid hashes are created (until the implementation is complete). Also uses `Script.without` to remove OP_CODESEPARATOR from the Scripts as required by the protocol. --- src/transaction.js | 49 ++++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 32 deletions(-) diff --git a/src/transaction.js b/src/transaction.js index 8090b3b..0135a1b 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -9,6 +9,7 @@ var convert = require('./convert') var crypto = require('./crypto') var ECKey = require('./eckey') var ecdsa = require('./ecdsa') +var opcodes = require('./opcodes') var DEFAULT_SEQUENCE = 0xffffffff @@ -196,49 +197,37 @@ var SIGHASH_ANYONECANPAY = 0x80 * hashType, serializes and finally hashes the result. This hash can then be * used to sign the transaction input in question. */ -Transaction.prototype.hashForSignature = - function (connectedScript, inIndex, hashType) -{ - var txTmp = this.clone() +Transaction.prototype.hashForSignature = function(scriptPubKey, inIndex, hashType) { + assert(inIndex >= 0, 'Invalid vin index') + assert(inIndex < this.ins.length, 'Invalid vin index') + assert(scriptPubKey instanceof Script, 'Invalid Script object') - // In case concatenating two scripts ends up with two codeseparators, - // or an extra one at the end, this prevents all those possible - // incompatibilities. - /*scriptCode = scriptCode.filter(function (val) { - return val !== OP_CODESEPARATOR - });*/ + var txTmp = this.clone() + var hashScript = scriptPubKey.without(opcodes.OP_CODESEPARATOR) // Blank out other inputs' signatures txTmp.ins.forEach(function(txin) { txin.script = new Script() }) + txTmp.ins[inIndex].script = hashScript - txTmp.ins[inIndex].script = connectedScript + var hashTypeModifier = hashType & 0x1f + if (hashTypeModifier === SIGHASH_NONE) { + assert(false, 'SIGHASH_NONE not yet supported') - // Blank out some of the outputs - if ((hashType & 0x1f) == SIGHASH_NONE) { - txTmp.outs = [] + } else if (hashTypeModifier === SIGHASH_SINGLE) { + assert(false, 'SIGHASH_SINGLE not yet supported') - // Let the others update at will - txTmp.ins.forEach(function(txin, i) { - if (i != inIndex) { - txTmp.ins[i].sequence = 0 - } - }) - - } else if ((hashType & 0x1f) == SIGHASH_SINGLE) { - // TODO: Implement } - // Blank out other inputs completely, not recommended for open transactions if (hashType & SIGHASH_ANYONECANPAY) { - txTmp.ins = [txTmp.ins[inIndex]] + assert(false, 'SIGHASH_ANYONECANPAY not yet supported') } - var htB = new Buffer(4) - htB.writeUInt32LE(hashType, 0) + var hashTypeBuffer = new Buffer(4) + hashTypeBuffer.writeInt32LE(hashType, 0) - var buffer = Buffer.concat([txTmp.toBuffer(), htB]) + var buffer = Buffer.concat([txTmp.toBuffer(), hashTypeBuffer]) return crypto.hash256(buffer) } @@ -364,11 +353,7 @@ Transaction.prototype.sign = function(index, key, type) { Transaction.prototype.signScriptSig = function(index, scriptPubKey, key, type) { type = type || SIGHASH_ALL - - assert((index >= 0), 'Invalid vin index') - assert(scriptPubKey instanceof Script, 'Invalid Script object') assert(key instanceof ECKey, 'Invalid private key') -// assert.equal(type & 0x7F, type, 'Invalid type') // TODO var hash = this.hashForSignature(scriptPubKey, index, type) var signature = key.sign(hash)