|
@ -7,6 +7,7 @@ var buffertools = imports.buffertools || require('buffertools'); |
|
|
var bignum = imports.bignum || require('bignum'); |
|
|
var bignum = imports.bignum || require('bignum'); |
|
|
var Util = imports.Util || require('./util/util'); |
|
|
var Util = imports.Util || require('./util/util'); |
|
|
var Script = require('./Script'); |
|
|
var Script = require('./Script'); |
|
|
|
|
|
var Key = require('./Key'); |
|
|
|
|
|
|
|
|
var SIGHASH_ALL = 1; |
|
|
var SIGHASH_ALL = 1; |
|
|
var SIGHASH_NONE = 2; |
|
|
var SIGHASH_NONE = 2; |
|
@ -61,7 +62,6 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
// The execution bit is true if there are no "false" values in the
|
|
|
// The execution bit is true if there are no "false" values in the
|
|
|
// execution stack. (A "false" value indicates that we're in the
|
|
|
// execution stack. (A "false" value indicates that we're in the
|
|
|
// inactive branch of an if statement.)
|
|
|
// inactive branch of an if statement.)
|
|
@ -411,13 +411,10 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
this.stackPop(); |
|
|
this.stackPop(); |
|
|
this.stackPop(); |
|
|
this.stackPop(); |
|
|
this.stack.push(new Buffer([value ? 1 : 0])); |
|
|
this.stack.push(new Buffer([value ? 1 : 0])); |
|
|
console.log(script.toHumanReadable()); |
|
|
|
|
|
if (opcode === OP_EQUALVERIFY) { |
|
|
if (opcode === OP_EQUALVERIFY) { |
|
|
if (value) { |
|
|
if (value) { |
|
|
this.stackPop(); |
|
|
this.stackPop(); |
|
|
} else { |
|
|
} else { |
|
|
console.log(v1); |
|
|
|
|
|
console.log(v2); |
|
|
|
|
|
throw new Error("OP_EQUALVERIFY negative"); |
|
|
throw new Error("OP_EQUALVERIFY negative"); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -628,7 +625,6 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
|
|
|
|
|
|
// Verify signature
|
|
|
// Verify signature
|
|
|
checkSig(sig, pubkey, scriptCode, tx, inIndex, hashType, function(e, result) { |
|
|
checkSig(sig, pubkey, scriptCode, tx, inIndex, hashType, function(e, result) { |
|
|
try { |
|
|
|
|
|
var success; |
|
|
var success; |
|
|
|
|
|
|
|
|
if (e) { |
|
|
if (e) { |
|
@ -653,9 +649,6 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
|
|
|
|
|
|
// Run next step
|
|
|
// Run next step
|
|
|
executeStep.call(this, cb); |
|
|
executeStep.call(this, cb); |
|
|
} catch (e) { |
|
|
|
|
|
cb(e); |
|
|
|
|
|
} |
|
|
|
|
|
}.bind(this)); |
|
|
}.bind(this)); |
|
|
|
|
|
|
|
|
// Note that for asynchronous opcodes we have to return here to prevent
|
|
|
// Note that for asynchronous opcodes we have to return here to prevent
|
|
@ -710,13 +703,11 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
checkMultiSigStep.call(this); |
|
|
checkMultiSigStep.call(this); |
|
|
|
|
|
|
|
|
function checkMultiSigStep() { |
|
|
function checkMultiSigStep() { |
|
|
try { |
|
|
|
|
|
if (success && sigsCount > 0) { |
|
|
if (success && sigsCount > 0) { |
|
|
var sig = sigs[isig]; |
|
|
var sig = sigs[isig]; |
|
|
var key = keys[ikey]; |
|
|
var key = keys[ikey]; |
|
|
|
|
|
|
|
|
checkSig(sig, key, scriptCode, tx, inIndex, hashType, function(e, result) { |
|
|
checkSig(sig, key, scriptCode, tx, inIndex, hashType, function(e, result) { |
|
|
try { |
|
|
|
|
|
if (!e && result) { |
|
|
if (!e && result) { |
|
|
isig++; |
|
|
isig++; |
|
|
sigsCount--; |
|
|
sigsCount--; |
|
@ -732,9 +723,6 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
checkMultiSigStep.call(this); |
|
|
checkMultiSigStep.call(this); |
|
|
} catch (e) { |
|
|
|
|
|
cb(e); |
|
|
|
|
|
} |
|
|
|
|
|
}.bind(this)); |
|
|
}.bind(this)); |
|
|
} else { |
|
|
} else { |
|
|
this.stack.push(new Buffer([success ? 1 : 0])); |
|
|
this.stack.push(new Buffer([success ? 1 : 0])); |
|
@ -749,9 +737,6 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
// Run next step
|
|
|
// Run next step
|
|
|
executeStep.call(this, cb); |
|
|
executeStep.call(this, cb); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
|
|
|
cb(e); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
// Note that for asynchronous opcodes we have to return here to prevent
|
|
|
// Note that for asynchronous opcodes we have to return here to prevent
|
|
@ -768,18 +753,13 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Run next step
|
|
|
// Run next step
|
|
|
if (pc % 100) { |
|
|
if (false && pc % 100) { |
|
|
// V8 allows for much deeper stacks than Bitcoin's scripting language,
|
|
|
// V8 allows for much deeper stacks than Bitcoin's scripting language,
|
|
|
// but just to be safe, we'll reset the stack every 100 steps
|
|
|
// but just to be safe, we'll reset the stack every 100 steps
|
|
|
process.nextTick(executeStep.bind(this, cb)); |
|
|
process.nextTick(executeStep.bind(this, cb)); |
|
|
} else { |
|
|
} else { |
|
|
executeStep.call(this, cb); |
|
|
executeStep.call(this, cb); |
|
|
} |
|
|
} |
|
|
} catch (e) { |
|
|
|
|
|
log.debug("Script aborted: " + |
|
|
|
|
|
(e.message ? e.message : e)); |
|
|
|
|
|
cb(e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
@ -849,15 +829,15 @@ ScriptInterpreter.prototype.stackSwap = function stackSwap(a, b) { |
|
|
* integer. Any longer Buffer is converted to a hex string. |
|
|
* integer. Any longer Buffer is converted to a hex string. |
|
|
*/ |
|
|
*/ |
|
|
ScriptInterpreter.prototype.getPrimitiveStack = function getPrimitiveStack() { |
|
|
ScriptInterpreter.prototype.getPrimitiveStack = function getPrimitiveStack() { |
|
|
return this.stack.map(function(entry) { |
|
|
return this.stack.map(function(chunk) { |
|
|
if (entry.length > 2) { |
|
|
if (chunk.length > 2) { |
|
|
return buffertools.toHex(entry.slice(0)); |
|
|
return buffertools.toHex(chunk.slice(0)); |
|
|
} |
|
|
} |
|
|
var num = bufferSMToInt(entry); |
|
|
var num = bufferSMToInt(chunk); |
|
|
if (num.cmp(-128) >= 0 && num.cmp(127) <= 0) { |
|
|
if (num.cmp(-128) >= 0 && num.cmp(127) <= 0) { |
|
|
return num.toNumber(); |
|
|
return num.toNumber(); |
|
|
} else { |
|
|
} else { |
|
|
return buffertools.toHex(entry.slice(0)); |
|
|
return buffertools.toHex(chunk.slice(0)); |
|
|
} |
|
|
} |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
@ -904,12 +884,7 @@ ScriptInterpreter.verify = |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Cast result to bool
|
|
|
// Cast result to bool
|
|
|
try { |
|
|
|
|
|
var result = si.getResult(); |
|
|
var result = si.getResult(); |
|
|
} catch (err) { |
|
|
|
|
|
callback(err); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
callback(null, result); |
|
|
callback(null, result); |
|
|
}); |
|
|
}); |
|
@ -992,8 +967,15 @@ ScriptInterpreter.prototype.verifyFull = function(scriptSig, scriptPubKey, |
|
|
var that = this; |
|
|
var that = this; |
|
|
this.eval(scriptSig, txTo, nIn, hashType, function(err) { |
|
|
this.eval(scriptSig, txTo, nIn, hashType, function(err) { |
|
|
if (err) callback(err); |
|
|
if (err) callback(err); |
|
|
else that.verifyStep2(scriptSig, scriptPubKey, txTo, nIn, |
|
|
else { |
|
|
|
|
|
var e = new Error('dummy'); |
|
|
|
|
|
var stack = e.stack.replace(/^[^\(]+?[\n$]/gm, '') |
|
|
|
|
|
.replace(/^\s+at\s+/gm, '') |
|
|
|
|
|
.replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') |
|
|
|
|
|
.split('\n'); |
|
|
|
|
|
that.verifyStep2(scriptSig, scriptPubKey, txTo, nIn, |
|
|
hashType, callback, siCopy); |
|
|
hashType, callback, siCopy); |
|
|
|
|
|
} |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
}; |
|
|
}; |
|
@ -1013,17 +995,13 @@ var checkSig = ScriptInterpreter.checkSig = |
|
|
} |
|
|
} |
|
|
sig = sig.slice(0, sig.length - 1); |
|
|
sig = sig.slice(0, sig.length - 1); |
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
// Signature verification requires a special hash procedure
|
|
|
// Signature verification requires a special hash procedure
|
|
|
var hash = tx.hashForSignature(scriptCode, n, hashType); |
|
|
var hash = tx.hashForSignature(scriptCode, n, hashType); |
|
|
|
|
|
|
|
|
// Verify signature
|
|
|
// Verify signature
|
|
|
var key = new Util.BitcoinKey(); |
|
|
var key = new Key(); |
|
|
key.public = pubkey; |
|
|
key.public = pubkey; |
|
|
key.verifySignature(hash, sig, callback); |
|
|
key.verifySignature(hash, sig, callback); |
|
|
} catch (err) { |
|
|
|
|
|
callback(null, false); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
ScriptInterpreter.prototype.isCanonicalSignature = function(sig) { |
|
|
ScriptInterpreter.prototype.isCanonicalSignature = function(sig) { |
|
|