From fbeefe03c7935d9583905f587bb1ab5e5c8fcc49 Mon Sep 17 00:00:00 2001 From: Christopher Jeffrey Date: Wed, 27 Apr 2016 20:06:55 -0700 Subject: [PATCH] more accurate sighashing. --- lib/bcoin/script.js | 39 ++++++++++++++++++++++++++++++--------- lib/bcoin/tx.js | 3 +++ test/tx-test.js | 2 +- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/bcoin/script.js b/lib/bcoin/script.js index 3ecbe409..79dff160 100644 --- a/lib/bcoin/script.js +++ b/lib/bcoin/script.js @@ -927,9 +927,6 @@ Script.prototype.toRaw = function toRaw(enc) { /** * Get the script's "subscript" starting at a separator. - * Remove all OP_CODESEPARATORs if present. This bizarre - * behavior is necessary for signing and verification when - * code separators are present. * @param {Number?} lastSep - The last separator to sign/verify beyond. * @returns {Script} Subscript. */ @@ -938,14 +935,38 @@ Script.prototype.getSubscript = function getSubscript(lastSep) { var code = []; var i; - if (lastSep == null) - lastSep = -1; + // Optimization: avoid re-rendering + // of the script in 99.9% of cases. + if (lastSep === 0) { + code = this.clone(); + code.raw = this.raw; + return code; + } - assert(lastSep <= 0 || this.code[lastSep] === opcodes.OP_CODESEPARATOR); - - for (i = lastSep + 1; i < this.code.length; i++) { + for (i = lastSep; i < this.code.length; i++) { if (Script.isBadPush(this.code[i])) break; + code.push(this.code[i]); + } + + return new Script(code); +}; + +/** + * Get the script's "subscript" starting at a separator. + * Remove all OP_CODESEPARATORs if present. This bizarre + * behavior is necessary for signing and verification when + * code separators are present. + * @returns {Script} Subscript. + */ + +Script.prototype.removeSeparators = function removeSeparators() { + var code = []; + var i; + + for (i = 0; i < this.code.length; i++) { + // NOTE: We do not check for bad pushes here. Bad + // pushes may have been created by FindAndDelete(). if (this.code[i] !== opcodes.OP_CODESEPARATOR) code.push(this.code[i]); } @@ -974,7 +995,7 @@ Script.prototype.getSubscript = function getSubscript(lastSep) { Script.prototype.execute = function execute(stack, flags, tx, index, version) { var ip = 0; - var lastSep = -1; + var lastSep = 0; var opCount = 0; var op, val, v1, v2, v3; var n, n1, n2, n3; diff --git a/lib/bcoin/tx.js b/lib/bcoin/tx.js index 78569bd3..5b5d7087 100644 --- a/lib/bcoin/tx.js +++ b/lib/bcoin/tx.js @@ -402,6 +402,9 @@ TX.prototype.signatureHashV0 = function signatureHashV0(index, prev, type) { for (i = 0; i < copy.inputs.length; i++) copy.inputs[i].script = new Script([]); + // Remove all code separators. + prev = prev.removeSeparators(); + // Set our input to previous output's script copy.inputs[index].script = prev; diff --git a/test/tx-test.js b/test/tx-test.js index 53f8cbe2..eb360731 100644 --- a/test/tx-test.js +++ b/test/tx-test.js @@ -263,7 +263,7 @@ describe('TX', function() { if (hexType.length % 2 !== 0) hexType = '0' + hexType; it('should get signature hash of ' + data[4] + ' (' + hexType + ')' + suffix, function () { - var subscript = script.getSubscript(); + var subscript = script.getSubscript(0).removeSeparators(); var hash = tx.signatureHash(index, subscript, type, 0).toString('hex'); assert.equal(hash, expected); });