def test_op_else(): s = Script("OP_1 OP_IF OP_2 OP_3 OP_ELSE OP_15 OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 3 assert list(si.stack) == [2, 3, 4] assert len(si._if_else_stack) == 0 s = Script("OP_0 OP_IF OP_2 OP_3 OP_ELSE OP_15 OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 2 assert list(si.stack) == [15, 4] assert len(si._if_else_stack) == 0 s = Script( "OP_0 OP_IF OP_2 OP_3 OP_ELSE OP_1 OP_2 OP_SUB OP_IF OP_3 OP_ENDIF OP_ENDIF OP_4" ) si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 2 assert list(si.stack) == [3, 4] assert len(si._if_else_stack) == 0
def test_op_checkmultisig(): txn = Transaction.from_hex( "01000000010506344de69d47e432eb0174500d6e188a9e63c1e84a9e8796ec98c99b7559f701000000fdfd00004730440220695a28c42daa23c13e192e36a20d03a2a79994e0fe1c3c6b612d0ae23743064602200ca19003e7c1ce0cecb0bbfba9a825fc3b83cf54e4c3261cd15f080d24a8a5b901483045022100aa9096ce71995c24545694f20ab0482099a98c99b799c706c333c521e51db66002206578f023fa46f4a863a6fa7f18b95eebd1a91fcdf6ce714e8795d902bd6b682b014c69522102b66fcb1064d827094685264aaa90d0126861688932eafbd1d1a4ba149de3308b21025cab5e31095551582630f168280a38eb3a62b0b3e230b20f8807fc5463ccca3c21021098babedb3408e9ac2984adcf2a8e4c48e56a785065893f76d0fa0ff507f01053aeffffffff01c8af0000000000001976a91458b7a60f11a904feef35a639b6048de8dd4d9f1c88ac00000000" ) # nopep8 sig_script = txn.inputs[0].script redeem_script = Script(sig_script.ast[-1][-1]) script_pub_key = Script.build_p2sh(redeem_script.hash160()) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=redeem_script) si.run_script(sig_script) assert len(si.stack) == 4 si.run_script(script_pub_key) assert len(si.stack) == 4 assert si.stack[-1] is True assert si.valid si._op_verify() # This will do the OP_CHECKMULTISIG si.run_script(redeem_script) assert len(si.stack) == 1 assert si.stack[0] is True assert si.valid assert len(si.stack) == 1
def test_op_checkmultisig(): txn = Transaction.from_hex("01000000010506344de69d47e432eb0174500d6e188a9e63c1e84a9e8796ec98c99b7559f701000000fdfd00004730440220695a28c42daa23c13e192e36a20d03a2a79994e0fe1c3c6b612d0ae23743064602200ca19003e7c1ce0cecb0bbfba9a825fc3b83cf54e4c3261cd15f080d24a8a5b901483045022100aa9096ce71995c24545694f20ab0482099a98c99b799c706c333c521e51db66002206578f023fa46f4a863a6fa7f18b95eebd1a91fcdf6ce714e8795d902bd6b682b014c69522102b66fcb1064d827094685264aaa90d0126861688932eafbd1d1a4ba149de3308b21025cab5e31095551582630f168280a38eb3a62b0b3e230b20f8807fc5463ccca3c21021098babedb3408e9ac2984adcf2a8e4c48e56a785065893f76d0fa0ff507f01053aeffffffff01c8af0000000000001976a91458b7a60f11a904feef35a639b6048de8dd4d9f1c88ac00000000") # nopep8 sig_script = txn.inputs[0].script redeem_script = Script(sig_script.ast[-1][-1]) script_pub_key = Script.build_p2sh(redeem_script.hash160()) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=redeem_script) si.run_script(sig_script) assert len(si.stack) == 4 si.run_script(script_pub_key) assert len(si.stack) == 4 assert si.stack[-1] is True assert si.valid si._op_verify() # This will do the OP_CHECKMULTISIG si.run_script(redeem_script) assert len(si.stack) == 1 assert si.stack[0] is True assert si.valid assert len(si.stack) == 1
def test_op_if(): s = Script("OP_1 OP_IF OP_2 OP_3 OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 3 assert list(si.stack) == [2, 3, 4] assert len(si._if_else_stack) == 0 s = Script("OP_0 OP_IF OP_2 OP_3 OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [4] assert len(si._if_else_stack) == 0 s = Script( "OP_1 OP_IF OP_2 OP_3 OP_IF OP_15 OP_ADD OP_ENDIF OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 2 assert list(si.stack) == [17, 4] assert len(si._if_else_stack) == 0
def test_serialization(): scr = 'OP_ADD OP_IF OP_DUP OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY OP_CHECKSIG OP_ELSE OP_IF OP_DUP OP_ELSE OP_2ROT OP_ENDIF OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUAL OP_ENDIF 0x010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101' # nopep8 s = Script(scr) assert s._tokens == ['OP_ADD', 'OP_IF', 'OP_DUP', 'OP_HASH160', b'h\xbf\x82z/\xa3\xb3\x1eS!^]\xd1\x92`\xd2\x1f\xdf\x05>', 'OP_EQUALVERIFY', 'OP_CHECKSIG', 'OP_ELSE', 'OP_IF', 'OP_DUP', 'OP_ELSE', 'OP_2ROT', 'OP_ENDIF', 'OP_HASH160', b'h\xbf\x82z/\xa3\xb3\x1eS!^]\xd1\x92`\xd2\x1f\xdf\x05>', 'OP_EQUAL', 'OP_ENDIF', b'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01'] # nopep8 s_bytes = bytes(s) s_hex_str = bytes_to_str(s_bytes) s1 = Script.from_bytes(pack_var_str(s_bytes))[0] assert bytes(s1) == s_bytes raw_scr = "483045022100d60baf72dbaed8d15c3150e3309c9f7725fbdf91b0560330f3e2a0ccb606dfba02206422b1c73ce390766f0dc4e9143d0fbb400cc207e4a9fd9130e7f79e52bf81220121034ccd52d8f72cfdd680077a1a171458a1f7574ebaa196095390ae45e68adb3688" # nopep8 s = Script(bytes.fromhex(raw_scr)) s._check_tokenized() assert s._tokens assert s._ast s_hex_str = bytes_to_str(bytes(s)) assert s_hex_str == raw_scr s = Script('OP_0 OP_IF 0x1337c0de OP_ENDIF OP_1') b = bytes.fromhex("0063041337c0de6851") s1 = Script.from_bytes(pack_var_str(b))[0] assert bytes(s) == b assert bytes(s) == bytes(s1)
def test_op_within(): s = Script("OP_4 OP_1 OP_15 OP_WITHIN") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] s = Script("OP_4 OP_5 OP_15 OP_WITHIN") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0] s = Script("OP_4 OP_4 OP_15 OP_WITHIN") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] s = Script("OP_15 OP_4 OP_15 OP_WITHIN") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0]
def test_op_checklocktimeverify(): prev_txn_hash = Hash( '6eae1e03964799c4e29039db459ea4fad4df57c2b06f730b60032a48fb075620') txn_input = TransactionInput(prev_txn_hash, 0, Script(""), 1) addr = "1HJiL6AYYmtkbJzC9bxAorznWijwNK5Z8E" out_script_pub_key = Script.build_p2pkh(utils.address_to_key_hash(addr)[1]) txn_output = TransactionOutput(9000, out_script_pub_key) # Create the txn txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, [txn_input], [txn_output], 367987) # This is one more (367988) so it should fail s = Script("0x749d05 OP_CHECKLOCKTIMEVERIFY") si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.valid # This is negative, so it should fail s = Script("0xfff74d05 OP_CHECKLOCKTIMEVERIFY") si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.valid # This is one less (367986) so it should pass s = Script("0x729d05 OP_CHECKLOCKTIMEVERIFY") si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.stop # Now reformulate the txn so that the input is finalized txn_input.sequence_num = 0xffffffff si.run_script(s) assert not si.valid # The last check is if there are mismatching notions of locktime txn_input.sequence_num = 1 txn.lock_time = 500000001 si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.valid
def test_validate_template(): template = ['OP_HASH160', bytes, 'OP_EQUALVERIFY', 'OP_CHECKSIG'] scr = Script('OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY OP_NOP') assert not Script.validate_template(scr, template) scr[-1] = 'OP_CHECKSIG' assert Script.validate_template(scr, template)
def test_list_operations(): s = Script('OP_0 OP_1 OP_2') assert s[0] == 'OP_0' del s[2] assert s._tokens == ['OP_0', 'OP_1'] s.append('OP_3') assert str(s) == 'OP_0 OP_1 OP_3' s.insert(2, 'OP_2') assert s._tokens == ['OP_0', 'OP_1', 'OP_2', 'OP_3'] assert s._ast == ['OP_0', 'OP_1', 'OP_2', 'OP_3'] for i, o in enumerate(s): assert o == 'OP_%d' % i s = Script('OP_1 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF') with pytest.raises(ScriptParsingError): del s[1] s = Script('OP_1 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF') del s[3] assert s._tokens == ['OP_1', 'OP_IF', 'OP_2', 'OP_3', 'OP_ENDIF'] assert len(s) == 5 assert str(s) == 'OP_1 OP_IF OP_2 OP_3 OP_ENDIF' s = Script('OP_1 OP_IF OP_2 OP_ELSE OP_3 OP_ENDIF') with pytest.raises(ScriptParsingError): del s[5] s = Script(['OP_1', 'OP_3']) assert len(s) == 2 assert s._tokens == ['OP_1', 'OP_3']
def test_remove_op(): scr = "OP_ADD OP_CODESEPARATOR OP_DUP OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY OP_CHECKSIG" # nopep8 s = Script(scr) s1 = s.remove_op("OP_CODESEPARATOR") assert str(s1) == "OP_ADD OP_DUP OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY OP_CHECKSIG" s2 = s1.remove_op("OP_DUP") assert str(s2) == "OP_ADD OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY OP_CHECKSIG" s3 = s2.remove_op("OP_EQUAL") assert str(s2) == str(s3)
def test_op_negate(): s = Script("OP_3 OP_NEGATE") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [-3] si.run_script(Script("OP_NEGATE")) assert list(si.stack) == [3]
def test_op_checksig(): # This is from the same example as in test_signing.py txn = Transaction.from_hex( "0100000001205607fb482a03600b736fb0c257dfd4faa49e45db3990e2c4994796031eae6e000000001976a914e9f061ff2c9885c7b137de35e416cbd5d3e1087c88acffffffff0128230000000000001976a914f1fd1dc65af03c30fe743ac63cef3a120ffab57d88ac00000000" ) # nopep8 pub_key_hex = "0x04e674caf81eb3bb4a97f2acf81b54dc930d9db6a6805fd46ca74ac3ab212c0bbf62164a11e7edaf31fbf24a878087d925303079f2556664f3b32d125f2138cbef" # nopep8 sig_hex = "0x3045022100ed84be709227397fb1bc13b749f235e1f98f07ef8216f15da79e926b99d2bdeb02206ff39819d91bc81fecd74e59a721a38b00725389abb9cbecb42ad1c939fd826201" # nopep8 s = Script("%s %s OP_CHECKSIG" % (sig_hex, pub_key_hex)) prev_script_pub_key = Script.build_p2pkh( utils.address_to_key_hash("1NKxQnbtKDdL6BY1UaKdrzCxQHfn3TQnqZ")[1]) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] is True s = Script("%s %s OP_CHECKSIGVERIFY" % (sig_hex, pub_key_hex)) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 0 assert not si.stop # Try it once more with an incorrect sig pub_key_hex = "0x04e674caf81eb3bb4a97f2acf81b54dc930d9db6a6805fd46ca74ac3ab212c0bbf62164a11e7edaf31fbf24a878087d925303079f2556664f3b32d125f2138cbef" # nopep8 sig_hex = "0x3045022100ed84be709227397fc1bc13b749f235e1f98f07ef8216f15da79e926b99d2bdeb02206ff39819d91bc81fecd74e59a721a38b00725389abb9cbecb42ad1c939fd826201" # nopep8 s = Script("%s %s OP_CHECKSIG" % (sig_hex, pub_key_hex)) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] is False s = Script("%s %s OP_CHECKSIGVERIFY" % (sig_hex, pub_key_hex)) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 0 assert si.stop
def test_op_0notequal(): s = Script("OP_1 OP_0NOTEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] si.run_script(Script("OP_NOT")) assert list(si.stack) == [0] si.run_script(Script("OP_0NOTEQUAL")) assert list(si.stack) == [0]
def test_op_not(): s = Script("OP_1 OP_NOT") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0] si.run_script(Script("OP_2 OP_NOT")) assert list(si.stack) == [0, 0] si.run_script(Script("OP_NOT")) assert list(si.stack) == [0, 1]
def test_op_verify(): s = Script("0x01 OP_VERIFY") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 0 assert not si.stop s = Script("0x00 OP_VERIFY") si.run_script(s) assert len(si.stack) == 0 assert si.stop
def test_multisig_sig(): sig_script = Script('OP_0 0x30440220762ce7bca626942975bfd5b130ed3470b9f538eb2ac120c2043b445709369628022051d73c80328b543f744aa64b7e9ebefa7ade3e5c716eab4a09b408d2c307ccd701 0x3045022100abf740b58d79cab000f8b0d328c2fff7eb88933971d1b63f8b99e89ca3f2dae602203354770db3cc2623349c87dea7a50cee1f78753141a5052b2d58aeb592bcf50f01 0x524104a882d414e478039cd5b52a92ffb13dd5e6bd4515497439dffd691a0f12af9575fa349b5694ed3155b136f09e63975a1700c9f4d4df849323dac06cf3bd6458cd41046ce31db9bdd543e72fe3039a1f1c047dab87037c36a669ff90e28da1848f640de68c2fe913d363a51154a0c62d7adea1b822d05035077418267b1a1379790187410411ffd36c70776538d079fbae117dc38effafb33304af83ce4894589747aee1ef992f63280567f52f5ba870678b4ab4ff6c8ea600bd217870a8b4f1f09f3a8e8353ae') # nopep8 assert sig_script.is_multisig_sig() r = sig_script.extract_multisig_sig_info() redeem_info = r['redeem_script'].extract_multisig_redeem_info() assert len(r['signatures']) == 2 assert r['redeem_script'] assert isinstance(r['redeem_script'], Script) s = Script.build_multisig_sig(r['signatures'], r['redeem_script']) assert bytes(s) == bytes(sig_script) # This is a test case where there is no OP_PUSHDATA raw_scr = "00483045022100fa1225f8828fd6fe52665c3c4258169a84af52b41525f2e288082f174c032f47022022758d5519db3ab2cec4a330e96568b9289fb77c5653bce49397df01a3fcff5101475221038b5fa60aee4c4e9ab3a66e6bb32211a54da6b054c6143dd221c122ce936315d921023180e1b49b7f3fd1254a19c7aa8016ad995089b99c9dac89752cd17e40d9072d52ae" # nopep8 s, _ = Script.from_bytes(pack_var_str(bytes.fromhex(raw_scr))) assert sig_script.is_multisig_sig() r = s.extract_multisig_sig_info() assert len(r['signatures']) == 1 assert r['redeem_script'] assert isinstance(r['redeem_script'], Script) sig_addresses = sig_script.get_addresses() assert len(sig_addresses) == redeem_info['n'] + 1 assert sig_addresses == ['1JzVFZSN1kxGLTHG41EVvY5gHxLAX7q1Rh', '14JfSvgEq8A8S7qcvxeaSCxhn1u1L71vo4', '1Kyy7pxzSKG75L9HhahRZgYoer9FePZL4R', '347N1Thc213QqfYCz3PZkjoJpNv5b14kBd']
def test_op_pushdata(): s = Script("0x" + "12" * 0x4e) si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] == bytes([0x12] * 0x4e) s = Script("0x" + "12" * 0x4eff) si.run_script(s) assert len(si.stack) == 2 assert si.stack[1] == bytes([0x12] * 0x4eff)
def txn_from_json(txn_json): inputs = [] for i in txn_json['inputs']: if 'output_hash' in i: outpoint = Hash(i['output_hash']) script = Script(bytes.fromhex(i['script_signature_hex'])) # Do this to test script de/serialization script._disassemble() inp = TransactionInput(outpoint, i['output_index'], script, i['sequence']) else: # Coinbase txn, we pass in a block version of 1 since the # coinbase script from api.chain.com already has the # height in there. Don't want our stuff to repack it in. inp = CoinbaseInput(txn_json['block_height'], bytes.fromhex(i['coinbase']), i['sequence'], 1) inputs.append(inp) outputs = [] for o in txn_json['outputs']: scr = Script(bytes.fromhex(o['script_hex'])) scr._disassemble() out = TransactionOutput(o['value'], scr) outputs.append(out) txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, inputs, outputs, txn_json['lock_time']) return txn
def test_is_p2sh(): s = Script("OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUAL") assert s.is_p2sh() assert not s.is_multisig_redeem() assert not s.is_p2pkh_sig() s = Script.build_p2sh(bytes.fromhex("68bf827a2fa3b31e53215e5dd19260d21fdf053e")) assert s.is_p2sh() s = Script("OP_ADD OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY") assert not s.is_p2sh() assert not s.is_multisig_redeem()
def test_op_max(): s = Script("OP_1 OP_2 OP_MAX") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [2] s = Script("OP_2 OP_2 OP_MAX") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [2]
def test_op_checklocktimeverify(): prev_txn_hash = Hash('6eae1e03964799c4e29039db459ea4fad4df57c2b06f730b60032a48fb075620') txn_input = TransactionInput(prev_txn_hash, 0, Script(""), 1) addr = "1HJiL6AYYmtkbJzC9bxAorznWijwNK5Z8E" out_script_pub_key = Script.build_p2pkh( utils.address_to_key_hash(addr)[1]) txn_output = TransactionOutput(9000, out_script_pub_key) # Create the txn txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, [txn_input], [txn_output], 367987) # This is one more (367988) so it should fail s = Script("0x749d05 OP_CHECKLOCKTIMEVERIFY") si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.valid # This is negative, so it should fail s = Script("0xfff74d05 OP_CHECKLOCKTIMEVERIFY") si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.valid # This is one less (367986) so it should pass s = Script("0x729d05 OP_CHECKLOCKTIMEVERIFY") si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.stop # Now reformulate the txn so that the input is finalized txn_input.sequence_num = 0xffffffff si.run_script(s) assert not si.valid # The last check is if there are mismatching notions of locktime txn_input.sequence_num = 1 txn.lock_time = 500000001 si = ScriptInterpreter(txn=txn, input_index=0, sub_script=out_script_pub_key) si.run_script(s) assert not si.valid
def test_op_greaterthanequal(): s = Script("OP_1 OP_2 OP_GREATERTHANEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] s = Script("OP_2 OP_1 OP_GREATERTHANEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0]
def test_op_numnotequal(): s = Script("OP_1 OP_2 OP_NUMNOTEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] s = Script("OP_16 OP_16 OP_NUMNOTEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0]
def test_op_numequalverify(): s = Script("OP_1 OP_2 OP_NUMEQUALVERIFY OP_3") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 0 assert list(si.stack) == [] s = Script("OP_16 OP_16 OP_NUMEQUALVERIFY OP_3") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [3]
def test_op_booland(): s = Script("OP_1 OP_2 OP_BOOLAND") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] s = Script("OP_1 OP_1 OP_NOT OP_BOOLAND") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0]
def test_op_equal(): s = Script("0x01 0x01 OP_EQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] is True s = Script("0x01 0x02 OP_EQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] is False
def test_op_notif(): s = Script("OP_1 OP_NOTIF OP_2 OP_3 OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [4] s = Script("OP_0 OP_NOTIF OP_2 OP_3 OP_ENDIF OP_4") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 3 assert list(si.stack) == [2, 3, 4]
def test_op_sub(): s = Script("OP_1 OP_2 OP_SUB") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1] s = Script("OP_2 OP_1 OP_SUB") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [-1]
def test_disabled_ops(): for opcode in ScriptInterpreter.DISABLED_OPS: si = ScriptInterpreter() si.run_script(Script("OP_1 " + opcode + " OP_2")) assert not si.valid assert list(si.stack) == [1]
def test_op_lessthanequal(): s = Script("OP_1 OP_2 OP_LESSTHANEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [0] s = Script("OP_2 OP_2 OP_LESSTHANEQUAL") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [1]
def test_op_1sub(): s = Script("OP_3 OP_1SUB") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [2]
def test_op_abs(): s = Script("OP_3 OP_NEGATE OP_ABS") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [3]
def test_op_add(): s = Script("OP_1 OP_2 OP_ADD") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert list(si.stack) == [3]
def test_op_1negate(): s = Script("OP_1NEGATE") si = ScriptInterpreter() si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] == -1
def set_txn_side_effect_for_hd_discovery(self): # For each used account, there are at least 2 calls required: # 1 for the first DISCOVERY_INCREMENT payout addresses and 1 # for the first DISCOVERY_INCREMENT change # addresses. Depending on the number of used addresses for the # account, this will change. effects = [] n = self._num_used_accounts if n == 0: n = 1 for acct_num in range(n): for change in [0, 1]: num_used = self._num_used_addresses[acct_num][change] r = math.ceil((num_used + HDAccount.GAP_LIMIT) / self.address_increment) k = 'change_addresses' if change else 'payout_addresses' addr_list = self._acct_keys[acct_num][k] if change: metadata = dict(block=234790 + r, block_hash=Hash("000000000000000007d57f03ebe36dbe4f87ab2f340e93b45999ab249b6dc0df"), confirmations=23890 - r) else: metadata = dict(block=None, block_hash=None, confirmations=0) if r == 0: r = 1 for i in range(r): start = i * self.address_increment end = (i + 1) * self.address_increment addr_range = range(start, end) out = TransactionOutput(value=100000, script=Script.build_p2pkh( address_to_key_hash( addr_list[i])[1])) dummy_txn = Transaction(1, [], [out], 0) m = MockTxnDict(num_used=num_used, addr_range=addr_range, addr_list=addr_list, used_value=[dict(metadata=metadata, transaction=dummy_txn)], unused_value=[]) effects.append(m) self.get_transactions.side_effect = effects return len(effects)
def test_op_checksig(): # This is from the same example as in test_signing.py txn = Transaction.from_hex("0100000001205607fb482a03600b736fb0c257dfd4faa49e45db3990e2c4994796031eae6e000000001976a914e9f061ff2c9885c7b137de35e416cbd5d3e1087c88acffffffff0128230000000000001976a914f1fd1dc65af03c30fe743ac63cef3a120ffab57d88ac00000000") # nopep8 pub_key_hex = "0x04e674caf81eb3bb4a97f2acf81b54dc930d9db6a6805fd46ca74ac3ab212c0bbf62164a11e7edaf31fbf24a878087d925303079f2556664f3b32d125f2138cbef" # nopep8 sig_hex = "0x3045022100ed84be709227397fb1bc13b749f235e1f98f07ef8216f15da79e926b99d2bdeb02206ff39819d91bc81fecd74e59a721a38b00725389abb9cbecb42ad1c939fd826201" # nopep8 s = Script("%s %s OP_CHECKSIG" % (sig_hex, pub_key_hex)) prev_script_pub_key = Script.build_p2pkh(utils.address_to_key_hash( "1NKxQnbtKDdL6BY1UaKdrzCxQHfn3TQnqZ")[1]) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] is True s = Script("%s %s OP_CHECKSIGVERIFY" % (sig_hex, pub_key_hex)) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 0 assert not si.stop # Try it once more with an incorrect sig pub_key_hex = "0x04e674caf81eb3bb4a97f2acf81b54dc930d9db6a6805fd46ca74ac3ab212c0bbf62164a11e7edaf31fbf24a878087d925303079f2556664f3b32d125f2138cbef" # nopep8 sig_hex = "0x3045022100ed84be709227397fc1bc13b749f235e1f98f07ef8216f15da79e926b99d2bdeb02206ff39819d91bc81fecd74e59a721a38b00725389abb9cbecb42ad1c939fd826201" # nopep8 s = Script("%s %s OP_CHECKSIG" % (sig_hex, pub_key_hex)) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 1 assert si.stack[0] is False s = Script("%s %s OP_CHECKSIGVERIFY" % (sig_hex, pub_key_hex)) si = ScriptInterpreter(txn=txn, input_index=0, sub_script=prev_script_pub_key) si.run_script(s) assert len(si.stack) == 0 assert si.stop
def __init__(self, height, raw_script, sequence=MAX_INT, block_version=3): self.height = height if block_version == 1: scr = raw_script else: scr = Script.build_push_int(self.height) + raw_script # Coinbase scripts are basically whatever, so we don't # try to create a script object from them. super().__init__(self.NULL_OUTPOINT, self.MAX_INT, scr, sequence)
def test_multisig(): # This test-case taken from: # https://gist.github.com/gavinandresen/3966071 pubkeys = [ "0491bba2510912a5bd37da1fb5b1673010e43d2c6d812c514e91bfa9f2eb129e1c183329db55bd868e209aac2fbc02cb33d98fe74bf23f0c235d6126b1d8334f86", # nopep8 "04865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac09ef122b1a986818a7cb624532f062c1d1f8722084861c5c3291ccffef4ec6874", # nopep8 "048d2455d2403e08708fc1f556002f1b6cd83f992d085097f9974ab08a28838f07896fbab08f39495e15fa6fad6edbfb1e754e35fa1c7844c41f322a1863d46213"] # nopep8 serialized_pubkeys = [bytes.fromhex(p) for p in pubkeys] redeem_script = Script.build_multisig_redeem(2, serialized_pubkeys) assert bytes_to_str(bytes(redeem_script)) == "52410491bba2510912a5bd37da1fb5b1673010e43d2c6d812c514e91bfa9f2eb129e1c183329db55bd868e209aac2fbc02cb33d98fe74bf23f0c235d6126b1d8334f864104865c40293a680cb9c020e7b1e106d8c1916d3cef99aa431a56d253e69256dac09ef122b1a986818a7cb624532f062c1d1f8722084861c5c3291ccffef4ec687441048d2455d2403e08708fc1f556002f1b6cd83f992d085097f9974ab08a28838f07896fbab08f39495e15fa6fad6edbfb1e754e35fa1c7844c41f322a1863d4621353ae" # nopep8 assert redeem_script.is_multisig_redeem() # Get the address of the redeem script assert redeem_script.address(True).startswith("2") address = redeem_script.address() assert address == "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC"
def from_bytes(b): """ Deserializes a byte stream into a TransactionInput. Args: b (bytes): byte stream starting with the outpoint. Returns: tuple: First element of the tuple is the TransactionInput object and the second is the remaining byte stream. """ outpoint = b[0:32] outpoint_index, b1 = unpack_u32(b[32:]) script, b1 = Script.from_bytes(b1) sequence_num, b1 = unpack_u32(b1) return ( TransactionInput(Hash(outpoint), outpoint_index, script, sequence_num), b1 )
def txn_from_json(txn_json): """ Returns a new Transaction from a JSON-serialized transaction Args: txn_json: JSON with the following format: { "hash": "0bf0de38c26195919179f...", "block_hash": "000000000000000...", "block_height": 303404, "block_time": "2014-05-30T23:54:55Z", "chain_received_at": "2015-08-13T10:52:21.718Z", "confirmations": 69389, "lock_time": 0, "inputs": [ { "transaction_hash": "0bf0de38c2619...", "output_hash": "b84a66c46e24fe71f9...", "output_index": 0, "value": 300000, "addresses": [ "3L7dKYQGNoZub928CJ8NC2WfrM8U8GGBjr" ], "script_signature": "03046022100de7b67b9...", "script_signature_hex": "00493046022100de7b...", "sequence": 4294967295 } ], "outputs": [ { "transaction_hash": "0bf0de38c261959...", "output_index": 0, "value": 290000, "addresses": [ "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb" ], "script": "OP_DUP OP_HASH160 c629680b8d...", "script_hex": "76a914c629680b8d13...", "script_type": "pubkeyhash", "required_signatures": 1, "spent": false, "spending_transaction": null } ], "fees": 10000, "amount": 290000 }, Transaction.DEFAULT_TRANSACTION_VERSION Returns: two1.bitcoin.Transaction: a deserialized transaction derived from the provided json. """ inputs = [] outputs = [] addr_keys = set() for i in sorted(txn_json["vin"], key=lambda i: i["n"]): if 'coinbase' in i: inputs.append(CoinbaseInput(height=0, raw_script=bytes.fromhex(i['coinbase']), sequence=i['sequence'], block_version=1)) else: script = Script.from_hex(i["scriptSig"]["hex"]) inputs.append(TransactionInput(Hash(i["txid"]), i["vout"], script, i["sequence"])) if "addr" in i: addr_keys.add(i["addr"]) for o in sorted(txn_json["vout"], key=lambda o: o["n"]): script = Script.from_hex(o["scriptPubKey"]["hex"]) value = int(decimal.Decimal(str(o["value"])) * decimal.Decimal('1e8')) outputs.append(TransactionOutput(value, script)) if "addresses" in o["scriptPubKey"]: for a in o["scriptPubKey"]["addresses"]: addr_keys.add(a) txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, inputs, outputs, txn_json["locktime"]) assert txn.hash == Hash(txn_json['txid']) return txn, addr_keys
def _do_multisig_script(self, sigs, message, current_script_sig, redeem_script, hash_type): # If the current script is empty or None, create it sig_script = None if current_script_sig is None or not str(current_script_sig): sig_bytes = [s['signature'].to_der() + pack_compact_int(hash_type) for s in sigs] sig_script = Script.build_multisig_sig(sigs=sig_bytes, redeem_script=redeem_script) else: # Need to extract all the sigs already present multisig_params = redeem_script.extract_multisig_redeem_info() sig_info = current_script_sig.extract_multisig_sig_info() # Do a few quick sanity checks if str(sig_info['redeem_script']) != str(redeem_script): raise ValueError( "Redeem script in signature script does not match redeem_script!") if len(sig_info['signatures']) == multisig_params['n']: # Already max number of signatures return current_script_sig # Go through the signatures and match them up to the public keys # in the redeem script pub_keys = [] for pk in multisig_params['public_keys']: pub_keys.append(crypto.PublicKey.from_bytes(pk)) existing_sigs = [] for s in sig_info['signatures']: s1, h = s[:-1], s[-1] # Last byte is hash_type existing_sigs.append(crypto.Signature.from_der(s1)) if h != hash_type: raise ValueError("hash_type does not match that of the existing signatures.") # Match them up existing_sig_indices = self._match_sigs_to_pub_keys(existing_sigs, pub_keys, message) sig_indices = {s['index']: s['signature'] for s in sigs} # Make sure there are no dups all_indices = set(list(existing_sig_indices.keys()) + list(sig_indices.keys())) if len(all_indices) < len(existing_sig_indices) + len(sig_indices): raise ValueError("At least one signature matches an existing signature.") if len(all_indices) > multisig_params['n']: raise ValueError("There are too many signatures.") all_sigs = [] for i in sorted(all_indices): if i in existing_sig_indices: all_sigs.append(existing_sig_indices[i]) elif i in sig_indices: all_sigs.append(sig_indices[i]) all_sigs_bytes = [s.to_der() + pack_compact_int(hash_type) for s in all_sigs] sig_script = Script.build_multisig_sig(all_sigs_bytes, redeem_script) return sig_script
def txn_from_json(txn_json): """ Returns a new Transaction from a JSON-serialized transaction Args: txn_json: JSON with the following format: { "hash": "0bf0de38c26195919179f...", "block_hash": "000000000000000...", "block_height": 303404, "block_time": "2014-05-30T23:54:55Z", "chain_received_at": "2015-08-13T10:52:21.718Z", "confirmations": 69389, "lock_time": 0, "inputs": [ { "transaction_hash": "0bf0de38c2619...", "output_hash": "b84a66c46e24fe71f9...", "output_index": 0, "value": 300000, "addresses": [ "3L7dKYQGNoZub928CJ8NC2WfrM8U8GGBjr" ], "script_signature": "03046022100de7b67b9...", "script_signature_hex": "00493046022100de7b...", "sequence": 4294967295 } ], "outputs": [ { "transaction_hash": "0bf0de38c261959...", "output_index": 0, "value": 290000, "addresses": [ "1K4nPxBMy6sv7jssTvDLJWk1ADHBZEoUVb" ], "script": "OP_DUP OP_HASH160 c629680b8d...", "script_hex": "76a914c629680b8d13...", "script_type": "pubkeyhash", "required_signatures": 1, "spent": false, "spending_transaction": null } ], "fees": 10000, "amount": 290000 }, Transaction.DEFAULT_TRANSACTION_VERSION Returns: two1.bitcoin.Transaction: a deserialized transaction derived from the provided json. """ inputs = [] outputs = [] addr_keys = set() for i in txn_json["inputs"]: if 'coinbase' in i: inputs.append( CoinbaseInput( height=txn_json["block_height"] or 0, raw_script=bytes.fromhex(i['coinbase']), sequence=i['sequence'], block_version=1)) else: # Script length etc. are not returned so we need to # prepend that. script, _ = Script.from_bytes( pack_var_str(bytes.fromhex(i["script_signature_hex"]))) inputs.append(TransactionInput(Hash(i["output_hash"]), i["output_index"], script, i["sequence"])) if "addresses" in i: addr_keys.add(i["addresses"][0]) for i in txn_json["outputs"]: script, _ = Script.from_bytes( pack_var_str(bytes.fromhex(i["script_hex"]))) outputs.append(TransactionOutput(i["value"], script)) if "addresses" in i: addr_keys.add(i["addresses"][0]) txn = Transaction(Transaction.DEFAULT_TRANSACTION_VERSION, inputs, outputs, txn_json["lock_time"]) return txn, addr_keys
def test_is_p2pkh(): s = Script("OP_DUP OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY OP_CHECKSIG") assert s.is_p2pkh() assert not s.is_multisig_redeem() assert not s.is_p2pkh_sig() assert s.address() addresses = s.get_addresses() assert len(addresses) == 1 assert addresses[0] == '1AYrhH1SAQqhT8w5NguBSogN63ajS6PxNL' s = Script.build_p2pkh(bytes.fromhex("68bf827a2fa3b31e53215e5dd19260d21fdf053e")) assert s.is_p2pkh() s = Script("OP_ADD OP_HASH160 0x68bf827a2fa3b31e53215e5dd19260d21fdf053e OP_EQUALVERIFY") assert not s.is_p2pkh() assert not s.is_multisig_redeem()