From 8e6abdb1257ccef62e5d05e4bcd64f51f8745082 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Thu, 29 Jan 2015 14:39:44 -0600 Subject: [PATCH] Make several of the reg tests more consistent. This commit modifies various regression tests to make them more consistent with other tests throughout the code base. Also, it allows of all the tests to run in parallel. --- opcode_test.go | 970 ++++++++++++------------ script_test.go | 124 +-- stack_test.go | 1972 ++++++++++++++++++++++++------------------------ 3 files changed, 1556 insertions(+), 1510 deletions(-) diff --git a/opcode_test.go b/opcode_test.go index 0de1b7dd..9b4ac4d8 100644 --- a/opcode_test.go +++ b/opcode_test.go @@ -12,475 +12,475 @@ import ( "github.com/btcsuite/btcwire" ) -// test scripts to test as many opcodes as possible. -// All run on a fake tx with a single in, single out. -type opcodeTest struct { - script []byte - canonical bool - shouldPass bool - shouldFail error -} +// TestScripts tests script execution for a wide variety of opcodes. All tests +// against a fake transaction with a single input and output. +func TestScripts(t *testing.T) { + t.Parallel() -var opcodeTests = []opcodeTest{ - // does nothing, but doesn't put a true on the stack, should fail - {script: []byte{btcscript.OP_NOP}, shouldPass: false}, - // should just put true on the stack, thus passes. - {script: []byte{btcscript.OP_TRUE}, shouldPass: true}, - // should just put false on the stack, thus fails. - {script: []byte{btcscript.OP_FALSE}, shouldPass: false}, - // tests OP_VERIFY (true). true is needed since else stack is empty. - {script: []byte{btcscript.OP_TRUE, btcscript.OP_VERIFY, - btcscript.OP_TRUE}, shouldPass: true}, - // tests OP_VERIFY (false), will error out. - {script: []byte{btcscript.OP_FALSE, btcscript.OP_VERIFY, - btcscript.OP_TRUE}, shouldPass: false}, - // tests OP_VERIFY with empty stack (errors) - {script: []byte{btcscript.OP_VERIFY}, shouldPass: false}, - // test OP_RETURN immediately fails the script (empty stack) - {script: []byte{btcscript.OP_RETURN}, shouldPass: false}, - // test OP_RETURN immediately fails the script (full stack) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_RETURN}, - shouldPass: false}, - // tests numequal with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMEQUAL}, shouldPass: true}, - // tests numequal with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMEQUAL}, shouldPass: false}, - // tests numequal with insufficient arguments (1/2) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMEQUAL}, - shouldPass: false}, - // tests numequal with insufficient arguments (0/2) - {script: []byte{btcscript.OP_NUMEQUAL}, shouldPass: false}, - // tests numnotequal with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMNOTEQUAL}, shouldPass: true}, - // tests numnotequal with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, - // tests numnotequal with insufficient arguments (1/2) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMNOTEQUAL}, - shouldPass: false}, - // tests numnotequal with insufficient arguments (0/2) - {script: []byte{btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, - // test numequal_verify with a trivial example (passing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, - shouldPass: true}, - // test numequal_verify with a trivial example (failing) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, - shouldPass: false}, - // test OP_1ADD by adding 1 to 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_1ADD}, - shouldPass: true}, - // test OP_1ADD without args (should error) - {script: []byte{btcscript.OP_1ADD}, shouldPass: false}, - // test OP_1NEGATE by adding 1 to -1 - {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, - shouldPass: false}, - // test OP_1NEGATE by adding negating -1 - {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_NEGATE}, - shouldPass: true}, - // test OP_NEGATE by adding 1 to -1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, - btcscript.OP_1ADD}, shouldPass: false}, - // test OP_NEGATE with no args - {script: []byte{btcscript.OP_NEGATE}, shouldPass: false}, - // test OP_1SUB -> 1 - 1 = 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_1SUB}, - shouldPass: false}, - // test OP_1SUB -> negate(0 -1) = 1 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_1SUB, - btcscript.OP_NEGATE}, shouldPass: true}, - // test OP_1SUB with empty stack - {script: []byte{btcscript.OP_1SUB}, shouldPass: false}, - // OP_DEPTH with empty stack, means 0 on stack at end - {script: []byte{btcscript.OP_DEPTH}, shouldPass: false}, - // 1 +1 -1 = 1. tests depth + add - {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, btcscript.OP_ADD, - btcscript.OP_1SUB}, shouldPass: true}, - // 1 +1 -1 = 0 . tests dept + add - {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, - btcscript.OP_ADD, btcscript.OP_1SUB, btcscript.OP_1SUB}, - shouldPass: false}, - // OP_ADD with only one thing on stack should error - {script: []byte{btcscript.OP_TRUE, btcscript.OP_ADD}, - shouldPass: false}, - // OP_ADD with nothing on stack should error - {script: []byte{btcscript.OP_ADD}, shouldPass: false}, - // OP_SUB: 1-1=0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_SUB}, shouldPass: false}, - // OP_SUB: 1+1-1=1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_ADD, btcscript.OP_SUB}, shouldPass: true}, - // OP_SUB with only one thing on stack should error - {script: []byte{btcscript.OP_TRUE, btcscript.OP_SUB}, - shouldPass: false}, - // OP_SUB with nothing on stack should error - {script: []byte{btcscript.OP_SUB}, shouldPass: false}, - // OP_LESSTHAN 1 < 1 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_LESSTHAN}, shouldPass: false}, - // OP_LESSTHAN 1 < 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_LESSTHAN}, shouldPass: false}, - // OP_LESSTHAN 0 < 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_LESSTHAN}, shouldPass: true}, - // OP_LESSTHAN only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHAN}, - shouldPass: false}, - // OP_LESSTHAN no args - {script: []byte{btcscript.OP_LESSTHAN}, shouldPass: false}, + tests := []struct { + script []byte + canonical bool + shouldPass bool + shouldFail error + }{ + // does nothing, but doesn't put a true on the stack, should fail + {script: []byte{btcscript.OP_NOP}, shouldPass: false}, + // should just put true on the stack, thus passes. + {script: []byte{btcscript.OP_TRUE}, shouldPass: true}, + // should just put false on the stack, thus fails. + {script: []byte{btcscript.OP_FALSE}, shouldPass: false}, + // tests OP_VERIFY (true). true is needed since else stack is empty. + {script: []byte{btcscript.OP_TRUE, btcscript.OP_VERIFY, + btcscript.OP_TRUE}, shouldPass: true}, + // tests OP_VERIFY (false), will error out. + {script: []byte{btcscript.OP_FALSE, btcscript.OP_VERIFY, + btcscript.OP_TRUE}, shouldPass: false}, + // tests OP_VERIFY with empty stack (errors) + {script: []byte{btcscript.OP_VERIFY}, shouldPass: false}, + // test OP_RETURN immediately fails the script (empty stack) + {script: []byte{btcscript.OP_RETURN}, shouldPass: false}, + // test OP_RETURN immediately fails the script (full stack) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_RETURN}, + shouldPass: false}, + // tests numequal with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMEQUAL}, shouldPass: true}, + // tests numequal with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMEQUAL}, shouldPass: false}, + // tests numequal with insufficient arguments (1/2) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMEQUAL}, + shouldPass: false}, + // tests numequal with insufficient arguments (0/2) + {script: []byte{btcscript.OP_NUMEQUAL}, shouldPass: false}, + // tests numnotequal with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMNOTEQUAL}, shouldPass: true}, + // tests numnotequal with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + // tests numnotequal with insufficient arguments (1/2) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NUMNOTEQUAL}, + shouldPass: false}, + // tests numnotequal with insufficient arguments (0/2) + {script: []byte{btcscript.OP_NUMNOTEQUAL}, shouldPass: false}, + // test numequal_verify with a trivial example (passing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + shouldPass: true}, + // test numequal_verify with a trivial example (failing) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_NUMEQUALVERIFY, btcscript.OP_TRUE}, + shouldPass: false}, + // test OP_1ADD by adding 1 to 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_1ADD}, + shouldPass: true}, + // test OP_1ADD without args (should error) + {script: []byte{btcscript.OP_1ADD}, shouldPass: false}, + // test OP_1NEGATE by adding 1 to -1 + {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_1ADD}, + shouldPass: false}, + // test OP_1NEGATE by adding negating -1 + {script: []byte{btcscript.OP_1NEGATE, btcscript.OP_NEGATE}, + shouldPass: true}, + // test OP_NEGATE by adding 1 to -1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, + btcscript.OP_1ADD}, shouldPass: false}, + // test OP_NEGATE with no args + {script: []byte{btcscript.OP_NEGATE}, shouldPass: false}, + // test OP_1SUB -> 1 - 1 = 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_1SUB}, + shouldPass: false}, + // test OP_1SUB -> negate(0 -1) = 1 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_1SUB, + btcscript.OP_NEGATE}, shouldPass: true}, + // test OP_1SUB with empty stack + {script: []byte{btcscript.OP_1SUB}, shouldPass: false}, + // OP_DEPTH with empty stack, means 0 on stack at end + {script: []byte{btcscript.OP_DEPTH}, shouldPass: false}, + // 1 +1 -1 = 1. tests depth + add + {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, btcscript.OP_ADD, + btcscript.OP_1SUB}, shouldPass: true}, + // 1 +1 -1 = 0 . tests dept + add + {script: []byte{btcscript.OP_TRUE, btcscript.OP_DEPTH, + btcscript.OP_ADD, btcscript.OP_1SUB, btcscript.OP_1SUB}, + shouldPass: false}, + // OP_ADD with only one thing on stack should error + {script: []byte{btcscript.OP_TRUE, btcscript.OP_ADD}, + shouldPass: false}, + // OP_ADD with nothing on stack should error + {script: []byte{btcscript.OP_ADD}, shouldPass: false}, + // OP_SUB: 1-1=0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_SUB}, shouldPass: false}, + // OP_SUB: 1+1-1=1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_ADD, btcscript.OP_SUB}, shouldPass: true}, + // OP_SUB with only one thing on stack should error + {script: []byte{btcscript.OP_TRUE, btcscript.OP_SUB}, + shouldPass: false}, + // OP_SUB with nothing on stack should error + {script: []byte{btcscript.OP_SUB}, shouldPass: false}, + // OP_LESSTHAN 1 < 1 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_LESSTHAN}, shouldPass: false}, + // OP_LESSTHAN 1 < 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_LESSTHAN}, shouldPass: false}, + // OP_LESSTHAN 0 < 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_LESSTHAN}, shouldPass: true}, + // OP_LESSTHAN only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHAN}, + shouldPass: false}, + // OP_LESSTHAN no args + {script: []byte{btcscript.OP_LESSTHAN}, shouldPass: false}, - // OP_LESSTHANOREQUAL 1 <= 1 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, - // OP_LESSTHANOREQUAL 1 <= 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, - // OP_LESSTHANOREQUAL 0 <= 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, - // OP_LESSTHANOREQUAL only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHANOREQUAL}, - shouldPass: false}, - // OP_LESSTHANOREQUAL no args - {script: []byte{btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + // OP_LESSTHANOREQUAL 1 <= 1 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + // OP_LESSTHANOREQUAL 1 <= 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, + // OP_LESSTHANOREQUAL 0 <= 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_LESSTHANOREQUAL}, shouldPass: true}, + // OP_LESSTHANOREQUAL only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_LESSTHANOREQUAL}, + shouldPass: false}, + // OP_LESSTHANOREQUAL no args + {script: []byte{btcscript.OP_LESSTHANOREQUAL}, shouldPass: false}, - // OP_GREATERTHAN 1 > 1 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHAN}, shouldPass: false}, - // OP_GREATERTHAN 1 > 0 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_GREATERTHAN}, shouldPass: true}, - // OP_GREATERTHAN 0 > 1 == false - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHAN}, shouldPass: false}, - // OP_GREATERTHAN only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHAN}, - shouldPass: false}, - // OP_GREATERTHAN no args - {script: []byte{btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN 1 > 1 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN 1 > 0 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_GREATERTHAN}, shouldPass: true}, + // OP_GREATERTHAN 0 > 1 == false + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHAN}, shouldPass: false}, + // OP_GREATERTHAN only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHAN}, + shouldPass: false}, + // OP_GREATERTHAN no args + {script: []byte{btcscript.OP_GREATERTHAN}, shouldPass: false}, - // OP_GREATERTHANOREQUAL 1 >= 1 == true - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, - // OP_GREATERTHANOREQUAL 1 >= 0 == false - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, - // OP_GREATERTHANOREQUAL 0 >= 1 == true - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, - // OP_GREATERTHANOREQUAL only one arg - {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHANOREQUAL}, - shouldPass: false}, - // OP_GREATERTHANOREQUAL no args - {script: []byte{btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + // OP_GREATERTHANOREQUAL 1 >= 1 == true + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + // OP_GREATERTHANOREQUAL 1 >= 0 == false + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: true}, + // OP_GREATERTHANOREQUAL 0 >= 1 == true + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, + // OP_GREATERTHANOREQUAL only one arg + {script: []byte{btcscript.OP_TRUE, btcscript.OP_GREATERTHANOREQUAL}, + shouldPass: false}, + // OP_GREATERTHANOREQUAL no args + {script: []byte{btcscript.OP_GREATERTHANOREQUAL}, shouldPass: false}, - // OP_MIN basic functionality -> min(0,1) = 0 = min(1,0) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_MIN}, shouldPass: false}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_MIN}, shouldPass: false}, - // OP_MIN -> 1 arg errors - {script: []byte{btcscript.OP_TRUE, btcscript.OP_MIN}, - shouldPass: false}, - // OP_MIN -> 0 arg errors - {script: []byte{btcscript.OP_MIN}, shouldPass: false}, - // OP_MAX basic functionality -> max(0,1) = 1 = max(1,0) - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_MAX}, shouldPass: true}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_MAX}, shouldPass: true}, - // OP_MAX -> 1 arg errors - {script: []byte{btcscript.OP_TRUE, btcscript.OP_MAX}, - shouldPass: false}, - // OP_MAX -> 0 arg errors - {script: []byte{btcscript.OP_MAX}, shouldPass: false}, + // OP_MIN basic functionality -> min(0,1) = 0 = min(1,0) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_MIN}, shouldPass: false}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_MIN}, shouldPass: false}, + // OP_MIN -> 1 arg errors + {script: []byte{btcscript.OP_TRUE, btcscript.OP_MIN}, + shouldPass: false}, + // OP_MIN -> 0 arg errors + {script: []byte{btcscript.OP_MIN}, shouldPass: false}, + // OP_MAX basic functionality -> max(0,1) = 1 = max(1,0) + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_MAX}, shouldPass: true}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_MAX}, shouldPass: true}, + // OP_MAX -> 1 arg errors + {script: []byte{btcscript.OP_TRUE, btcscript.OP_MAX}, + shouldPass: false}, + // OP_MAX -> 0 arg errors + {script: []byte{btcscript.OP_MAX}, shouldPass: false}, - // By this point we know a number of operations appear to be working - // correctly. we can use them to test the other number pushing - // operations - {script: []byte{btcscript.OP_TRUE, btcscript.OP_1ADD, btcscript.OP_2, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_2, btcscript.OP_1ADD, btcscript.OP_3, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_3, btcscript.OP_1ADD, btcscript.OP_4, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_4, btcscript.OP_1ADD, btcscript.OP_5, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_5, btcscript.OP_1ADD, btcscript.OP_6, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_6, btcscript.OP_1ADD, btcscript.OP_7, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_7, btcscript.OP_1ADD, btcscript.OP_8, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_8, btcscript.OP_1ADD, btcscript.OP_9, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_9, btcscript.OP_1ADD, btcscript.OP_10, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_10, btcscript.OP_1ADD, btcscript.OP_11, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_11, btcscript.OP_1ADD, btcscript.OP_12, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_12, btcscript.OP_1ADD, btcscript.OP_13, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_13, btcscript.OP_1ADD, btcscript.OP_14, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_14, btcscript.OP_1ADD, btcscript.OP_15, - btcscript.OP_EQUAL}, shouldPass: true}, - {script: []byte{btcscript.OP_15, btcscript.OP_1ADD, btcscript.OP_16, - btcscript.OP_EQUAL}, shouldPass: true}, + // By this point we know a number of operations appear to be working + // correctly. we can use them to test the other number pushing + // operations + {script: []byte{btcscript.OP_TRUE, btcscript.OP_1ADD, btcscript.OP_2, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_2, btcscript.OP_1ADD, btcscript.OP_3, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_3, btcscript.OP_1ADD, btcscript.OP_4, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_4, btcscript.OP_1ADD, btcscript.OP_5, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_5, btcscript.OP_1ADD, btcscript.OP_6, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_6, btcscript.OP_1ADD, btcscript.OP_7, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_7, btcscript.OP_1ADD, btcscript.OP_8, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_8, btcscript.OP_1ADD, btcscript.OP_9, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_9, btcscript.OP_1ADD, btcscript.OP_10, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_10, btcscript.OP_1ADD, btcscript.OP_11, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_11, btcscript.OP_1ADD, btcscript.OP_12, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_12, btcscript.OP_1ADD, btcscript.OP_13, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_13, btcscript.OP_1ADD, btcscript.OP_14, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_14, btcscript.OP_1ADD, btcscript.OP_15, + btcscript.OP_EQUAL}, shouldPass: true}, + {script: []byte{btcscript.OP_15, btcscript.OP_1ADD, btcscript.OP_16, + btcscript.OP_EQUAL}, shouldPass: true}, - // Test OP_WITHIN x, min, max - // 0 <= 1 < 2 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: true}, - // 1 <= 0 < 2 FAIL - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: false}, - // 1 <= 1 < 2 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: true}, - // 1 <= 2 < 2 FAIL - {script: []byte{btcscript.OP_2, btcscript.OP_TRUE, btcscript.OP_2, - btcscript.OP_WITHIN}, shouldPass: false}, - // only two arguments - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_WITHIN}, shouldPass: false}, - // only one argument - {script: []byte{btcscript.OP_TRUE, btcscript.OP_WITHIN}, - shouldPass: false}, - // no arguments - {script: []byte{btcscript.OP_WITHIN}, shouldPass: false}, + // Test OP_WITHIN x, min, max + // 0 <= 1 < 2 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: true}, + // 1 <= 0 < 2 FAIL + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: false}, + // 1 <= 1 < 2 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: true}, + // 1 <= 2 < 2 FAIL + {script: []byte{btcscript.OP_2, btcscript.OP_TRUE, btcscript.OP_2, + btcscript.OP_WITHIN}, shouldPass: false}, + // only two arguments + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_WITHIN}, shouldPass: false}, + // only one argument + {script: []byte{btcscript.OP_TRUE, btcscript.OP_WITHIN}, + shouldPass: false}, + // no arguments + {script: []byte{btcscript.OP_WITHIN}, shouldPass: false}, - // OP_BOOLAND - // 1 && 1 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_BOOLAND}, shouldPass: true}, - // 1 && 0 == 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_BOOLAND}, shouldPass: false}, - // 0 && 1 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_BOOLAND}, shouldPass: false}, - // 0 && 0 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, - btcscript.OP_BOOLAND}, shouldPass: false}, - // 0 && - boom - {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLAND}, - shouldPass: false}, - // && - boom - {script: []byte{btcscript.OP_BOOLAND}, shouldPass: false}, + // OP_BOOLAND + // 1 && 1 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_BOOLAND}, shouldPass: true}, + // 1 && 0 == 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && 1 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && 0 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, + btcscript.OP_BOOLAND}, shouldPass: false}, + // 0 && - boom + {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLAND}, + shouldPass: false}, + // && - boom + {script: []byte{btcscript.OP_BOOLAND}, shouldPass: false}, - // OP_BOOLOR - // 1 || 1 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, - btcscript.OP_BOOLOR}, shouldPass: true}, - // 1 || 0 == 1 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, - btcscript.OP_BOOLOR}, shouldPass: true}, - // 0 || 1 == 1 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, - btcscript.OP_BOOLOR}, shouldPass: true}, - // 0 || 0 == 0 - {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, - btcscript.OP_BOOLOR}, shouldPass: false}, - // 0 && - boom - {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLOR}, - shouldPass: false}, - // && - boom - {script: []byte{btcscript.OP_BOOLOR}, shouldPass: false}, + // OP_BOOLOR + // 1 || 1 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_TRUE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 1 || 0 == 1 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_FALSE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 0 || 1 == 1 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_TRUE, + btcscript.OP_BOOLOR}, shouldPass: true}, + // 0 || 0 == 0 + {script: []byte{btcscript.OP_FALSE, btcscript.OP_FALSE, + btcscript.OP_BOOLOR}, shouldPass: false}, + // 0 && - boom + {script: []byte{btcscript.OP_TRUE, btcscript.OP_BOOLOR}, + shouldPass: false}, + // && - boom + {script: []byte{btcscript.OP_BOOLOR}, shouldPass: false}, - // OP_0NOTEQUAL - // 1 with input != 0 XXX check output is actually 1. - {script: []byte{btcscript.OP_TRUE, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_2, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_3, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_4, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_5, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_6, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_7, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_8, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_9, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_10, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_11, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_12, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_13, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_14, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_15, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_16, btcscript.OP_0NOTEQUAL}, - shouldPass: true}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_0NOTEQUAL}, shouldPass: false}, - // No arguments also blows up - {script: []byte{btcscript.OP_0NOTEQUAL}, shouldPass: false}, + // OP_0NOTEQUAL + // 1 with input != 0 XXX check output is actually 1. + {script: []byte{btcscript.OP_TRUE, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_2, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_3, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_4, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_5, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_6, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_7, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_8, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_9, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_10, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_11, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_12, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_13, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_14, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_15, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_16, btcscript.OP_0NOTEQUAL}, + shouldPass: true}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_0NOTEQUAL}, shouldPass: false}, + // No arguments also blows up + {script: []byte{btcscript.OP_0NOTEQUAL}, shouldPass: false}, - // OP_NOT: 1 i input is 0, else 0 - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_2, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_3, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_4, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_5, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_6, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_7, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_8, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_9, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_10, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_11, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_12, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_13, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_14, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_15, btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_16, btcscript.OP_NOT}, shouldPass: false}, - // check negative numbers too - {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, - btcscript.OP_NOT}, shouldPass: false}, - {script: []byte{btcscript.OP_FALSE, btcscript.OP_NOT}, - shouldPass: true}, - // No arguments also blows up - {script: []byte{btcscript.OP_NOT}, shouldPass: false}, + // OP_NOT: 1 i input is 0, else 0 + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_2, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_3, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_4, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_5, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_6, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_7, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_8, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_9, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_10, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_11, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_12, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_13, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_14, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_15, btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_16, btcscript.OP_NOT}, shouldPass: false}, + // check negative numbers too + {script: []byte{btcscript.OP_TRUE, btcscript.OP_NEGATE, + btcscript.OP_NOT}, shouldPass: false}, + {script: []byte{btcscript.OP_FALSE, btcscript.OP_NOT}, + shouldPass: true}, + // No arguments also blows up + {script: []byte{btcscript.OP_NOT}, shouldPass: false}, - // Conditional Execution - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, - {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, - {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, - {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, - /* up here because error from sig parsing is undefined. */ - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, - 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, - 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, - 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, - 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, - 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, - 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - canonical: false, - shouldPass: false}, - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, - 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, - 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, - 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, - 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, - 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, - 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, - canonical: true, - shouldPass: false}, - /* up here because no defined error case. */ - {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, - 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, - 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, - 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, - 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, - 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, - 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, - 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, - btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, - shouldPass: false}, + // Conditional Execution + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_0, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2, btcscript.OP_ENDIF}, shouldPass: false}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_2}, shouldFail: btcscript.ErrStackMissingEndif}, + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_1, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_1, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_IF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_0, btcscript.OP_IF, btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF, btcscript.OP_ELSE, btcscript.OP_1, btcscript.OP_ENDIF}, shouldPass: true}, + {script: []byte{btcscript.OP_NOTIF, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackUnderflow}, + {script: []byte{btcscript.OP_ELSE, btcscript.OP_0, btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, + {script: []byte{btcscript.OP_ENDIF}, shouldFail: btcscript.ErrStackNoIf}, + /* up here because error from sig parsing is undefined. */ + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, + canonical: false, + shouldPass: false}, + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIG}, + canonical: true, + shouldPass: false}, + /* up here because no defined error case. */ + {script: []byte{btcscript.OP_1, btcscript.OP_1, btcscript.OP_DATA_65, + 0x04, 0xae, 0x1a, 0x62, 0xfe, 0x09, 0xc5, 0xf5, 0x1b, 0x13, + 0x90, 0x5f, 0x07, 0xf0, 0x6b, 0x99, 0xa2, 0xf7, 0x15, 0x9b, + 0x22, 0x25, 0xf3, 0x74, 0xcd, 0x37, 0x8d, 0x71, 0x30, 0x2f, + 0xa2, 0x84, 0x14, 0xe7, 0xaa, 0xb3, 0x73, 0x97, 0xf5, 0x54, + 0xa7, 0xdf, 0x5f, 0x14, 0x2c, 0x21, 0xc1, 0xb7, 0x30, 0x3b, + 0x8a, 0x06, 0x26, 0xf1, 0xba, 0xde, 0xd5, 0xc7, 0x2a, 0x70, + 0x4f, 0x7e, 0x6c, 0xd8, 0x4c, + btcscript.OP_1, btcscript.OP_CHECKMULTISIGVERIFY}, + shouldPass: false}, - // Invalid Opcodes - {script: []byte{186}, shouldPass: false}, - {script: []byte{187}, shouldPass: false}, - {script: []byte{188}, shouldPass: false}, - {script: []byte{189}, shouldPass: false}, - {script: []byte{190}, shouldPass: false}, - {script: []byte{191}, shouldPass: false}, - {script: []byte{192}, shouldPass: false}, - {script: []byte{193}, shouldPass: false}, - {script: []byte{194}, shouldPass: false}, - {script: []byte{195}, shouldPass: false}, - {script: []byte{195}, shouldPass: false}, - {script: []byte{196}, shouldPass: false}, - {script: []byte{197}, shouldPass: false}, - {script: []byte{198}, shouldPass: false}, - {script: []byte{199}, shouldPass: false}, - {script: []byte{200}, shouldPass: false}, - {script: []byte{201}, shouldPass: false}, - {script: []byte{202}, shouldPass: false}, - {script: []byte{203}, shouldPass: false}, - {script: []byte{204}, shouldPass: false}, - {script: []byte{205}, shouldPass: false}, - {script: []byte{206}, shouldPass: false}, - {script: []byte{207}, shouldPass: false}, - {script: []byte{208}, shouldPass: false}, - {script: []byte{209}, shouldPass: false}, - {script: []byte{210}, shouldPass: false}, - {script: []byte{211}, shouldPass: false}, - {script: []byte{212}, shouldPass: false}, - {script: []byte{213}, shouldPass: false}, - {script: []byte{214}, shouldPass: false}, - {script: []byte{215}, shouldPass: false}, - {script: []byte{216}, shouldPass: false}, - {script: []byte{217}, shouldPass: false}, - {script: []byte{218}, shouldPass: false}, - {script: []byte{219}, shouldPass: false}, - {script: []byte{220}, shouldPass: false}, - {script: []byte{221}, shouldPass: false}, - {script: []byte{222}, shouldPass: false}, - {script: []byte{223}, shouldPass: false}, - {script: []byte{224}, shouldPass: false}, - {script: []byte{225}, shouldPass: false}, - {script: []byte{226}, shouldPass: false}, - {script: []byte{227}, shouldPass: false}, - {script: []byte{228}, shouldPass: false}, - {script: []byte{229}, shouldPass: false}, - {script: []byte{230}, shouldPass: false}, - {script: []byte{231}, shouldPass: false}, - {script: []byte{232}, shouldPass: false}, - {script: []byte{233}, shouldPass: false}, - {script: []byte{234}, shouldPass: false}, - {script: []byte{235}, shouldPass: false}, - {script: []byte{236}, shouldPass: false}, - {script: []byte{237}, shouldPass: false}, - {script: []byte{238}, shouldPass: false}, - {script: []byte{239}, shouldPass: false}, - {script: []byte{240}, shouldPass: false}, - {script: []byte{241}, shouldPass: false}, - {script: []byte{242}, shouldPass: false}, - {script: []byte{243}, shouldPass: false}, - {script: []byte{244}, shouldPass: false}, - {script: []byte{245}, shouldPass: false}, - {script: []byte{246}, shouldPass: false}, - {script: []byte{247}, shouldPass: false}, - {script: []byte{248}, shouldPass: false}, - {script: []byte{249}, shouldPass: false}, - {script: []byte{250}, shouldPass: false}, - {script: []byte{251}, shouldPass: false}, - {script: []byte{252}, shouldPass: false}, -} + // Invalid Opcodes + {script: []byte{186}, shouldPass: false}, + {script: []byte{187}, shouldPass: false}, + {script: []byte{188}, shouldPass: false}, + {script: []byte{189}, shouldPass: false}, + {script: []byte{190}, shouldPass: false}, + {script: []byte{191}, shouldPass: false}, + {script: []byte{192}, shouldPass: false}, + {script: []byte{193}, shouldPass: false}, + {script: []byte{194}, shouldPass: false}, + {script: []byte{195}, shouldPass: false}, + {script: []byte{195}, shouldPass: false}, + {script: []byte{196}, shouldPass: false}, + {script: []byte{197}, shouldPass: false}, + {script: []byte{198}, shouldPass: false}, + {script: []byte{199}, shouldPass: false}, + {script: []byte{200}, shouldPass: false}, + {script: []byte{201}, shouldPass: false}, + {script: []byte{202}, shouldPass: false}, + {script: []byte{203}, shouldPass: false}, + {script: []byte{204}, shouldPass: false}, + {script: []byte{205}, shouldPass: false}, + {script: []byte{206}, shouldPass: false}, + {script: []byte{207}, shouldPass: false}, + {script: []byte{208}, shouldPass: false}, + {script: []byte{209}, shouldPass: false}, + {script: []byte{210}, shouldPass: false}, + {script: []byte{211}, shouldPass: false}, + {script: []byte{212}, shouldPass: false}, + {script: []byte{213}, shouldPass: false}, + {script: []byte{214}, shouldPass: false}, + {script: []byte{215}, shouldPass: false}, + {script: []byte{216}, shouldPass: false}, + {script: []byte{217}, shouldPass: false}, + {script: []byte{218}, shouldPass: false}, + {script: []byte{219}, shouldPass: false}, + {script: []byte{220}, shouldPass: false}, + {script: []byte{221}, shouldPass: false}, + {script: []byte{222}, shouldPass: false}, + {script: []byte{223}, shouldPass: false}, + {script: []byte{224}, shouldPass: false}, + {script: []byte{225}, shouldPass: false}, + {script: []byte{226}, shouldPass: false}, + {script: []byte{227}, shouldPass: false}, + {script: []byte{228}, shouldPass: false}, + {script: []byte{229}, shouldPass: false}, + {script: []byte{230}, shouldPass: false}, + {script: []byte{231}, shouldPass: false}, + {script: []byte{232}, shouldPass: false}, + {script: []byte{233}, shouldPass: false}, + {script: []byte{234}, shouldPass: false}, + {script: []byte{235}, shouldPass: false}, + {script: []byte{236}, shouldPass: false}, + {script: []byte{237}, shouldPass: false}, + {script: []byte{238}, shouldPass: false}, + {script: []byte{239}, shouldPass: false}, + {script: []byte{240}, shouldPass: false}, + {script: []byte{241}, shouldPass: false}, + {script: []byte{242}, shouldPass: false}, + {script: []byte{243}, shouldPass: false}, + {script: []byte{244}, shouldPass: false}, + {script: []byte{245}, shouldPass: false}, + {script: []byte{246}, shouldPass: false}, + {script: []byte{247}, shouldPass: false}, + {script: []byte{248}, shouldPass: false}, + {script: []byte{249}, shouldPass: false}, + {script: []byte{250}, shouldPass: false}, + {script: []byte{251}, shouldPass: false}, + {script: []byte{252}, shouldPass: false}, + } -func testScript(t *testing.T, script []byte, canonical bool) (err error) { - // mock up fake tx. - tx := &btcwire.MsgTx{ + // Mock up fake tx used during script execution. + mockTx := &btcwire.MsgTx{ Version: 1, TxIn: []*btcwire.TxIn{ { @@ -501,38 +501,38 @@ func testScript(t *testing.T, script []byte, canonical bool) (err error) { LockTime: 0, } - tx.TxOut[0].PkScript = script + for i, test := range tests { + // Parse and execute the test script. + var flags btcscript.ScriptFlags + if test.canonical { + flags = btcscript.ScriptCanonicalSignatures + } + mockTx.TxOut[0].PkScript = test.script + sigScript := mockTx.TxIn[0].SignatureScript + engine, err := btcscript.NewScript(sigScript, test.script, 0, + mockTx, flags) + if err == nil { + err = engine.Execute() + } - var flags btcscript.ScriptFlags - if canonical { - flags = btcscript.ScriptCanonicalSignatures - } - - engine, err := btcscript.NewScript(tx.TxIn[0].SignatureScript, - tx.TxOut[0].PkScript, 0, tx, flags) - if err != nil { - return err - } - return engine.Execute() -} - -func TestScripts(t *testing.T) { - // for each entry in the list - for i := range opcodeTests { - shouldPass := opcodeTests[i].shouldPass - shouldFail := opcodeTests[i].shouldFail - err := testScript(t, opcodeTests[i].script, opcodeTests[i].canonical) - if shouldFail != nil { + if test.shouldFail != nil { if err == nil { - t.Errorf("test %d passed should fail with %v", i, err) - } else if shouldFail != err { - t.Errorf("test %d failed with wrong error [%v], expected [%v]", i, err, shouldFail) + t.Errorf("test %d passed should fail with %v", + i, test.shouldFail) + continue + } else if test.shouldFail != err { + t.Errorf("test %d failed with wrong error "+ + "[%v], expected [%v]", i, err, + test.shouldFail) + continue } } - if shouldPass && err != nil { + if test.shouldPass && err != nil { t.Errorf("test %d failed: %v", i, err) - } else if !shouldPass && err == nil { + continue + } else if !test.shouldPass && err == nil { t.Errorf("test %d passed, should fail", i) + continue } } } @@ -4374,6 +4374,8 @@ func testOpcode(t *testing.T, test *detailedTest) { } func TestOpcodes(t *testing.T) { + t.Parallel() + for i := range detailedTests { testOpcode(t, &detailedTests[i]) } @@ -4402,6 +4404,8 @@ func testDisasmString(t *testing.T, test *detailedTest) { } func TestDisasmStrings(t *testing.T) { + t.Parallel() + for i := range detailedTests { testDisasmString(t, &detailedTests[i]) } @@ -4414,6 +4418,8 @@ func TestDisasmStrings(t *testing.T) { // While this isn't as precise as using full transaction scripts, this gives // us coverage over a wider range of opcodes. func TestSigOps(t *testing.T) { + t.Parallel() + for _, test := range detailedTests { count := btcscript.GetSigOpCount(test.script) if count != test.nSigOps { @@ -4432,6 +4438,8 @@ func TestSigOps(t *testing.T) { // us coverage over a wider range of opcodes. See script_test.go for tests // using real transactions to provide a bit more coverage. func TestPreciseSigOps(t *testing.T) { + t.Parallel() + for _, test := range detailedTests { count := btcscript.GetPreciseSigOpCount( []byte{btcscript.OP_1}, test.script, false) diff --git a/script_test.go b/script_test.go index 8ff919a7..388bd8d2 100644 --- a/script_test.go +++ b/script_test.go @@ -30,6 +30,8 @@ func builderScript(builder *btcscript.ScriptBuilder) []byte { } func TestPushedData(t *testing.T) { + t.Parallel() + var tests = []struct { in []byte out [][]byte @@ -90,6 +92,8 @@ func TestPushedData(t *testing.T) { } func TestStandardPushes(t *testing.T) { + t.Parallel() + for i := 0; i < 65535; i++ { builder := btcscript.NewScriptBuilder() builder.AddInt64(int64(i)) @@ -1652,12 +1656,16 @@ func testTx(t *testing.T, test txTest) { } func TestTX(t *testing.T) { + t.Parallel() + for i := range txTests { testTx(t, txTests[i]) } } func TestGetPreciseSignOps(t *testing.T) { + t.Parallel() + // First we go over the range of tests in testTx and count the sigops in // them. for _, test := range txTests { @@ -1742,6 +1750,8 @@ type scriptInfoTest struct { } func TestScriptInfo(t *testing.T) { + t.Parallel() + for _, test := range txTests { si, err := btcscript.CalcScriptInfo( test.tx.TxIn[test.idx].SignatureScript, @@ -1996,6 +2006,8 @@ func testRemoveOpcode(t *testing.T, test *removeOpcodeTest) { } func TestRemoveOpcodes(t *testing.T) { + t.Parallel() + for i := range removeOpcodeTests { testRemoveOpcode(t, &removeOpcodeTests[i]) } @@ -2134,6 +2146,8 @@ func testRemoveOpcodeByData(t *testing.T, test *removeOpcodeByDataTest) { } } func TestRemoveOpcodeByDatas(t *testing.T) { + t.Parallel() + for i := range removeOpcodeByDataTests { testRemoveOpcodeByData(t, &removeOpcodeByDataTests[i]) } @@ -2361,12 +2375,16 @@ func testScriptType(t *testing.T, test *scriptTypeTest) { } func TestScriptTypes(t *testing.T) { + t.Parallel() + for i := range scriptTypeTests { testScriptType(t, &scriptTypeTests[i]) } } func TestIsPayToScriptHash(t *testing.T) { + t.Parallel() + for _, test := range scriptTypeTests { shouldBe := (test.scripttype == btcscript.ScriptHashTy) p2sh := btcscript.IsPayToScriptHash(test.script) @@ -2380,6 +2398,8 @@ func TestIsPayToScriptHash(t *testing.T) { // This test sets the pc to a deliberately bad result then confirms that Step() // and Disasm fail correctly. func TestBadPC(t *testing.T) { + t.Parallel() + type pcTest struct { script, off int } @@ -2452,6 +2472,8 @@ func TestBadPC(t *testing.T) { // Most codepaths in CheckErrorCondition() are testd elsewhere, this tests // the execute early test. func TestCheckErrorCondition(t *testing.T) { + t.Parallel() + // tx with almost empty scripts. tx := &btcwire.MsgTx{ Version: 1, @@ -2787,6 +2809,8 @@ var SigScriptTests = []TstSigScript{ // created for the MsgTxs in txTests, since they come from the blockchain // and we don't have the private keys. func TestSignatureScript(t *testing.T) { + t.Parallel() + privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privKeyD) nexttest: @@ -2868,50 +2892,52 @@ nexttest: } } -var classStringifyTests = []struct { - name string - scriptclass btcscript.ScriptClass - stringed string -}{ - { - name: "nonstandardty", - scriptclass: btcscript.NonStandardTy, - stringed: "nonstandard", - }, - { - name: "pubkey", - scriptclass: btcscript.PubKeyTy, - stringed: "pubkey", - }, - { - name: "pubkeyhash", - scriptclass: btcscript.PubKeyHashTy, - stringed: "pubkeyhash", - }, - { - name: "scripthash", - scriptclass: btcscript.ScriptHashTy, - stringed: "scripthash", - }, - { - name: "multisigty", - scriptclass: btcscript.MultiSigTy, - stringed: "multisig", - }, - { - name: "nulldataty", - scriptclass: btcscript.NullDataTy, - stringed: "nulldata", - }, - { - name: "broken", - scriptclass: btcscript.ScriptClass(255), - stringed: "Invalid", - }, -} - func TestStringifyClass(t *testing.T) { - for _, test := range classStringifyTests { + t.Parallel() + + tests := []struct { + name string + scriptclass btcscript.ScriptClass + stringed string + }{ + { + name: "nonstandardty", + scriptclass: btcscript.NonStandardTy, + stringed: "nonstandard", + }, + { + name: "pubkey", + scriptclass: btcscript.PubKeyTy, + stringed: "pubkey", + }, + { + name: "pubkeyhash", + scriptclass: btcscript.PubKeyHashTy, + stringed: "pubkeyhash", + }, + { + name: "scripthash", + scriptclass: btcscript.ScriptHashTy, + stringed: "scripthash", + }, + { + name: "multisigty", + scriptclass: btcscript.MultiSigTy, + stringed: "multisig", + }, + { + name: "nulldataty", + scriptclass: btcscript.NullDataTy, + stringed: "nulldata", + }, + { + name: "broken", + scriptclass: btcscript.ScriptClass(255), + stringed: "Invalid", + }, + } + + for _, test := range tests { typeString := test.scriptclass.String() if typeString != test.stringed { t.Errorf("%s: got \"%s\" expected \"%s\"", test.name, @@ -2948,6 +2974,8 @@ func (b *bogusAddress) String() string { } func TestPayToAddrScript(t *testing.T) { + t.Parallel() + // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX p2pkhMain, err := btcutil.NewAddressPubKeyHash([]byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, @@ -3102,6 +3130,8 @@ func TestPayToAddrScript(t *testing.T) { } func TestMultiSigScript(t *testing.T) { + t.Parallel() + // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg p2pkCompressedMain, err := btcutil.NewAddressPubKey([]byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, @@ -3322,6 +3352,8 @@ func mkGetScript(scripts map[string][]byte) btcscript.ScriptDB { } func TestSignTxOutput(t *testing.T) { + t.Parallel() + // make key // make script based on key. // sign with magic pixie dust. @@ -4614,6 +4646,8 @@ func TestSignTxOutput(t *testing.T) { } func TestCalcMultiSigStats(t *testing.T) { + t.Parallel() + tests := []struct { name string script []byte @@ -4691,6 +4725,8 @@ func TestCalcMultiSigStats(t *testing.T) { } func TestHasCanonicalPushes(t *testing.T) { + t.Parallel() + tests := []struct { name string script []byte @@ -4723,6 +4759,8 @@ func TestHasCanonicalPushes(t *testing.T) { } func TestIsPushOnlyScript(t *testing.T) { + t.Parallel() + test := struct { name string script []byte diff --git a/stack_test.go b/stack_test.go index df58c28f..0da1f1d6 100644 --- a/stack_test.go +++ b/stack_test.go @@ -14,992 +14,992 @@ import ( "github.com/btcsuite/btcscript" ) -type stackTest struct { - name string - before [][]byte - operation func(*btcscript.Stack) error - expectedReturn error - after [][]byte -} - -var stackTests = []stackTest{ - { - "noop", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - return nil - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {5}}, - }, - { - "peek underflow (byte)", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - _, err := stack.PeekByteArray(5) - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "peek underflow (int)", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - _, err := stack.PeekInt(5) - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "peek underflow (bool)", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - _, err := stack.PeekBool(5) - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "pop", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopByteArray() - if err != nil { - return err - } - if !bytes.Equal(val, []byte{5}) { - return errors.New("not equal!") - } - return err - }, - nil, - [][]byte{{1}, {2}, {3}, {4}}, - }, - { - "pop", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopByteArray() - if err != nil { - return err - } - if !bytes.Equal(val, []byte{5}) { - return errors.New("not equal!") - } - return err - }, - nil, - [][]byte{{1}, {2}, {3}, {4}}, - }, - { - "pop everything", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - for i := 0; i < 5; i++ { - _, err := stack.PopByteArray() - if err != nil { - return err - } - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop underflow", - [][]byte{{1}, {2}, {3}, {4}, {5}}, - func(stack *btcscript.Stack) error { - for i := 0; i < 6; i++ { - _, err := stack.PopByteArray() - if err != nil { - return err - } - } - return nil - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "pop bool", - [][]byte{{0}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopBool() - if err != nil { - return err - } - - if val != false { - return errors.New("unexpected value") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop bool", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - val, err := stack.PopBool() - if err != nil { - return err - } - - if val != true { - return errors.New("unexpected value") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop bool", - [][]byte{}, - func(stack *btcscript.Stack) error { - _, err := stack.PopBool() - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "popInt 0", - [][]byte{{0x0}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Sign() != 0 { - return errors.New("0 != 0 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt -0", - [][]byte{{0x80}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Sign() != 0 { - return errors.New("-0 != 0 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt 1", - [][]byte{{0x01}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(1)) != 0 { - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt 1 leading 0", - [][]byte{{0x01, 0x00, 0x00, 0x00}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(1)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(1)) - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt -1", - [][]byte{{0x81}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(-1)) != 0 { - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "popInt -1 leading 0", - [][]byte{{0x01, 0x00, 0x00, 0x80}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(-1)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(-1)) - return errors.New("-1 != -1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - // Triggers the multibyte case in asInt - { - "popInt -513", - [][]byte{{0x1, 0x82}}, - func(stack *btcscript.Stack) error { - v, err := stack.PopInt() - if err != nil { - return err - } - if v.Cmp(big.NewInt(-513)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(-513)) - return errors.New("1 != 1 on popInt") - } - return nil - }, - nil, - [][]byte{}, - }, - // Confirm that the asInt code doesn't modify the base data. - { - "peekint nomodify -1", - [][]byte{{0x01, 0x00, 0x00, 0x80}}, - func(stack *btcscript.Stack) error { - v, err := stack.PeekInt(0) - if err != nil { - return err - } - if v.Cmp(big.NewInt(-1)) != 0 { - fmt.Printf("%v != %v\n", v, big.NewInt(-1)) - return errors.New("-1 != -1 on popInt") - } - return nil - }, - nil, - [][]byte{{0x01, 0x00, 0x00, 0x80}}, - }, - { - "PushInt 0", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(0)) - return nil - }, - nil, - [][]byte{{}}, - }, - { - "PushInt 1", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(1)) - return nil - }, - nil, - [][]byte{{0x1}}, - }, - { - "PushInt -1", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(-1)) - return nil - }, - nil, - [][]byte{{0x81}}, - }, - { - "PushInt two bytes", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(256)) - return nil - }, - nil, - // little endian.. *sigh* - [][]byte{{0x00, 0x01}}, - }, - { - "PushInt leading zeros", - [][]byte{}, - func(stack *btcscript.Stack) error { - // this will have the highbit set - stack.PushInt(big.NewInt(128)) - return nil - }, - nil, - [][]byte{{0x80, 0x00}}, - }, - { - "dup", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(1) - if err != nil { - return err - } - - return nil - }, - nil, - [][]byte{{1}, {1}}, - }, - { - "dup2", - [][]byte{{1}, {2}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(2) - if err != nil { - return err - } - - return nil - }, - nil, - [][]byte{{1}, {2}, {1}, {2}}, - }, - { - "dup3", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(3) - if err != nil { - return err - } - - return nil - }, - nil, - [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, - }, - { - "dup0", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(0) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "dup-1", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(-1) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "dup too much", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(2) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "dup-1", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - err := stack.DupN(-1) - if err != nil { - return err - } - - return nil - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "PushBool true", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(true) - - return nil - }, - nil, - [][]byte{{1}}, - }, - { - "PushBool false", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(false) - - return nil - }, - nil, - [][]byte{{0}}, - }, - { - "PushBool PopBool", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(true) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != true { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushBool PopBool 2", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushBool(false) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != false { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushInt PopBool", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(1)) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != true { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushInt PopBool 2", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(0)) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != false { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "PushInt PopBool 2", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(0)) - val, err := stack.PopBool() - if err != nil { - return err - } - if val != false { - return errors.New("unexpected value") - } - - return nil - }, - nil, - [][]byte{}, - }, - { - "Nip top", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.NipN(0) - }, - nil, - [][]byte{{1}, {2}}, - }, - { - "Nip middle", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.NipN(1) - }, - nil, - [][]byte{{1}, {3}}, - }, - { - "Nip low", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.NipN(2) - }, - nil, - [][]byte{{2}, {3}}, - }, - { - "Nip too much", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - // bite off more than we can chew - return stack.NipN(3) - }, - btcscript.ErrStackUnderflow, - [][]byte{{2}, {3}}, - }, - { - "Nip too much", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - // bite off more than we can chew - return stack.NipN(3) - }, - btcscript.ErrStackUnderflow, - [][]byte{{2}, {3}}, - }, - { - "keep on tucking", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.Tuck() - }, - nil, - [][]byte{{1}, {3}, {2}, {3}}, - }, - { - "a little tucked up", - [][]byte{{1}}, // too few arguments for tuck - func(stack *btcscript.Stack) error { - return stack.Tuck() - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "all tucked up", - [][]byte{}, // too few arguments for tuck - func(stack *btcscript.Stack) error { - return stack.Tuck() - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "drop 1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(1) - }, - nil, - [][]byte{{1}, {2}, {3}}, - }, - { - "drop 2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(2) - }, - nil, - [][]byte{{1}, {2}}, - }, - { - "drop 3", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(3) - }, - nil, - [][]byte{{1}}, - }, - { - "drop 4", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(4) - }, - nil, - [][]byte{}, - }, - { - "drop 4/5", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(5) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "drop invalid", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.DropN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Rot1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.RotN(1) - }, - nil, - [][]byte{{1}, {3}, {4}, {2}}, - }, - { - "Rot2", - [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, - func(stack *btcscript.Stack) error { - return stack.RotN(2) - }, - nil, - [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, - }, - { - "Rot too little", - [][]byte{{1}, {2}}, - func(stack *btcscript.Stack) error { - return stack.RotN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Rot0", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.RotN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Swap1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(1) - }, - nil, - [][]byte{{1}, {2}, {4}, {3}}, - }, - { - "Swap2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(2) - }, - nil, - [][]byte{{3}, {4}, {1}, {2}}, - }, - { - "Swap too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Swap0", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.SwapN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Over1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.OverN(1) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {3}}, - }, - { - "Over2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.OverN(2) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, - }, - { - "Over too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.OverN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Over0", - [][]byte{{1}, {2}, {3}}, - func(stack *btcscript.Stack) error { - return stack.OverN(0) - }, - btcscript.ErrStackInvalidArgs, - [][]byte{}, - }, - { - "Pick1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.PickN(1) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {3}}, - }, - { - "Pick2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.PickN(2) - }, - nil, - [][]byte{{1}, {2}, {3}, {4}, {2}}, - }, - { - "Pick too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.PickN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Roll1", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.RollN(1) - }, - nil, - [][]byte{{1}, {2}, {4}, {3}}, - }, - { - "Roll2", - [][]byte{{1}, {2}, {3}, {4}}, - func(stack *btcscript.Stack) error { - return stack.RollN(2) - }, - nil, - [][]byte{{1}, {3}, {4}, {2}}, - }, - { - "Roll too little", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - return stack.RollN(1) - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, - { - "Peek bool", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - // Peek bool is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekBool(0) - if err != nil { - return err - } - if val != true { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{1}}, - }, - { - "Peek bool 2", - [][]byte{{0}}, - func(stack *btcscript.Stack) error { - // Peek bool is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekBool(0) - if err != nil { - return err - } - if val != false { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{0}}, - }, - { - "Peek int", - [][]byte{{1}}, - func(stack *btcscript.Stack) error { - // Peek int is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekInt(0) - if err != nil { - return err - } - if val.Cmp(big.NewInt(1)) != 0 { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{1}}, - }, - { - "Peek int 2", - [][]byte{{0}}, - func(stack *btcscript.Stack) error { - // Peek int is otherwise pretty well tested, just check - // it works. - val, err := stack.PeekInt(0) - if err != nil { - return err - } - if val.Cmp(big.NewInt(0)) != 0 { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{{0}}, - }, - { - "pop int", - [][]byte{}, - func(stack *btcscript.Stack) error { - stack.PushInt(big.NewInt(1)) - // Peek int is otherwise pretty well tested, just check - // it works. - val, err := stack.PopInt() - if err != nil { - return err - } - if val.Cmp(big.NewInt(1)) != 0 { - return errors.New("invalid result") - } - return nil - }, - nil, - [][]byte{}, - }, - { - "pop empty", - [][]byte{}, - func(stack *btcscript.Stack) error { - // Peek int is otherwise pretty well tested, just check - // it works. - _, err := stack.PopInt() - return err - }, - btcscript.ErrStackUnderflow, - [][]byte{}, - }, -} - -func doTest(t *testing.T, test stackTest) { - stack := btcscript.Stack{} - - for i := range test.before { - stack.PushByteArray(test.before[i]) - } - err := test.operation(&stack) - if err != test.expectedReturn { - t.Errorf("%s: operation return not what expected: %v vs %v", - test.name, err, test.expectedReturn) - } - if err != nil { - return - } - if len(test.after) != stack.Depth() { - t.Errorf("%s: stack depth doesn't match expected: %v vs %v", - test.name, len(test.after), stack.Depth()) - } - for i := range test.after { - val, err := stack.PeekByteArray(stack.Depth() - i - 1) - if err != nil { - t.Errorf("%s: can't peek %dth stack entry: %v", - test.name, i, err) - break - } - - if !bytes.Equal(val, test.after[i]) { - t.Errorf("%s: %dth stack entry doesn't match "+ - "expected: %v vs %v", test.name, i, val, - test.after[i]) - break - } - } -} - +// TestStack tests that all of the stack operations work as expected. func TestStack(t *testing.T) { - for i := range stackTests { - doTest(t, stackTests[i]) + t.Parallel() + + tests := []struct { + name string + before [][]byte + operation func(*btcscript.Stack) error + expectedReturn error + after [][]byte + }{ + { + "noop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + return nil + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {5}}, + }, + { + "peek underflow (byte)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekByteArray(5) + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "peek underflow (int)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekInt(5) + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "peek underflow (bool)", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + _, err := stack.PeekBool(5) + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "pop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopByteArray() + if err != nil { + return err + } + if !bytes.Equal(val, []byte{5}) { + return errors.New("not equal!") + } + return err + }, + nil, + [][]byte{{1}, {2}, {3}, {4}}, + }, + { + "pop", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopByteArray() + if err != nil { + return err + } + if !bytes.Equal(val, []byte{5}) { + return errors.New("not equal!") + } + return err + }, + nil, + [][]byte{{1}, {2}, {3}, {4}}, + }, + { + "pop everything", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + for i := 0; i < 5; i++ { + _, err := stack.PopByteArray() + if err != nil { + return err + } + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop underflow", + [][]byte{{1}, {2}, {3}, {4}, {5}}, + func(stack *btcscript.Stack) error { + for i := 0; i < 6; i++ { + _, err := stack.PopByteArray() + if err != nil { + return err + } + } + return nil + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "pop bool", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopBool() + if err != nil { + return err + } + + if val != false { + return errors.New("unexpected value") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop bool", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + val, err := stack.PopBool() + if err != nil { + return err + } + + if val != true { + return errors.New("unexpected value") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop bool", + [][]byte{}, + func(stack *btcscript.Stack) error { + _, err := stack.PopBool() + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "popInt 0", + [][]byte{{0x0}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Sign() != 0 { + return errors.New("0 != 0 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -0", + [][]byte{{0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Sign() != 0 { + return errors.New("-0 != 0 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt 1", + [][]byte{{0x01}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt 1 leading 0", + [][]byte{{0x01, 0x00, 0x00, 0x00}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(1)) + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -1", + [][]byte{{0x81}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "popInt -1 leading 0", + [][]byte{{0x01, 0x00, 0x00, 0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-1)) + return errors.New("-1 != -1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + // Triggers the multibyte case in asInt + { + "popInt -513", + [][]byte{{0x1, 0x82}}, + func(stack *btcscript.Stack) error { + v, err := stack.PopInt() + if err != nil { + return err + } + if v.Cmp(big.NewInt(-513)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-513)) + return errors.New("1 != 1 on popInt") + } + return nil + }, + nil, + [][]byte{}, + }, + // Confirm that the asInt code doesn't modify the base data. + { + "peekint nomodify -1", + [][]byte{{0x01, 0x00, 0x00, 0x80}}, + func(stack *btcscript.Stack) error { + v, err := stack.PeekInt(0) + if err != nil { + return err + } + if v.Cmp(big.NewInt(-1)) != 0 { + fmt.Printf("%v != %v\n", v, big.NewInt(-1)) + return errors.New("-1 != -1 on popInt") + } + return nil + }, + nil, + [][]byte{{0x01, 0x00, 0x00, 0x80}}, + }, + { + "PushInt 0", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + return nil + }, + nil, + [][]byte{{}}, + }, + { + "PushInt 1", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + return nil + }, + nil, + [][]byte{{0x1}}, + }, + { + "PushInt -1", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(-1)) + return nil + }, + nil, + [][]byte{{0x81}}, + }, + { + "PushInt two bytes", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(256)) + return nil + }, + nil, + // little endian.. *sigh* + [][]byte{{0x00, 0x01}}, + }, + { + "PushInt leading zeros", + [][]byte{}, + func(stack *btcscript.Stack) error { + // this will have the highbit set + stack.PushInt(big.NewInt(128)) + return nil + }, + nil, + [][]byte{{0x80, 0x00}}, + }, + { + "dup", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(1) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {1}}, + }, + { + "dup2", + [][]byte{{1}, {2}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(2) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {2}, {1}, {2}}, + }, + { + "dup3", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(3) + if err != nil { + return err + } + + return nil + }, + nil, + [][]byte{{1}, {2}, {3}, {1}, {2}, {3}}, + }, + { + "dup0", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(0) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "dup-1", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(-1) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "dup too much", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(2) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "dup-1", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + err := stack.DupN(-1) + if err != nil { + return err + } + + return nil + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "PushBool true", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(true) + + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "PushBool false", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(false) + + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "PushBool PopBool", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(true) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != true { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushBool PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushBool(false) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != true { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "PushInt PopBool 2", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(0)) + val, err := stack.PopBool() + if err != nil { + return err + } + if val != false { + return errors.New("unexpected value") + } + + return nil + }, + nil, + [][]byte{}, + }, + { + "Nip top", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(0) + }, + nil, + [][]byte{{1}, {2}}, + }, + { + "Nip middle", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(1) + }, + nil, + [][]byte{{1}, {3}}, + }, + { + "Nip low", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.NipN(2) + }, + nil, + [][]byte{{2}, {3}}, + }, + { + "Nip too much", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + // bite off more than we can chew + return stack.NipN(3) + }, + btcscript.ErrStackUnderflow, + [][]byte{{2}, {3}}, + }, + { + "Nip too much", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + // bite off more than we can chew + return stack.NipN(3) + }, + btcscript.ErrStackUnderflow, + [][]byte{{2}, {3}}, + }, + { + "keep on tucking", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + nil, + [][]byte{{1}, {3}, {2}, {3}}, + }, + { + "a little tucked up", + [][]byte{{1}}, // too few arguments for tuck + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "all tucked up", + [][]byte{}, // too few arguments for tuck + func(stack *btcscript.Stack) error { + return stack.Tuck() + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "drop 1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(1) + }, + nil, + [][]byte{{1}, {2}, {3}}, + }, + { + "drop 2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(2) + }, + nil, + [][]byte{{1}, {2}}, + }, + { + "drop 3", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(3) + }, + nil, + [][]byte{{1}}, + }, + { + "drop 4", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(4) + }, + nil, + [][]byte{}, + }, + { + "drop 4/5", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(5) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "drop invalid", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.DropN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Rot1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RotN(1) + }, + nil, + [][]byte{{1}, {3}, {4}, {2}}, + }, + { + "Rot2", + [][]byte{{1}, {2}, {3}, {4}, {5}, {6}}, + func(stack *btcscript.Stack) error { + return stack.RotN(2) + }, + nil, + [][]byte{{3}, {4}, {5}, {6}, {1}, {2}}, + }, + { + "Rot too little", + [][]byte{{1}, {2}}, + func(stack *btcscript.Stack) error { + return stack.RotN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Rot0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.RotN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Swap1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(1) + }, + nil, + [][]byte{{1}, {2}, {4}, {3}}, + }, + { + "Swap2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(2) + }, + nil, + [][]byte{{3}, {4}, {1}, {2}}, + }, + { + "Swap too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Swap0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.SwapN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Over1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.OverN(1) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {3}}, + }, + { + "Over2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.OverN(2) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {1}, {2}}, + }, + { + "Over too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.OverN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Over0", + [][]byte{{1}, {2}, {3}}, + func(stack *btcscript.Stack) error { + return stack.OverN(0) + }, + btcscript.ErrStackInvalidArgs, + [][]byte{}, + }, + { + "Pick1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.PickN(1) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {3}}, + }, + { + "Pick2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.PickN(2) + }, + nil, + [][]byte{{1}, {2}, {3}, {4}, {2}}, + }, + { + "Pick too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.PickN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Roll1", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RollN(1) + }, + nil, + [][]byte{{1}, {2}, {4}, {3}}, + }, + { + "Roll2", + [][]byte{{1}, {2}, {3}, {4}}, + func(stack *btcscript.Stack) error { + return stack.RollN(2) + }, + nil, + [][]byte{{1}, {3}, {4}, {2}}, + }, + { + "Roll too little", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + return stack.RollN(1) + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + { + "Peek bool", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + // Peek bool is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekBool(0) + if err != nil { + return err + } + if val != true { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "Peek bool 2", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + // Peek bool is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekBool(0) + if err != nil { + return err + } + if val != false { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "Peek int", + [][]byte{{1}}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekInt(0) + if err != nil { + return err + } + if val.Cmp(big.NewInt(1)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{1}}, + }, + { + "Peek int 2", + [][]byte{{0}}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, + // just check it works. + val, err := stack.PeekInt(0) + if err != nil { + return err + } + if val.Cmp(big.NewInt(0)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{{0}}, + }, + { + "pop int", + [][]byte{}, + func(stack *btcscript.Stack) error { + stack.PushInt(big.NewInt(1)) + // Peek int is otherwise pretty well tested, + // just check it works. + val, err := stack.PopInt() + if err != nil { + return err + } + if val.Cmp(big.NewInt(1)) != 0 { + return errors.New("invalid result") + } + return nil + }, + nil, + [][]byte{}, + }, + { + "pop empty", + [][]byte{}, + func(stack *btcscript.Stack) error { + // Peek int is otherwise pretty well tested, + // just check it works. + _, err := stack.PopInt() + return err + }, + btcscript.ErrStackUnderflow, + [][]byte{}, + }, + } + + for _, test := range tests { + stack := btcscript.Stack{} + + for i := range test.before { + stack.PushByteArray(test.before[i]) + } + err := test.operation(&stack) + if err != test.expectedReturn { + t.Errorf("%s: operation return not what expected: %v "+ + "vs %v", test.name, err, test.expectedReturn) + } + if err != nil { + continue + } + + if len(test.after) != stack.Depth() { + t.Errorf("%s: stack depth doesn't match expected: %v "+ + "vs %v", test.name, len(test.after), + stack.Depth()) + } + + for i := range test.after { + val, err := stack.PeekByteArray(stack.Depth() - i - 1) + if err != nil { + t.Errorf("%s: can't peek %dth stack entry: %v", + test.name, i, err) + break + } + + if !bytes.Equal(val, test.after[i]) { + t.Errorf("%s: %dth stack entry doesn't match "+ + "expected: %v vs %v", test.name, i, val, + test.after[i]) + break + } + } } }