From a2bd68f456bcbb126ce5f467c0ed2f0ea79cfebf Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 26 Feb 2014 16:31:49 -0300 Subject: [PATCH 1/8] add bitcoin/bitcoin test data --- test/data/base58_encode_decode.json | 14 + test/data/script_invalid.json | 329 ++++++++++++++++++++++ test/data/script_valid.json | 415 ++++++++++++++++++++++++++++ test/data/sig_canonical.json | 7 + test/data/sig_noncanonical.json | 22 ++ test/data/tx_invalid.json | 80 ++++++ test/data/tx_valid.json | 122 ++++++++ 7 files changed, 989 insertions(+) create mode 100644 test/data/base58_encode_decode.json create mode 100644 test/data/script_invalid.json create mode 100644 test/data/script_valid.json create mode 100644 test/data/sig_canonical.json create mode 100644 test/data/sig_noncanonical.json create mode 100644 test/data/tx_invalid.json create mode 100644 test/data/tx_valid.json diff --git a/test/data/base58_encode_decode.json b/test/data/base58_encode_decode.json new file mode 100644 index 0000000..9448f25 --- /dev/null +++ b/test/data/base58_encode_decode.json @@ -0,0 +1,14 @@ +[ +["", ""], +["61", "2g"], +["626262", "a3gV"], +["636363", "aPEr"], +["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"], +["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"], +["516b6fcd0f", "ABnLTmg"], +["bf4f89001e670274dd", "3SEo3LWLoPntC"], +["572e4794", "3EFU7m"], +["ecac89cad93923c02321", "EJDM8drfXA6uyA"], +["10c8511e", "Rt5zm"], +["00000000000000000000", "1111111111"] +] diff --git a/test/data/script_invalid.json b/test/data/script_invalid.json new file mode 100644 index 0000000..761cc4a --- /dev/null +++ b/test/data/script_invalid.json @@ -0,0 +1,329 @@ +[ +["", ""], +["", "NOP"], +["NOP", ""], +["NOP","NOP"], + +["0x4c01","0x01 NOP", "PUSHDATA1 with not enough bytes"], +["0x4d0200ff","0x01 NOP", "PUSHDATA2 with not enough bytes"], +["0x4e03000000ffff","0x01 NOP", "PUSHDATA4 with not enough bytes"], + +["1", "IF 0x50 ENDIF 1", "0x50 is reserved"], +["0x52", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], +["0","NOP"], +["1", "IF VER ELSE 1 ENDIF", "VER non-functional"], +["0", "IF VERIF ELSE 1 ENDIF", "VERIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERIF ENDIF", "VERIF illegal everywhere"], +["0", "IF VERNOTIF ELSE 1 ENDIF", "VERNOTIF illegal everywhere"], +["0", "IF ELSE 1 ELSE VERNOTIF ENDIF", "VERNOTIF illegal everywhere"], + +["1 IF", "1 ENDIF", "IF/ENDIF can't span scriptSig/scriptPubKey"], +["1 IF 0 ENDIF", "1 ENDIF"], +["1 ELSE 0 ENDIF", "1"], +["0 NOTIF", "123"], + +["0", "DUP IF ENDIF"], +["0", "IF 1 ENDIF"], +["0", "DUP IF ELSE ENDIF"], +["0", "IF 1 ELSE ENDIF"], +["0", "NOTIF ELSE 1 ENDIF"], + +["0 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["0 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1", "IF RETURN ELSE ELSE 1 ENDIF", "Multiple ELSEs"], +["1", "IF 1 ELSE ELSE RETURN ENDIF"], + +["1", "ENDIF", "Malformed IF/ELSE/ENDIF sequence"], +["1", "ELSE ENDIF"], +["1", "ENDIF ELSE"], +["1", "ENDIF ELSE IF"], +["1", "IF ELSE ENDIF ELSE"], +["1", "IF ELSE ENDIF ELSE ENDIF"], +["1", "IF ENDIF ENDIF"], +["1", "IF ELSE ELSE ENDIF ENDIF"], + +["1", "RETURN"], +["1", "DUP IF RETURN ENDIF"], + +["1", "RETURN 'data'", "canonical prunable txout format"], +["0 IF", "RETURN ENDIF 1", "still prunable because IF/ENDIF can't span scriptSig/scriptPubKey"], + +["0", "VERIFY 1"], +["1", "VERIFY"], +["1", "VERIFY 0"], + +["1 TOALTSTACK", "FROMALTSTACK 1", "alt stack not shared between sig/pubkey"], + +["IFDUP", "DEPTH 0 EQUAL"], +["DROP", "DEPTH 0 EQUAL"], +["DUP", "DEPTH 0 EQUAL"], +["1", "DUP 1 ADD 2 EQUALVERIFY 0 EQUAL"], +["NOP", "NIP"], +["NOP", "1 NIP"], +["NOP", "1 0 NIP"], +["NOP", "OVER 1"], +["1", "OVER"], +["0 1", "OVER DEPTH 3 EQUALVERIFY"], +["19 20 21", "PICK 19 EQUALVERIFY DEPTH 2 EQUAL"], +["NOP", "0 PICK"], +["1", "-1 PICK"], +["19 20 21", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], +["19 20 21", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], +["19 20 21", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], +["NOP", "0 ROLL"], +["1", "-1 ROLL"], +["19 20 21", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], +["19 20 21", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], +["19 20 21", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], +["NOP", "ROT 1"], +["NOP", "1 ROT 1"], +["NOP", "1 2 ROT 1"], +["NOP", "0 1 2 ROT"], +["NOP", "SWAP 1"], +["1", "SWAP 1"], +["0 1", "SWAP 1 EQUALVERIFY"], +["NOP", "TUCK 1"], +["1", "TUCK 1"], +["1 0", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], +["NOP", "2DUP 1"], +["1", "2DUP 1"], +["NOP", "3DUP 1"], +["1", "3DUP 1"], +["1 2", "3DUP 1"], +["NOP", "2OVER 1"], +["1", "2 3 2OVER 1"], +["NOP", "2SWAP 1"], +["1", "2 3 2SWAP 1"], + +["'a' 'b'", "CAT", "CAT disabled"], +["'a' 'b' 0", "IF CAT ELSE 1 ENDIF", "CAT disabled"], +["'abc' 1 1", "SUBSTR", "SUBSTR disabled"], +["'abc' 1 1 0", "IF SUBSTR ELSE 1 ENDIF", "SUBSTR disabled"], +["'abc' 2 0", "IF LEFT ELSE 1 ENDIF", "LEFT disabled"], +["'abc' 2 0", "IF RIGHT ELSE 1 ENDIF", "RIGHT disabled"], + +["NOP", "SIZE 1"], + +["'abc'", "IF INVERT ELSE 1 ENDIF", "INVERT disabled"], +["1 2 0 IF AND ELSE 1 ENDIF", "NOP", "AND disabled"], +["1 2 0 IF OR ELSE 1 ENDIF", "NOP", "OR disabled"], +["1 2 0 IF XOR ELSE 1 ENDIF", "NOP", "XOR disabled"], +["2 0 IF 2MUL ELSE 1 ENDIF", "NOP", "2MUL disabled"], +["2 0 IF 2DIV ELSE 1 ENDIF", "NOP", "2DIV disabled"], +["2 2 0 IF MUL ELSE 1 ENDIF", "NOP", "MUL disabled"], +["2 2 0 IF DIV ELSE 1 ENDIF", "NOP", "DIV disabled"], +["2 2 0 IF MOD ELSE 1 ENDIF", "NOP", "MOD disabled"], +["2 2 0 IF LSHIFT ELSE 1 ENDIF", "NOP", "LSHIFT disabled"], +["2 2 0 IF RSHIFT ELSE 1 ENDIF", "NOP", "RSHIFT disabled"], + +["0 1","EQUAL"], +["1 1 ADD", "0 EQUAL"], +["11 1 ADD 12 SUB", "11 EQUAL"], + +["2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], +["-2147483648 0 ADD", "NOP", "arithmetic operands must be in range [-2^31...2^31] "], +["2147483647 DUP ADD", "4294967294 NUMEQUAL", "NUMEQUAL must be in numeric range"], +["'abcdef' NOT", "0 EQUAL", "NOT is an arithmetic operand"], + +["2 DUP MUL", "4 EQUAL", "disabled"], +["2 DUP DIV", "1 EQUAL", "disabled"], +["2 2MUL", "4 EQUAL", "disabled"], +["2 2DIV", "1 EQUAL", "disabled"], +["7 3 MOD", "1 EQUAL", "disabled"], +["2 2 LSHIFT", "8 EQUAL", "disabled"], +["2 1 RSHIFT", "1 EQUAL", "disabled"], + +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 2 EQUAL"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_11' EQUAL"], + +["0x50","1", "opcode 0x50 is reserved"], +["1", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], +["1", "IF 0xbb ELSE 1 ENDIF"], +["1", "IF 0xbc ELSE 1 ENDIF"], +["1", "IF 0xbd ELSE 1 ENDIF"], +["1", "IF 0xbe ELSE 1 ENDIF"], +["1", "IF 0xbf ELSE 1 ENDIF"], +["1", "IF 0xc0 ELSE 1 ENDIF"], +["1", "IF 0xc1 ELSE 1 ENDIF"], +["1", "IF 0xc2 ELSE 1 ENDIF"], +["1", "IF 0xc3 ELSE 1 ENDIF"], +["1", "IF 0xc4 ELSE 1 ENDIF"], +["1", "IF 0xc5 ELSE 1 ENDIF"], +["1", "IF 0xc6 ELSE 1 ENDIF"], +["1", "IF 0xc7 ELSE 1 ENDIF"], +["1", "IF 0xc8 ELSE 1 ENDIF"], +["1", "IF 0xc9 ELSE 1 ENDIF"], +["1", "IF 0xca ELSE 1 ENDIF"], +["1", "IF 0xcb ELSE 1 ENDIF"], +["1", "IF 0xcc ELSE 1 ENDIF"], +["1", "IF 0xcd ELSE 1 ENDIF"], +["1", "IF 0xce ELSE 1 ENDIF"], +["1", "IF 0xcf ELSE 1 ENDIF"], +["1", "IF 0xd0 ELSE 1 ENDIF"], +["1", "IF 0xd1 ELSE 1 ENDIF"], +["1", "IF 0xd2 ELSE 1 ENDIF"], +["1", "IF 0xd3 ELSE 1 ENDIF"], +["1", "IF 0xd4 ELSE 1 ENDIF"], +["1", "IF 0xd5 ELSE 1 ENDIF"], +["1", "IF 0xd6 ELSE 1 ENDIF"], +["1", "IF 0xd7 ELSE 1 ENDIF"], +["1", "IF 0xd8 ELSE 1 ENDIF"], +["1", "IF 0xd9 ELSE 1 ENDIF"], +["1", "IF 0xda ELSE 1 ENDIF"], +["1", "IF 0xdb ELSE 1 ENDIF"], +["1", "IF 0xdc ELSE 1 ENDIF"], +["1", "IF 0xdd ELSE 1 ENDIF"], +["1", "IF 0xde ELSE 1 ENDIF"], +["1", "IF 0xdf ELSE 1 ENDIF"], +["1", "IF 0xe0 ELSE 1 ENDIF"], +["1", "IF 0xe1 ELSE 1 ENDIF"], +["1", "IF 0xe2 ELSE 1 ENDIF"], +["1", "IF 0xe3 ELSE 1 ENDIF"], +["1", "IF 0xe4 ELSE 1 ENDIF"], +["1", "IF 0xe5 ELSE 1 ENDIF"], +["1", "IF 0xe6 ELSE 1 ENDIF"], +["1", "IF 0xe7 ELSE 1 ENDIF"], +["1", "IF 0xe8 ELSE 1 ENDIF"], +["1", "IF 0xe9 ELSE 1 ENDIF"], +["1", "IF 0xea ELSE 1 ENDIF"], +["1", "IF 0xeb ELSE 1 ENDIF"], +["1", "IF 0xec ELSE 1 ENDIF"], +["1", "IF 0xed ELSE 1 ENDIF"], +["1", "IF 0xee ELSE 1 ENDIF"], +["1", "IF 0xef ELSE 1 ENDIF"], +["1", "IF 0xf0 ELSE 1 ENDIF"], +["1", "IF 0xf1 ELSE 1 ENDIF"], +["1", "IF 0xf2 ELSE 1 ENDIF"], +["1", "IF 0xf3 ELSE 1 ENDIF"], +["1", "IF 0xf4 ELSE 1 ENDIF"], +["1", "IF 0xf5 ELSE 1 ENDIF"], +["1", "IF 0xf6 ELSE 1 ENDIF"], +["1", "IF 0xf7 ELSE 1 ENDIF"], +["1", "IF 0xf8 ELSE 1 ENDIF"], +["1", "IF 0xf9 ELSE 1 ENDIF"], +["1", "IF 0xfa ELSE 1 ENDIF"], +["1", "IF 0xfb ELSE 1 ENDIF"], +["1", "IF 0xfc ELSE 1 ENDIF"], +["1", "IF 0xfd ELSE 1 ENDIF"], +["1", "IF 0xfe ELSE 1 ENDIF"], +["1", "IF 0xff ELSE 1 ENDIF"], + +["1 IF 1 ELSE", "0xff ENDIF", "invalid because scriptSig and scriptPubKey are processed separately"], + +["NOP", "RIPEMD160"], +["NOP", "SHA1"], +["NOP", "SHA256"], +["NOP", "HASH160"], +["NOP", "HASH256"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +">520 byte push"], +["0", +"IF 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' ENDIF 1", +">520 byte push in non-executed IF branch"], +["1", +"0x61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +">201 opcodes executed. 0x61 is NOP"], +["0", +"IF 0x6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 ENDIF 1", +">201 opcodes including non-executed IF branch. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +">1,000 stack size (0x6f is 3DUP)"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 TOALTSTACK 2 TOALTSTACK 3 4 5 6 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +">1,000 stack+altstack size"], +["NOP", +"0 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"10,001-byte scriptPubKey"], + +["NOP1","NOP10"], + +["1","VER", "OP_VER is reserved"], +["1","VERIF", "OP_VERIF is reserved"], +["1","VERNOTIF", "OP_VERNOTIF is reserved"], +["1","RESERVED", "OP_RESERVED is reserved"], +["1","RESERVED1", "OP_RESERVED1 is reserved"], +["1","RESERVED2", "OP_RESERVED2 is reserved"], +["1","0xba", "0xba == OP_NOP10 + 1"], + +["2147483648", "1ADD 1", "We cannot do math on 5-byte integers"], +["-2147483648", "1ADD 1", "Because we use a sign bit, -2147483648 is also 5 bytes"], + +["1", "1 ENDIF", "ENDIF without IF"], +["1", "IF 1", "IF without ENDIF"], +["1 IF 1", "ENDIF", "IFs don't carry over"], + +["NOP", "IF 1 ENDIF", "The following tests check the if(stack.size() < N) tests in each opcode"], +["NOP", "NOTIF 1 ENDIF", "They are here to catch copy-and-paste errors"], +["NOP", "VERIFY 1", "Most of them are duplicated elsewhere,"], + +["NOP", "TOALTSTACK 1", "but, hey, more is always better, right?"], +["1", "FROMALTSTACK"], +["1", "2DROP 1"], +["1", "2DUP"], +["1 1", "3DUP"], +["1 1 1", "2OVER"], +["1 1 1 1 1", "2ROT"], +["1 1 1", "2SWAP"], +["NOP", "IFDUP 1"], +["NOP", "DROP 1"], +["NOP", "DUP 1"], +["1", "NIP"], +["1", "OVER"], +["1 1 1 3", "PICK"], +["0", "PICK 1"], +["1 1 1 3", "ROLL"], +["0", "ROLL 1"], +["1 1", "ROT"], +["1", "SWAP"], +["1", "TUCK"], + +["NOP", "SIZE 1"], + +["1", "EQUAL 1"], +["1", "EQUALVERIFY 1"], + +["NOP", "1ADD 1"], +["NOP", "1SUB 1"], +["NOP", "NEGATE 1"], +["NOP", "ABS 1"], +["NOP", "NOT 1"], +["NOP", "0NOTEQUAL 1"], + +["1", "ADD"], +["1", "SUB"], +["1", "BOOLAND"], +["1", "BOOLOR"], +["1", "NUMEQUAL"], +["1", "NUMEQUALVERIFY 1"], +["1", "NUMNOTEQUAL"], +["1", "LESSTHAN"], +["1", "GREATERTHAN"], +["1", "LESSTHANOREQUAL"], +["1", "GREATERTHANOREQUAL"], +["1", "MIN"], +["1", "MAX"], +["1 1", "WITHIN"], + +["NOP", "RIPEMD160 1"], +["NOP", "SHA1 1"], +["NOP", "SHA256 1"], +["NOP", "HASH160 1"], +["NOP", "HASH256 1"], + +["NOP 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Tests for Script.IsPushOnly()"], +["NOP1 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], + +["0 0x01 0x50", "HASH160 0x14 0xece424a6bb6ddf4db592c0faed60685047a361b1 EQUAL", "OP_RESERVED in P2SH should fail"], +["0 0x01 VER", "HASH160 0x14 0x0f4d7845db968f2a81b530b6f3c1d6246d4c7e01 EQUAL", "OP_VER in P2SH should fail"] +] diff --git a/test/data/script_valid.json b/test/data/script_valid.json new file mode 100644 index 0000000..e4c181c --- /dev/null +++ b/test/data/script_valid.json @@ -0,0 +1,415 @@ +[ +["0x01 0x0b", "11 EQUAL", "push 1 byte"], +["0x02 0x417a", "'Az' EQUAL"], +["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", + "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "push 75 bytes"], + +["0x4c 0x01 0x07","7 EQUAL", "0x4c is OP_PUSHDATA1"], +["0x4d 0x0100 0x08","8 EQUAL", "0x4d is OP_PUSHDATA2"], +["0x4e 0x01000000 0x09","9 EQUAL", "0x4e is OP_PUSHDATA4"], + +["0x4c 0x00","0 EQUAL"], +["0x4d 0x0000","0 EQUAL"], +["0x4e 0x00000000","0 EQUAL"], +["0x4f 1000 ADD","999 EQUAL"], +["0", "IF 0x50 ENDIF 1", "0x50 is reserved (ok if not executed)"], +["0x51", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], +["1","NOP"], +["0", "IF VER ELSE 1 ENDIF", "VER non-functional (ok if not executed)"], +["0", "IF RESERVED RESERVED1 RESERVED2 ELSE 1 ENDIF", "RESERVED ok in un-executed IF"], + +["1", "DUP IF ENDIF"], +["1", "IF 1 ENDIF"], +["1", "DUP IF ELSE ENDIF"], +["1", "IF 1 ELSE ENDIF"], +["0", "IF ELSE 1 ENDIF"], + +["1 1", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "IF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 0", "IF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 1", "NOTIF IF 1 ELSE 0 ENDIF ENDIF"], +["1 0", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], +["0 1", "NOTIF IF 1 ELSE 0 ENDIF ELSE IF 0 ELSE 1 ENDIF ENDIF"], + +["0", "IF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and executed inverts on each ELSE encountered"], +["1", "IF 1 ELSE 0 ELSE ENDIF"], +["1", "IF ELSE 0 ELSE 1 ENDIF"], +["1", "IF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"], +["'' 1", "IF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL"], + +["1", "NOTIF 0 ELSE 1 ELSE 0 ENDIF", "Multiple ELSE's are valid and execution inverts on each ELSE encountered"], +["0", "NOTIF 1 ELSE 0 ELSE ENDIF"], +["0", "NOTIF ELSE 0 ELSE 1 ENDIF"], +["0", "NOTIF 1 ELSE 0 ELSE 1 ENDIF ADD 2 EQUAL"], +["'' 0", "NOTIF SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ELSE ELSE SHA1 ENDIF 0x14 0x68ca4fec736264c13b859bac43d5173df6871682 EQUAL"], + +["0", "IF 1 IF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 1 IF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL", "Nested ELSE ELSE"], +["1", "NOTIF 0 NOTIF RETURN ELSE RETURN ELSE RETURN ENDIF ELSE 0 NOTIF 1 ELSE RETURN ELSE 1 ENDIF ELSE RETURN ENDIF ADD 2 EQUAL"], + +["0", "IF RETURN ENDIF 1", "RETURN only works if executed"], + +["1 1", "VERIFY"], + +["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"], +["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"], + +["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL"], +["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL"], +["0 DROP", "DEPTH 0 EQUAL"], +["0", "DUP 1 ADD 1 EQUALVERIFY 0 EQUAL"], +["0 1", "NIP"], +["1 0", "OVER DEPTH 3 EQUALVERIFY"], +["22 21 20", "0 PICK 20 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "1 PICK 21 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "2 PICK 22 EQUALVERIFY DEPTH 3 EQUAL"], +["22 21 20", "0 ROLL 20 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "1 ROLL 21 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "2 ROLL 22 EQUALVERIFY DEPTH 2 EQUAL"], +["22 21 20", "ROT 22 EQUAL"], +["22 21 20", "ROT DROP 20 EQUAL"], +["22 21 20", "ROT DROP DROP 21 EQUAL"], +["22 21 20", "ROT ROT 21 EQUAL"], +["22 21 20", "ROT ROT ROT 20 EQUAL"], +["25 24 23 22 21 20", "2ROT 24 EQUAL"], +["25 24 23 22 21 20", "2ROT DROP 25 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 20 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP DROP 21 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP 22 EQUAL"], +["25 24 23 22 21 20", "2ROT 2DROP 2DROP DROP 23 EQUAL"], +["25 24 23 22 21 20", "2ROT 2ROT 22 EQUAL"], +["25 24 23 22 21 20", "2ROT 2ROT 2ROT 20 EQUAL"], +["1 0", "SWAP 1 EQUALVERIFY 0 EQUAL"], +["0 1", "TUCK DEPTH 3 EQUALVERIFY SWAP 2DROP"], +["13 14", "2DUP ROT EQUALVERIFY EQUAL"], +["-1 0 1 2", "3DUP DEPTH 7 EQUALVERIFY ADD ADD 3 EQUALVERIFY 2DROP 0 EQUALVERIFY"], +["1 2 3 5", "2OVER ADD ADD 8 EQUALVERIFY ADD ADD 6 EQUAL"], +["1 3 5 7", "2SWAP ADD 4 EQUALVERIFY ADD 12 EQUAL"], +["0", "SIZE 0 EQUAL"], +["1", "SIZE 1 EQUAL"], +["127", "SIZE 1 EQUAL"], +["128", "SIZE 2 EQUAL"], +["32767", "SIZE 2 EQUAL"], +["32768", "SIZE 3 EQUAL"], +["8388607", "SIZE 3 EQUAL"], +["8388608", "SIZE 4 EQUAL"], +["2147483647", "SIZE 4 EQUAL"], +["2147483648", "SIZE 5 EQUAL"], +["-1", "SIZE 1 EQUAL"], +["-127", "SIZE 1 EQUAL"], +["-128", "SIZE 2 EQUAL"], +["-32767", "SIZE 2 EQUAL"], +["-32768", "SIZE 3 EQUAL"], +["-8388607", "SIZE 3 EQUAL"], +["-8388608", "SIZE 4 EQUAL"], +["-2147483647", "SIZE 4 EQUAL"], +["-2147483648", "SIZE 5 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SIZE 26 EQUAL"], + + +["2 -2 ADD", "0 EQUAL"], +["2147483647 -2147483647 ADD", "0 EQUAL"], +["-1 -1 ADD", "-2 EQUAL"], + +["0 0","EQUAL"], +["1 1 ADD", "2 EQUAL"], +["1 1ADD", "2 EQUAL"], +["111 1SUB", "110 EQUAL"], +["111 1 ADD 12 SUB", "100 EQUAL"], +["0 ABS", "0 EQUAL"], +["16 ABS", "16 EQUAL"], +["-16 ABS", "-16 NEGATE EQUAL"], +["0 NOT", "NOP"], +["1 NOT", "0 EQUAL"], +["11 NOT", "0 EQUAL"], +["0 0NOTEQUAL", "0 EQUAL"], +["1 0NOTEQUAL", "1 EQUAL"], +["111 0NOTEQUAL", "1 EQUAL"], +["-111 0NOTEQUAL", "1 EQUAL"], +["1 1 BOOLAND", "NOP"], +["1 0 BOOLAND", "NOT"], +["0 1 BOOLAND", "NOT"], +["0 0 BOOLAND", "NOT"], +["16 17 BOOLAND", "NOP"], +["1 1 BOOLOR", "NOP"], +["1 0 BOOLOR", "NOP"], +["0 1 BOOLOR", "NOP"], +["0 0 BOOLOR", "NOT"], +["16 17 BOOLOR", "NOP"], +["11 10 1 ADD", "NUMEQUAL"], +["11 10 1 ADD", "NUMEQUALVERIFY 1"], +["11 10 1 ADD", "NUMNOTEQUAL NOT"], +["111 10 1 ADD", "NUMNOTEQUAL"], +["11 10", "LESSTHAN NOT"], +["4 4", "LESSTHAN NOT"], +["10 11", "LESSTHAN"], +["-11 11", "LESSTHAN"], +["-11 -10", "LESSTHAN"], +["11 10", "GREATERTHAN"], +["4 4", "GREATERTHAN NOT"], +["10 11", "GREATERTHAN NOT"], +["-11 11", "GREATERTHAN NOT"], +["-11 -10", "GREATERTHAN NOT"], +["11 10", "LESSTHANOREQUAL NOT"], +["4 4", "LESSTHANOREQUAL"], +["10 11", "LESSTHANOREQUAL"], +["-11 11", "LESSTHANOREQUAL"], +["-11 -10", "LESSTHANOREQUAL"], +["11 10", "GREATERTHANOREQUAL"], +["4 4", "GREATERTHANOREQUAL"], +["10 11", "GREATERTHANOREQUAL NOT"], +["-11 11", "GREATERTHANOREQUAL NOT"], +["-11 -10", "GREATERTHANOREQUAL NOT"], +["1 0 MIN", "0 NUMEQUAL"], +["0 1 MIN", "0 NUMEQUAL"], +["-1 0 MIN", "-1 NUMEQUAL"], +["0 -2147483647 MIN", "-2147483647 NUMEQUAL"], +["2147483647 0 MAX", "2147483647 NUMEQUAL"], +["0 100 MAX", "100 NUMEQUAL"], +["-100 0 MAX", "0 NUMEQUAL"], +["0 -2147483647 MAX", "0 NUMEQUAL"], +["0 0 1", "WITHIN"], +["1 0 1", "WITHIN NOT"], +["0 -2147483647 2147483647", "WITHIN"], +["-1 -100 100", "WITHIN"], +["11 -100 100", "WITHIN"], +["-2147483647 -100 100", "WITHIN NOT"], +["2147483647 -100 100", "WITHIN NOT"], + +["2147483647 2147483647 SUB", "0 EQUAL"], +["2147483647 DUP ADD", "4294967294 EQUAL", ">32 bit EQUAL is valid"], +["2147483647 NEGATE DUP ADD", "-4294967294 EQUAL"], + +["''", "RIPEMD160 0x14 0x9c1185a5c5e9fc54612808977ee8f548b2258d31 EQUAL"], +["'a'", "RIPEMD160 0x14 0x0bdc9d2d256b3ee9daae347be6f4dc835a467ffe EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "RIPEMD160 0x14 0xf71c27109c692c1b56bbdceb5b9d2865b3708dbc EQUAL"], +["''", "SHA1 0x14 0xda39a3ee5e6b4b0d3255bfef95601890afd80709 EQUAL"], +["'a'", "SHA1 0x14 0x86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA1 0x14 0x32d10c7b8cf96570ca04ce37f2a19d84240d3a89 EQUAL"], +["''", "SHA256 0x20 0xe3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 EQUAL"], +["'a'", "SHA256 0x20 0xca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "SHA256 0x20 0x71c480df93d6ae2f1efad1447c66c9525e316218cf51fc8d9ed832f2daf18b73 EQUAL"], +["''", "DUP HASH160 SWAP SHA256 RIPEMD160 EQUAL"], +["''", "DUP HASH256 SWAP SHA256 SHA256 EQUAL"], +["''", "NOP HASH160 0x14 0xb472a266d0bd89c13706a4132ccfb16f7c3b9fcb EQUAL"], +["'a'", "HASH160 NOP 0x14 0x994355199e516ff76c4fa4aab39337b9d84cf12b EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH160 0x4c 0x14 0xc286a1af0947f58d1ad787385b1c2c4a976f9e71 EQUAL"], +["''", "HASH256 0x20 0x5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456 EQUAL"], +["'a'", "HASH256 0x20 0xbf5d3affb73efd2ec6c36ad3112dd933efed63c4e1cbffcfa88e2759c144f2d8 EQUAL"], +["'abcdefghijklmnopqrstuvwxyz'", "HASH256 0x4c 0x20 0xca139bc10c2f660da42666f72e89a225936fc60f193c161124a672050c434671 EQUAL"], + + +["1","NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10 1 EQUAL"], +["'NOP_1_to_10' NOP1 NOP2 NOP3 NOP4 NOP5 NOP6 NOP7 NOP8 NOP9 NOP10","'NOP_1_to_10' EQUAL"], + +["0", "IF 0xba ELSE 1 ENDIF", "opcodes above NOP10 invalid if executed"], +["0", "IF 0xbb ELSE 1 ENDIF"], +["0", "IF 0xbc ELSE 1 ENDIF"], +["0", "IF 0xbd ELSE 1 ENDIF"], +["0", "IF 0xbe ELSE 1 ENDIF"], +["0", "IF 0xbf ELSE 1 ENDIF"], +["0", "IF 0xc0 ELSE 1 ENDIF"], +["0", "IF 0xc1 ELSE 1 ENDIF"], +["0", "IF 0xc2 ELSE 1 ENDIF"], +["0", "IF 0xc3 ELSE 1 ENDIF"], +["0", "IF 0xc4 ELSE 1 ENDIF"], +["0", "IF 0xc5 ELSE 1 ENDIF"], +["0", "IF 0xc6 ELSE 1 ENDIF"], +["0", "IF 0xc7 ELSE 1 ENDIF"], +["0", "IF 0xc8 ELSE 1 ENDIF"], +["0", "IF 0xc9 ELSE 1 ENDIF"], +["0", "IF 0xca ELSE 1 ENDIF"], +["0", "IF 0xcb ELSE 1 ENDIF"], +["0", "IF 0xcc ELSE 1 ENDIF"], +["0", "IF 0xcd ELSE 1 ENDIF"], +["0", "IF 0xce ELSE 1 ENDIF"], +["0", "IF 0xcf ELSE 1 ENDIF"], +["0", "IF 0xd0 ELSE 1 ENDIF"], +["0", "IF 0xd1 ELSE 1 ENDIF"], +["0", "IF 0xd2 ELSE 1 ENDIF"], +["0", "IF 0xd3 ELSE 1 ENDIF"], +["0", "IF 0xd4 ELSE 1 ENDIF"], +["0", "IF 0xd5 ELSE 1 ENDIF"], +["0", "IF 0xd6 ELSE 1 ENDIF"], +["0", "IF 0xd7 ELSE 1 ENDIF"], +["0", "IF 0xd8 ELSE 1 ENDIF"], +["0", "IF 0xd9 ELSE 1 ENDIF"], +["0", "IF 0xda ELSE 1 ENDIF"], +["0", "IF 0xdb ELSE 1 ENDIF"], +["0", "IF 0xdc ELSE 1 ENDIF"], +["0", "IF 0xdd ELSE 1 ENDIF"], +["0", "IF 0xde ELSE 1 ENDIF"], +["0", "IF 0xdf ELSE 1 ENDIF"], +["0", "IF 0xe0 ELSE 1 ENDIF"], +["0", "IF 0xe1 ELSE 1 ENDIF"], +["0", "IF 0xe2 ELSE 1 ENDIF"], +["0", "IF 0xe3 ELSE 1 ENDIF"], +["0", "IF 0xe4 ELSE 1 ENDIF"], +["0", "IF 0xe5 ELSE 1 ENDIF"], +["0", "IF 0xe6 ELSE 1 ENDIF"], +["0", "IF 0xe7 ELSE 1 ENDIF"], +["0", "IF 0xe8 ELSE 1 ENDIF"], +["0", "IF 0xe9 ELSE 1 ENDIF"], +["0", "IF 0xea ELSE 1 ENDIF"], +["0", "IF 0xeb ELSE 1 ENDIF"], +["0", "IF 0xec ELSE 1 ENDIF"], +["0", "IF 0xed ELSE 1 ENDIF"], +["0", "IF 0xee ELSE 1 ENDIF"], +["0", "IF 0xef ELSE 1 ENDIF"], +["0", "IF 0xf0 ELSE 1 ENDIF"], +["0", "IF 0xf1 ELSE 1 ENDIF"], +["0", "IF 0xf2 ELSE 1 ENDIF"], +["0", "IF 0xf3 ELSE 1 ENDIF"], +["0", "IF 0xf4 ELSE 1 ENDIF"], +["0", "IF 0xf5 ELSE 1 ENDIF"], +["0", "IF 0xf6 ELSE 1 ENDIF"], +["0", "IF 0xf7 ELSE 1 ENDIF"], +["0", "IF 0xf8 ELSE 1 ENDIF"], +["0", "IF 0xf9 ELSE 1 ENDIF"], +["0", "IF 0xfa ELSE 1 ENDIF"], +["0", "IF 0xfb ELSE 1 ENDIF"], +["0", "IF 0xfc ELSE 1 ENDIF"], +["0", "IF 0xfd ELSE 1 ENDIF"], +["0", "IF 0xfe ELSE 1 ENDIF"], +["0", "IF 0xff ELSE 1 ENDIF"], + +["NOP", +"'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'", +"520 byte push"], +["1", +"0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"201 opcodes executed. 0x61 is NOP"], +["1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1,000 stack size (0x6f is 3DUP)"], +["1 TOALTSTACK 2 TOALTSTACK 3 4 5 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1 2 3 4 5 6 7 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"1,000 stack size (altstack cleared between scriptSig/scriptPubKey)"], +["'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f", +"'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb' 0x6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f6f 2DUP 0x616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161", +"Max-size (10,000-byte), max-push(520 bytes), max-opcodes(201), max stack size(1,000 items). 0x6f is 3DUP, 0x61 is NOP"], + +["0", +"IF 0x5050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050505050 ENDIF 1", +">201 opcodes, but RESERVED (0x50) doesn't count towards opcode limit."], + +["NOP","1"], + +["1", "0x01 0x01 EQUAL", "The following is useful for checking implementations of BN_bn2mpi"], +["127", "0x01 0x7F EQUAL"], +["128", "0x02 0x8000 EQUAL", "Leave room for the sign bit"], +["32767", "0x02 0xFF7F EQUAL"], +["32768", "0x03 0x008000 EQUAL"], +["8388607", "0x03 0xFFFF7F EQUAL"], +["8388608", "0x04 0x00008000 EQUAL"], +["2147483647", "0x04 0xFFFFFF7F EQUAL"], +["2147483648", "0x05 0x0000008000 EQUAL"], +["-1", "0x01 0x81 EQUAL", "Numbers are little-endian with the MSB being a sign bit"], +["-127", "0x01 0xFF EQUAL"], +["-128", "0x02 0x8080 EQUAL"], +["-32767", "0x02 0xFFFF EQUAL"], +["-32768", "0x03 0x008080 EQUAL"], +["-8388607", "0x03 0xFFFFFF EQUAL"], +["-8388608", "0x04 0x00008080 EQUAL"], +["-2147483647", "0x04 0xFFFFFFFF EQUAL"], +["-2147483648", "0x05 0x0000008080 EQUAL"], + +["2147483647", "1ADD 2147483648 EQUAL", "We can do math on 4-byte integers, and compare 5-byte ones"], +["2147483647", "1ADD 1"], +["-2147483647", "1ADD 1"], + +["1", "0x02 0x0100 EQUAL NOT", "Not the same byte array..."], +["1", "0x02 0x0100 NUMEQUAL", "... but they are numerically equal"], +["11", "0x4c 0x03 0x0b0000 NUMEQUAL"], +["0", "0x01 0x80 EQUAL NOT"], +["0", "0x01 0x80 NUMEQUAL", "Zero numerically equals negative zero"], +["0", "0x02 0x0080 NUMEQUAL"], +["0x03 0x000080", "0x04 0x00000080 NUMEQUAL"], +["0x03 0x100080", "0x04 0x10000080 NUMEQUAL"], +["0x03 0x100000", "0x04 0x10000000 NUMEQUAL"], + +["NOP", "NOP 1", "The following tests check the if(stack.size() < N) tests in each opcode"], +["1", "IF 1 ENDIF", "They are here to catch copy-and-paste errors"], +["0", "NOTIF 1 ENDIF", "Most of them are duplicated elsewhere,"], +["1", "VERIFY 1", "but, hey, more is always better, right?"], + +["0", "TOALTSTACK 1"], +["1", "TOALTSTACK FROMALTSTACK"], +["0 0", "2DROP 1"], +["0 1", "2DUP"], +["0 0 1", "3DUP"], +["0 1 0 0", "2OVER"], +["0 1 0 0 0 0", "2ROT"], +["0 1 0 0", "2SWAP"], +["1", "IFDUP"], +["NOP", "DEPTH 1"], +["0", "DROP 1"], +["1", "DUP"], +["0 1", "NIP"], +["1 0", "OVER"], +["1 0 0 0 3", "PICK"], +["1 0", "PICK"], +["1 0 0 0 3", "ROLL"], +["1 0", "ROLL"], +["1 0 0", "ROT"], +["1 0", "SWAP"], +["0 1", "TUCK"], + +["1", "SIZE"], + +["0 0", "EQUAL"], +["0 0", "EQUALVERIFY 1"], + +["0", "1ADD"], +["2", "1SUB"], +["-1", "NEGATE"], +["-1", "ABS"], +["0", "NOT"], +["-1", "0NOTEQUAL"], + +["1 0", "ADD"], +["1 0", "SUB"], +["-1 -1", "BOOLAND"], +["-1 0", "BOOLOR"], +["0 0", "NUMEQUAL"], +["0 0", "NUMEQUALVERIFY 1"], +["-1 0", "NUMNOTEQUAL"], +["-1 0", "LESSTHAN"], +["1 0", "GREATERTHAN"], +["0 0", "LESSTHANOREQUAL"], +["0 0", "GREATERTHANOREQUAL"], +["-1 0", "MIN"], +["1 0", "MAX"], +["-1 -1 0", "WITHIN"], + +["0", "RIPEMD160"], +["0", "SHA1"], +["0", "SHA256"], +["0", "HASH160"], +["0", "HASH256"], +["NOP", "CODESEPARATOR 1"], + +["NOP", "NOP1 1"], +["NOP", "NOP2 1"], +["NOP", "NOP3 1"], +["NOP", "NOP4 1"], +["NOP", "NOP5 1"], +["NOP", "NOP6 1"], +["NOP", "NOP7 1"], +["NOP", "NOP8 1"], +["NOP", "NOP9 1"], +["NOP", "NOP10 1"], + +["0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL", "Very basic P2SH"], +["0x4c 0 0x01 1", "HASH160 0x14 0xda1745e9b549bd0bfa1a569971c77eba30cd5a4b EQUAL"], + +["0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", +"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", +"Basic PUSH signedness check"], + +["0x4c 0x40 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242", +"0x4d 0x4000 0x42424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242424242 EQUAL", +"Basic PUSHDATA1 signedness check"] +] diff --git a/test/data/sig_canonical.json b/test/data/sig_canonical.json new file mode 100644 index 0000000..e43a086 --- /dev/null +++ b/test/data/sig_canonical.json @@ -0,0 +1,7 @@ +[ + "300602010002010001", + "3008020200ff020200ff01", + "304402203932c892e2e550f3af8ee4ce9c215a87f9bb831dcac87b2838e2c2eaa891df0c022030b61dd36543125d56b9f9f3a1f9353189e5af33cdda8d77a5209aec03978fa001", + "30450220076045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01", + "3046022100876045be6f9eca28ff1ec606b833d0b87e70b2a630f5e3a496b110967a40f90a0221008fffd599910eefe00bc803c688c2eca1d2ba7f6b180620eaa03488e6585db6ba01" +] diff --git a/test/data/sig_noncanonical.json b/test/data/sig_noncanonical.json new file mode 100644 index 0000000..d9a6c1c --- /dev/null +++ b/test/data/sig_noncanonical.json @@ -0,0 +1,22 @@ +[ + "non-hex strings are ignored", + + "too short:", "30050201FF020001", + "too long:", "30470221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105022200002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "hashtype:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed11", + "type:", "314402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "total length:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "S len oob:", "301F01205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb101", + "R+S:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed0001", + + "R type:", "304401205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "R len = 0:", "3024020002202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "R<0:", "304402208990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "R padded:", "30450221005990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610502202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + + + "S type:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba610501202d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "S len = 0:", "302402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba6105020001", + "S<0:", "304402205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050220fd5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01", + "S padded:", "304502205990e0584b2b238e1dfaad8d6ed69ecc1a4a13ac85fc0b31d0df395eb1ba61050221002d5876262c288beb511d061691bf26777344b702b00f8fe28621fe4e566695ed01" +] diff --git a/test/data/tx_invalid.json b/test/data/tx_invalid.json new file mode 100644 index 0000000..faf40ef --- /dev/null +++ b/test/data/tx_invalid.json @@ -0,0 +1,80 @@ +[ +["The following are deserialized transactions which are invalid."], +["They are in the form"], +["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], +["serializedTransaction, enforceP2SH]"], +["Objects that are only a single string (like this one) are ignored"], + +["0e1b5688cf179cd9f7cbda1fac0090f6e684bbf8cd946660120197c3f3681809 but with extra junk appended to the end of the scriptPubKey"], +[[["6ca7ec7b1847f6bdbd737176050e6a08d66ccd55bb94ad24f4018024107a5827", 0, "0x41 0x043b640e983c9690a14c039a2037ecc3467b27a0dcd58f19d76c7bc118d09fec45adc5370a1c5bf8067ca9f5557a4cf885fdb0fe0dcc9c3a7137226106fbc779a5 CHECKSIG VERIFY 1"]], +"010000000127587a10248001f424ad94bb55cd6cd6086a0e05767173bdbdf647187beca76c000000004948304502201b822ad10d6adc1a341ae8835be3f70a25201bbff31f59cbb9c5353a5f0eca18022100ea7b2f7074e9aa9cf70aa8d0ffee13e6b45dddabf1ab961bda378bcdb778fa4701ffffffff0100f2052a010000001976a914fc50c5907d86fed474ba5ce8b12a66e0a4c139d888ac00000000", true], + +["This is the nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG from tx_valid.json"], +["but with the signature duplicated in the scriptPubKey with a non-standard pushdata prefix"], +["See FindAndDelete, which will only remove if it uses the same pushdata prefix as is standard"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["Same as above, but with the sig in the scriptSig also pushed with the same non-standard OP_PUSHDATA"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x4c 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006b4c473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["An invalid P2SH Transaction"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", true], + +["Tests for CheckTransaction()"], +["No inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"0100000000010000000000000000015100000000", true], + +["No outputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x05ab9e14d983742513f0f451e105ffb4198d1dd4 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022100f16703104aab4e4088317c862daec83440242411b039d14280e03dd33b487ab802201318a7be236672c5c56083eb7a5a195bc57a40af7923ff8545016cd3b571e2a601232103c40e5d339df3f30bf753e7e04450ae4ef76c9e45587d1d993bdc4cd06f0651c7acffffffff0000000000", true], + +["Negative output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xae609aca8061d77c5e111f6bb62501a6bbe2bfdb EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d4830450220063222cbb128731fc09de0d7323746539166544d6c1df84d867ccea84bcc8903022100bf568e8552844de664cd41648a031554327aa8844af34b4f27397c65b92c04de0123210243ec37dee0e2e053a9c976f43147e79bc7d9dc606ea51010af1ac80db6b069e1acffffffff01ffffffffffffffff015100000000", true], + +["MAX_MONEY + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010140075af0750700015100000000", true], + +["MAX_MONEY output + 1 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510001000000000000015100000000", true], + +["Duplicate inputs"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x236d0639db62b0773fd8ac34dc85ae19e9aba80a EQUAL"]], +"01000000020001000000000000000000000000000000000000000000000000000000000000000000006c47304402204bb1197053d0d7799bf1b30cd503c44b58d6240cccbdc85b6fe76d087980208f02204beeed78200178ffc6c74237bb74b3f276bbb4098b5605d814304fe128bf1431012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff0001000000000000000000000000000000000000000000000000000000000000000000006c47304402202306489afef52a6f62e90bf750bbcdf40c06f5c6b138286e6b6b86176bb9341802200dba98486ea68380f47ebb19a7df173b99e6bc9c681d6ccf3bde31465d1f16b3012321039e8815e15952a7c3fada1905f8cf55419837133bd7756c0ef14fc8dfe50c0deaacffffffff010000000000000000015100000000", true], + +["Coinbase of size 1"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 101"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff655151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], + +["Null txin"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "HASH160 0x14 0x02dae7dbbda56097959cba59b1989dd3e47937bf EQUAL"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6e49304602210086f39e028e46dafa8e1e3be63906465f4cf038fbe5ed6403dc3e74ae876e6431022100c4625c675cfc5c7e3a0e0d7eaec92ac24da20c73a88eb40d09253e51ac6def5201232103a183ddc41e84753aca47723c965d1b5c8b0e2b537963518355e6dd6cf8415e50acffffffff010000000000000000015100000000", true], + +["Same as the transactions in valid with one input SIGHASH_ALL and one SIGHASH_ANYONECANPAY, but we set the _ANYONECANPAY sequence number, invalidating the SIGHASH_ALL signature"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], + ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df10101000000000200000000000000000000000000000000000000000000000000000000000000000000484730440220201dc2d030e380e8f9cfb41b442d930fa5a685bb2c8db5906671f865507d0670022018d9e7a8d4c8d86a73c2a724ee38ef983ec249827e0e464841735955c707ece98101000000010100000000000000015100000000", true], + +["Incorrect signature order"], +["Note the input is just required to make the tester happy"], +[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe000048304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f401483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], + +["Empty stack when we try to run CHECKSIG"], +[[["ad503f72c18df5801ee64d76090afe4c607fb2b822e9b7b63c5826c50e22fc3b", 0, "0x21 0x027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5 CHECKSIG NOT"]], +"01000000013bfc220ec526583cb6b7e922b8b27f604cfe0a09764de61e80f58dc1723f50ad0000000000ffffffff0101000000000000002321027c3a97665bf283a102a587a62a30a0c102d4d3b141015e2cae6f64e2543113e5ac00000000", true], + +["Make diffs cleaner by leaving a comment here without comma at the end"] +] diff --git a/test/data/tx_valid.json b/test/data/tx_valid.json new file mode 100644 index 0000000..c206f7a --- /dev/null +++ b/test/data/tx_valid.json @@ -0,0 +1,122 @@ +[ +["The following are deserialized transactions which are valid."], +["They are in the form"], +["[[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], +["serializedTransaction, enforceP2SH]"], +["Objects that are only a single string (like this one) are ignored"], + +["The following is 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It is of particular interest because it contains an invalidly-encoded signature which OpenSSL accepts"], +["See http://r6.ca/blog/20111119T211504Z.html"], +["It is also the first OP_CHECKMULTISIG transaction in standard form"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], + +["The following is a tweaked form of 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63"], +["It has an arbitrary extra byte stuffed into the signature at pos length - 2"], +[[["60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1", 0, "1 0x41 0x04cc71eb30d653c0c3163990c47b976f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a473e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d11fcdd0d348ac4 0x41 0x0461cbdcc5409fb4b4d42b51d33381354d80e550078cb532a34bfa2fcfdeb7d76519aecc62770f5b0e4ef8551946d8a540911abe3e7854a26f39f58b25c15342af 2 OP_CHECKMULTISIG"]], +"0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba260000000004A0048304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2bab01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000", true], + +["The following is c99c49da4c38af669dea436d3e73780dfdb6c1ecf9958baa52960e8baee30e73"], +["It is of interest because it contains a 0-sequence as well as a signature of SIGHASH type 0 (which is not a real type)"], +[[["406b2b06bcd34d3c8733e6b79f7a394c8a431fbf4ff5ac705c93f4076bb77602", 0, "DUP HASH160 0x14 0xdc44b1164188067c3a32d4780f5996fa14a4f2d9 EQUALVERIFY CHECKSIG"]], +"01000000010276b76b07f4935c70acf54fbf1f438a4c397a9fb7e633873c4dd3bc062b6b40000000008c493046022100d23459d03ed7e9511a47d13292d3430a04627de6235b6e51a40f9cd386f2abe3022100e7d25b080f0bb8d8d5f878bba7d54ad2fda650ea8d158a33ee3cbd11768191fd004104b0e2c879e4daf7b9ab68350228c159766676a14f5815084ba166432aab46198d4cca98fa3e9981d0a90b2effc514b76279476550ba3663fdcaff94c38420e9d5000000000100093d00000000001976a9149a7b0f3b80c6baaeedce0a0842553800f832ba1f88ac00000000", true], + +["A nearly-standard transaction with CHECKSIGVERIFY 1 instead of CHECKSIG"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["Same as above, but with the signature duplicated in the scriptPubKey with the proper pushdata prefix"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0x5b6462475454710f3c22f5fdf0b40704c92f25c3 EQUALVERIFY CHECKSIGVERIFY 1 0x47 0x3044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a01"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006a473044022067288ea50aa799543a536ff9306f8e1cba05b9c6b10951175b924f96732555ed022026d7b5265f38d21541519e4a1e55044d5b9e17e15cdbaf29ae3792e99e883e7a012103ba8c8b86dea131c22ab967e6dd99bdae8eff7a1f75a2c35f1f944109e3fe5e22ffffffff010000000000000000015100000000", true], + +["The following is f7fdd091fa6d8f5e7a8c2458f5c38faffff2d3f1406b6e4fe2c99dcc0d2d1cbb"], +["It caught a bug in the workaround for 23b397edccd3740a74adb603c9756370fafcde9bcc4483eb271ecad09a94dd63 in an overly simple implementation"], +[[["b464e85df2a238416f8bdae11d120add610380ea07f4ef19c5f9dfd472f96c3d", 0, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"], +["b7978cc96e59a8b13e0865d3f95657561a7f725be952438637475920bac9eb21", 1, "DUP HASH160 0x14 0xbef80ecf3a44500fda1bc92176e442891662aed2 EQUALVERIFY CHECKSIG"]], +"01000000023d6cf972d4dff9c519eff407ea800361dd0a121de1da8b6f4138a2f25de864b4000000008a4730440220ffda47bfc776bcd269da4832626ac332adfca6dd835e8ecd83cd1ebe7d709b0e022049cffa1cdc102a0b56e0e04913606c70af702a1149dc3b305ab9439288fee090014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff21ebc9ba20594737864352e95b727f1a565756f9d365083eb1a8596ec98c97b7010000008a4730440220503ff10e9f1e0de731407a4a245531c9ff17676eda461f8ceeb8c06049fa2c810220c008ac34694510298fa60b3f000df01caa244f165b727d4896eb84f81e46bcc4014104266abb36d66eb4218a6dd31f09bb92cf3cfa803c7ea72c1fc80a50f919273e613f895b855fb7465ccbc8919ad1bd4a306c783f22cd3227327694c4fa4c1c439affffffff01f0da5200000000001976a914857ccd42dded6df32949d4646dfa10a92458cfaa88ac00000000", true], + +["The following tests for the presence of a bug in the handling of SIGHASH_SINGLE"], +["It results in signing the constant 1, instead of something generated based on the transaction,"], +["when the input doing the signing has an index greater than the maximum output index"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "DUP HASH160 0x14 0xe52b482f2faa8ecbf0db344f93c84ac908557f33 EQUALVERIFY CHECKSIG"], ["0000000000000000000000000000000000000000000000000000000000000200", 0, "1"]], +"01000000020002000000000000000000000000000000000000000000000000000000000000000000000151ffffffff0001000000000000000000000000000000000000000000000000000000000000000000006b483045022100c9cdd08798a28af9d1baf44a6c77bcc7e279f47dc487c8c899911bc48feaffcc0220503c5c50ae3998a733263c5c0f7061b483e2b56c4c41b456e7d2f5a78a74c077032102d5c25adb51b61339d2b05315791e21bbe80ea470a49db0135720983c905aace0ffffffff010000000000000000015100000000", true], + +["An invalid P2SH Transaction"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x7a052c840ba73af26755de42cf01cc9e0a49fef0 EQUAL"]], +"010000000100010000000000000000000000000000000000000000000000000000000000000000000009085768617420697320ffffffff010000000000000000015100000000", false], + +["A valid P2SH Transaction using the standard transaction type put forth in BIP 16"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x8febbed40483661de6958d957412f82deed8e2f7 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100c66c9cdf4c43609586d15424c54707156e316d88b0a1534c9e6b0d4f311406310221009c0fe51dbc9c4ab7cc25d3fdbeccf6679fe6827f08edf2b4a9f16ee3eb0e438a0123210338e8034509af564c62644c07691942e0c056752008a173c89f60ab2a88ac2ebfacffffffff010000000000000000015100000000", true], + +["Tests for CheckTransaction()"], +["MAX_MONEY output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0x32afac281462b822adbec5094b8d4d337dd5bd6a EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006e493046022100e1eadba00d9296c743cb6ecc703fd9ddc9b3cd12906176a226ae4c18d6b00796022100a71aef7d2874deff681ba6080f1b278bac7bb99c61b08a85f4311970ffe7f63f012321030c0588dc44d92bdcbf8e72093466766fdc265ead8db64517b0c542275b70fffbacffffffff010040075af0750700015100000000", true], + +["MAX_MONEY output + 0 output"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "HASH160 0x14 0xb558cbf4930954aa6a344363a15668d7477ae716 EQUAL"]], +"01000000010001000000000000000000000000000000000000000000000000000000000000000000006d483045022027deccc14aa6668e78a8c9da3484fbcd4f9dcc9bb7d1b85146314b21b9ae4d86022100d0b43dece8cfb07348de0ca8bc5b86276fa88f7f2138381128b7c36ab2e42264012321029bb13463ddd5d2cc05da6e84e37536cb9525703cfd8f43afdb414988987a92f6acffffffff020040075af075070001510000000000000000015100000000", true], + +["Coinbase of size 2"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff025151ffffffff010000000000000000015100000000", true], + +["Coinbase of size 100"], +["Note the input is just required to make the tester happy"], +[[["0000000000000000000000000000000000000000000000000000000000000000", -1, "1"]], +"01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff6451515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151515151ffffffff010000000000000000015100000000", true], + +["Simple transaction with first input is signed with SIGHASH_ALL, second with SIGHASH_ANYONECANPAY"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], + ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], + "010000000200010000000000000000000000000000000000000000000000000000000000000000000049483045022100d180fd2eb9140aeb4210c9204d3f358766eb53842b2a9473db687fa24b12a3cc022079781799cd4f038b85135bbe49ec2b57f306b2bb17101b17f71f000fcab2b6fb01ffffffff0002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + +["Same as above, but we change the sequence number of the first input to check that SIGHASH_ANYONECANPAY is being followed"], +[[["0000000000000000000000000000000000000000000000000000000000000100", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"], + ["0000000000000000000000000000000000000000000000000000000000000200", 0, "0x21 0x035e7f0d4d0841bcd56c39337ed086b1a633ee770c1ffdd94ac552a95ac2ce0efc CHECKSIG"]], + "01000000020001000000000000000000000000000000000000000000000000000000000000000000004948304502203a0f5f0e1f2bdbcd04db3061d18f3af70e07f4f467cbc1b8116f267025f5360b022100c792b6e215afc5afc721a351ec413e714305cb749aae3d7fee76621313418df101010000000002000000000000000000000000000000000000000000000000000000000000000000004847304402205f7530653eea9b38699e476320ab135b74771e1c48b81a5d041e2ca84b9be7a802200ac8d1f40fb026674fe5a5edd3dea715c27baa9baca51ed45ea750ac9dc0a55e81ffffffff010100000000000000015100000000", true], + +["afd9c17f8913577ec3509520bd6e5d63e9c0fd2a5f70c787993b097ba6ca9fae which has several SIGHASH_SINGLE signatures"], +[[["63cfa5a09dc540bf63e53713b82d9ea3692ca97cd608c384f2aa88e51a0aac70", 0, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], + ["04e8d0fcf3846c6734477b98f0f3d4badfb78f020ee097a0be5fe347645b817d", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"], + ["ee1377aff5d0579909e11782e1d2f5f7b84d26537be7f5516dd4e43373091f3f", 1, "DUP HASH160 0x14 0xdcf72c4fd02f5a987cf9b02f2fabfcac3341a87d EQUALVERIFY CHECKSIG"]], + "010000000370ac0a1ae588aaf284c308d67ca92c69a39e2db81337e563bf40c59da0a5cf63000000006a4730440220360d20baff382059040ba9be98947fd678fb08aab2bb0c172efa996fd8ece9b702201b4fb0de67f015c90e7ac8a193aeab486a1f587e0f54d0fb9552ef7f5ce6caec032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff7d815b6447e35fbea097e00e028fb7dfbad4f3f0987b4734676c84f3fcd0e804010000006b483045022100c714310be1e3a9ff1c5f7cacc65c2d8e781fc3a88ceb063c6153bf950650802102200b2d0979c76e12bb480da635f192cc8dc6f905380dd4ac1ff35a4f68f462fffd032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff3f1f097333e4d46d51f5e77b53264db8f7f5d2e18217e1099957d0f5af7713ee010000006c493046022100b663499ef73273a3788dea342717c2640ac43c5a1cf862c9e09b206fcb3f6bb8022100b09972e75972d9148f2bdd462e5cb69b57c1214b88fc55ca638676c07cfc10d8032103579ca2e6d107522f012cd00b52b9a65fb46f0c57b9b8b6e377c48f526a44741affffffff0380841e00000000001976a914bfb282c70c4191f45b5a6665cad1682f2c9cfdfb88ac80841e00000000001976a9149857cc07bed33a5cf12b9c5e0500b675d500c81188ace0fd1c00000000001976a91443c52850606c872403c0601e69fa34b26f62db4a88ac00000000", true], + + ["ddc454a1c0c35c188c98976b17670f69e586d9c0f3593ea879928332f0a069e7, which spends an input that pushes using a PUSHDATA1 that is negative when read as signed"], + [[["c5510a5dd97a25f43175af1fe649b707b1df8e1a41489bac33a23087027a2f48", 0, "0x4c 0xae 0x606563686f2022553246736447566b58312b5a536e587574356542793066794778625456415675534a6c376a6a334878416945325364667657734f53474f36633338584d7439435c6e543249584967306a486956304f376e775236644546673d3d22203e20743b206f70656e73736c20656e63202d7061737320706173733a5b314a564d7751432d707269766b65792d6865785d202d64202d6165732d3235362d636263202d61202d696e207460 DROP DUP HASH160 0x14 0xbfd7436b6265aa9de506f8a994f881ff08cc2872 EQUALVERIFY CHECKSIG"]], + "0100000001482f7a028730a233ac9b48411a8edfb107b749e61faf7531f4257ad95d0a51c5000000008b483045022100bf0bbae9bde51ad2b222e87fbf67530fbafc25c903519a1e5dcc52a32ff5844e022028c4d9ad49b006dd59974372a54291d5764be541574bb0c4dc208ec51f80b7190141049dd4aad62741dc27d5f267f7b70682eee22e7e9c1923b9c0957bdae0b96374569b460eb8d5b40d972e8c7c0ad441de3d94c4a29864b212d56050acb980b72b2bffffffff0180969800000000001976a914e336d0017a9d28de99d16472f6ca6d5a3a8ebc9988ac00000000", true], + +["Correct signature order"], +["Note the input is just required to make the tester happy"], +[[["b3da01dd4aae683c7aee4d5d8b52a540a508e1115f77cd7fa9a291243f501223", 0, "HASH160 0x14 0xb1ce99298d5f07364b57b1e5c9cc00be0b04a954 EQUAL"]], +"01000000012312503f2491a2a97fcd775f11e108a540a5528b5d4dee7a3c68ae4add01dab300000000fdfe0000483045022100f6649b0eddfdfd4ad55426663385090d51ee86c3481bdc6b0c18ea6c0ece2c0b0220561c315b07cffa6f7dd9df96dbae9200c2dee09bf93cc35ca05e6cdf613340aa0148304502207aacee820e08b0b174e248abd8d7a34ed63b5da3abedb99934df9fddd65c05c4022100dfe87896ab5ee3df476c2655f9fbe5bd089dccbef3e4ea05b5d121169fe7f5f4014c695221031d11db38972b712a9fe1fc023577c7ae3ddb4a3004187d41c45121eecfdbb5b7210207ec36911b6ad2382860d32989c7b8728e9489d7bbc94a6b5509ef0029be128821024ea9fac06f666a4adc3fc1357b7bec1fd0bdece2b9d08579226a8ebde53058e453aeffffffff0180380100000000001976a914c9b99cddf847d10685a4fabaa0baf505f7c3dfab88ac00000000", true], + +["cc60b1f899ec0a69b7c3f25ddf32c4524096a9c5b01cbd84c6d0312a0c478984, which is a fairly strange transaction which relies on OP_CHECKSIG returning 0 when checking a completely invalid sig of length 0"], +[[["cbebc4da731e8995fe97f6fadcd731b36ad40e5ecb31e38e904f6e5982fa09f7", 0, "0x2102085c6600657566acc2d6382a47bc3f324008d2aa10940dd7705a48aa2a5a5e33ac7c2103f5d0fb955f95dd6be6115ce85661db412ec6a08abcbfce7da0ba8297c6cc0ec4ac7c5379a820d68df9e32a147cffa36193c6f7c43a1c8c69cda530e1c6db354bfabdcfefaf3c875379a820f531f3041d3136701ea09067c53e7159c8f9b2746a56c3d82966c54bbc553226879a5479827701200122a59a5379827701200122a59a6353798277537982778779679a68"]], +"0100000001f709fa82596e4f908ee331cb5e0ed46ab331d7dcfaf697fe95891e73dac4ebcb000000008c20ca42095840735e89283fec298e62ac2ddea9b5f34a8cbb7097ad965b87568100201b1b01dc829177da4a14551d2fc96a9db00c6501edfa12f22cd9cefd335c227f483045022100a9df60536df5733dd0de6bc921fab0b3eee6426501b43a228afa2c90072eb5ca02201c78b74266fac7d1db5deff080d8a403743203f109fbcabf6d5a760bf87386d20100ffffffff01c075790000000000232103611f9a45c18f28f06f19076ad571c344c82ce8fcfe34464cf8085217a2d294a6ac00000000", true], + +["Empty pubkey"], +[[["229257c295e7f555421c1bfec8538dd30a4b5c37c1c8810bbe83cafa7811652c", 0, "0x00 CHECKSIG NOT"]], +"01000000012c651178faca83be0b81c8c1375c4b0ad38d53c8fe1b1c4255f5e795c25792220000000049483045022100d6044562284ac76c985018fc4a90127847708c9edb280996c507b28babdc4b2a02203d74eca3f1a4d1eea7ff77b528fde6d5dc324ec2dbfdb964ba885f643b9704cd01ffffffff010100000000000000232102c2410f8891ae918cab4ffc4bb4a3b0881be67c7a1e7faa8b5acf9ab8932ec30cac00000000", true], + +["Empty signature"], +[[["9ca93cfd8e3806b9d9e2ba1cf64e3cc6946ee0119670b1796a09928d14ea25f7", 0, "0x21 0x028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02 CHECKSIG NOT"]], +"0100000001f725ea148d92096a79b1709611e06e94c63c4ef61cbae2d9b906388efd3ca99c000000000100ffffffff0101000000000000002321028a1d66975dbdf97897e3a4aef450ebeb5b5293e4a0b4a6d3a2daaa0b2b110e02ac00000000", true], + +[[["444e00ed7840d41f20ecd9c11d3f91982326c731a02f3c05748414a4fa9e59be", 0, "1 0x00 0x21 0x02136b04758b0b6e363e7a6fbe83aaf527a153db2b060d36cc29f7f8309ba6e458 2 CHECKMULTISIG"]], +"0100000001be599efaa4148474053c2fa031c7262398913f1dc1d9ec201fd44078ed004e44000000004900473044022022b29706cb2ed9ef0cb3c97b72677ca2dfd7b4160f7b4beb3ba806aa856c401502202d1e52582412eba2ed474f1f437a427640306fd3838725fab173ade7fe4eae4a01ffffffff010100000000000000232103ac4bba7e7ca3e873eea49e08132ad30c7f03640b6539e9b59903cf14fd016bbbac00000000", true], + +[[["e16abbe80bf30c080f63830c8dbf669deaef08957446e95940227d8c5e6db612", 0, "1 0x21 0x03905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9f 0x00 2 CHECKMULTISIG"]], +"010000000112b66d5e8c7d224059e946749508efea9d66bf8d0c83630f080cf30be8bb6ae100000000490047304402206ffe3f14caf38ad5c1544428e99da76ffa5455675ec8d9780fac215ca17953520220779502985e194d84baa36b9bd40a0dbd981163fa191eb884ae83fc5bd1c86b1101ffffffff010100000000000000232103905380c7013e36e6e19d305311c1b81fce6581f5ee1c86ef0627c68c9362fc9fac00000000", true], + +[[["ebbcf4bfce13292bd791d6a65a2a858d59adbf737e387e40370d4e64cc70efb0", 0, "2 0x21 0x033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194 0x21 0x03a88b326f8767f4f192ce252afe33c94d25ab1d24f27f159b3cb3aa691ffe1423 2 CHECKMULTISIG NOT"]], +"0100000001b0ef70cc644e0d37407e387e73bfad598d852a5aa6d691d72b2913cebff4bceb000000004a00473044022068cd4851fc7f9a892ab910df7a24e616f293bcb5c5fbdfbc304a194b26b60fba022078e6da13d8cb881a22939b952c24f88b97afd06b4c47a47d7f804c9a352a6d6d0100ffffffff0101000000000000002321033bcaa0a602f0d44cc9d5637c6e515b0471db514c020883830b7cefd73af04194ac00000000", true], + +[[["ba4cd7ae2ad4d4d13ebfc8ab1d93a63e4a6563f25089a18bf0fc68f282aa88c1", 0, "2 0x21 0x037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1 0x21 0x02edc823cd634f2c4033d94f5755207cb6b60c4b1f1f056ad7471c47de5f2e4d50 2 CHECKMULTISIG NOT"]], +"0100000001c188aa82f268fcf08ba18950f263654a3ea6931dabc8bf3ed1d4d42aaed74cba000000004b0000483045022100940378576e069aca261a6b26fb38344e4497ca6751bb10905c76bb689f4222b002204833806b014c26fd801727b792b1260003c55710f87c5adbd7a9cb57446dbc9801ffffffff0101000000000000002321037c615d761e71d38903609bf4f46847266edc2fb37532047d747ba47eaae5ffe1ac00000000", true], + +["Make diffs cleaner by leaving a comment here without comma at the end"] +] From 63973b29e3059fbc0d832bb28c58953f2065f8f9 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 26 Feb 2014 17:56:57 -0300 Subject: [PATCH 2/8] added encode tests --- test/test.misc.js | 8 ++++++++ test/testdata.js | 2 ++ 2 files changed, 10 insertions(+) diff --git a/test/test.misc.js b/test/test.misc.js index 58720e1..804ff7c 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -5,9 +5,12 @@ var bitcore = require('../bitcore'); var should = chai.should(); +var test_data = require('./testdata'); + var bignum = bitcore.bignum; var base58 = bitcore.base58; var base58Check = base58.base58Check; +var util = bitcore.util; describe('Miscelaneous stuff', function() { it('should initialze the config object', function() { @@ -55,6 +58,11 @@ describe('Miscelaneous stuff', function() { var m = '1QCJj1gPZKx2EwzGo9Ri8mMBs39STvDYcv'; base58Check.encode(base58Check.decode(m)).should.equal(m); }); + test_data.dataEncodeDecode.forEach(function(datum) { + it('base58 encode/decode checks ' + datum, function() { + base58.encode(new Buffer(datum[0], 'hex')).should.equal(datum[1]); + }); + }); }); diff --git a/test/testdata.js b/test/testdata.js index ecbd663..7eaaa0b 100644 --- a/test/testdata.js +++ b/test/testdata.js @@ -4,6 +4,8 @@ var fs = require('fs'); var dataValid = JSON.parse(fs.readFileSync('test/data/base58_keys_valid.json')); var dataInvalid = JSON.parse(fs.readFileSync('test/data/base58_keys_invalid.json')); +var dataEncodeDecode = JSON.parse(fs.readFileSync('test/data/base58_encode_decode.json')); module.exports.dataValid = dataValid; module.exports.dataInvalid = dataInvalid; +module.exports.dataEncodeDecode = dataEncodeDecode; From d2b74c2f7c2f23652584c9eba27f2f8688d58779 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 26 Feb 2014 18:36:01 -0300 Subject: [PATCH 3/8] added decode test --- test/test.misc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test.misc.js b/test/test.misc.js index 804ff7c..f8d59b6 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -11,6 +11,7 @@ var bignum = bitcore.bignum; var base58 = bitcore.base58; var base58Check = base58.base58Check; var util = bitcore.util; +var buffertools = require('buffertools'); describe('Miscelaneous stuff', function() { it('should initialze the config object', function() { @@ -61,6 +62,7 @@ describe('Miscelaneous stuff', function() { test_data.dataEncodeDecode.forEach(function(datum) { it('base58 encode/decode checks ' + datum, function() { base58.encode(new Buffer(datum[0], 'hex')).should.equal(datum[1]); + buffertools.toHex(base58.decode(datum[1])).should.equal(datum[0]); }); }); From d77cc28f7a2e595d1abd31c60eae261556e6730b Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Wed, 26 Feb 2014 18:40:19 -0300 Subject: [PATCH 4/8] added references to bitcoin/bitcoin tests --- test/test.misc.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/test.misc.js b/test/test.misc.js index f8d59b6..bceebc2 100644 --- a/test/test.misc.js +++ b/test/test.misc.js @@ -61,6 +61,8 @@ describe('Miscelaneous stuff', function() { }); test_data.dataEncodeDecode.forEach(function(datum) { it('base58 encode/decode checks ' + datum, function() { + // from bitcoin/bitcoin tests: + // Goal: test low-level base58 encoding functionality base58.encode(new Buffer(datum[0], 'hex')).should.equal(datum[1]); buffertools.toHex(base58.decode(datum[1])).should.equal(datum[0]); }); From 6755b84fbf585ef50561ce13a1504add1772141d Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 27 Feb 2014 18:09:02 -0300 Subject: [PATCH 5/8] Transaction new tests not working --- Transaction.js | 14 +++++++++++++- test/test.Transaction.js | 42 +++++++++++++++++++++++++++++++++++++++- test/testdata.js | 4 ++++ 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/Transaction.js b/Transaction.js index d362039..16564e9 100644 --- a/Transaction.js +++ b/Transaction.js @@ -25,6 +25,14 @@ function spec(b) { } if (data.o) { this.o = data.o; + } else { + if (data.oTxHash && typeof data.oIndex !== 'undefined') { + var hash = new Buffer(data.oTxHash, 'hex'); + hash = buffertools.reverse(hash); + var voutBuf = new Buffer(4); + voutBuf.writeUInt32LE(data.oIndex, 0); + this.o = Buffer.concat([hash, voutBuf]); + } } this.s = Buffer.isBuffer(data.s) ? data.s : Buffer.isBuffer(data.script) ? data.script : util.EMPTY_BUFFER; @@ -44,7 +52,8 @@ function spec(b) { var qbuf = new Buffer(4); qbuf.writeUInt32LE(this.q, 0); - return Buffer.concat([this.o, slen, this.s, qbuf]); + var ret = Buffer.concat([this.o, slen, this.s, qbuf]); + return ret; }; TransactionIn.prototype.getOutpointHash = function getOutpointHash() { @@ -144,6 +153,7 @@ function spec(b) { bufs.push(buf); bufs.push(util.varIntBuf(this.ins.length)); + console.log(this.ins.length); this.ins.forEach(function (txin) { bufs.push(txin.serialize()); }); @@ -640,6 +650,8 @@ function spec(b) { Transaction.prototype.parse = function (parser) { if (Buffer.isBuffer(parser)) { + console.dir(parser); + this._buffer = parser; parser = new Parser(parser); } diff --git a/test/test.Transaction.js b/test/test.Transaction.js index 98889de..570a0b0 100644 --- a/test/test.Transaction.js +++ b/test/test.Transaction.js @@ -7,6 +7,11 @@ var should = chai.should(); var TransactionModule = bitcore.Transaction; var Transaction; +var In; +var Out; +var Script = bitcore.Script.class(); +var buffertools = require('buffertools'); +var test_data = require('./testdata'); describe('Transaction', function() { it('should initialze the main object', function() { @@ -15,14 +20,49 @@ describe('Transaction', function() { it('should be able to create class', function() { Transaction = TransactionModule.class(); should.exist(Transaction); + In = Transaction.In; + Out = Transaction.Out; + should.exist(In); + should.exist(Out); }); it('should be able to create instance', function() { var t = new Transaction(); should.exist(t); }); -}); + // Read tests from test/data/tx_valid.json + // Format is an array of arrays + // Inner arrays are either [ "comment" ] + // or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...],"], serializedTransaction, enforceP2SH + // ... where all scripts are stringified scripts. + test_data.dataTxValid.forEach(function(datum) { + if (datum.length === 3) { + it('valid tx=' + datum[1], function() { + var inputs = datum[0]; + var mapprevOutScriptPubKeys = {}; + var ins = []; + inputs.forEach(function(vin) { + var hash = vin[0]; + var index = vin[1]; + var scriptPubKey = vin[2]; + var input = new In({ + s: scriptPubKey, + q: 0xffffffff, + oTxHash: hash, + oIndex: index + }); + //mapprevOutScriptPubKeys[input] = new Script(scriptPubKey); + ins.push(input); + }); + var raw = new Buffer(datum[1]); + var tx = new Transaction(); + tx.parse(raw); + buffertools.toHex(tx.serialize()).should.equal(buffertools.toHex(raw)); + }); + } + }); +}); diff --git a/test/testdata.js b/test/testdata.js index 7eaaa0b..3d587fc 100644 --- a/test/testdata.js +++ b/test/testdata.js @@ -5,7 +5,11 @@ var fs = require('fs'); var dataValid = JSON.parse(fs.readFileSync('test/data/base58_keys_valid.json')); var dataInvalid = JSON.parse(fs.readFileSync('test/data/base58_keys_invalid.json')); var dataEncodeDecode = JSON.parse(fs.readFileSync('test/data/base58_encode_decode.json')); +var dataTxValid = JSON.parse(fs.readFileSync('test/data/tx_valid.json')); +var dataTxInvalid = JSON.parse(fs.readFileSync('test/data/tx_invalid.json')); module.exports.dataValid = dataValid; module.exports.dataInvalid = dataInvalid; module.exports.dataEncodeDecode = dataEncodeDecode; +module.exports.dataTxValid = dataTxValid; +module.exports.dataTxInvalid = dataTxInvalid; From ade6f36c34a3b0421ff7e9777656ee28f5c34c27 Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 28 Feb 2014 09:37:02 -0300 Subject: [PATCH 6/8] basic Transaction test working --- Transaction.js | 4 +--- test/test.Transaction.js | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Transaction.js b/Transaction.js index 16564e9..94531a7 100644 --- a/Transaction.js +++ b/Transaction.js @@ -26,7 +26,7 @@ function spec(b) { if (data.o) { this.o = data.o; } else { - if (data.oTxHash && typeof data.oIndex !== 'undefined') { + if (data.oTxHash && typeof data.oIndex !== 'undefined' && data.oIndex >= 0) { var hash = new Buffer(data.oTxHash, 'hex'); hash = buffertools.reverse(hash); var voutBuf = new Buffer(4); @@ -153,7 +153,6 @@ function spec(b) { bufs.push(buf); bufs.push(util.varIntBuf(this.ins.length)); - console.log(this.ins.length); this.ins.forEach(function (txin) { bufs.push(txin.serialize()); }); @@ -650,7 +649,6 @@ function spec(b) { Transaction.prototype.parse = function (parser) { if (Buffer.isBuffer(parser)) { - console.dir(parser); this._buffer = parser; parser = new Parser(parser); } diff --git a/test/test.Transaction.js b/test/test.Transaction.js index 570a0b0..989a634 100644 --- a/test/test.Transaction.js +++ b/test/test.Transaction.js @@ -55,13 +55,10 @@ describe('Transaction', function() { ins.push(input); }); - var raw = new Buffer(datum[1]); + var raw = new Buffer(datum[1], 'hex'); var tx = new Transaction(); tx.parse(raw); buffertools.toHex(tx.serialize()).should.equal(buffertools.toHex(raw)); - - - }); } }); From 40ee699453a1aad69270b904e56e742bb7b47dda Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Fri, 28 Feb 2014 16:32:10 -0300 Subject: [PATCH 7/8] working on Transaction verification and Script tests --- Script.js | 36 +- ScriptInterpreter.js | 1480 ++++++++++++++++++----------------- package.json | 3 +- test/data/script_valid.json | 10 +- test/test.Script.js | 14 + test/test.Transaction.js | 35 +- test/testdata.js | 4 + 7 files changed, 835 insertions(+), 747 deletions(-) diff --git a/Script.js b/Script.js index 82559c6..2b8bad5 100644 --- a/Script.js +++ b/Script.js @@ -280,6 +280,30 @@ function spec(b) { return this.buffer; }; + Script.fromStringContent = function(s) { + var chunks = []; + var split = s.split(' '); + console.log(split); + for (var i=0; i 2 && word.substring(0,2) === '0x') { + chunks.push(new Buffer(word.substring(2,word.length), 'hex')); + } else { + var integer = parseInt(word); + if (isNaN(integer)) { + chunks.push(Opcode.map['OP_'+word]); + } else { + var hexi = integer.toString(16); + if (hexi.length %2 === 1) hexi = '0'+hexi; + console.log(hexi); + chunks.push(new Buffer(hexi,'hex')); + } + } + + } + return Script.fromChunks(chunks); + }; + Script.prototype.getStringContent = function (truncate, maxEl) { if (truncate === null) { @@ -290,26 +314,26 @@ function spec(b) { maxEl = 15; } - var script = ''; + var s = ''; for (var i = 0, l = this.chunks.length; i < l; i++) { var chunk = this.chunks[i]; if (i > 0) { - script += " "; + s += ' '; } if (Buffer.isBuffer(chunk)) { - script += "0x"+util.formatBuffer(chunk, truncate ? null : 0); + s += '0x'+util.formatBuffer(chunk, truncate ? null : 0); } else { - script += Opcode.reverseMap[chunk]; + s += Opcode.reverseMap[chunk]; } if (maxEl && i > maxEl) { - script += " ..."; + s += ' ...'; break; } } - return script; + return s; }; Script.prototype.toString = function (truncate, maxEl) diff --git a/ScriptInterpreter.js b/ScriptInterpreter.js index 35ec400..ae42214 100644 --- a/ScriptInterpreter.js +++ b/ScriptInterpreter.js @@ -22,8 +22,7 @@ function spec(b) { this.disableUnsafeOpcodes = true; }; - ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, callback) - { + ScriptInterpreter.prototype.eval = function eval(script, tx, inIndex, hashType, callback) { if ("function" !== typeof callback) { throw new Error("ScriptInterpreter.eval() requires a callback"); } @@ -75,637 +74,679 @@ function spec(b) { } if (this.disableUnsafeOpcodes && - "number" === typeof opcode && - (opcode === OP_CAT || - opcode === OP_SUBSTR || - opcode === OP_LEFT || - opcode === OP_RIGHT || - opcode === OP_INVERT || - opcode === OP_AND || - opcode === OP_OR || - opcode === OP_XOR || - opcode === OP_2MUL || - opcode === OP_2DIV || - opcode === OP_MUL || - opcode === OP_DIV || - opcode === OP_MOD || - opcode === OP_LSHIFT || - opcode === OP_RSHIFT)) { + "number" === typeof opcode && + (opcode === OP_CAT || + opcode === OP_SUBSTR || + opcode === OP_LEFT || + opcode === OP_RIGHT || + opcode === OP_INVERT || + opcode === OP_AND || + opcode === OP_OR || + opcode === OP_XOR || + opcode === OP_2MUL || + opcode === OP_2DIV || + opcode === OP_MUL || + opcode === OP_DIV || + opcode === OP_MOD || + opcode === OP_LSHIFT || + opcode === OP_RSHIFT)) { throw new Error("Encountered a disabled opcode"); } if (exec && Buffer.isBuffer(opcode)) this.stack.push(opcode); else if (exec || (OP_IF <= opcode && opcode <= OP_ENDIF)) - switch (opcode) { - case OP_0: - this.stack.push(new Buffer([])); - break; - - case OP_1NEGATE: - case OP_1: - case OP_2: - case OP_3: - case OP_4: - case OP_5: - case OP_6: - case OP_7: - case OP_8: - case OP_9: - case OP_10: - case OP_11: - case OP_12: - case OP_13: - case OP_14: - case OP_15: - case OP_16: - this.stack.push(bigintToBuffer(opcode - OP_1 + 1)); - break; - - case OP_NOP: - case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: - case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: - break; - - case OP_IF: - case OP_NOTIF: - // if [statements] [else [statements]] endif - var value = false; - if (exec) { - value = castBool(this.stackPop()); - if (opcode === OP_NOTIF) { - value = !value; - } - } - execStack.push(value); - break; + switch (opcode) { + case OP_0: + this.stack.push(new Buffer([])); + break; + + case OP_1NEGATE: + case OP_1: + case OP_2: + case OP_3: + case OP_4: + case OP_5: + case OP_6: + case OP_7: + case OP_8: + case OP_9: + case OP_10: + case OP_11: + case OP_12: + case OP_13: + case OP_14: + case OP_15: + case OP_16: + this.stack.push(bigintToBuffer(opcode - OP_1 + 1)); + break; + + case OP_NOP: + case OP_NOP1: + case OP_NOP2: + case OP_NOP3: + case OP_NOP4: + case OP_NOP5: + case OP_NOP6: + case OP_NOP7: + case OP_NOP8: + case OP_NOP9: + case OP_NOP10: + break; + + case OP_IF: + case OP_NOTIF: + // if [statements] [else [statements]] endif + var value = false; + if (exec) { + value = castBool(this.stackPop()); + if (opcode === OP_NOTIF) { + value = !value; + } + } + execStack.push(value); + break; - case OP_ELSE: - if (execStack.length < 1) { - throw new Error("Unmatched OP_ELSE"); - } - execStack[execStack.length-1] = !execStack[execStack.length-1]; - break; + case OP_ELSE: + if (execStack.length < 1) { + throw new Error("Unmatched OP_ELSE"); + } + execStack[execStack.length - 1] = !execStack[execStack.length - 1]; + break; - case OP_ENDIF: - if (execStack.length < 1) { - throw new Error("Unmatched OP_ENDIF"); - } - execStack.pop(); - break; - - case OP_VERIFY: - var value = castBool(this.stackTop()); - if (value) { - this.stackPop(); - } else { - throw new Error("OP_VERIFY negative"); - } - break; + case OP_ENDIF: + if (execStack.length < 1) { + throw new Error("Unmatched OP_ENDIF"); + } + execStack.pop(); + break; - case OP_RETURN: - throw new Error("OP_RETURN"); + case OP_VERIFY: + var value = castBool(this.stackTop()); + if (value) { + this.stackPop(); + } else { + throw new Error("OP_VERIFY negative"); + } + break; - case OP_TOALTSTACK: - altStack.push(this.stackPop()); - break; + case OP_RETURN: + throw new Error("OP_RETURN"); - case OP_FROMALTSTACK: - if (altStack.length < 1) { - throw new Error("OP_FROMALTSTACK with alt stack empty"); - } - this.stack.push(altStack.pop()); - break; - - case OP_2DROP: - // (x1 x2 -- ) - this.stackPop(); - this.stackPop(); - break; - - case OP_2DUP: - // (x1 x2 -- x1 x2 x1 x2) - var v1 = this.stackTop(2); - var v2 = this.stackTop(1); - this.stack.push(v1); - this.stack.push(v2); - break; - - case OP_3DUP: - // (x1 x2 -- x1 x2 x1 x2) - var v1 = this.stackTop(3); - var v2 = this.stackTop(2); - var v3 = this.stackTop(1); - this.stack.push(v1); - this.stack.push(v2); - this.stack.push(v3); - break; - - case OP_2OVER: - // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) - var v1 = this.stackTop(4); - var v2 = this.stackTop(3); - this.stack.push(v1); - this.stack.push(v2); - break; - - case OP_2ROT: - // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) - var v1 = this.stackTop(6); - var v2 = this.stackTop(5); - this.stack.splice(this.stack.length - 6, 2); - this.stack.push(v1); - this.stack.push(v2); - break; - - case OP_2SWAP: - // (x1 x2 x3 x4 -- x3 x4 x1 x2) - this.stackSwap(4, 2); - this.stackSwap(3, 1); - break; - - case OP_IFDUP: - // (x - 0 | x x) - var value = this.stackTop(); - if (castBool(value)) { - this.stack.push(value); - } - break; - - case OP_DEPTH: - // -- stacksize - var value = bignum(this.stack.length); - this.stack.push(bigintToBuffer(value)); - break; - - case OP_DROP: - // (x -- ) - this.stackPop(); - break; - - case OP_DUP: - // (x -- x x) - this.stack.push(this.stackTop()); - break; - - case OP_NIP: - // (x1 x2 -- x2) - if (this.stack.length < 2) { - throw new Error("OP_NIP insufficient stack size"); - } - this.stack.splice(this.stack.length - 2, 1); - break; - - case OP_OVER: - // (x1 x2 -- x1 x2 x1) - this.stack.push(this.stackTop(2)); - break; - - case OP_PICK: - case OP_ROLL: - // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) - // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) - var n = castInt(this.stackPop()); - if (n < 0 || n >= this.stack.length) { - throw new Error("OP_PICK/OP_ROLL insufficient stack size"); - } - var value = this.stackTop(n+1); - if (opcode === OP_ROLL) { - this.stack.splice(this.stack.length - n - 1, 1); - } - this.stack.push(value); - break; - - case OP_ROT: - // (x1 x2 x3 -- x2 x3 x1) - // x2 x1 x3 after first swap - // x2 x3 x1 after second swap - this.stackSwap(3, 2); - this.stackSwap(2, 1); - break; - - case OP_SWAP: - // (x1 x2 -- x2 x1) - this.stackSwap(2, 1); - break; - - case OP_TUCK: - // (x1 x2 -- x2 x1 x2) - if (this.stack.length < 2) { - throw new Error("OP_TUCK insufficient stack size"); - } - this.stack.splice(this.stack.length - 2, 0, this.stackTop()); - break; - - case OP_CAT: - // (x1 x2 -- out) - var v1 = this.stackTop(2); - var v2 = this.stackTop(1); - this.stackPop(); - this.stackPop(); - this.stack.push(Buffer.concat([v1, v2])); - break; - - case OP_SUBSTR: - // (in begin size -- out) - var buf = this.stackTop(3); - var start = castInt(this.stackTop(2)); - var len = castInt(this.stackTop(1)); - if (start < 0 || len < 0) { - throw new Error("OP_SUBSTR start < 0 or len < 0"); - } - if ((start + len) >= buf.length) { - throw new Error("OP_SUBSTR range out of bounds"); - } - this.stackPop(); - this.stackPop(); - this.stack[this.stack.length-1] = buf.slice(start, start + len); - break; - - case OP_LEFT: - case OP_RIGHT: - // (in size -- out) - var buf = this.stackTop(2); - var size = castInt(this.stackTop(1)); - if (size < 0) { - throw new Error("OP_LEFT/OP_RIGHT size < 0"); - } - if (size > buf.length) { - size = buf.length; - } - this.stackPop(); - if (opcode === OP_LEFT) { - this.stack[this.stack.length-1] = buf.slice(0, size); - } else { - this.stack[this.stack.length-1] = buf.slice(buf.length - size); - } - break; - - case OP_SIZE: - // (in -- in size) - var value = bignum(this.stackTop().length); - this.stack.push(bigintToBuffer(value)); - break; - - case OP_INVERT: - // (in - out) - var buf = this.stackTop(); - for (var i = 0, l = buf.length; i < l; i++) { - buf[i] = ~buf[i]; - } - break; - - case OP_AND: - case OP_OR: - case OP_XOR: - // (x1 x2 - out) - var v1 = this.stackTop(2); - var v2 = this.stackTop(1); - this.stackPop(); - this.stackPop(); - var out = new Buffer(Math.max(v1.length, v2.length)); - if (opcode === OP_AND) { - for (var i = 0, l = out.length; i < l; i++) { - out[i] = v1[i] & v2[i]; - } - } else if (opcode === OP_OR) { - for (var i = 0, l = out.length; i < l; i++) { - out[i] = v1[i] | v2[i]; - } - } else if (opcode === OP_XOR) { - for (var i = 0, l = out.length; i < l; i++) { - out[i] = v1[i] ^ v2[i]; - } - } - this.stack.push(out); - break; - - case OP_EQUAL: - case OP_EQUALVERIFY: - //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL - // (x1 x2 - bool) - var v1 = this.stackTop(2); - var v2 = this.stackTop(1); - var value = buffertools.compare(v1, v2) === 0; - - // OP_NOTEQUAL is disabled because it would be too easy to say - // something like n != 1 and have some wiseguy pass in 1 with extra - // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) - //if (opcode == OP_NOTEQUAL) - // fEqual = !fEqual; - - this.stackPop(); - this.stackPop(); - this.stack.push(new Buffer([value ? 1 : 0])); - if (opcode === OP_EQUALVERIFY) { - if (value) { + case OP_TOALTSTACK: + altStack.push(this.stackPop()); + break; + + case OP_FROMALTSTACK: + if (altStack.length < 1) { + throw new Error("OP_FROMALTSTACK with alt stack empty"); + } + this.stack.push(altStack.pop()); + break; + + case OP_2DROP: + // (x1 x2 -- ) this.stackPop(); - } else { - throw new Error("OP_EQUALVERIFY negative"); - } - } - break; - - case OP_1ADD: - case OP_1SUB: - case OP_2MUL: - case OP_2DIV: - case OP_NEGATE: - case OP_ABS: - case OP_NOT: - case OP_0NOTEQUAL: - // (in -- out) - var num = castBigint(this.stackTop()); - switch (opcode) { - case OP_1ADD: num = num.add(bignum(1)); break; - case OP_1SUB: num = num.sub(bignum(1)); break; - case OP_2MUL: num = num.mul(bignum(2)); break; - case OP_2DIV: num = num.div(bignum(2)); break; - case OP_NEGATE: num = num.neg(); break; - case OP_ABS: num = num.abs(); break; - case OP_NOT: num = bignum(num.cmp(0) == 0 ? 1 : 0); break; - case OP_0NOTEQUAL: num = bignum(num.cmp(0) == 0 ? 0 : 1); break; - } - this.stack[this.stack.length-1] = bigintToBuffer(num); - break; - - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_MOD: - case OP_LSHIFT: - case OP_RSHIFT: - case OP_BOOLAND: - case OP_BOOLOR: - case OP_NUMEQUAL: - case OP_NUMEQUALVERIFY: - case OP_NUMNOTEQUAL: - case OP_LESSTHAN: - case OP_GREATERTHAN: - case OP_LESSTHANOREQUAL: - case OP_GREATERTHANOREQUAL: - case OP_MIN: - case OP_MAX: - // (x1 x2 -- out) - var v1 = castBigint(this.stackTop(2)); - var v2 = castBigint(this.stackTop(1)); - var num; - switch (opcode) { - case OP_ADD: num = v1.add(v2); break; - case OP_SUB: num = v1.sub(v2); break; - case OP_MUL: num = v1.mul(v2); break; - case OP_DIV: num = v1.div(v2); break; - case OP_MOD: num = v1.mod(v2); break; - - case OP_LSHIFT: - if (v2.cmp(0) < 0 || v2.cmp(2048) > 0) { - throw new Error("OP_LSHIFT parameter out of bounds"); - } - num = v1.shiftLeft(v2); - break; - - case OP_RSHIFT: - if (v2.cmp(0) < 0 || v2.cmp(2048) > 0) { - throw new Error("OP_RSHIFT parameter out of bounds"); - } - num = v1.shiftRight(v2); - break; - - case OP_BOOLAND: - num = bignum((v1.cmp(0) != 0 && v2.cmp(0) != 0) ? 1 : 0); - break; - - case OP_BOOLOR: - num = bignum((v1.cmp(0) != 0 || v2.cmp(0) != 0) ? 1 : 0); - break; - - case OP_NUMEQUAL: - case OP_NUMEQUALVERIFY: - num = bignum(v1.cmp(v2) == 0 ? 1 : 0); - break; - - case OP_NUMNOTEQUAL:; - num = bignum(v1.cmp(v2) != 0 ? 1 : 0); - break; - - case OP_LESSTHAN: - num = bignum(v1.lt(v2) ? 1 : 0); - break; - - case OP_GREATERTHAN: - num = bignum(v1.gt(v2) ? 1 : 0); - break; - - case OP_LESSTHANOREQUAL: - num = bignum(v1.gt(v2) ? 0 : 1); - break; - - case OP_GREATERTHANOREQUAL: - num = bignum(v1.lt(v2) ? 0 : 1); - break; - - case OP_MIN: num = (v1.lt(v2) ? v1 : v2); break; - case OP_MAX: num = (v1.gt(v2) ? v1 : v2); break; - } - this.stackPop(); - this.stackPop(); - this.stack.push(bigintToBuffer(num)); + this.stackPop(); + break; + + case OP_2DUP: + // (x1 x2 -- x1 x2 x1 x2) + var v1 = this.stackTop(2); + var v2 = this.stackTop(1); + this.stack.push(v1); + this.stack.push(v2); + break; + + case OP_3DUP: + // (x1 x2 -- x1 x2 x1 x2) + var v1 = this.stackTop(3); + var v2 = this.stackTop(2); + var v3 = this.stackTop(1); + this.stack.push(v1); + this.stack.push(v2); + this.stack.push(v3); + break; + + case OP_2OVER: + // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) + var v1 = this.stackTop(4); + var v2 = this.stackTop(3); + this.stack.push(v1); + this.stack.push(v2); + break; + + case OP_2ROT: + // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) + var v1 = this.stackTop(6); + var v2 = this.stackTop(5); + this.stack.splice(this.stack.length - 6, 2); + this.stack.push(v1); + this.stack.push(v2); + break; + + case OP_2SWAP: + // (x1 x2 x3 x4 -- x3 x4 x1 x2) + this.stackSwap(4, 2); + this.stackSwap(3, 1); + break; + + case OP_IFDUP: + // (x - 0 | x x) + var value = this.stackTop(); + if (castBool(value)) { + this.stack.push(value); + } + break; + + case OP_DEPTH: + // -- stacksize + var value = bignum(this.stack.length); + this.stack.push(bigintToBuffer(value)); + break; - if (opcode === OP_NUMEQUALVERIFY) { - if (castBool(this.stackTop())) { + case OP_DROP: + // (x -- ) this.stackPop(); - } else { - throw new Error("OP_NUMEQUALVERIFY negative"); - } - } - break; - - case OP_WITHIN: - // (x min max -- out) - var v1 = castBigint(this.stackTop(3)); - var v2 = castBigint(this.stackTop(2)); - var v3 = castBigint(this.stackTop(1)); - this.stackPop(); - this.stackPop(); - this.stackPop(); - var value = v1.cmp(v2) >= 0 && v1.cmp(v3) < 0; - this.stack.push(bigintToBuffer(value ? 1 : 0)); - break; - - case OP_RIPEMD160: - case OP_SHA1: - case OP_SHA256: - case OP_HASH160: - case OP_HASH256: - // (in -- hash) - var value = this.stackPop(); - var hash; - if (opcode === OP_RIPEMD160) { - hash = Util.ripe160(value); - } else if (opcode === OP_SHA1) { - hash = Util.sha1(value); - } else if (opcode === OP_SHA256) { - hash = Util.sha256(value); - } else if (opcode === OP_HASH160) { - hash = Util.sha256ripe160(value); - } else if (opcode === OP_HASH256) { - hash = Util.twoSha256(value); - } - this.stack.push(hash); - break; - - case OP_CODESEPARATOR: - // Hash starts after the code separator - hashStart = pc; - break; - - case OP_CHECKSIG: - case OP_CHECKSIGVERIFY: - // (sig pubkey -- bool) - var sig = this.stackTop(2); - var pubkey = this.stackTop(1); - - // Get the part of this script since the last OP_CODESEPARATOR - var scriptChunks = script.chunks.slice(hashStart); - - // Convert to binary - var scriptCode = Script.fromChunks(scriptChunks); - - // Remove signature if present (a signature can't sign itself) - scriptCode.findAndDelete(sig); - - // Verify signature - checkSig(sig, pubkey, scriptCode, tx, inIndex, hashType, function (e, result) { - try { - var success; - - if (e) { - // We intentionally ignore errors during signature verification and - // treat these cases as an invalid signature. - success = false; + break; + + case OP_DUP: + // (x -- x x) + this.stack.push(this.stackTop()); + break; + + case OP_NIP: + // (x1 x2 -- x2) + if (this.stack.length < 2) { + throw new Error("OP_NIP insufficient stack size"); + } + this.stack.splice(this.stack.length - 2, 1); + break; + + case OP_OVER: + // (x1 x2 -- x1 x2 x1) + this.stack.push(this.stackTop(2)); + break; + + case OP_PICK: + case OP_ROLL: + // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) + // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) + var n = castInt(this.stackPop()); + if (n < 0 || n >= this.stack.length) { + throw new Error("OP_PICK/OP_ROLL insufficient stack size"); + } + var value = this.stackTop(n + 1); + if (opcode === OP_ROLL) { + this.stack.splice(this.stack.length - n - 1, 1); + } + this.stack.push(value); + break; + + case OP_ROT: + // (x1 x2 x3 -- x2 x3 x1) + // x2 x1 x3 after first swap + // x2 x3 x1 after second swap + this.stackSwap(3, 2); + this.stackSwap(2, 1); + break; + + case OP_SWAP: + // (x1 x2 -- x2 x1) + this.stackSwap(2, 1); + break; + + case OP_TUCK: + // (x1 x2 -- x2 x1 x2) + if (this.stack.length < 2) { + throw new Error("OP_TUCK insufficient stack size"); + } + this.stack.splice(this.stack.length - 2, 0, this.stackTop()); + break; + + case OP_CAT: + // (x1 x2 -- out) + var v1 = this.stackTop(2); + var v2 = this.stackTop(1); + this.stackPop(); + this.stackPop(); + this.stack.push(Buffer.concat([v1, v2])); + break; + + case OP_SUBSTR: + // (in begin size -- out) + var buf = this.stackTop(3); + var start = castInt(this.stackTop(2)); + var len = castInt(this.stackTop(1)); + if (start < 0 || len < 0) { + throw new Error("OP_SUBSTR start < 0 or len < 0"); + } + if ((start + len) >= buf.length) { + throw new Error("OP_SUBSTR range out of bounds"); + } + this.stackPop(); + this.stackPop(); + this.stack[this.stack.length - 1] = buf.slice(start, start + len); + break; + + case OP_LEFT: + case OP_RIGHT: + // (in size -- out) + var buf = this.stackTop(2); + var size = castInt(this.stackTop(1)); + if (size < 0) { + throw new Error("OP_LEFT/OP_RIGHT size < 0"); + } + if (size > buf.length) { + size = buf.length; + } + this.stackPop(); + if (opcode === OP_LEFT) { + this.stack[this.stack.length - 1] = buf.slice(0, size); } else { - success = result; + this.stack[this.stack.length - 1] = buf.slice(buf.length - size); + } + break; + + case OP_SIZE: + // (in -- in size) + var value = bignum(this.stackTop().length); + this.stack.push(bigintToBuffer(value)); + break; + + case OP_INVERT: + // (in - out) + var buf = this.stackTop(); + for (var i = 0, l = buf.length; i < l; i++) { + buf[i] = ~buf[i]; + } + break; + + case OP_AND: + case OP_OR: + case OP_XOR: + // (x1 x2 - out) + var v1 = this.stackTop(2); + var v2 = this.stackTop(1); + this.stackPop(); + this.stackPop(); + var out = new Buffer(Math.max(v1.length, v2.length)); + if (opcode === OP_AND) { + for (var i = 0, l = out.length; i < l; i++) { + out[i] = v1[i] & v2[i]; + } + } else if (opcode === OP_OR) { + for (var i = 0, l = out.length; i < l; i++) { + out[i] = v1[i] | v2[i]; + } + } else if (opcode === OP_XOR) { + for (var i = 0, l = out.length; i < l; i++) { + out[i] = v1[i] ^ v2[i]; + } } + this.stack.push(out); + break; + + case OP_EQUAL: + case OP_EQUALVERIFY: + //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL + // (x1 x2 - bool) + var v1 = this.stackTop(2); + var v2 = this.stackTop(1); + var value = buffertools.compare(v1, v2) === 0; + + // OP_NOTEQUAL is disabled because it would be too easy to say + // something like n != 1 and have some wiseguy pass in 1 with extra + // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) + //if (opcode == OP_NOTEQUAL) + // fEqual = !fEqual; - // Update stack this.stackPop(); this.stackPop(); - this.stack.push(new Buffer([success ? 1 : 0])); - if (opcode === OP_CHECKSIGVERIFY) { - if (success) { + this.stack.push(new Buffer([value ? 1 : 0])); + if (opcode === OP_EQUALVERIFY) { + if (value) { this.stackPop(); } else { - throw new Error("OP_CHECKSIGVERIFY negative"); + throw new Error("OP_EQUALVERIFY negative"); } } + break; + + case OP_1ADD: + case OP_1SUB: + case OP_2MUL: + case OP_2DIV: + case OP_NEGATE: + case OP_ABS: + case OP_NOT: + case OP_0NOTEQUAL: + // (in -- out) + var num = castBigint(this.stackTop()); + switch (opcode) { + case OP_1ADD: + num = num.add(bignum(1)); + break; + case OP_1SUB: + num = num.sub(bignum(1)); + break; + case OP_2MUL: + num = num.mul(bignum(2)); + break; + case OP_2DIV: + num = num.div(bignum(2)); + break; + case OP_NEGATE: + num = num.neg(); + break; + case OP_ABS: + num = num.abs(); + break; + case OP_NOT: + num = bignum(num.cmp(0) == 0 ? 1 : 0); + break; + case OP_0NOTEQUAL: + num = bignum(num.cmp(0) == 0 ? 0 : 1); + break; + } + this.stack[this.stack.length - 1] = bigintToBuffer(num); + break; + + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_MOD: + case OP_LSHIFT: + case OP_RSHIFT: + case OP_BOOLAND: + case OP_BOOLOR: + case OP_NUMEQUAL: + case OP_NUMEQUALVERIFY: + case OP_NUMNOTEQUAL: + case OP_LESSTHAN: + case OP_GREATERTHAN: + case OP_LESSTHANOREQUAL: + case OP_GREATERTHANOREQUAL: + case OP_MIN: + case OP_MAX: + // (x1 x2 -- out) + var v1 = castBigint(this.stackTop(2)); + var v2 = castBigint(this.stackTop(1)); + var num; + switch (opcode) { + case OP_ADD: + num = v1.add(v2); + break; + case OP_SUB: + num = v1.sub(v2); + break; + case OP_MUL: + num = v1.mul(v2); + break; + case OP_DIV: + num = v1.div(v2); + break; + case OP_MOD: + num = v1.mod(v2); + break; + + case OP_LSHIFT: + if (v2.cmp(0) < 0 || v2.cmp(2048) > 0) { + throw new Error("OP_LSHIFT parameter out of bounds"); + } + num = v1.shiftLeft(v2); + break; - // Run next step - executeStep.call(this, cb); - } catch(e) { - cb(e); - } - }.bind(this)); - - // Note that for asynchronous opcodes we have to return here to prevent - // the next opcode from being executed. - return; - - case OP_CHECKMULTISIG: - case OP_CHECKMULTISIGVERIFY: - // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) - var keysCount = castInt(this.stackPop()); - if (keysCount < 0 || keysCount > 20) { - throw new Error("OP_CHECKMULTISIG keysCount out of bounds"); - } - opCount += keysCount; - if (opCount > 201) { - throw new Error("Opcode limit exceeded (>200)"); - } - var keys = []; - for (var i = 0, l = keysCount; i < l; i++) { - keys.push(this.stackPop()); - } - var sigsCount = castInt(this.stackPop()); - if (sigsCount < 0 || sigsCount > keysCount) { - throw new Error("OP_CHECKMULTISIG sigsCount out of bounds"); - } - var sigs = []; - for (var i = 0, l = sigsCount; i < l; i++) { - sigs.push(this.stackPop()); - } - - // The original client has a bug where it pops an extra element off the - // stack. It can't be fixed without causing a chain split and we need to - // imitate this behavior as well. - this.stackPop(); - - // Get the part of this script since the last OP_CODESEPARATOR - var scriptChunks = script.chunks.slice(hashStart); + case OP_RSHIFT: + if (v2.cmp(0) < 0 || v2.cmp(2048) > 0) { + throw new Error("OP_RSHIFT parameter out of bounds"); + } + num = v1.shiftRight(v2); + break; + + case OP_BOOLAND: + num = bignum((v1.cmp(0) != 0 && v2.cmp(0) != 0) ? 1 : 0); + break; + + case OP_BOOLOR: + num = bignum((v1.cmp(0) != 0 || v2.cmp(0) != 0) ? 1 : 0); + break; + + case OP_NUMEQUAL: + case OP_NUMEQUALVERIFY: + num = bignum(v1.cmp(v2) == 0 ? 1 : 0); + break; + + case OP_NUMNOTEQUAL: + ; + num = bignum(v1.cmp(v2) != 0 ? 1 : 0); + break; + + case OP_LESSTHAN: + num = bignum(v1.lt(v2) ? 1 : 0); + break; + + case OP_GREATERTHAN: + num = bignum(v1.gt(v2) ? 1 : 0); + break; + + case OP_LESSTHANOREQUAL: + num = bignum(v1.gt(v2) ? 0 : 1); + break; + + case OP_GREATERTHANOREQUAL: + num = bignum(v1.lt(v2) ? 0 : 1); + break; + + case OP_MIN: + num = (v1.lt(v2) ? v1 : v2); + break; + case OP_MAX: + num = (v1.gt(v2) ? v1 : v2); + break; + } + this.stackPop(); + this.stackPop(); + this.stack.push(bigintToBuffer(num)); - // Convert to binary - var scriptCode = Script.fromChunks(scriptChunks); + if (opcode === OP_NUMEQUALVERIFY) { + if (castBool(this.stackTop())) { + this.stackPop(); + } else { + throw new Error("OP_NUMEQUALVERIFY negative"); + } + } + break; - // Drop the signatures, since a signature can't sign itself - sigs.forEach(function (sig) { - scriptCode.findAndDelete(sig); - }); + case OP_WITHIN: + // (x min max -- out) + var v1 = castBigint(this.stackTop(3)); + var v2 = castBigint(this.stackTop(2)); + var v3 = castBigint(this.stackTop(1)); + this.stackPop(); + this.stackPop(); + this.stackPop(); + var value = v1.cmp(v2) >= 0 && v1.cmp(v3) < 0; + this.stack.push(bigintToBuffer(value ? 1 : 0)); + break; + + case OP_RIPEMD160: + case OP_SHA1: + case OP_SHA256: + case OP_HASH160: + case OP_HASH256: + // (in -- hash) + var value = this.stackPop(); + var hash; + if (opcode === OP_RIPEMD160) { + hash = Util.ripe160(value); + } else if (opcode === OP_SHA1) { + hash = Util.sha1(value); + } else if (opcode === OP_SHA256) { + hash = Util.sha256(value); + } else if (opcode === OP_HASH160) { + hash = Util.sha256ripe160(value); + } else if (opcode === OP_HASH256) { + hash = Util.twoSha256(value); + } + this.stack.push(hash); + break; + + case OP_CODESEPARATOR: + // Hash starts after the code separator + hashStart = pc; + break; + + case OP_CHECKSIG: + case OP_CHECKSIGVERIFY: + // (sig pubkey -- bool) + var sig = this.stackTop(2); + var pubkey = this.stackTop(1); + + // Get the part of this script since the last OP_CODESEPARATOR + var scriptChunks = script.chunks.slice(hashStart); + + // Convert to binary + var scriptCode = Script.fromChunks(scriptChunks); + + // Remove signature if present (a signature can't sign itself) + scriptCode.findAndDelete(sig); + + // Verify signature + checkSig(sig, pubkey, scriptCode, tx, inIndex, hashType, function(e, result) { + try { + var success; + + if (e) { + // We intentionally ignore errors during signature verification and + // treat these cases as an invalid signature. + success = false; + } else { + success = result; + } - var success = true, isig = 0, ikey = 0; - checkMultiSigStep.call(this); + // Update stack + this.stackPop(); + this.stackPop(); + this.stack.push(new Buffer([success ? 1 : 0])); + if (opcode === OP_CHECKSIGVERIFY) { + if (success) { + this.stackPop(); + } else { + throw new Error("OP_CHECKSIGVERIFY negative"); + } + } - function checkMultiSigStep() { - try { - if (success && sigsCount > 0) { - var sig = sigs[isig]; - var key = keys[ikey]; + // Run next step + executeStep.call(this, cb); + } catch (e) { + cb(e); + } + }.bind(this)); + + // Note that for asynchronous opcodes we have to return here to prevent + // the next opcode from being executed. + return; + + case OP_CHECKMULTISIG: + case OP_CHECKMULTISIGVERIFY: + // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) + var keysCount = castInt(this.stackPop()); + if (keysCount < 0 || keysCount > 20) { + throw new Error("OP_CHECKMULTISIG keysCount out of bounds"); + } + opCount += keysCount; + if (opCount > 201) { + throw new Error("Opcode limit exceeded (>200)"); + } + var keys = []; + for (var i = 0, l = keysCount; i < l; i++) { + keys.push(this.stackPop()); + } + var sigsCount = castInt(this.stackPop()); + if (sigsCount < 0 || sigsCount > keysCount) { + throw new Error("OP_CHECKMULTISIG sigsCount out of bounds"); + } + var sigs = []; + for (var i = 0, l = sigsCount; i < l; i++) { + sigs.push(this.stackPop()); + } - checkSig(sig, key, scriptCode, tx, inIndex, hashType, function (e, result) { - try { - if (!e && result) { - isig++; - sigsCount--; - } else { - ikey++; - keysCount--; + // The original client has a bug where it pops an extra element off the + // stack. It can't be fixed without causing a chain split and we need to + // imitate this behavior as well. + this.stackPop(); - // If there are more signatures than keys left, then too many - // signatures have failed - if (sigsCount > keysCount) { - success = false; + // Get the part of this script since the last OP_CODESEPARATOR + var scriptChunks = script.chunks.slice(hashStart); + + // Convert to binary + var scriptCode = Script.fromChunks(scriptChunks); + + // Drop the signatures, since a signature can't sign itself + sigs.forEach(function(sig) { + scriptCode.findAndDelete(sig); + }); + + var success = true, + isig = 0, + ikey = 0; + checkMultiSigStep.call(this); + + function checkMultiSigStep() { + try { + if (success && sigsCount > 0) { + var sig = sigs[isig]; + var key = keys[ikey]; + + checkSig(sig, key, scriptCode, tx, inIndex, hashType, function(e, result) { + try { + if (!e && result) { + isig++; + sigsCount--; + } else { + ikey++; + keysCount--; + + // If there are more signatures than keys left, then too many + // signatures have failed + if (sigsCount > keysCount) { + success = false; + } + } + + checkMultiSigStep.call(this); + } catch (e) { + cb(e); + } + }.bind(this)); + } else { + this.stack.push(new Buffer([success ? 1 : 0])); + if (opcode === OP_CHECKMULTISIGVERIFY) { + if (success) { + this.stackPop(); + } else { + throw new Error("OP_CHECKMULTISIGVERIFY negative"); } } - checkMultiSigStep.call(this); - } catch (e) { - cb(e); - } - }.bind(this)); - } else { - this.stack.push(new Buffer([success ? 1 : 0])); - if (opcode === OP_CHECKMULTISIGVERIFY) { - if (success) { - this.stackPop(); - } else { - throw new Error("OP_CHECKMULTISIGVERIFY negative"); + // Run next step + executeStep.call(this, cb); } + } catch (e) { + cb(e); } + }; - // Run next step - executeStep.call(this, cb); - } - } catch(e) { - cb(e); - } - }; - - // Note that for asynchronous opcodes we have to return here to prevent - // the next opcode from being executed. - return; + // Note that for asynchronous opcodes we have to return here to prevent + // the next opcode from being executed. + return; - default: - throw new Error("Unknown opcode encountered"); - } + default: + console.log('opcode '+opcode); + throw new Error("Unknown opcode encountered"); + } // Size limits if ((this.stack.length + altStack.length) > 1000) { @@ -721,26 +762,25 @@ function spec(b) { executeStep.call(this, cb); } } catch (e) { - log.debug("Script aborted: "+ - (e.message ? e : e)); + log.debug("Script aborted: " + + (e.message ? e : e)); cb(e); } } }; ScriptInterpreter.prototype.evalTwo = - function evalTwo(scriptSig, scriptPubkey, tx, n, hashType, callback) - { - var self = this; + function evalTwo(scriptSig, scriptPubkey, tx, n, hashType, callback) { + var self = this; - self.eval(scriptSig, tx, n, hashType, function (e) { - if (e) { - callback(e) - return; - } + self.eval(scriptSig, tx, n, hashType, function(e) { + if (e) { + callback(e) + return; + } - self.eval(scriptPubkey, tx, n, hashType, callback); - }); + self.eval(scriptPubkey, tx, n, hashType, callback); + }); }; /** @@ -757,11 +797,10 @@ function spec(b) { throw new Error('ScriptInterpreter.stackTop(): Stack underrun'); } - return this.stack[this.stack.length-offset]; + return this.stack[this.stack.length - offset]; }; - ScriptInterpreter.prototype.stackBack = function stackBack() - { + ScriptInterpreter.prototype.stackBack = function stackBack() { return this.stack[-1]; }; @@ -782,7 +821,7 @@ function spec(b) { } var s = this.stack, - l = s.length; + l = s.length; var tmp = s[l - a]; s[l - a] = s[l - b]; @@ -796,7 +835,7 @@ function spec(b) { * integer. Any longer Buffer is converted to a hex string. */ ScriptInterpreter.prototype.getPrimitiveStack = function getPrimitiveStack() { - return this.stack.map(function (entry) { + return this.stack.map(function(entry) { if (entry.length > 2) { return buffertools.toHex(entry.slice(0)); } @@ -813,7 +852,7 @@ function spec(b) { for (var i = 0, l = v.length; i < l; i++) { if (v[i] != 0) { // Negative zero is still zero - if (i == (l-1) && v[i] == 0x80) { + if (i == (l - 1) && v[i] == 0x80) { return false; } return true; @@ -850,7 +889,7 @@ function spec(b) { v = bignum(v); } - var b,c; + var b, c; var cmp = v.cmp(0); if (cmp > 0) { @@ -884,148 +923,143 @@ function spec(b) { throw new Error("Empty stack after script evaluation"); } - return castBool(this.stack[this.stack.length-1]); + return castBool(this.stack[this.stack.length - 1]); }; ScriptInterpreter.verify = - function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) - { - if ("function" !== typeof callback) { - throw new Error("ScriptInterpreter.verify() requires a callback"); - } + function verify(scriptSig, scriptPubKey, txTo, n, hashType, callback) { + if ("function" !== typeof callback) { + throw new Error("ScriptInterpreter.verify() requires a callback"); + } - // Create execution environment - var si = new ScriptInterpreter(); + // Create execution environment + var si = new ScriptInterpreter(); - // Evaluate scripts - si.evalTwo(scriptSig, scriptPubKey, txTo, n, hashType, function (err) { - if (err) { - callback(err); - return; - } + // Evaluate scripts + si.evalTwo(scriptSig, scriptPubKey, txTo, n, hashType, function(err) { + if (err) { + callback(err); + return; + } - // Cast result to bool - try { - var result = si.getResult(); - } catch (err) { - callback(err); - return; - } + // Cast result to bool + try { + var result = si.getResult(); + } catch (err) { + callback(err); + return; + } - callback(null, result); - }); + callback(null, result); + }); - return si; + return si; }; function verifyStep4(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy) - { - if (siCopy.stack.length == 0) { - callback(null, false); - return; - } - - callback(null, castBool(siCopy.stackBack())); + hashType, opts, callback, si, siCopy) { + if (siCopy.stack.length == 0) { + callback(null, false); + return; + } + + callback(null, castBool(siCopy.stackBack())); } function verifyStep3(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy) - { - if (si.stack.length == 0) { - callback(null, false); - return; - } + hashType, opts, callback, si, siCopy) { + if (si.stack.length == 0) { + callback(null, false); + return; + } if (castBool(si.stackBack()) == false) { - callback(null, false); - return; - } + callback(null, false); + return; + } - // if not P2SH, we're done - if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) { - callback(null, true); - return; - } + // if not P2SH, we're done + if (!opts.verifyP2SH || !scriptPubKey.isP2SH()) { + callback(null, true); + return; + } - if (!scriptSig.isPushOnly()) { - callback(null, false); - return; - } + if (!scriptSig.isPushOnly()) { + callback(null, false); + return; + } - assert.notEqual(siCopy.length, 0); + assert.notEqual(siCopy.length, 0); - var subscript = new Script(siCopy.stackPop()); + var subscript = new Script(siCopy.stackPop()); - ok = true; - siCopy.eval(subscript, txTo, nIn, hashType, function (err) { - if (err) - callback(err); - else - verifyStep4(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy); - }); + ok = true; + siCopy.eval(subscript, txTo, nIn, hashType, function(err) { + if (err) + callback(err); + else + verifyStep4(scriptSig, scriptPubKey, txTo, nIn, + hashType, opts, callback, si, siCopy); + }); } function verifyStep2(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy) - { - if (opts.verifyP2SH) { - si.stack.forEach(function(item) { - siCopy.stack.push(item); - }); - } + hashType, opts, callback, si, siCopy) { + if (opts.verifyP2SH) { + si.stack.forEach(function(item) { + siCopy.stack.push(item); + }); + } - si.eval(scriptPubKey, txTo, nIn, hashType, function (err) { - if (err) - callback(err); - else - verifyStep3(scriptSig, scriptPubKey, txTo, nIn, - hashType, opts, callback, si, siCopy); - }); + si.eval(scriptPubKey, txTo, nIn, hashType, function(err) { + if (err) + callback(err); + else + verifyStep3(scriptSig, scriptPubKey, txTo, nIn, + hashType, opts, callback, si, siCopy); + }); } ScriptInterpreter.verifyFull = - function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType, - opts, callback) - { - var si = new ScriptInterpreter(); - var siCopy = new ScriptInterpreter(); - - si.eval(scriptSig, txTo, nIn, hashType, function (err) { - if (err) - callback(err); - else - verifyStep2(scriptSig, scriptPubKey, txTo, nIn, + function verifyFull(scriptSig, scriptPubKey, txTo, nIn, hashType, + opts, callback) { + var si = new ScriptInterpreter(); + var siCopy = new ScriptInterpreter(); + + si.eval(scriptSig, txTo, nIn, hashType, function(err) { + if (err) + callback(err); + else + verifyStep2(scriptSig, scriptPubKey, txTo, nIn, hashType, opts, callback, si, siCopy); - }); + }); }; var checkSig = ScriptInterpreter.checkSig = - function (sig, pubkey, scriptCode, tx, n, hashType, callback) { - if (!sig.length) { - callback(null, false); - return; - } + function(sig, pubkey, scriptCode, tx, n, hashType, callback) { + if (!sig.length) { + callback(null, false); + return; + } - if (hashType == 0) { - hashType = sig[sig.length -1]; - } else if (hashType != sig[sig.length -1]) { - callback(null, false); - return; - } - sig = sig.slice(0, sig.length-1); + if (hashType == 0) { + hashType = sig[sig.length - 1]; + } else if (hashType != sig[sig.length - 1]) { + callback(null, false); + return; + } + sig = sig.slice(0, sig.length - 1); - try { - // Signature verification requires a special hash procedure - var hash = tx.hashForSignature(scriptCode, n, hashType); + try { + // Signature verification requires a special hash procedure + var hash = tx.hashForSignature(scriptCode, n, hashType); - // Verify signature - var key = new Util.BitcoinKey(); - key.public = pubkey; - key.verifySignature(hash, sig, callback); - } catch (err) { - callback(null, false); - } + // Verify signature + var key = new Util.BitcoinKey(); + key.public = pubkey; + key.verifySignature(hash, sig, callback); + } catch (err) { + callback(null, false); + } }; return ScriptInterpreter; diff --git a/package.json b/package.json index ad522b4..68fb6e2 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,8 @@ "browserify-bignum": "git://github.com/maraoz/browserify-bignum.git", "browserify-buffertools": "~1.0.2", "chai": "~1.9.0", - "brfs": "~1.0.0" + "brfs": "~1.0.0", + "async": "~0.2.10" }, "license": "MIT" } diff --git a/test/data/script_valid.json b/test/data/script_valid.json index e4c181c..ae3390f 100644 --- a/test/data/script_valid.json +++ b/test/data/script_valid.json @@ -1,8 +1,8 @@ [ ["0x01 0x0b", "11 EQUAL", "push 1 byte"], -["0x02 0x417a", "'Az' EQUAL"], +["0x02 0x417a", "0x417a EQUAL"], ["0x4b 0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a", - "'Azzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz' EQUAL", "push 75 bytes"], + "0x417a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a7a EQUAL", "push 75 bytes"], ["0x4c 0x01 0x07","7 EQUAL", "0x4c is OP_PUSHDATA1"], ["0x4d 0x0100 0x08","8 EQUAL", "0x4d is OP_PUSHDATA2"], @@ -11,7 +11,7 @@ ["0x4c 0x00","0 EQUAL"], ["0x4d 0x0000","0 EQUAL"], ["0x4e 0x00000000","0 EQUAL"], -["0x4f 1000 ADD","999 EQUAL"], +["0x4f 0x03e8 ADD","0x03e7 EQUAL"], ["0", "IF 0x50 ENDIF 1", "0x50 is reserved (ok if not executed)"], ["0x51", "0x5f ADD 0x60 EQUAL", "0x51 through 0x60 push 1 through 16 onto stack"], ["1","NOP"], @@ -53,8 +53,8 @@ ["1 1", "VERIFY"], -["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 21 EQUAL"], -["'gavin_was_here' TOALTSTACK 11 FROMALTSTACK", "'gavin_was_here' EQUALVERIFY 11 EQUAL"], +["10 0 11 TOALTSTACK DROP FROMALTSTACK", "ADD 0x15 EQUAL"], +["0x676176696e5f7761735f68657265 TOALTSTACK 11 FROMALTSTACK", "0x676176696e5f7761735f68657265 EQUALVERIFY 11 EQUAL"], ["0 IFDUP", "DEPTH 1 EQUALVERIFY 0 EQUAL"], ["1 IFDUP", "DEPTH 2 EQUALVERIFY 1 EQUALVERIFY 1 EQUAL"], diff --git a/test/test.Script.js b/test/test.Script.js index bf2a71c..9b04dae 100644 --- a/test/test.Script.js +++ b/test/test.Script.js @@ -9,6 +9,7 @@ var ScriptModule = bitcore.Script; var Address = bitcore.Address.class(); var networks = bitcore.networks; var Script; +var test_data = require('./testdata'); describe('Script', function() { it('should initialze the main object', function() { @@ -82,4 +83,17 @@ describe('Script', function() { script.chunks[0].should.equal(0); }); }); + + + + test_data.dataScriptValid.forEach(function(datum) { + if (datum.length < 2) throw new Error('Invalid test data'); + var human = datum[1]; + it('should parse script from human readable ' + human, function() { + Script.fromStringContent(human).getStringContent(false, null).should.equal(human); + }); + + + }); + }); diff --git a/test/test.Transaction.js b/test/test.Transaction.js index 989a634..fbc3a9e 100644 --- a/test/test.Transaction.js +++ b/test/test.Transaction.js @@ -12,6 +12,7 @@ var Out; var Script = bitcore.Script.class(); var buffertools = require('buffertools'); var test_data = require('./testdata'); +var async = require('async'); describe('Transaction', function() { it('should initialze the main object', function() { @@ -37,28 +38,38 @@ describe('Transaction', function() { // ... where all scripts are stringified scripts. test_data.dataTxValid.forEach(function(datum) { if (datum.length === 3) { - it('valid tx=' + datum[1], function() { + it.skip('valid tx=' + datum[1], function(done) { var inputs = datum[0]; - var mapprevOutScriptPubKeys = {}; - var ins = []; + var map = {}; inputs.forEach(function(vin) { var hash = vin[0]; var index = vin[1]; - var scriptPubKey = vin[2]; - var input = new In({ - s: scriptPubKey, - q: 0xffffffff, - oTxHash: hash, - oIndex: index - }); - //mapprevOutScriptPubKeys[input] = new Script(scriptPubKey); - ins.push(input); + var scriptPubKey = new Script(new Buffer(vin[2])); + map[[hash, index]] = scriptPubKey;//Script.fromStringContent(scriptPubKey); + console.log(scriptPubKey.getStringContent()); + console.log('********************************'); }); var raw = new Buffer(datum[1], 'hex'); var tx = new Transaction(); tx.parse(raw); + buffertools.toHex(tx.serialize()).should.equal(buffertools.toHex(raw)); + + var i = 0; + var stx = tx.getStandardizedObject(); + async.eachSeries(tx.ins, + function(txin, next) { + var scriptPubKey = map[[stx.in[i].prev_out.hash, stx.in[i].prev_out.n]]; + i += 1; + next(); + + }, + function(err) { + should.not.exist(err); + done(); + } + ); }); } }); diff --git a/test/testdata.js b/test/testdata.js index 3d587fc..9d62e9d 100644 --- a/test/testdata.js +++ b/test/testdata.js @@ -7,9 +7,13 @@ var dataInvalid = JSON.parse(fs.readFileSync('test/data/base58_keys_invalid.json var dataEncodeDecode = JSON.parse(fs.readFileSync('test/data/base58_encode_decode.json')); var dataTxValid = JSON.parse(fs.readFileSync('test/data/tx_valid.json')); var dataTxInvalid = JSON.parse(fs.readFileSync('test/data/tx_invalid.json')); +var dataScriptValid = JSON.parse(fs.readFileSync('test/data/script_valid.json')); +var dataScriptInvalid = JSON.parse(fs.readFileSync('test/data/script_invalid.json')); module.exports.dataValid = dataValid; module.exports.dataInvalid = dataInvalid; module.exports.dataEncodeDecode = dataEncodeDecode; module.exports.dataTxValid = dataTxValid; module.exports.dataTxInvalid = dataTxInvalid; +module.exports.dataScriptValid = dataScriptValid; +module.exports.dataScriptInvalid = dataScriptInvalid; From 05c55381620d9a9f503a73e62ac722b35577725a Mon Sep 17 00:00:00 2001 From: Manuel Araoz Date: Thu, 6 Mar 2014 17:23:00 -0300 Subject: [PATCH 8/8] script parser code added and tested --- Script.js | 288 ++++++++++++++++++--------------------- test/test.Script.js | 5 +- test/test.Transaction.js | 19 +-- test/test.util.js | 19 +++ util/util.js | 24 ++++ 5 files changed, 180 insertions(+), 175 deletions(-) diff --git a/Script.js b/Script.js index 2b8bad5..322b4e6 100644 --- a/Script.js +++ b/Script.js @@ -31,7 +31,7 @@ function spec(b) { ]; function Script(buffer) { - if(buffer) { + if (buffer) { this.buffer = buffer; } else { this.buffer = util.EMPTY_BUFFER; @@ -41,13 +41,13 @@ function spec(b) { }; this.class = Script; - Script.TX_UNKNOWN=TX_UNKNOWN; - Script.TX_PUBKEY=TX_PUBKEY; - Script.TX_PUBKEYHASH=TX_PUBKEYHASH; - Script.TX_MULTISIG=TX_MULTISIG; - Script.TX_SCRIPTHASH=TX_SCRIPTHASH; + Script.TX_UNKNOWN = TX_UNKNOWN; + Script.TX_PUBKEY = TX_PUBKEY; + Script.TX_PUBKEYHASH = TX_PUBKEYHASH; + Script.TX_MULTISIG = TX_MULTISIG; + Script.TX_SCRIPTHASH = TX_SCRIPTHASH; - Script.prototype.parse = function () { + Script.prototype.parse = function() { this.chunks = []; var parser = new Parser(this.buffer); @@ -73,8 +73,7 @@ function spec(b) { } }; - Script.prototype.isPushOnly = function () - { + Script.prototype.isPushOnly = function() { for (var i = 0; i < this.chunks.length; i++) if (!Buffer.isBuffer(this.chunks[i])) return false; @@ -82,8 +81,7 @@ function spec(b) { return true; }; - Script.prototype.isP2SH = function () - { + Script.prototype.isP2SH = function() { return (this.chunks.length == 3 && this.chunks[0] == OP_HASH160 && Buffer.isBuffer(this.chunks[1]) && @@ -91,46 +89,41 @@ function spec(b) { this.chunks[2] == OP_EQUAL); }; - Script.prototype.isPubkey = function () - { + Script.prototype.isPubkey = function() { return (this.chunks.length == 2 && - Buffer.isBuffer(this.chunks[0]) && - this.chunks[1] == OP_CHECKSIG); + Buffer.isBuffer(this.chunks[0]) && + this.chunks[1] == OP_CHECKSIG); }; - Script.prototype.isPubkeyHash = function () - { + Script.prototype.isPubkeyHash = function() { return (this.chunks.length == 5 && - this.chunks[0] == OP_DUP && - this.chunks[1] == OP_HASH160 && + this.chunks[0] == OP_DUP && + this.chunks[1] == OP_HASH160 && Buffer.isBuffer(this.chunks[2]) && this.chunks[2].length == 20 && - this.chunks[3] == OP_EQUALVERIFY && - this.chunks[4] == OP_CHECKSIG); + this.chunks[3] == OP_EQUALVERIFY && + this.chunks[4] == OP_CHECKSIG); }; - function isSmallIntOp(opcode) - { + function isSmallIntOp(opcode) { return ((opcode == OP_0) || - ((opcode >= OP_1) && (opcode <= OP_16))); + ((opcode >= OP_1) && (opcode <= OP_16))); }; - Script.prototype.isMultiSig = function () - { + Script.prototype.isMultiSig = function() { return (this.chunks.length > 3 && - isSmallIntOp(this.chunks[0]) && - isSmallIntOp(this.chunks[this.chunks.length-2]) && - this.chunks[this.chunks.length-1] == OP_CHECKMULTISIG); + isSmallIntOp(this.chunks[0]) && + isSmallIntOp(this.chunks[this.chunks.length - 2]) && + this.chunks[this.chunks.length - 1] == OP_CHECKMULTISIG); }; - Script.prototype.finishedMultiSig = function() - { + Script.prototype.finishedMultiSig = function() { var nsigs = 0; - for (var i = 0; i < this.chunks.length-1; i++) + for (var i = 0; i < this.chunks.length - 1; i++) if (this.chunks[i] !== 0) nsigs++; - var serializedScript = this.chunks[this.chunks.length-1]; + var serializedScript = this.chunks[this.chunks.length - 1]; var script = new Script(serializedScript); var nreq = script.chunks[0] - 80; //see OP_2-OP_16 @@ -140,11 +133,9 @@ function spec(b) { return false; } - Script.prototype.removePlaceHolders = function() - { + Script.prototype.removePlaceHolders = function() { var chunks = []; - for (var i in this.chunks) - { + for (var i in this.chunks) { if (this.chunks.hasOwnProperty(i)) { var chunk = this.chunks[i]; if (chunk != 0) @@ -156,8 +147,7 @@ function spec(b) { return this; } - Script.prototype.prependOp0 = function() - { + Script.prototype.prependOp0 = function() { var chunks = [0]; for (i in this.chunks) { if (this.chunks.hasOwnProperty(i)) { @@ -170,62 +160,61 @@ function spec(b) { } // is this a script form we know? - Script.prototype.classify = function () - { + Script.prototype.classify = function() { if (this.isPubkeyHash()) - return TX_PUBKEYHASH; - if (this.isP2SH()) - return TX_SCRIPTHASH; - if (this.isMultiSig()) - return TX_MULTISIG; - if (this.isPubkey()) - return TX_PUBKEY; - return TX_UNKNOWN; + return TX_PUBKEYHASH; + if (this.isP2SH()) + return TX_SCRIPTHASH; + if (this.isMultiSig()) + return TX_MULTISIG; + if (this.isPubkey()) + return TX_PUBKEY; + return TX_UNKNOWN; }; // extract useful data items from known scripts - Script.prototype.capture = function () - { + Script.prototype.capture = function() { var txType = this.classify(); - var res = []; - switch (txType) { - case TX_PUBKEY: - res.push(this.chunks[0]); - break; - case TX_PUBKEYHASH: - res.push(this.chunks[2]); - break; - case TX_MULTISIG: - for (var i = 1; i < (this.chunks.length - 2); i++) - res.push(this.chunks[i]); - break; - case TX_SCRIPTHASH: - res.push(this.chunks[1]); - break; - - case TX_UNKNOWN: - default: - // do nothing - break; - } + var res = []; + switch (txType) { + case TX_PUBKEY: + res.push(this.chunks[0]); + break; + case TX_PUBKEYHASH: + res.push(this.chunks[2]); + break; + case TX_MULTISIG: + for (var i = 1; i < (this.chunks.length - 2); i++) + res.push(this.chunks[i]); + break; + case TX_SCRIPTHASH: + res.push(this.chunks[1]); + break; - return res; + case TX_UNKNOWN: + default: + // do nothing + break; + } + + return res; }; // return first extracted data item from script - Script.prototype.captureOne = function () - { + Script.prototype.captureOne = function() { var arr = this.capture(); - return arr[0]; + return arr[0]; }; - Script.prototype.getOutType = function () - { + Script.prototype.getOutType = function() { var txType = this.classify(); switch (txType) { - case TX_PUBKEY: return 'Pubkey'; - case TX_PUBKEYHASH: return 'Address'; - default: return 'Strange'; + case TX_PUBKEY: + return 'Pubkey'; + case TX_PUBKEYHASH: + return 'Address'; + default: + return 'Strange'; } }; @@ -233,84 +222,79 @@ function spec(b) { return TX_TYPES[this.classify()]; }; - Script.prototype.simpleOutHash = function () - { + Script.prototype.simpleOutHash = function() { switch (this.getOutType()) { - case 'Address': - return this.chunks[2]; - case 'Pubkey': - return util.sha256ripe160(this.chunks[0]); - default: - log.debug("Encountered non-standard scriptPubKey"); - log.debug("Strange script was: " + this.toString()); - return null; + case 'Address': + return this.chunks[2]; + case 'Pubkey': + return util.sha256ripe160(this.chunks[0]); + default: + log.debug("Encountered non-standard scriptPubKey"); + log.debug("Strange script was: " + this.toString()); + return null; } }; - Script.prototype.getInType = function () - { + Script.prototype.getInType = function() { if (this.chunks.length == 1) { // Direct IP to IP transactions only have the public key in their scriptSig. return 'Pubkey'; } else if (this.chunks.length == 2 && - Buffer.isBuffer(this.chunks[0]) && - Buffer.isBuffer(this.chunks[1])) { + Buffer.isBuffer(this.chunks[0]) && + Buffer.isBuffer(this.chunks[1])) { return 'Address'; } else { return 'Strange'; } }; - Script.prototype.simpleInPubKey = function () - { + Script.prototype.simpleInPubKey = function() { switch (this.getInType()) { - case 'Address': - return this.chunks[1]; - case 'Pubkey': - return null; - default: - log.debug("Encountered non-standard scriptSig"); - log.debug("Strange script was: " + this.toString()); - return null; + case 'Address': + return this.chunks[1]; + case 'Pubkey': + return null; + default: + log.debug("Encountered non-standard scriptSig"); + log.debug("Strange script was: " + this.toString()); + return null; } }; - Script.prototype.getBuffer = function () - { + Script.prototype.getBuffer = function() { return this.buffer; }; Script.fromStringContent = function(s) { var chunks = []; var split = s.split(' '); - console.log(split); - for (var i=0; i 2 && word.substring(0,2) === '0x') { - chunks.push(new Buffer(word.substring(2,word.length), 'hex')); - } else { - var integer = parseInt(word); - if (isNaN(integer)) { - chunks.push(Opcode.map['OP_'+word]); - } else { - var hexi = integer.toString(16); - if (hexi.length %2 === 1) hexi = '0'+hexi; - console.log(hexi); - chunks.push(new Buffer(hexi,'hex')); - } - } - + for (var i = 0; i < split.length; i++) { + var word = split[i]; + if (word.length > 2 && word.substring(0, 2) === '0x') { + chunks.push(new Buffer(word.substring(2, word.length), 'hex')); + } else { + var opcode = Opcode.map['OP_' + word]; + if (opcode) { + chunks.push(opcode); + } else { + var integer = parseInt(word); + if (!isNaN(integer)) { + //console.log(integer+' bits=\t'+integer.toString(2).replace('-','').length); + var data = util.intToBuffer(integer); + chunks.push(data); + } + } + } } return Script.fromChunks(chunks); }; - Script.prototype.getStringContent = function (truncate, maxEl) - { + Script.prototype.getStringContent = function(truncate, maxEl) { if (truncate === null) { truncate = true; } - if ("undefined" === typeof maxEl) { + if ('undefined' === typeof maxEl) { maxEl = 15; } @@ -323,7 +307,7 @@ function spec(b) { } if (Buffer.isBuffer(chunk)) { - s += '0x'+util.formatBuffer(chunk, truncate ? null : 0); + s += '0x' + util.formatBuffer(chunk, truncate ? null : 0); } else { s += Opcode.reverseMap[chunk]; } @@ -336,8 +320,7 @@ function spec(b) { return s; }; - Script.prototype.toString = function (truncate, maxEl) - { + Script.prototype.toString = function(truncate, maxEl) { var script = "