Merge pull request #30 from jgarzik/p2sh
Script, ScriptInterpreter: Verify P2SH scripts and signatures
This commit is contained in:
commit
ca35fa4506
|
@ -66,6 +66,15 @@ function spec(b) {
|
|||
}
|
||||
};
|
||||
|
||||
Script.prototype.isPushOnly = function ()
|
||||
{
|
||||
for (var i = 0; i < this.chunks.length; i++)
|
||||
if (!Buffer.isBuffer(this.chunks[i]))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
Script.prototype.isP2SH = function ()
|
||||
{
|
||||
return (this.chunks.length == 3 &&
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
require('classtool');
|
||||
|
||||
function spec(b) {
|
||||
var assert = require('assert');
|
||||
var config = b.config || require('./config');
|
||||
var log = b.log || require('./util/log')(config);
|
||||
|
||||
|
@ -758,6 +759,11 @@ function spec(b) {
|
|||
return this.stack[this.stack.length-offset];
|
||||
};
|
||||
|
||||
ScriptInterpreter.prototype.stackBack = function stackBack()
|
||||
{
|
||||
return this.stack[-1];
|
||||
};
|
||||
|
||||
/**
|
||||
* Pop the top element off the stack and return it.
|
||||
*/
|
||||
|
@ -911,6 +917,88 @@ function spec(b) {
|
|||
return si;
|
||||
};
|
||||
|
||||
function verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy)
|
||||
{
|
||||
if (siCopy.stack.length == 0) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(null, castBool(siCopy.stackBack()));
|
||||
}
|
||||
|
||||
function verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy)
|
||||
{
|
||||
if (si.stack.length == 0) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
if (castBool(si.stackBack()) == false) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// if not P2SH, we're done
|
||||
if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) {
|
||||
callback(null, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scriptSig.isPushOnly()) {
|
||||
callback(null, false);
|
||||
return;
|
||||
}
|
||||
|
||||
assert.notEqual(siCopy.length, 0);
|
||||
|
||||
var subscript = new Script(siCopy.stackPop());
|
||||
|
||||
ok = true;
|
||||
siCopy.eval(subscript, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep4(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
}
|
||||
|
||||
function verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy)
|
||||
{
|
||||
if (opts.verifyP2SH) {
|
||||
si.stack.forEach(function(item) {
|
||||
siCopy.stack.push(item);
|
||||
});
|
||||
}
|
||||
|
||||
si.eval(scriptPubKey, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
}
|
||||
|
||||
ScriptInterpreter.verifyFull =
|
||||
function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType,
|
||||
opts, callback)
|
||||
{
|
||||
var si = new ScriptInterpreter();
|
||||
var siCopy = new ScriptInterpreter();
|
||||
|
||||
si.eval(scriptSig, txTo, nIn, hashType, function (err) {
|
||||
if (err)
|
||||
callback(err);
|
||||
else
|
||||
verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
|
||||
hashType, opts, callback, si, siCopy);
|
||||
});
|
||||
};
|
||||
|
||||
var checkSig = ScriptInterpreter.checkSig =
|
||||
function (sig, pubkey, scriptCode, tx, n, hashType, callback) {
|
||||
if (!sig.length) {
|
||||
|
|
Loading…
Reference in New Issue