Browse Source

Unit test coverage for script interpreter verifyWitnessProgram

patch-2
Braydon Fuller 9 years ago
committed by Braydon Fuller
parent
commit
2bc76b1570
  1. 25
      lib/script/interpreter.js
  2. 106
      test/script/interpreter.js

25
lib/script/interpreter.js

@ -38,7 +38,7 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
if (version === 0) { if (version === 0) {
if (program.length === 32) { if (program.length === 32) {
if (witness.length === 0) { if (witness.length === 0) {
this.errstr = 'v0 scripthash program empty'; this.errstr = 'SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY';
return false; return false;
} }
@ -46,14 +46,14 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
scriptPubKey = new Script(scriptPubKeyBuffer); scriptPubKey = new Script(scriptPubKeyBuffer);
var hash = Hash.sha256(scriptPubKeyBuffer); var hash = Hash.sha256(scriptPubKeyBuffer);
if (hash.toString('hex') !== program.toString('hex')) { if (hash.toString('hex') !== program.toString('hex')) {
this.errstr = 'witness program mismatch'; this.errstr = 'SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH';
return false; return false;
} }
stack = witness.slice(0, -1); stack = witness.slice(0, -1);
} else if (program.length === 20) { } else if (program.length === 20) {
if (witness.length !== 2) { if (witness.length !== 2) {
this.errstr = 'witness program mismatch'; this.errstr = 'SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH';
return false; return false;
} }
@ -66,11 +66,11 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness,
stack = witness; stack = witness;
} else { } else {
this.errstr = 'Witness program wrong length'; this.errstr = 'SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH';
return false; return false;
} }
} else if ((flags & this.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)) { } else if ((flags & Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM)) {
this.errstr = 'Upgradeable witness program discouraged'; this.errstr = 'SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM';
return false; return false;
} else { } else {
return true; return true;
@ -248,17 +248,17 @@ Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags,
return false; return false;
} }
if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) { if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) {
var witnessValues = {}; var p2shWitnessValues = {};
if (redeemScript.isWitnessProgram(witnessValues)) { if (redeemScript.isWitnessProgram(p2shWitnessValues)) {
hadWitness = true; hadWitness = true;
var redeemScriptPush = new Script(); var redeemScriptPush = new Script();
redeemScriptPush.add(redeemScript.toBuffer()); redeemScriptPush.add(redeemScript.toBuffer());
if (scriptSig.toHex() !== redeemScriptPush.toHex()) { if (scriptSig.toHex() !== redeemScriptPush.toHex()) {
this.errstr = 'Malleated scriptSig'; this.errstr = 'SCRIPT_ERR_WITNESS_MALLEATED_P2SH';
return false; return false;
} }
if (!this.verifyWitnessProgram(witnessValues.version, witnessValues.program, witness, satoshis, flags)) { if (!this.verifyWitnessProgram(p2shWitnessValues.version, p2shWitnessValues.program, witness, satoshis, flags)) {
return false; return false;
} }
@ -268,7 +268,7 @@ Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags,
if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) { if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) {
if (!hadWitness && witness.length > 0) { if (!hadWitness && witness.length > 0) {
this.errstr = 'Witness unexpected'; this.errstr = 'SCRIPT_ERR_WITNESS_UNEXPECTED';
return false; return false;
} }
} }
@ -320,6 +320,9 @@ Interpreter.LOCKTIME_THRESHOLD_BN = new BN(Interpreter.LOCKTIME_THRESHOLD);
// bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104 // bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104
Interpreter.SCRIPT_VERIFY_NONE = 0; Interpreter.SCRIPT_VERIFY_NONE = 0;
// Making v1-v16 witness program non-standard
Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM = (1 << 12);
// Evaluate P2SH subscripts (softfork safe, BIP16). // Evaluate P2SH subscripts (softfork safe, BIP16).
Interpreter.SCRIPT_VERIFY_P2SH = (1 << 0); Interpreter.SCRIPT_VERIFY_P2SH = (1 << 0);

106
test/script/interpreter.js

@ -1,6 +1,7 @@
'use strict'; 'use strict';
var should = require('chai').should(); var should = require('chai').should();
var sinon = require('sinon');
var bitcore = require('../..'); var bitcore = require('../..');
var Interpreter = bitcore.Script.Interpreter; var Interpreter = bitcore.Script.Interpreter;
var Transaction = bitcore.Transaction; var Transaction = bitcore.Transaction;
@ -97,6 +98,111 @@ describe('Interpreter', function() {
}); });
describe('#verifyWitnessProgram', function() {
it('will return true if witness program greater than 0', function() {
var si = Interpreter();
var version = 1;
var program = new Buffer('bcbd1db07ce89d1f4050645c26c90ce78b67eff78460002a4d5c10410958e064', 'hex');
var witness = [new Buffer('bda0eeeb166c8bfeaee88dedc8efa82d3bea35aac5be253902f59d52908bfe25', 'hex')];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(true);
});
it('will return false with error if witness length is 0', function() {
var si = Interpreter();
var version = 0;
var program = new Buffer('bcbd1db07ce89d1f4050645c26c90ce78b67eff78460002a4d5c10410958e064', 'hex');
var witness = [];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY');
});
it('will return false if program hash mismatch (version 0, 32 byte program)', function() {
var si = Interpreter();
var version = 0;
var program = new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex');
var witness = [
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH');
});
it('will return false if witness stack doesn\'t have two items (version 0, 20 byte program)', function() {
var si = Interpreter();
var version = 0;
var program = new Buffer('b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc6', 'hex');
var witness = [
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH');
});
it('will return false if program wrong length for version 0', function() {
var si = Interpreter();
var version = 0;
var program = new Buffer('b8bcb07f6344b42ab04250c86a6e8b75d3', 'hex');
var witness = [
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_WITNESS_PROGRAM_WRONG_LENGTH');
});
it('will return false with discourage upgradable witness program', function() {
var si = Interpreter();
var version = 1;
var program = new Buffer('b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc6', 'hex');
var witness = [
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
];
var satoshis = 1;
var flags = Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM');
});
it('will return false with error if stack doesn\'t have exactly one item', function() {
var si = Interpreter();
si.evaluate = sinon.stub().returns(true);
var version = 0;
var program = new Buffer('b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc6', 'hex');
var witness = [
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_EVAL_FALSE');
});
it('will return false if last item in stack casts to false', function() {
var si = Interpreter();
si.evaluate = function() {
si.stack = [new Buffer('00', 'hex')];
return true;
};
var version = 0;
var program = new Buffer('b8bcb07f6344b42ab04250c86a6e8b75d3fdbbc6', 'hex');
var witness = [
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex'),
new Buffer('0000000000000000000000000000000000000000000000000000000000000000', 'hex')
];
var satoshis = 1;
var flags = 0;
si.verifyWitnessProgram(version, program, witness, satoshis, flags).should.equal(false);
si.errstr.should.equal('SCRIPT_ERR_EVAL_FALSE_IN_STACK');
});
});
describe('#verify', function() { describe('#verify', function() {
it('should verify these trivial scripts', function() { it('should verify these trivial scripts', function() {

Loading…
Cancel
Save