diff --git a/lib/script/interpreter.js b/lib/script/interpreter.js index c6305cb55..2639206ed 100644 --- a/lib/script/interpreter.js +++ b/lib/script/interpreter.js @@ -44,9 +44,7 @@ Interpreter.prototype.verifyWitnessProgram = function(version, program, witness, } var scriptPubKeyBuffer = witness[witness.length - 1]; -console.log('[interpreter.js.46:scriptPubKeyBuffer:]',scriptPubKeyBuffer); //TODO scriptPubKey = new Script(scriptPubKeyBuffer); -console.log('[interpreter.js.47:scriptPubKey:]',scriptPubKey); //TODO var hash = Hash.sha256(scriptPubKeyBuffer); if (hash.toString('hex') !== program.toString('hex')) { this.errstr = 'SCRIPT_ERR_WITNESS_PROGRAM_MISMATCH'; @@ -85,7 +83,8 @@ console.log('[interpreter.js.47:scriptPubKey:]',scriptPubKey); //TODO script: scriptPubKey, stack: stack, sigversion: 1, - satoshis: satoshis + satoshis: satoshis, + flags: flags, }); if (!this.evaluate()) { @@ -124,7 +123,6 @@ console.log('[interpreter.js.47:scriptPubKey:]',scriptPubKey); //TODO * Translated from bitcoind's VerifyScript */ Interpreter.prototype.verify = function(scriptSig, scriptPubkey, tx, nin, flags, witness, satoshis) { -console.log('[interpreter.js.126:witness:]',witness); //TODO var Transaction = require('../transaction'); if (_.isUndefined(tx)) { @@ -194,8 +192,6 @@ console.log('[interpreter.js.126:witness:]',witness); //TODO } var hadWitness = false; -console.log('[interpreter.js.195:hadWitness:]',hadWitness); //TODO - if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) { var witnessValues = {}; if (scriptPubkey.isWitnessProgram(witnessValues)) { @@ -203,27 +199,20 @@ console.log('[interpreter.js.195:hadWitness:]',hadWitness); //TODO if (scriptSig.toBuffer().length !== 0) { return false; } -console.log('[interpreter.js.206:witnessValues:]',witnessValues); //TODO - - if (!this.verifyWitnessProgram(witnessValues.version, witnessValues.program, witness, satoshis, flags)) { + if (!this.verifyWitnessProgram(witnessValues.version, witnessValues.program, witness, satoshis, this.flags)) { return false; } } } -console.log('[interpreter.js.213]', scriptPubkey.isScriptHashOut()); //TODO -console.log('[interpreter.js.214:scriptPubkey:]',scriptPubkey); //TODO // Additional validation for spend-to-script-hash transactions: if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) && scriptPubkey.isScriptHashOut()) { - -console.log('[interpreter.js.217]'); //TODO // scriptSig must be literals-only or validation fails if (!scriptSig.isPushOnly()) { this.errstr = 'SCRIPT_ERR_SIG_PUSHONLY'; return false; } -console.log('[interpreter.js.222]'); //TODO // stackCopy cannot be empty here, because if it was the // P2SH HASH <> EQUAL scriptPubKey would be evaluated with // an empty stack and the EvalScript above would return false. @@ -231,7 +220,6 @@ console.log('[interpreter.js.222]'); //TODO throw new Error('internal error - stack copy empty'); } -console.log('[interpreter.js.229]'); //TODO var redeemScriptSerialized = stackCopy[stackCopy.length - 1]; var redeemScript = Script.fromBuffer(redeemScriptSerialized); stackCopy.pop(); @@ -270,7 +258,7 @@ console.log('[interpreter.js.229]'); //TODO return false; } - if (!this.verifyWitnessProgram(p2shWitnessValues.version, p2shWitnessValues.program, witness, satoshis, flags)) { + if (!this.verifyWitnessProgram(p2shWitnessValues.version, p2shWitnessValues.program, witness, satoshis, this.flags)) { return false; } // Bypass the cleanstack check at the end. The actual stack is obviously not clean @@ -280,19 +268,15 @@ console.log('[interpreter.js.229]'); //TODO } } -console.log('[interpreter.js.282]'); //TODO - - - // The CLEANSTACK check is only performed after potential P2SH evaluation, // as the non-P2SH evaluation of a P2SH script will obviously not result in // a clean stack (the P2SH inputs remain). The same holds for witness // evaluation. - if ((flags & Interpreter.SCRIPT_VERIFY_CLEANSTACK) != 0) { + if ((this.flags & Interpreter.SCRIPT_VERIFY_CLEANSTACK) != 0) { // Disallow CLEANSTACK without P2SH, as otherwise a switch // CLEANSTACK->P2SH+CLEANSTACK would be possible, which is not a // softfork (and P2SH should be one). - if ((flags & Interpreter.SCRIPT_VERIFY_P2SH) == 0) + if ((this.flags & Interpreter.SCRIPT_VERIFY_P2SH) == 0) throw 'flags & SCRIPT_VERIFY_P2SH'; if (stackCopy.length != 1) { @@ -301,15 +285,13 @@ console.log('[interpreter.js.282]'); //TODO } } - if ((flags & Interpreter.SCRIPT_VERIFY_WITNESS)) { + if ((this.flags & Interpreter.SCRIPT_VERIFY_WITNESS)) { if (!hadWitness && witness.length > 0) { this.errstr = 'SCRIPT_ERR_WITNESS_UNEXPECTED'; return false; } } - - return true; }; @@ -415,27 +397,27 @@ Interpreter.SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS = (1 << 11); // support CHECKSEQUENCEVERIFY opcode // // See BIP112 for details -Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1 << 10), +Interpreter.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY = (1 << 10); // Signature(s) must be empty vector if an CHECK(MULTI)SIG operation failed // -Interpreter.SCRIPT_VERIFY_NULLFAIL = (1 << 14), +Interpreter.SCRIPT_VERIFY_NULLFAIL = (1 << 14); // Public keys in scripts must be compressed // -Interpreter.SCRIPT_VERIFY_COMPRESSED_PUBKEYTYPE = (1 << 15), +Interpreter.SCRIPT_VERIFY_WITNESS_PUBKEYTYPE = (1 << 15); // Do we accept signature using SIGHASH_FORKID // -Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID = (1 << 16), +Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID = (1 << 16); // Do we accept activate replay protection using a different fork id. // -Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17), +Interpreter.SCRIPT_ENABLE_REPLAY_PROTECTION = (1 << 17); // Enable new opcodes. // -Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 18), +Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES = (1 << 18); @@ -513,6 +495,13 @@ Interpreter.prototype.checkPubkeyEncoding = function(buf) { this.errstr = 'SCRIPT_ERR_PUBKEYTYPE'; return false; } + + // Only compressed keys are accepted in segwit + if ((this.flags & Interpreter.SCRIPT_VERIFY_WITNESS_PUBKEYTYPE) != 0 && this.sigversion == 1 && !PublicKey.fromBuffer(buf).compressed) { + this.errstr = 'SCRIPT_ERR_WITNESS_PUBKEYTYPE'; + return false; + } + return true; }; @@ -663,7 +652,6 @@ Interpreter.prototype.checkSequence = function(nSequence) { * bitcoind commit: b5d1b1092998bc95313856d535c632ea5a8f9104 */ Interpreter.prototype.step = function() { - var fRequireMinimal = (this.flags & Interpreter.SCRIPT_VERIFY_MINIMALDATA) !== 0; //bool fExec = !count(vfExec.begin(), vfExec.end(), false); @@ -1436,7 +1424,6 @@ Interpreter.prototype.step = function() { bufSig = this.stack[this.stack.length - 2]; bufPubkey = this.stack[this.stack.length - 1]; - if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) { return false; } diff --git a/test/script/interpreter.js b/test/script/interpreter.js index 666f3acfc..ba98adccc 100644 --- a/test/script/interpreter.js +++ b/test/script/interpreter.js @@ -309,6 +309,15 @@ describe('Interpreter', function() { flags = flags | Interpreter.SCRIPT_VERIFY_CLEANSTACK; } +console.log('[interpreter.js.311]', flagstr); //TODO + if (flagstr.indexOf('WITNESS_PUBKEYTYPE') !== -1) { + +console.log('[interpreter.js.314] IN!'); //TODO + flags = flags | Interpreter.SCRIPT_VERIFY_WITNESS_PUBKEYTYPE; + } + +console.log('ANTES XXX ', flags & Interpreter.SCRIPT_VERIFY_WITNESS_PUBKEYTYPE); //TODO +console.log('[interpreter.js.320:flags:]',flags); //TODO return flags; }; @@ -357,6 +366,7 @@ console.log('[interpreter.js.377:witness:]wit:',witness); //TODO satoshis: amount, })); +console.log('[interpreter.js.370:flags:]',flags); //TODO var interp = new Interpreter(); var verified = interp.verify(scriptSig, scriptPubkey, spendtx, 0, flags, witness, amount); verified.should.equal(expected);