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 + } + } } }