Browse Source

script: interpreter witness program fixes

patch-2
Braydon Fuller 9 years ago
parent
commit
c6079e9556
  1. 38
      lib/script/interpreter.js
  2. 19
      lib/script/script.js
  3. 7
      lib/transaction/transaction.js

38
lib/script/interpreter.js

@ -32,25 +32,26 @@ var Interpreter = function Interpreter(obj) {
};
Interpreter.prototype.verifyWitnessProgram = function(version, program, witness, satoshis, flags) {
var scriptPubKey = new Script;
var scriptPubKey = new Script();
var stack = [];
if (version == 0) {
if (version === 0) {
if (program.length == 32) {
if (witness.length == 0) {
this.errstr = 'v0 scripthash program empty';
return false;
}
scriptPubKey = witness[witness.length - 1];
var hash = Hash.sha256(scriptPubKey);
if (hash !== program.script) {
var scriptPubKeyBuffer = witness[witness.length - 1];
scriptPubKey = new Script(scriptPubKeyBuffer);
var hash = Hash.sha256(scriptPubKeyBuffer);
if (hash.toString('hex') !== program.toString('hex')) {
this.errstr = 'witness program mismatch';
return false;
}
stack = witness.slice(0, -1);
} else if (program.script.length == 20) {
} else if (program.length == 20) {
if (witness.length != 2) {
this.errstr = 'witness program mismatch';
return false;
@ -69,6 +70,7 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
return true;
}
this.initialize();
this.set({
script: scriptPubKey,
stack: stack,
@ -110,7 +112,7 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
*
* Translated from bitcoind's VerifyScript
*/
Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags, witness, satoshis) {
Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags, witness, satoshis) {
var Transaction = require('../transaction');
if (_.isUndefined(tx)) {
@ -183,15 +185,14 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
var version, program;
if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) {
if (scriptPubkey.isWitnessProgram()) {
version = scriptPubkey[0];
program = s.toProgram();
var witnessValues = {};
if (scriptPubkey.isWitnessProgram(witnessValues)) {
hadWitness = true;
if (scriptSig.toBuffer().length != 0) {
return false;
}
if (!this.verifyWitnessProgram(version, program, witness, satoshis, flags)) {
if (!this.verifyWitnessProgram(witnessValues.version, witnessValues.program, witness, satoshis, flags)) {
return false;
}
}
@ -239,17 +240,18 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
this.errstr = 'SCRIPT_ERR_EVAL_FALSE_IN_P2SH_STACK';
return false;
}
if ((flags & this.SCRIPT_VERIFY_WITNESS)) {
if (redeemScript.isWitnessOut()) {
version = redeemScript[0];
program = redeemScript.toProgram();
if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) {
var witnessValues = {};
if (redeemScript.isWitnessProgram(witnessValues)) {
hadWitness = true;
if (scriptSig !== redeemScript) {
var redeemScriptPush = new Script();
redeemScriptPush.add(redeemScript.toBuffer());
if (scriptSig.toHex() !== redeemScriptPush.toHex()) {
this.errstr = 'Malleated scriptSig';
return false;
}
if (!this.verifyWitnessProgram(version, program, witness, satoshis, flags)) {
if (!this.verifyWitnessProgram(witnessValues.version, witnessValues.program, witness, satoshis, flags)) {
return false;
}
@ -257,7 +259,7 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
}
}
if ((flags & this.SCRIPT_VERIFY_WITNESS)) {
if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) {
if (!hadWitness && witness.length > 0) {
this.errstr = 'Witness unexpected';
return false;

19
lib/script/script.js

@ -405,29 +405,32 @@ Script.prototype.isWitnessPublicKeyHashOut = function() {
};
/**
* @param {Object=} values - The return values
* @param {Number} values.version - Set with the witness version
* @param {Buffer} values.program - Set with the witness program
* @returns {boolean} if this is a p2wpkh output script
*/
Script.prototype.isWitnessProgram = function() {
Script.prototype.isWitnessProgram = function(values) {
if (!values) {
values = {};
}
var buf = this.toBuffer();
if (buf.length < 4 || buf.length > 34) {
return false;
}
if (buf[0] !== Opcode.OP_0 && (buf[0] < Opcode.OP_1 && buf[1] > Opcode.OP_16)) {
if (buf[0] >= Opcode.OP_0 && (buf[0] < 1 && buf[0] > 16)) {
return false;
}
if (buf.length == buf[1] + 2) {
if (buf.length === buf[1] + 2) {
values.version = buf[0];
values.program = buf.slice(2, buf.length);
return true;
}
return false;
};
Script.prototype.toProgram = function () {
var buf = this.toBuffer();
return buf.slice(2, buf.end);
};
/**
* @returns {boolean} if this is a p2sh input script
* Note that these are frequently indistinguishable from pubkeyhashin

7
lib/transaction/transaction.js

@ -1201,7 +1201,12 @@ Transaction.prototype.verifySignature = function(sig, pubkey, nin, subscript, si
}
if (sigversion == 1) {
return SighashWitness.verify(this, sig, pubkey, nin, subscript, this.inputs[nin].getSatoshisBuffer());
var subscriptBuffer = subscript.toBuffer();
var scriptCodeWriter = new BufferWriter();
scriptCodeWriter.writeVarintNum(subscriptBuffer.length);
scriptCodeWriter.write(subscriptBuffer);
return SighashWitness.verify(this, sig, pubkey, nin, scriptCodeWriter.toBuffer(), this.inputs[nin].getSatoshisBuffer());
}
return Sighash.verify(this, sig, pubkey, nin, subscript);

Loading…
Cancel
Save