fcoin/test/script-test.js
Christopher Jeffrey bf2e7d1486
test: fix tx tests.
2016-12-10 08:11:24 -08:00

355 lines
8.5 KiB
JavaScript

'use strict';
var assert = require('assert');
var Script = require('../lib/script/script');
var Witness = require('../lib/script/witness');
var Stack = require('../lib/script/stack');
var TX = require('../lib/primitives/tx');
var util = require('../lib/utils/util');
var crypto = require('../lib/crypto/crypto');
var constants = require('../lib/protocol/constants');
var opcodes = constants.opcodes;
var scripts = require('./data/script_tests');
function success(res, stack) {
if (!res)
return false;
if (stack.length === 0)
return false;
if (!Script.bool(stack.top(-1)))
return false;
return true;
}
describe('Script', function() {
it('should encode/decode script', function() {
var src, decoded, dst;
src = '20'
+ '000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f'
+ '20'
+ '101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f'
+ 'ac';
decoded = Script.fromRaw(src, 'hex');
assert.equal(decoded.code.length, 3);
assert.equal(decoded.code[0].data.toString('hex'),
'000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f');
assert.equal(decoded.code[1].data.toString('hex'),
'101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f');
assert.equal(decoded.code[2].value, opcodes.OP_CHECKSIG);
dst = decoded.toRaw();
assert.equal(dst.toString('hex'), src);
});
it('should encode/decode numbers', function() {
var script = [0, 0x51, 0x52, 0x60];
var encoded = Script.fromArray(script).raw;
var decoded = Script(encoded).toArray();
assert.deepEqual(decoded, script);
});
it('should recognize a P2SH output', function() {
var hex = 'a91419a7d869032368fd1f1e26e5e73a4ad0e474960e87';
var decoded = Script.fromRaw(hex, 'hex');
assert(decoded.isScripthash());
});
it('should recognize a Null Data output', function() {
var hex = '6a28590c080112220a1b353930632e6f7267282a5f'
+ '5e294f7665726c6179404f7261636c65103b1a010c';
var decoded = Script.fromRaw(hex, 'hex');
assert(decoded.isNulldata());
});
it('should handle if statements correctly', function() {
var input, output, stack, res;
input = new Script([opcodes.OP_1, opcodes.OP_2]);
output = new Script([
opcodes.OP_2,
opcodes.OP_EQUAL,
opcodes.OP_IF,
opcodes.OP_3,
opcodes.OP_ELSE,
opcodes.OP_4,
opcodes.OP_ENDIF,
opcodes.OP_5
]);
stack = new Stack();
input.execute(stack);
res = output.execute(stack);
assert(res);
assert.deepEqual(stack.items, [[1], [3], [5]]);
input = new Script([opcodes.OP_1, opcodes.OP_2]);
output = new Script([
opcodes.OP_9,
opcodes.OP_EQUAL,
opcodes.OP_IF,
opcodes.OP_3,
opcodes.OP_ELSE,
opcodes.OP_4,
opcodes.OP_ENDIF,
opcodes.OP_5
]);
stack = new Stack();
input.execute(stack);
res = output.execute(stack);
assert(res);
assert.deepEqual(stack.items, [[1], [4], [5]]);
input = new Script([opcodes.OP_1, opcodes.OP_2]);
output = new Script([
opcodes.OP_2,
opcodes.OP_EQUAL,
opcodes.OP_IF,
opcodes.OP_3,
opcodes.OP_ENDIF,
opcodes.OP_5
]);
stack = new Stack();
input.execute(stack);
res = output.execute(stack);
assert(res);
assert.deepEqual(stack.items, [[1], [3], [5]]);
input = new Script([opcodes.OP_1, opcodes.OP_2]);
output = new Script([
opcodes.OP_9,
opcodes.OP_EQUAL,
opcodes.OP_IF,
opcodes.OP_3,
opcodes.OP_ENDIF,
opcodes.OP_5
]);
stack = new Stack();
input.execute(stack);
res = output.execute(stack);
assert(res);
assert.deepEqual(stack.items, [[1], [5]]);
input = new Script([opcodes.OP_1, opcodes.OP_2]);
output = new Script([
opcodes.OP_9,
opcodes.OP_EQUAL,
opcodes.OP_NOTIF,
opcodes.OP_3,
opcodes.OP_ENDIF,
opcodes.OP_5
]);
stack = new Stack();
input.execute(stack);
res = output.execute(stack);
assert(res);
assert.deepEqual(stack.items, [[1], [3], [5]]);
});
it('should handle CScriptNums correctly', function() {
var s1, s2, stack;
s1 = new Script([
new Buffer([0xff, 0xff, 0xff, 0x7f]),
opcodes.OP_NEGATE,
opcodes.OP_DUP,
opcodes.OP_ADD
]);
s2 = new Script([
new Buffer([0xfe, 0xff, 0xff, 0xff, 0x80]),
opcodes.OP_EQUAL
]);
stack = new Stack();
assert(s1.execute(stack));
assert(success(s2.execute(stack), stack));
});
it('should handle CScriptNums correctly', function() {
var s1, s2, stack;
s1 = new Script([
opcodes.OP_11,
opcodes.OP_10,
opcodes.OP_1,
opcodes.OP_ADD
]);
s2 = new Script([
opcodes.OP_NUMNOTEQUAL,
opcodes.OP_NOT
]);
stack = new Stack();
assert(s1.execute(stack));
assert(success(s2.execute(stack), stack));
});
it('should handle OP_ROLL correctly', function() {
var s1, s2, stack;
s1 = new Script([
new Buffer([0x16]),
new Buffer([0x15]),
new Buffer([0x14])
]);
s2 = new Script([
opcodes.OP_0,
opcodes.OP_ROLL,
new Buffer([0x14]),
opcodes.OP_EQUALVERIFY,
opcodes.OP_DEPTH,
opcodes.OP_2,
opcodes.OP_EQUAL
]);
stack = new Stack();
assert(s1.execute(stack));
assert(success(s2.execute(stack), stack));
});
scripts.forEach(function(data) {
var witness = Array.isArray(data[0]) ? data.shift() : [];
var input = data[0] ? data[0].trim() : data[0] || '';
var output = data[1] ? data[1].trim() : data[1] || '';
var flags = data[2] ? data[2].trim().split(/,\s*/) : [];
var expected = data[3] || '';
var comments = Array.isArray(data[4]) ? data[4].join('. ') : data[4] || '';
var amount = 0;
var flag = 0;
var i, name, err, res;
if (data.length === 1)
return;
if (!comments)
comments = output.slice(0, 60);
comments += ' (' + expected + ')';
if (witness.length !== 0)
amount = witness.pop() * 100000000;
witness = Witness.fromString(witness);
input = Script.fromString(input);
output = Script.fromString(output);
for (i = 0; i < flags.length; i++) {
name = 'VERIFY_' + flags[i];
assert(constants.flags[name] != null, 'Unknown flag.');
flag |= constants.flags[name];
}
flags = flag;
[false, true].forEach(function(nocache) {
var suffix = nocache ? ' without cache' : ' with cache';
it('should handle script test' + suffix + ': ' + comments, function() {
var prev, tx, err, res;
// Funding transaction.
prev = new TX({
version: 1,
flag: 1,
inputs: [{
prevout: {
hash: constants.NULL_HASH,
index: 0xffffffff
},
script: [Script.array(0), Script.array(0)],
witness: new Witness(),
sequence: 0xffffffff
}],
outputs: [{
script: output,
value: amount
}],
locktime: 0
});
// Spending transaction.
tx = new TX({
version: 1,
flag: 1,
inputs: [{
prevout: {
hash: prev.hash('hex'),
index: 0
},
script: input,
witness: witness,
sequence: 0xffffffff
}],
outputs: [{
script: new Script(),
value: amount
}],
locktime: 0
});
if (nocache) {
tx._raw = null;
tx._size = -1;
tx._witnessSize = -1;
tx._hash = null;
tx._hhash = null;
tx._whash = null;
tx._inputValue = -1;
tx._outputValue = -1;
tx._hashPrevouts = null;
tx._hashSequence = null;
tx._hashOutputs = null;
prev._raw = null;
prev._size = -1;
prev._witnessSize = -1;
prev._hash = null;
prev._inputValue = -1;
prev._outputValue = -1;
prev._hashPrevouts = null;
prev._hashSequence = null;
prev._hashOutputs = null;
}
try {
res = Script.verify(input, witness, output, tx, 0, amount, flags);
} catch (e) {
err = e;
}
if (expected !== 'OK') {
assert(!res);
assert(err);
assert.equal(err.code, expected);
return;
}
assert.ifError(err);
assert(res);
});
});
});
});