Lint script/interpreter

This commit is contained in:
Esteban Ordano 2014-12-19 14:17:41 -03:00
parent 85169a3874
commit 490279acb0
1 changed files with 79 additions and 73 deletions

View File

@ -6,8 +6,6 @@ var Script = require('./script');
var Opcode = require('../opcode');
var BN = require('../crypto/bn');
var Hash = require('../crypto/hash');
var BufferReader = require('../encoding/bufferreader');
var BufferWriter = require('../encoding/bufferwriter');
var Signature = require('../crypto/signature');
var PublicKey = require('../publickey');
@ -323,7 +321,9 @@ Interpreter.prototype.step = function() {
//bool fExec = !count(vfExec.begin(), vfExec.end(), false);
var fExec = (this.vfExec.indexOf(false) === -1);
var buf, buf1, buf2, spliced, n, x1, x2, bn, bn1, bn2, bufSig, bufPubkey, subscript;
var sig, pubkey;
var fValue, fSuccess;
// Read instruction
var chunk = this.script.chunks[this.pc];
@ -399,8 +399,8 @@ Interpreter.prototype.step = function() {
{
// ( -- value)
// ScriptNum bn((int)opcode - (int)(Opcode.OP_1 - 1));
var n = opcodenum - (Opcode.OP_1 - 1);
var buf = BN(n).toScriptNumBuffer();
n = opcodenum - (Opcode.OP_1 - 1);
buf = BN(n).toScriptNumBuffer();
this.stack.push(buf);
// The result of these opcodes should always be the minimal way to push the data
// they push, so no need for a CheckMinimalPush here.
@ -437,16 +437,17 @@ Interpreter.prototype.step = function() {
{
// <expression> if [statements] [else [statements]] endif
// bool fValue = false;
var fValue = false;
fValue = false;
if (fExec) {
if (this.stack.length < 1) {
this.errstr = 'SCRIPT_ERR_UNBALANCED_CONDITIONAL';
return false;
}
var buf = this.stack.pop();
buf = this.stack.pop();
fValue = Interpreter.castToBool(buf);
if (opcodenum === Opcode.OP_NOTIF)
if (opcodenum === Opcode.OP_NOTIF) {
fValue = !fValue;
}
}
this.vfExec.push(fValue);
}
@ -480,11 +481,11 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf = this.stack[this.stack.length - 1];
var fValue = Interpreter.castToBool(buf);
if (fValue)
buf = this.stack[this.stack.length - 1];
fValue = Interpreter.castToBool(buf);
if (fValue) {
this.stack.pop();
else {
} else {
this.errstr = 'SCRIPT_ERR_VERIFY';
return false;
}
@ -541,8 +542,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf1 = this.stack[this.stack.length - 2];
var buf2 = this.stack[this.stack.length - 1];
buf1 = this.stack[this.stack.length - 2];
buf2 = this.stack[this.stack.length - 1];
this.stack.push(buf1);
this.stack.push(buf2);
}
@ -555,8 +556,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf1 = this.stack[this.stack.length - 3];
var buf2 = this.stack[this.stack.length - 2];
buf1 = this.stack[this.stack.length - 3];
buf2 = this.stack[this.stack.length - 2];
var buf3 = this.stack[this.stack.length - 1];
this.stack.push(buf1);
this.stack.push(buf2);
@ -571,8 +572,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf1 = this.stack[this.stack.length - 4];
var buf2 = this.stack[this.stack.length - 3];
buf1 = this.stack[this.stack.length - 4];
buf2 = this.stack[this.stack.length - 3];
this.stack.push(buf1);
this.stack.push(buf2);
}
@ -585,7 +586,7 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var spliced = this.stack.splice(this.stack.length - 6, 2);
spliced = this.stack.splice(this.stack.length - 6, 2);
this.stack.push(spliced[0]);
this.stack.push(spliced[1]);
}
@ -598,7 +599,7 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var spliced = this.stack.splice(this.stack.length - 4, 2);
spliced = this.stack.splice(this.stack.length - 4, 2);
this.stack.push(spliced[0]);
this.stack.push(spliced[1]);
}
@ -611,17 +612,18 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf = this.stack[this.stack.length - 1];
var fValue = Interpreter.castToBool(buf);
if (fValue)
buf = this.stack[this.stack.length - 1];
fValue = Interpreter.castToBool(buf);
if (fValue) {
this.stack.push(buf);
}
}
break;
case Opcode.OP_DEPTH:
{
// -- stacksize
var buf = BN(this.stack.length).toScriptNumBuffer();
buf = BN(this.stack.length).toScriptNumBuffer();
this.stack.push(buf);
}
break;
@ -679,17 +681,18 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf = this.stack[this.stack.length - 1];
var bn = BN().fromScriptNumBuffer(buf, fRequireMinimal);
var n = bn.toNumber();
buf = this.stack[this.stack.length - 1];
bn = BN().fromScriptNumBuffer(buf, fRequireMinimal);
n = bn.toNumber();
this.stack.pop();
if (n < 0 || n >= this.stack.length) {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf = this.stack[this.stack.length - n - 1];
if (opcodenum === Opcode.OP_ROLL)
buf = this.stack[this.stack.length - n - 1];
if (opcodenum === Opcode.OP_ROLL) {
this.stack.splice(this.stack.length - n - 1, 1);
}
this.stack.push(buf);
}
break;
@ -703,8 +706,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var x1 = this.stack[this.stack.length - 3];
var x2 = this.stack[this.stack.length - 2];
x1 = this.stack[this.stack.length - 3];
x2 = this.stack[this.stack.length - 2];
var x3 = this.stack[this.stack.length - 1];
this.stack[this.stack.length - 3] = x2;
this.stack[this.stack.length - 2] = x3;
@ -719,8 +722,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var x1 = this.stack[this.stack.length - 2];
var x2 = this.stack[this.stack.length - 1];
x1 = this.stack[this.stack.length - 2];
x2 = this.stack[this.stack.length - 1];
this.stack[this.stack.length - 2] = x2;
this.stack[this.stack.length - 1] = x1;
}
@ -745,7 +748,7 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var bn = BN(this.stack[this.stack.length - 1].length);
bn = BN(this.stack[this.stack.length - 1].length);
this.stack.push(bn.toScriptNumBuffer());
}
break;
@ -763,8 +766,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf1 = this.stack[this.stack.length - 2];
var buf2 = this.stack[this.stack.length - 1];
buf1 = this.stack[this.stack.length - 2];
buf2 = this.stack[this.stack.length - 1];
var fEqual = buf1.toString('hex') === buf2.toString('hex');
// Opcode.OP_NOTEQUAL is disabled because it would be too easy to say
// something like n != 1 and have some wiseguy pass in 1 with extra
@ -775,9 +778,9 @@ Interpreter.prototype.step = function() {
this.stack.pop();
this.stack.push(fEqual ? Interpreter.true : Interpreter.false);
if (opcodenum === Opcode.OP_EQUALVERIFY) {
if (fEqual)
if (fEqual) {
this.stack.pop();
else {
} else {
this.errstr = 'SCRIPT_ERR_EQUALVERIFY';
return false;
}
@ -801,8 +804,8 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf = this.stack[this.stack.length - 1];
var bn = BN().fromScriptNumBuffer(buf, fRequireMinimal);
buf = this.stack[this.stack.length - 1];
bn = BN().fromScriptNumBuffer(buf, fRequireMinimal);
switch (opcodenum) {
case Opcode.OP_1ADD:
bn = bn.add(1);
@ -814,7 +817,9 @@ Interpreter.prototype.step = function() {
bn = bn.neg();
break;
case Opcode.OP_ABS:
if (bn.cmp(0) < 0) bn = bn.neg();
if (bn.cmp(0) < 0) {
bn = bn.neg();
}
break;
case Opcode.OP_NOT:
bn = BN((bn.cmp(0) === 0) + 0);
@ -848,9 +853,9 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var bn1 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
var bn2 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
var bn = BN(0);
bn1 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
bn2 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
bn = BN(0);
switch (opcodenum) {
case Opcode.OP_ADD:
@ -911,9 +916,9 @@ Interpreter.prototype.step = function() {
if (opcodenum === Opcode.OP_NUMEQUALVERIFY) {
// if (CastToBool(stacktop(-1)))
if (Interpreter.castToBool(this.stack[this.stack.length - 1]))
if (Interpreter.castToBool(this.stack[this.stack.length - 1])) {
this.stack.pop();
else {
} else {
this.errstr = 'SCRIPT_ERR_NUMEQUALVERIFY';
return false;
}
@ -928,11 +933,11 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var bn1 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal);
var bn2 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
bn1 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 3], fRequireMinimal);
bn2 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 2], fRequireMinimal);
var bn3 = BN().fromScriptNumBuffer(this.stack[this.stack.length - 1], fRequireMinimal);
//bool fValue = (bn2 <= bn1 && bn1 < bn3);
var fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0);
fValue = (bn2.cmp(bn1) <= 0) && (bn1.cmp(bn3) < 0);
this.stack.pop();
this.stack.pop();
this.stack.pop();
@ -955,19 +960,21 @@ Interpreter.prototype.step = function() {
this.errstr = 'SCRIPT_ERR_INVALID_STACK_OPERATION';
return false;
}
var buf = this.stack[this.stack.length - 1];
//valtype vchHash((opcode == Opcode.OP_RIPEMD160 || opcode == Opcode.OP_SHA1 || opcode == Opcode.OP_HASH160) ? 20 : 32);
buf = this.stack[this.stack.length - 1];
//valtype vchHash((opcode == Opcode.OP_RIPEMD160 ||
// opcode == Opcode.OP_SHA1 || opcode == Opcode.OP_HASH160) ? 20 : 32);
var bufHash;
if (opcodenum === Opcode.OP_RIPEMD160)
if (opcodenum === Opcode.OP_RIPEMD160) {
bufHash = Hash.ripemd160(buf);
else if (opcodenum === Opcode.OP_SHA1)
} else if (opcodenum === Opcode.OP_SHA1) {
bufHash = Hash.sha1(buf);
else if (opcodenum === Opcode.OP_SHA256)
} else if (opcodenum === Opcode.OP_SHA256) {
bufHash = Hash.sha256(buf);
else if (opcodenum === Opcode.OP_HASH160)
} else if (opcodenum === Opcode.OP_HASH160) {
bufHash = Hash.sha256ripemd160(buf);
else if (opcodenum === Opcode.OP_HASH256)
} else if (opcodenum === Opcode.OP_HASH256) {
bufHash = Hash.sha256sha256(buf);
}
this.stack.pop();
this.stack.push(bufHash);
}
@ -989,27 +996,26 @@ Interpreter.prototype.step = function() {
return false;
}
var bufSig = this.stack[this.stack.length - 2];
var bufPubkey = this.stack[this.stack.length - 1];
bufSig = this.stack[this.stack.length - 2];
bufPubkey = this.stack[this.stack.length - 1];
// Subset of script starting at the most recent codeseparator
// CScript scriptCode(pbegincodehash, pend);
var subscript = Script().set({
subscript = new Script().set({
chunks: this.script.chunks.slice(this.pbegincodehash)
});
// Drop the signature, since there's no way for a signature to sign itself
var tmpScript = Script().add(bufSig);
var tmpScript = new Script().add(bufSig);
subscript.findAndDelete(tmpScript);
if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
return false;
}
var fSuccess;
try {
var sig = Signature.fromTxFormat(bufSig);
var pubkey = PublicKey.fromBuffer(bufPubkey, false);
sig = Signature.fromTxFormat(bufSig);
pubkey = PublicKey.fromBuffer(bufPubkey, false);
fSuccess = this.tx.verifySignature(sig, pubkey, this.nin, subscript);
} catch (e) {
//invalid sig or pubkey
@ -1074,22 +1080,22 @@ Interpreter.prototype.step = function() {
}
// Subset of script starting at the most recent codeseparator
var subscript = Script().set({
subscript = new Script().set({
chunks: this.script.chunks.slice(this.pbegincodehash)
});
// Drop the signatures, since there's no way for a signature to sign itself
for (var k = 0; k < nSigsCount; k++) {
var bufSig = this.stack[this.stack.length - isig - k];
subscript.findAndDelete(Script().add(bufSig));
bufSig = this.stack[this.stack.length - isig - k];
subscript.findAndDelete(new Script().add(bufSig));
}
var fSuccess = true;
fSuccess = true;
while (fSuccess && nSigsCount > 0) {
// valtype& vchSig = stacktop(-isig);
var bufSig = this.stack[this.stack.length - isig];
bufSig = this.stack[this.stack.length - isig];
// valtype& vchPubKey = stacktop(-ikey);
var bufPubkey = this.stack[this.stack.length - ikey];
bufPubkey = this.stack[this.stack.length - ikey];
if (!this.checkSignatureEncoding(bufSig) || !this.checkPubkeyEncoding(bufPubkey)) {
return false;
@ -1097,8 +1103,8 @@ Interpreter.prototype.step = function() {
var fOk;
try {
var sig = Signature.fromTxFormat(bufSig);
var pubkey = PublicKey.fromBuffer(bufPubkey, false);
sig = Signature.fromTxFormat(bufSig);
pubkey = PublicKey.fromBuffer(bufPubkey, false);
fOk = this.tx.verifySignature(sig, pubkey, this.nin, subscript);
} catch (e) {
//invalid sig or pubkey
@ -1143,9 +1149,9 @@ Interpreter.prototype.step = function() {
this.stack.push(fSuccess ? Interpreter.true : Interpreter.false);
if (opcodenum === Opcode.OP_CHECKMULTISIGVERIFY) {
if (fSuccess)
if (fSuccess) {
this.stack.pop();
else {
} else {
this.errstr = 'SCRIPT_ERR_CHECKMULTISIGVERIFY';
return false;
}