Browse Source

tracking Transaction test problems

patch-2
Manuel Araoz 11 years ago
parent
commit
499b171947
  1. 69
      ScriptInterpreter.js
  2. 27
      test/test.Transaction.js

69
ScriptInterpreter.js

@ -33,6 +33,7 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType,
throw new Error("ScriptInterpreter.eval() requires a callback"); throw new Error("ScriptInterpreter.eval() requires a callback");
} }
console.log('eval script '+script.toHumanReadable());
var pc = 0; var pc = 0;
var execStack = []; var execStack = [];
var altStack = []; var altStack = [];
@ -718,6 +719,7 @@ ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType,
// If there are more signatures than keys left, then too many // If there are more signatures than keys left, then too many
// signatures have failed // signatures have failed
if (sigsCount > keysCount) { if (sigsCount > keysCount) {
console.log('CHECKMULTISIG sigsCount > keysCount');
success = false; success = false;
} }
} }
@ -866,7 +868,7 @@ ScriptInterpreter.prototype.getResult = function getResult() {
return castBool(this.stack[this.stack.length - 1]); return castBool(this.stack[this.stack.length - 1]);
}; };
// Use ScriptInterpreter.verifyFull instead // WARN: Use ScriptInterpreter.verifyFull instead
ScriptInterpreter.verify = ScriptInterpreter.verify =
function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) { function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) {
if ("function" !== typeof callback) { if ("function" !== typeof callback) {
@ -892,8 +894,8 @@ ScriptInterpreter.verify =
return si; return si;
}; };
ScriptInterpreter.prototype.verifyStep4 = function(scriptSig, scriptPubKey, ScriptInterpreter.prototype.verifyStep4 = function(callback, siCopy) {
txTo, nIn, hashType, callback, siCopy) { // 4th step, check P2SH subscript evaluated to true
if (siCopy.stack.length == 0) { if (siCopy.stack.length == 0) {
callback(null, false); callback(null, false);
return; return;
@ -904,77 +906,94 @@ ScriptInterpreter.prototype.verifyStep4 = function(scriptSig, scriptPubKey,
ScriptInterpreter.prototype.verifyStep3 = function(scriptSig, ScriptInterpreter.prototype.verifyStep3 = function(scriptSig,
scriptPubKey, txTo, nIn, hashType, callback, siCopy) { scriptPubKey, txTo, nIn, hashType, callback, siCopy) {
if (this.stack.length == 0) {
// 3rd step, check result (stack should contain true)
// if stack is empty, script considered invalid
if (this.stack.length === 0) {
console.log('3rd step: no stack');
callback(null, false); callback(null, false);
return; return;
} }
// if top of stack contains false, script evaluated to false
if (castBool(this.stackBack()) == false) { if (castBool(this.stackBack()) == false) {
console.log('3rd step: stack contains false');
callback(null, false); callback(null, false);
return; return;
} }
// if not P2SH, we're done // if not P2SH, script evaluated to true
if (!this.opts.verifyP2SH || !scriptPubKey.isP2SH()) { if (!this.opts.verifyP2SH || !scriptPubKey.isP2SH()) {
console.log('3rd step: done, true');
callback(null, true); callback(null, true);
return; return;
} }
// if P2SH, scriptSig should be push-only
if (!scriptSig.isPushOnly()) { if (!scriptSig.isPushOnly()) {
console.log('3rd step: scriptSig should be push only');
callback(null, false); callback(null, false);
return; return;
} }
if (siCopy.length === 0) // P2SH script should exist
if (siCopy.length === 0) {
throw new Error('siCopy should have length != 0'); throw new Error('siCopy should have length != 0');
}
var subscript = new Script(siCopy.stackPop()); var subscript = new Script(siCopy.stackPop());
var that = this; var that = this;
// evaluate the P2SH subscript
siCopy.eval(subscript, txTo, nIn, hashType, function(err) { siCopy.eval(subscript, txTo, nIn, hashType, function(err) {
if (err) callback(err); console.log('Err 3nd step: '+err);
else that.verifyStep4(scriptSig, scriptPubKey, txTo, nIn, if (err) return callback(err);
hashType, callback, siCopy); that.verifyStep4(callback, siCopy);
}); });
}; };
ScriptInterpreter.prototype.verifyStep2 = function(scriptSig, scriptPubKey, ScriptInterpreter.prototype.verifyStep2 = function(scriptSig, scriptPubKey,
txTo, nIn, hashType, callback, siCopy) { txTo, nIn, hashType, callback, siCopy) {
var siCopy;
if (this.opts.verifyP2SH) { if (this.opts.verifyP2SH) {
siCopy = new ScriptInterpreter(this.opts);
this.stack.forEach(function(item) { this.stack.forEach(function(item) {
siCopy.stack.push(item); siCopy.stack.push(item);
}); });
} }
var that = this; var that = this;
// 2nd step, evaluate scriptPubKey
this.eval(scriptPubKey, txTo, nIn, hashType, function(err) { this.eval(scriptPubKey, txTo, nIn, hashType, function(err) {
if (err) callback(err); console.log('Err 2nd step: '+err);
else that.verifyStep3(scriptSig, scriptPubKey, txTo, nIn, if (err) return callback(err);
that.verifyStep3(scriptSig, scriptPubKey, txTo, nIn,
hashType, callback, siCopy); hashType, callback, siCopy);
}); });
}; };
ScriptInterpreter.verifyFull =
function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType,
opts, callback) {
var si = new ScriptInterpreter(opts);
si.verifyFull(scriptSig, scriptPubKey,
txTo, nIn, hashType, callback);
};
ScriptInterpreter.prototype.verifyFull = function(scriptSig, scriptPubKey, ScriptInterpreter.prototype.verifyFull = function(scriptSig, scriptPubKey,
txTo, nIn, hashType, callback) { txTo, nIn, hashType, callback) {
var siCopy = new ScriptInterpreter(this.opts);
var that = this; var that = this;
// 1st step, evaluate scriptSig
this.eval(scriptSig, txTo, nIn, hashType, function(err) { this.eval(scriptSig, txTo, nIn, hashType, function(err) {
if (err) callback(err); console.log('Err 1st step: '+err);
else { if (err) return callback(err);
that.verifyStep2(scriptSig, scriptPubKey, txTo, nIn, that.verifyStep2(scriptSig, scriptPubKey, txTo, nIn,
hashType, callback, siCopy); hashType, callback);
}
}); });
};
ScriptInterpreter.verifyFull =
function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType,
opts, callback) {
var si = new ScriptInterpreter(opts);
si.verifyFull(scriptSig, scriptPubKey,
txTo, nIn, hashType, callback);
}; };
var checkSig = ScriptInterpreter.checkSig = var checkSig = ScriptInterpreter.checkSig =
function(sig, pubkey, scriptCode, tx, n, hashType, callback) { function(sig, pubkey, scriptCode, tx, n, hashType, callback) {
if (!sig.length) { if (!sig.length) {

27
test/test.Transaction.js

@ -72,19 +72,19 @@ describe('Transaction', function() {
var raw = datum[1]; var raw = datum[1];
var verifyP2SH = datum[2]; var verifyP2SH = datum[2];
it.skip((valid ? '' : 'in') + 'valid tx=' + raw, function(done) { describe((valid ? '' : 'in') + 'valid tx=' + raw, function() {
var cb = function(err, results) {
should.not.exist(err);
should.exist(results);
results.should.equal(valid);
done();
};
var testTx = parse_test_transaction(datum); var testTx = parse_test_transaction(datum);
it('should parse correctly', function() {
buffertools.toHex(testTx.transaction.serialize()).should.equal(raw); buffertools.toHex(testTx.transaction.serialize()).should.equal(raw);
});
var inputs = testTx.transaction.inputs(); var inputs = testTx.transaction.inputs();
for (var i = 0; i < inputs.length; i++) { var j = 0;
var input = inputs[i]; inputs.forEach(function(input) {
var i = j;
j += 1;
it('should validate input #' + i, function(done) {
buffertools.reverse(input[0]); buffertools.reverse(input[0]);
input[0] = buffertools.toHex(input[0]); input[0] = buffertools.toHex(input[0]);
var mapKey = [input]; var mapKey = [input];
@ -96,8 +96,15 @@ describe('Transaction', function() {
verifyP2SH: verifyP2SH, verifyP2SH: verifyP2SH,
dontVerifyStrictEnc: true dontVerifyStrictEnc: true
}, },
cb); function(err, results) {
should.not.exist(err);
should.exist(results);
results.should.equal(valid);
done();
} }
);
});
});
}); });
}); });
}; };

Loading…
Cancel
Save