|
|
@ -33,7 +33,6 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
|
throw new Error("ScriptInterpreter.eval() requires a callback"); |
|
|
|
} |
|
|
|
|
|
|
|
console.log('eval script '+script.toHumanReadable()); |
|
|
|
var pc = 0; |
|
|
|
var execStack = []; |
|
|
|
var altStack = []; |
|
|
@ -49,6 +48,7 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
|
executeStep.call(this, callback); |
|
|
|
|
|
|
|
function executeStep(cb) { |
|
|
|
try { |
|
|
|
// Once all chunks have been processed, execution ends
|
|
|
|
if (pc >= script.chunks.length) { |
|
|
|
// Execution stack must be empty at the end of the script
|
|
|
@ -713,18 +713,15 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
|
|
|
|
|
checkSig(sig, pubkey, scriptCode, tx, inIndex, hashType, function(e, result) { |
|
|
|
if (!e && result) { |
|
|
|
console.log('sig '+isig+' succeeded with key '+ikey); |
|
|
|
isig++; |
|
|
|
sigsCount--; |
|
|
|
} else { |
|
|
|
console.log('key '+ikey+' failed to verify sig '+isig+': '+e +' '+result); |
|
|
|
ikey++; |
|
|
|
keysCount--; |
|
|
|
|
|
|
|
// If there are more signatures than keys left, then too many
|
|
|
|
// signatures have failed
|
|
|
|
if (sigsCount > keysCount) { |
|
|
|
console.log('CHECKMULTISIG sigsCount > keysCount'); |
|
|
|
success = false; |
|
|
|
} |
|
|
|
} |
|
|
@ -767,6 +764,9 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
|
} else { |
|
|
|
executeStep.call(this, cb); |
|
|
|
} |
|
|
|
} catch (e) { |
|
|
|
cb(e); |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
@ -916,29 +916,24 @@ ScriptInterpreter.prototype.verifyStep3 = function(scriptSig, |
|
|
|
|
|
|
|
// if stack is empty, script considered invalid
|
|
|
|
if (this.stack.length === 0) { |
|
|
|
console.log('3rd step: no stack'); |
|
|
|
callback(null, false); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// if top of stack contains false, script evaluated to false
|
|
|
|
if (castBool(this.stackBack()) == false) { |
|
|
|
console.log('3rd step: stack contains false'); |
|
|
|
callback(null, false); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// if not P2SH, script evaluated to true
|
|
|
|
if (!this.opts.verifyP2SH || !scriptPubKey.isP2SH()) { |
|
|
|
console.log('3rd step: done, true'); |
|
|
|
callback(null, true); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
// if P2SH, scriptSig should be push-only
|
|
|
|
if (!scriptSig.isPushOnly()) { |
|
|
|
console.log('3rd step: scriptSig should be push only'); |
|
|
|
console.log(); |
|
|
|
callback(null, false); |
|
|
|
return; |
|
|
|
} |
|
|
@ -952,7 +947,6 @@ ScriptInterpreter.prototype.verifyStep3 = function(scriptSig, |
|
|
|
var that = this; |
|
|
|
// evaluate the P2SH subscript
|
|
|
|
siCopy.eval(subscript, tx, nIn, hashType, function(err) { |
|
|
|
console.log('Err 3nd step: '+err); |
|
|
|
if (err) return callback(err); |
|
|
|
that.verifyStep4(callback, siCopy); |
|
|
|
}); |
|
|
@ -971,7 +965,6 @@ ScriptInterpreter.prototype.verifyStep2 = function(scriptSig, scriptPubKey, |
|
|
|
var that = this; |
|
|
|
// 2nd step, evaluate scriptPubKey
|
|
|
|
this.eval(scriptPubKey, tx, nIn, hashType, function(err) { |
|
|
|
console.log('Err 2nd step: '+err); |
|
|
|
if (err) return callback(err); |
|
|
|
that.verifyStep3(scriptSig, scriptPubKey, tx, nIn, |
|
|
|
hashType, callback, siCopy); |
|
|
@ -984,7 +977,6 @@ ScriptInterpreter.prototype.verifyFull = function(scriptSig, scriptPubKey, |
|
|
|
|
|
|
|
// 1st step, evaluate scriptSig
|
|
|
|
this.eval(scriptSig, tx, nIn, hashType, function(err) { |
|
|
|
console.log('Err 1st step: '+err); |
|
|
|
if (err) return callback(err); |
|
|
|
that.verifyStep2(scriptSig, scriptPubKey, tx, nIn, |
|
|
|
hashType, callback); |
|
|
@ -1004,7 +996,6 @@ var checkSig = ScriptInterpreter.checkSig = |
|
|
|
function(sig, pubkey, scriptCode, tx, n, hashType, callback) { |
|
|
|
// https://en.bitcoin.it/wiki/OP_CHECKSIG#How_it_works
|
|
|
|
if (!sig.length) { |
|
|
|
console.log('sig length 0'); |
|
|
|
callback(null, false); |
|
|
|
return; |
|
|
|
} |
|
|
@ -1013,7 +1004,6 @@ var checkSig = ScriptInterpreter.checkSig = |
|
|
|
if (hashType === 0) { |
|
|
|
hashType = sig[sig.length - 1]; |
|
|
|
} else if (hashType != sig[sig.length - 1]) { |
|
|
|
console.log('wrong hashtype'); |
|
|
|
callback(null, false); |
|
|
|
return; |
|
|
|
} |
|
|
@ -1022,20 +1012,13 @@ var checkSig = ScriptInterpreter.checkSig = |
|
|
|
sig = sig.slice(0, sig.length - 1); |
|
|
|
|
|
|
|
// Signature verification requires a special hash procedure
|
|
|
|
console.log('rawtx '+buffertools.toHex(tx.serialize())); |
|
|
|
var hash = tx.hashForSignature(scriptCode, n, hashType); |
|
|
|
console.log('n ='+n+'; hashType='+hashType); |
|
|
|
console.log('hash ='+ buffertools.toHex(hash)); |
|
|
|
|
|
|
|
// Verify signature
|
|
|
|
var key = new Key(); |
|
|
|
if (pubkey.length === 0) pubkey = new Buffer('00', 'hex'); |
|
|
|
key.public = pubkey; |
|
|
|
|
|
|
|
console.log('pubkey before verification: '+buffertools.toHex(key.public)); |
|
|
|
console.log('sig before verification: '+buffertools.toHex(sig)); |
|
|
|
console.log('hash before verification: '+buffertools.toHex(hash)); |
|
|
|
|
|
|
|
key.verifySignature(hash, sig, callback); |
|
|
|
}; |
|
|
|
|
|
|
|