def test_build_spends(self): # first, here is the tx database TX_DB = {} # create a coinbase Tx where we know the public & private key key = network.ui.parse("5JMys7YfK72cRVTrbwkq5paxU7vgkMypB55KyXEtN5uSnjV7K8Y") exponent = key.secret_exponent() compressed = False public_key_sec = public_pair_to_sec(exponent * secp256k1_generator, compressed=compressed) the_coinbase_tx = Tx.coinbase_tx(public_key_sec, int(50 * 1e8), COINBASE_BYTES_FROM_80971) TX_DB[the_coinbase_tx.hash()] = the_coinbase_tx # now create a Tx that spends the coinbase compressed = False exponent_2 = int("137f3276686959c82b454eea6eefc9ab1b9e45bd4636fb9320262e114e321da1", 16) address_2 = public_pair_to_bitcoin_address(exponent_2 * secp256k1_generator, compressed=compressed) self.assertEqual("12WivmEn8AUth6x6U8HuJuXHaJzDw3gHNZ", address_2) coins_from = [(the_coinbase_tx.hash(), 0, the_coinbase_tx.txs_out[0])] coins_to = [(int(50 * 1e8), address_2)] unsigned_coinbase_spend_tx = standard_tx(coins_from, coins_to) solver = build_hash160_lookup([exponent], [secp256k1_generator]) coinbase_spend_tx = unsigned_coinbase_spend_tx.sign(solver) TX_DB[coinbase_spend_tx.hash()] = coinbase_spend_tx # now try to respend from priv_key_2 to priv_key_3 compressed = True exponent_3 = int("f8d39b8ecd0e1b6fee5a340519f239097569d7a403a50bb14fb2f04eff8db0ff", 16) address_3 = public_pair_to_bitcoin_address(exponent_3 * secp256k1_generator, compressed=compressed) self.assertEqual("13zzEHPCH2WUZJzANymow3ZrxcZ8iFBrY5", address_3) coins_from = [(coinbase_spend_tx.hash(), 0, coinbase_spend_tx.txs_out[0])] unsigned_spend_tx = standard_tx(coins_from, [(int(50 * 1e8), address_3)]) solver.update(build_hash160_lookup([exponent_2], [secp256k1_generator])) spend_tx = unsigned_spend_tx.sign(solver) # now check that it validates self.assertEqual(spend_tx.bad_solution_count(), 0)
def spend_pkh_fund(tx_ins, in_keys, tx_outs): """ p2pkh address send to p2pkh p2sh transaction :param tx_ins: list with tuple(tx_id, idx, balance, address) :param in_keys: list of private keys in hex format corresponding to each input :param tx_outs: balance, receiver_address :return: raw hex and tx id """ _txs_in = [] _un_spent = [] for tx_id, idx, balance, address in tx_ins: # must h2b_rev NOT h2b tx_id_b = h2b_rev(tx_id) _txs_in.append(TxIn(tx_id_b, idx)) script = network.contract.for_address(address) _un_spent.append(Spendable(balance, script, tx_id_b, idx)) _txs_out = [] for balance, receiver_address in tx_outs: _txs_out.append( TxOut(balance, network.contract.for_address(receiver_address))) version, lock_time = 1, 0 tx = Tx(version, _txs_in, _txs_out, lock_time) tx.set_unspents(_un_spent) solver = build_hash160_lookup([int(pri_hex, 16) for pri_hex in in_keys], [secp256k1_generator]) tx.sign(solver, hash_type=SIGHASH_ALL) return tx.as_hex(), tx.id()
def test_p2multisig_incremental(self): keys = [Key(i) for i in (1, 2, 3)] secs = [k.sec() for k in keys] tx = self.make_test_tx(script_for_multisig(3, secs)) tx_in_idx = 0 for k in keys: try: tx.check_solution(tx_in_idx) assert 0 except ScriptError: pass kwargs = { "hash160_lookup": build_hash160_lookup([k.secret_exponent()], [secp256k1_generator]) } kwargs["existing_script"] = [ data for opcode, data, pc, new_pc in network.script_tools.get_opcodes(tx.txs_in[tx_in_idx].script) if data is not None ] kwargs["nocheck"] = True kwargs[ "generator_for_signature_type_f"] = Solver.SolutionChecker.VM.generator_for_signature_type solution_list, witness_list = self.do_test_solve( tx, tx_in_idx, **kwargs) tx.check_solution(tx_in_idx)
def test_sign_bitcoind_partially_signed_2_of_2(self): # Finish signing a 2 of 2 transaction, that already has one signature signed by bitcoind # This tx can be found on testnet3 blockchain # txid: 9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2 raw_script = ( "522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c168851165521" "02b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452ae" ) p2sh_lookup = build_p2sh_lookup([h2b(raw_script)]) partially_signed_raw_tx = ( "010000000196238f11a5fd3ceef4efd5a186a7e6b9217d900418e72aca917cd6a6e634" "e74100000000910047304402201b41b471d9dd93cf97eed7cfc39a5767a546f6bfbf3e" "0c91ff9ad23ab9770f1f02205ce565666271d055be1f25a7e52e34cbf659f6c70770ff" "59bd783a6fcd1be3dd0147522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e4" "2cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff5" "0511830328c1b479986452aeffffffff01a0bb0d00000000001976a9143b3beefd6f78" "02fa8706983a76a51467bfa36f8b88ac00000000") tx = Tx.from_hex(partially_signed_raw_tx) tx_out = TxOut(1000000, h2b("a914a10dfa21ee8c33b028b92562f6fe04e60563d3c087")) tx.set_unspents([tx_out]) key = key_from_text( "cThRBRu2jAeshWL3sH3qbqdq9f4jDiDbd1SVz4qjTZD2xL1pdbsx") hash160_lookup = build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]) self.assertEqual(tx.bad_solution_count(), 1) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx.bad_solution_count(), 0) self.assertEqual( tx.id(), "9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2")
def do_test_tx(self, incoming_script, **kwargs): keys = [Key(i, generator=secp256k1_generator) for i in range(1, 20)] tx = self.make_test_tx(incoming_script) tx_in_idx = 0 kwargs["hash160_lookup"] = build_hash160_lookup((k.secret_exponent() for k in keys), [secp256k1_generator]) kwargs["generator_for_signature_type_f"] = Solver.SolutionChecker.VM.generator_for_signature_type self.do_test_solve(tx, tx_in_idx, **kwargs)
def test_multisig_one_at_a_time(self): M = 3 N = 3 keys = [ Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N + 2) ] tx_in = TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) ids = [ "403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058", "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db", "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44", "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771" ] for i in range(1, N + 1): self.assertEqual(tx2.bad_solution_count(), 1) self.assertEqual(tx2.id(), ids[i - 1]) hash160_lookup = build_hash160_lookup( (key.secret_exponent() for key in keys[i - 1:i]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) self.assertEqual(tx2.bad_solution_count(), 0)
def do_test_tx(self, incoming_script, **kwargs): keys = [Key(i) for i in range(1, 20)] tx = self.make_test_tx(incoming_script) tx_in_idx = 0 kwargs["hash160_lookup"] = build_hash160_lookup( (k.secret_exponent() for k in keys), [secp256k1_generator]) kwargs[ "generator_for_signature_type_f"] = Solver.SolutionChecker.VM.generator_for_signature_type self.do_test_solve(tx, tx_in_idx, **kwargs)
def check_tx_can_be_signed(self, tx_u, tx_s, private_keys=[], p2sh_values=[]): tx_u_prime = self.unsigned_copy(tx_s) tx_s_hex = tx_s.as_hex() tx_u_prime.set_unspents(tx_s.unspents) p2sh_lookup = build_p2sh_lookup([h2b(x) for x in p2sh_values]) hash160_lookup = build_hash160_lookup(private_keys, [secp256k1_generator]) tx_u_prime.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.check_signed(tx_u_prime) tx_hex = tx_u_prime.as_hex() self.assertEqual(tx_hex, tx_s_hex)
def test_sign_p2sh(self): tx_out_script = h2b("76a91491b24bf9f5288532960ac687abb035127b1d28a588ac") script = script_for_address("1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm") self.assertEqual(tx_out_script, script) tx_out = TxOut(100, tx_out_script) tx = Tx(1, [TxIn(b'\1' * 32, 1)], [TxOut(100, tx_out_script)]) tx.set_unspents([tx_out]) hl = build_hash160_lookup([1], [secp256k1_generator]) self.assertEqual(tx.bad_signature_count(), 1) tx.sign(hash160_lookup=hl) self.assertEqual(tx.bad_signature_count(), 0)
def test_sign_p2sh(self): tx_out_script = h2b( "76a91491b24bf9f5288532960ac687abb035127b1d28a588ac") script = script_for_address("1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm") self.assertEqual(tx_out_script, script) tx_out = TxOut(100, tx_out_script) tx = Tx(1, [TxIn(b'\1' * 32, 1)], [TxOut(100, tx_out_script)]) tx.set_unspents([tx_out]) hl = build_hash160_lookup([1], [secp256k1_generator]) self.assertEqual(tx.bad_solution_count(), 1) tx.sign(hash160_lookup=hl) self.assertEqual(tx.bad_solution_count(), 0)
def spend_sh_fund(tx_ins, wif_keys, tx_outs): """ spend script hash fund the key point of an input comes from multisig address is that, its sign script is combined with several individual signs :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script) :param wif_keys: private keys in wif format, technical should be the same order with the pubkey in redeem script, but pycoin has inner control, so here order is not mandatory :param tx_outs: balance, receiver_address :return: raw hex and tx id """ _txs_in = [] _un_spent = [] for tx_id, idx, balance, address, _ in tx_ins: # must h2b_rev NOT h2b tx_id_b = h2b_rev(tx_id) _txs_in.append(TxIn(tx_id_b, idx)) _un_spent.append( Spendable(balance, network.contract.for_address(address), tx_id_b, idx)) _txs_out = [] for balance, receiver_address in tx_outs: _txs_out.append( TxOut(balance, network.contract.for_address(receiver_address))) version, lock_time = 1, 0 tx = Tx(version, _txs_in, _txs_out, lock_time) tx.set_unspents(_un_spent) # construct hash160_lookup[hash160] = (secret_exponent, public_pair, compressed) for each individual key hash160_lookup = build_hash160_lookup( [network.parse.wif(wif_key).secret_exponent() for wif_key in wif_keys], [secp256k1_generator]) for i in range(0, len(tx_ins)): # you can add some conditions that if the input script is not p2sh type, not provide p2sh_lookup, # so that all kinds of inputs can work together p2sh_lookup = build_p2sh_lookup([binascii.unhexlify(tx_ins[i][-1])]) r = BitcoinSolver(tx).solve(hash160_lookup, i, hash_type=SIGHASH_ALL, p2sh_lookup=p2sh_lookup) if isinstance(r, bytes): tx.txs_in[i].script = r else: tx.txs_in[i].script = r[0] tx.set_witness(i, r[1]) return tx.as_hex(), tx.id()
def test_solve_pay_to_public_pair(self): for se in range(1, 10): key = Key(secret_exponent=se, generator=secp256k1_generator) for b in [True, False]: addr = key.address(use_uncompressed=b) script = script_for_p2pk(key.sec(use_uncompressed=b)) afs_address = address_for_script(script) self.assertEqual(afs_address, addr) hl = build_hash160_lookup([se], [secp256k1_generator]) tx = Tx(1, [], [Tx.TxOut(100, script)]) tx.sign(hash160_lookup=hl) afs_address = address_for_script(tx.txs_out[0].puzzle_script()) self.assertEqual(afs_address, addr)
def multisig_M_of_N(self, M, N, unsigned_id, signed_id): keys = [Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) self.assertEqual(tx2.id(), unsigned_id) self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup((key.secret_exponent() for key in keys[:M]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), signed_id) self.assertEqual(tx2.bad_signature_count(), 0)
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N+2)] tx_in = Tx.TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = Tx.TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) for partial_key_list in itertools.permutations(keys[:N], M): tx2 = create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) for key in partial_key_list: self.assertEqual(tx2.bad_signature_count(), 1) hash160_lookup = build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def test_p2sh_multisig_sequential_signing(self): raw_scripts = [ h2b("52210234abcffd2e80ad01c2ec0276ad02682808169c6fafdd25ebfb60703df272b461" "2102e5baaafff8094e4d77ce8b009d5ebc3de9110085ebd3d96e50cc7ce70faf175221" "0316ee25e80eb6e6fc734d9c86fa580cbb9c4bfd94a19f0373a22353ececd4db6853ae" ) ] spendable = { 'script_hex': 'a914c4ed4de526461e3efbb79c8b688a6f9282c0464687', 'does_seem_spent': 0, 'block_index_spent': 0, 'coin_value': 10000, 'block_index_available': 0, 'tx_out_index': 0, 'tx_hash_hex': '0ca152ba6b88db87a7ef1afd24554102aca1ab86cf2c10ccbc374472145dc943' } key_1 = key_from_text( 'Kz6pytJCigYHeMsGLmfHQPJhN5og2wpeSVrU43xWwgHLCAvpsprh') key_2 = key_from_text( 'Kz7NHgX7MBySA3RSKj9GexUSN6NepEDoPNugSPr5absRDoKgn2dT') for ordered_keys in [(key_1, key_2), (key_2, key_1)]: txs_in = [ TxIn(previous_hash=h2b( '43c95d14724437bccc102ccf86aba1ac02415524fd1aefa787db886bba52a10c' ), previous_index=0) ] txs_out = [ TxOut(10000, script_for_address('3KeGeLFmsbmbVdeMLrWp7WYKcA3tdsB4AR')) ] unspents = [Spendable.from_dict(spendable)] tx = Tx(version=DEFAULT_VERSION, txs_in=txs_in, txs_out=txs_out, unspents=unspents) for key in ordered_keys: self.assertEqual(tx.bad_solution_count(), 1) p2sh_lookup = build_p2sh_lookup(raw_scripts) tx.sign(build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]), p2sh_lookup=p2sh_lookup) self.assertEqual(tx.bad_solution_count(), 0)
def tether_tx(tx_ins, in_keys, send_amount, receiver, change_address): """ simple usdt transaction different address's utxo can be used for mine fee, but should be aware sender is determined by the first input in the tx bitcoin change can also be sent back to different address, but should be aware receiver is indicated by the last output address that is not the sender :param tx_ins: utxo from the sender :param in_keys: list of private keys in hex format corresponding to each input :param send_amount: (display amount) * (10 ** 8) :param receiver: address to receive usdt :param change_address: address to receive btc change """ _txs_in = [] _un_spent = [] total_bal = 0 for tx_id, idx, balance, address in tx_ins: total_bal += balance # must h2b_rev NOT h2b tx_id_b = h2b_rev(tx_id) _txs_in.append(TxIn(tx_id_b, idx)) _un_spent.append( Spendable(balance, network.contract.for_address(address), tx_id_b, idx)) satoshi_per_byte = recommend_satoshi_per_byte() txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 3) * satoshi_per_byte _txs_out = [ TxOut(total_bal - txn_fee - MIN_BTC_OUT, network.contract.for_address(change_address)), TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))), TxOut(MIN_BTC_OUT, network.contract.for_address(receiver)) ] version, lock_time = 1, 0 tx = Tx(version, _txs_in, _txs_out, lock_time) tx.set_unspents(_un_spent) solver = build_hash160_lookup([int(pri_hex, 16) for pri_hex in in_keys], [secp256k1_generator]) signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL) return signed_tx.as_hex(), signed_tx.id()
def multisig_M_of_N_individually(self, M, N): keys = [Key(secret_exponent=i) for i in range(1, N + 2)] tx_in = Tx.TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = Tx.TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) for partial_key_list in itertools.permutations(keys[:N], M): tx2 = create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) for key in partial_key_list: self.assertEqual(tx2.bad_solution_count(), 1) hash160_lookup = build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.bad_solution_count(), 0)
def test_sign_pay_to_script_multisig(self): M, N = 3, 3 keys = [Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') underlying_script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) address = address_for_p2s(underlying_script) self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q") script = script_for_address(address) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address]) hash160_lookup = build_hash160_lookup((key.secret_exponent() for key in keys[:N]), [secp256k1_generator]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx2.bad_signature_count(), 0)
def multisig_M_of_N(self, M, N, unsigned_id, signed_id): keys = [ Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N + 2) ] tx_in = TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) self.assertEqual(tx2.id(), unsigned_id) self.assertEqual(tx2.bad_solution_count(), 1) hash160_lookup = build_hash160_lookup( (key.secret_exponent() for key in keys[:M]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), signed_id) self.assertEqual(tx2.bad_solution_count(), 0)
def test_p2multisig_incremental(self): keys = [Key(i, generator=secp256k1_generator) for i in (1, 2, 3)] secs = [k.sec() for k in keys] tx = self.make_test_tx(script_for_multisig(3, secs)) tx_in_idx = 0 for k in keys: try: tx.check_solution(tx_in_idx) assert 0 except ScriptError: pass kwargs = {"hash160_lookup": build_hash160_lookup([k.secret_exponent()], [secp256k1_generator])} kwargs["existing_script"] = [ data for opcode, data, pc, new_pc in BitcoinScriptTools.get_opcodes( tx.txs_in[tx_in_idx].script) if data is not None] kwargs["nocheck"] = True kwargs["generator_for_signature_type_f"] = Solver.SolutionChecker.VM.generator_for_signature_type solution_list, witness_list = self.do_test_solve(tx, tx_in_idx, **kwargs) tx.check_solution(tx_in_idx)
def test_sign_pay_to_script_multisig(self): M, N = 3, 3 keys = [ Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N + 2) ] tx_in = TxIn.coinbase_tx_in(script=b'') underlying_script = script_for_multisig( m=M, sec_keys=[key.sec() for key in keys[:N]]) address = address_for_p2s(underlying_script) self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q") script = script_for_address(address) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address]) hash160_lookup = build_hash160_lookup( (key.secret_exponent() for key in keys[:N]), [secp256k1_generator]) p2sh_lookup = build_p2sh_lookup([underlying_script]) tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx2.bad_solution_count(), 0)
def test_multisig_one_at_a_time(self): M = 3 N = 3 keys = [Key(secret_exponent=i, generator=secp256k1_generator) for i in range(1, N+2)] tx_in = TxIn.coinbase_tx_in(script=b'') script = script_for_multisig(m=M, sec_keys=[key.sec() for key in keys[:N]]) tx_out = TxOut(1000000, script) tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out]) tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()]) ids = ["403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058", "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db", "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44", "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771"] for i in range(1, N+1): self.assertEqual(tx2.bad_signature_count(), 1) self.assertEqual(tx2.id(), ids[i-1]) hash160_lookup = build_hash160_lookup((key.secret_exponent() for key in keys[i-1:i]), [secp256k1_generator]) tx2.sign(hash160_lookup=hash160_lookup) self.assertEqual(tx2.id(), ids[i]) self.assertEqual(tx2.bad_signature_count(), 0)
def test_p2sh_multisig_sequential_signing(self): raw_scripts = [h2b( "52210234abcffd2e80ad01c2ec0276ad02682808169c6fafdd25ebfb60703df272b461" "2102e5baaafff8094e4d77ce8b009d5ebc3de9110085ebd3d96e50cc7ce70faf175221" "0316ee25e80eb6e6fc734d9c86fa580cbb9c4bfd94a19f0373a22353ececd4db6853ae")] spendable = {'script_hex': 'a914c4ed4de526461e3efbb79c8b688a6f9282c0464687', 'does_seem_spent': 0, 'block_index_spent': 0, 'coin_value': 10000, 'block_index_available': 0, 'tx_out_index': 0, 'tx_hash_hex': '0ca152ba6b88db87a7ef1afd24554102aca1ab86cf2c10ccbc374472145dc943'} key_1 = key_from_text('Kz6pytJCigYHeMsGLmfHQPJhN5og2wpeSVrU43xWwgHLCAvpsprh') key_2 = key_from_text('Kz7NHgX7MBySA3RSKj9GexUSN6NepEDoPNugSPr5absRDoKgn2dT') for ordered_keys in [(key_1, key_2), (key_2, key_1)]: txs_in = [TxIn(previous_hash=h2b('43c95d14724437bccc102ccf86aba1ac02415524fd1aefa787db886bba52a10c'), previous_index=0)] txs_out = [TxOut(10000, script_for_address('3KeGeLFmsbmbVdeMLrWp7WYKcA3tdsB4AR'))] unspents = [Spendable.from_dict(spendable)] tx = Tx(version=DEFAULT_VERSION, txs_in=txs_in, txs_out=txs_out, unspents=unspents) for key in ordered_keys: self.assertEqual(tx.bad_signature_count(), 1) p2sh_lookup = build_p2sh_lookup(raw_scripts) tx.sign(build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]), p2sh_lookup=p2sh_lookup) self.assertEqual(tx.bad_signature_count(), 0)
def tether_tx_flush(tx_ins, private_key, send_amount, receiver): """ this is just a tool function that sends all btc and usdt fund to the same receiver address params are same with tether_tx """ _txs_in = [] _un_spent = [] total_bal = 0 for tx_id, idx, balance, address in tx_ins: total_bal += balance # must h2b_rev NOT h2b tx_id_b = h2b_rev(tx_id) _txs_in.append(TxIn(tx_id_b, idx)) _un_spent.append( Spendable(balance, network.contract.for_address(address), tx_id_b, idx)) txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 2) * recommend_satoshi_per_byte() _txs_out = [ TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))), TxOut(total_bal - txn_fee, network.contract.for_address(receiver)) ] version, lock_time = 1, 0 tx = Tx(version, _txs_in, _txs_out, lock_time) tx.set_unspents(_un_spent) solver = build_hash160_lookup([int(private_key, 16)] * len(tx_ins), [secp256k1_generator]) signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL) return signed_tx.as_hex(), signed_tx.id()
def test_sign_bitcoind_partially_signed_2_of_2(self): # Finish signing a 2 of 2 transaction, that already has one signature signed by bitcoind # This tx can be found on testnet3 blockchain # txid: 9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2 raw_script = ("522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c168851165521" "02b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452ae") p2sh_lookup = build_p2sh_lookup([h2b(raw_script)]) partially_signed_raw_tx = ( "010000000196238f11a5fd3ceef4efd5a186a7e6b9217d900418e72aca917cd6a6e634" "e74100000000910047304402201b41b471d9dd93cf97eed7cfc39a5767a546f6bfbf3e" "0c91ff9ad23ab9770f1f02205ce565666271d055be1f25a7e52e34cbf659f6c70770ff" "59bd783a6fcd1be3dd0147522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e4" "2cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff5" "0511830328c1b479986452aeffffffff01a0bb0d00000000001976a9143b3beefd6f78" "02fa8706983a76a51467bfa36f8b88ac00000000") tx = Tx.from_hex(partially_signed_raw_tx) tx_out = TxOut(1000000, h2b("a914a10dfa21ee8c33b028b92562f6fe04e60563d3c087")) tx.set_unspents([tx_out]) key = key_from_text("cThRBRu2jAeshWL3sH3qbqdq9f4jDiDbd1SVz4qjTZD2xL1pdbsx") hash160_lookup = build_hash160_lookup([key.secret_exponent()], [secp256k1_generator]) self.assertEqual(tx.bad_signature_count(), 1) tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup) self.assertEqual(tx.bad_signature_count(), 0) self.assertEqual(tx.id(), "9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2")
def test_bip143_tx_5(self): tx_u5, tx_s5 = self.check_bip143_tx( "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787" "b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631" "e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84" "c138dbbd3c3ee41588ac00000000", "0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca2" "9787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1b" "b8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc" "0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e" "6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52e" "eb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e" "4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009" "a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62" "e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfe" "c54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a8913" "9c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b" "79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265" "f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553b" "a89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5" "d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1" "482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a" "34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae" "49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28" "bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703" "413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb8" "33092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94b" "a04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2" "f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", [(9.87654321, "a9149993a429037b5d912407a71c252019287b8d27a587")], 1, 2, 1, 0 ) tx_u5prime = self.unsigned_copy(tx_s5) tx_s_hex = tx_s5.as_hex() tx_u5prime.set_unspents(tx_s5.unspents) ss = ["56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", "0020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54"] p2sh_lookup = build_p2sh_lookup([h2b(x) for x in ss]) for se, sighash_type in [ (0x730fff80e1413068a05b57d6a58261f07551163369787f349438ea38ca80fac6, SIGHASH_ALL), (0x11fa3d25a17cbc22b29c44a484ba552b5a53149d106d3d853e22fdd05a2d8bb3, SIGHASH_NONE), (0x77bf4141a87d55bdd7f3cd0bdccf6e9e642935fec45f2f30047be7b799120661, SIGHASH_SINGLE), (0x14af36970f5025ea3e8b5542c0f8ebe7763e674838d08808896b63c3351ffe49, SIGHASH_ANYONECANPAY | SIGHASH_ALL), (0xfe9a95c19eef81dde2b95c1284ef39be497d128e2aa46916fb02d552485e0323, SIGHASH_ANYONECANPAY | SIGHASH_NONE), (0x428a7aee9f0c2af0cd19af3cf1c78149951ea528726989b2e83e4778d2c3f890, SIGHASH_ANYONECANPAY | SIGHASH_SINGLE), ]: tx_u5prime.sign(hash_type=sighash_type, hash160_lookup=build_hash160_lookup( [se], [secp256k1_generator]), p2sh_lookup=p2sh_lookup) self.check_signed(tx_u5prime) tx_hex = tx_u5prime.as_hex() self.assertEqual(tx_hex, tx_s_hex) sc = tx_s5.SolutionChecker(tx_s5) self.assertEqual(b2h(sc._hash_prevouts(SIGHASH_ALL)), "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0") self.assertEqual(b2h(sc._hash_sequence(SIGHASH_ALL)), "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044") self.assertEqual(b2h(sc._hash_outputs(SIGHASH_ALL, 0)), "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc") self.assertEqual(b2h(sc._hash_outputs(SIGHASH_SINGLE, 0)), "9efe0c13a6b16c14a41b04ebe6a63f419bdacb2f8705b494a43063ca3cd4f708") script = tx_s5.txs_in[0].witness[-1] self.assertEqual( b2h(sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_ALL)), "0100000074afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aa" "a03bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e706650443664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffffbc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fd" "bb8eb90307cc0000000001000000") self.assertEqual( b2h(sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_NONE)), "0100000074afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aa" "a000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff0000000000000000000000000000000000000000000000000000" "0000000000000000000002000000") self.assertEqual( b2h(sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_SINGLE)), "0100000074afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aa" "a000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff9efe0c13a6b16c14a41b04ebe6a63f419bdacb2f8705b494a430" "63ca3cd4f7080000000003000000") self.assertEqual( b2h(sc._segwit_signature_preimage( script=script, tx_in_idx=0, hash_type=SIGHASH_ALL | SIGHASH_ANYONECANPAY)), "0100000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffffbc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fd" "bb8eb90307cc0000000081000000") self.assertEqual( b2h(sc._segwit_signature_preimage( script=script, tx_in_idx=0, hash_type=SIGHASH_NONE | SIGHASH_ANYONECANPAY)), "0100000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff0000000000000000000000000000000000000000000000000000" "0000000000000000000082000000") self.assertEqual( b2h(sc._segwit_signature_preimage( script=script, tx_in_idx=0, hash_type=SIGHASH_SINGLE | SIGHASH_ANYONECANPAY)), "0100000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff9efe0c13a6b16c14a41b04ebe6a63f419bdacb2f8705b494a430" "63ca3cd4f7080000000083000000") tx = Tx.from_hex("010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac83" "87f14c1d000000ffffffff0101000000000000000000000000") tx.set_witness(0, [h2b(x) for x in [ "30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dc" "c9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c5" "3e01", "02a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c", "ad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d8915" "56dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae6" "26c53e01" ]]) tx = Tx.from_hex( "0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1" "ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c497" "4de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f8" "45d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61f" "b5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487f" "b382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf9" "5feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000") tx_hex = tx.as_hex() print(tx) print(tx_hex) tx = Tx.from_hex( "010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac83" "87f14c1d000000ffffffff0101000000000000000000000000") self.assertEqual( tx_hex, "0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1" "ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c497" "4de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f8" "45d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61f" "b5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487f" "b382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf9" "5feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000")
def tether_tx_sh(tx_ins, wif_keys, send_amount, receiver, change_address): """ spend usdt having p2sh utxo WARNING!!! THIS FUNCTION IS NOT FULLY TESTED AS MY FUND WAS STOLEN BY A SON OF BITCH AFTER I BY ACCIDENT COMMITTED MY PRIVATE KEY!!! :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script), redeem_script is required for p2sh utxo, set it None for p2pkh utxo :param wif_keys: private keys of the inputs :param send_amount: (display amount) * (10 ** 8) :param receiver: address to receive usdt :param change_address: address to receive btc change """ _txs_in = [] _un_spent = [] total_bal = 0 for tx_id, idx, balance, address, _ in tx_ins: total_bal += balance # must h2b_rev NOT h2b tx_id_b = h2b_rev(tx_id) _txs_in.append(TxIn(tx_id_b, idx)) _un_spent.append( Spendable(balance, network.contract.for_address(address), tx_id_b, idx)) txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 3) * recommend_satoshi_per_byte() / 3 _txs_out = [ TxOut(total_bal - txn_fee - MIN_BTC_OUT, network.contract.for_address(change_address)), TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))), TxOut(MIN_BTC_OUT, network.contract.for_address(receiver)) ] version, lock_time = 1, 0 tx = Tx(version, _txs_in, _txs_out, lock_time) tx.set_unspents(_un_spent) # construct hash160_lookup[hash160] = (secret_exponent, public_pair, compressed) for each individual key hash160_lookup = build_hash160_lookup( [network.parse.wif(wif_key).secret_exponent() for wif_key in wif_keys], [secp256k1_generator]) for i in range(0, len(tx_ins)): if tx_ins[i][-1]: p2sh_lookup = build_p2sh_lookup( [binascii.unhexlify(tx_ins[i][-1])]) else: p2sh_lookup = None r = BitcoinSolver(tx).solve(hash160_lookup, i, hash_type=SIGHASH_ALL, p2sh_lookup=p2sh_lookup) if isinstance(r, bytes): tx.txs_in[i].script = r else: tx.txs_in[i].script = r[0] tx.set_witness(i, r[1]) return tx.as_hex(), tx.id()
def network_build_hash160_lookup(iter): return build_hash160_lookup(iter, [generator])
def test_bip143_tx_5(self): tx_u5, tx_s5 = self.check_bip143_tx( "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787" "b96e0100000000ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631" "e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e6e84" "c138dbbd3c3ee41588ac00000000", "0100000000010136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca2" "9787b96e0100000023220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1b" "b8a09062c35f0dcb54ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc" "0631e88a821ffdbe9bfe2688acc0832f05000000001976a9147480a33f950689af511e" "6e84c138dbbd3c3ee41588ac080047304402206ac44d672dac41f9b00e28f4df20c52e" "eb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e" "4f98acaa594810388cf7409a1870ce01473044022068c7946a43232757cbdf9176f009" "a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62" "e027f64eefa2695578cc6432cdabce271502473044022059ebf56d98010a932cf8ecfe" "c54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a8913" "9c9fe7e499259875357e20fcbb15571c76795403483045022100fbefd94bd0a488d50b" "79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265" "f5a942e96213afae16d83321c8b31bb342142a14d16381483045022100a5263ea0553b" "a89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5" "d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a08824730440220525406a1" "482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a" "34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b4783cf56210307b8ae" "49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28" "bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21034b8113d703" "413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb8" "33092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6d48b1131e94b" "a04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b661b0b3302ee2" "f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae00000000", [(9.87654321, "a9149993a429037b5d912407a71c252019287b8d27a587")], 1, 2, 1, 0) tx_u5prime = self.unsigned_copy(tx_s5) tx_s_hex = tx_s5.as_hex() tx_u5prime.set_unspents(tx_s5.unspents) ss = [ "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56ae", "0020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54" ] p2sh_lookup = build_p2sh_lookup([h2b(x) for x in ss]) for se, sighash_type in [ (0x730fff80e1413068a05b57d6a58261f07551163369787f349438ea38ca80fac6, SIGHASH_ALL), (0x11fa3d25a17cbc22b29c44a484ba552b5a53149d106d3d853e22fdd05a2d8bb3, SIGHASH_NONE), (0x77bf4141a87d55bdd7f3cd0bdccf6e9e642935fec45f2f30047be7b799120661, SIGHASH_SINGLE), (0x14af36970f5025ea3e8b5542c0f8ebe7763e674838d08808896b63c3351ffe49, SIGHASH_ANYONECANPAY | SIGHASH_ALL), (0xfe9a95c19eef81dde2b95c1284ef39be497d128e2aa46916fb02d552485e0323, SIGHASH_ANYONECANPAY | SIGHASH_NONE), (0x428a7aee9f0c2af0cd19af3cf1c78149951ea528726989b2e83e4778d2c3f890, SIGHASH_ANYONECANPAY | SIGHASH_SINGLE), ]: tx_u5prime.sign(hash_type=sighash_type, hash160_lookup=build_hash160_lookup( [se], [secp256k1_generator]), p2sh_lookup=p2sh_lookup) self.check_signed(tx_u5prime) tx_hex = tx_u5prime.as_hex() self.assertEqual(tx_hex, tx_s_hex) sc = tx_s5.SolutionChecker(tx_s5) self.assertEqual( b2h(sc._hash_prevouts(SIGHASH_ALL)), "74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0") self.assertEqual( b2h(sc._hash_sequence(SIGHASH_ALL)), "3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044") self.assertEqual( b2h(sc._hash_outputs(SIGHASH_ALL, 0)), "bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc") self.assertEqual( b2h(sc._hash_outputs(SIGHASH_SINGLE, 0)), "9efe0c13a6b16c14a41b04ebe6a63f419bdacb2f8705b494a43063ca3cd4f708") script = tx_s5.txs_in[0].witness[-1] self.assertEqual( b2h( sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_ALL)), "0100000074afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aa" "a03bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e706650443664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffffbc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fd" "bb8eb90307cc0000000001000000") self.assertEqual( b2h( sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_NONE)), "0100000074afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aa" "a000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff0000000000000000000000000000000000000000000000000000" "0000000000000000000002000000") self.assertEqual( b2h( sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_SINGLE)), "0100000074afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aa" "a000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff9efe0c13a6b16c14a41b04ebe6a63f419bdacb2f8705b494a430" "63ca3cd4f7080000000003000000") self.assertEqual( b2h( sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_ALL | SIGHASH_ANYONECANPAY)), "0100000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffffbc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fd" "bb8eb90307cc0000000081000000") self.assertEqual( b2h( sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_NONE | SIGHASH_ANYONECANPAY)), "0100000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff0000000000000000000000000000000000000000000000000000" "0000000000000000000082000000") self.assertEqual( b2h( sc._segwit_signature_preimage(script=script, tx_in_idx=0, hash_type=SIGHASH_SINGLE | SIGHASH_ANYONECANPAY)), "0100000000000000000000000000000000000000000000000000000000000000000000" "0000000000000000000000000000000000000000000000000000000000000000003664" "1869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e01000000cf" "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3" "2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b21" "034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a2103" "3400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f42103a6" "d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac162102d8b6" "61b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b56aeb168de" "3a00000000ffffffff9efe0c13a6b16c14a41b04ebe6a63f419bdacb2f8705b494a430" "63ca3cd4f7080000000083000000") tx = Tx.from_hex( "010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac83" "87f14c1d000000ffffffff0101000000000000000000000000") tx.set_witness(0, [ h2b(x) for x in [ "30450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dc" "c9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c5" "3e01", "02a9781d66b61fb5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c", "ad4830450220487fb382c4974de3f7d834c1b617fe15860828c7f96454490edd6d8915" "56dcc9022100baf95feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae6" "26c53e01" ] ]) tx = Tx.from_hex( "0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1" "ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c497" "4de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f8" "45d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61f" "b5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487f" "b382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf9" "5feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000" ) tx_hex = tx.as_hex() print(tx) print(tx_hex) tx = Tx.from_hex( "010000000169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1ac83" "87f14c1d000000ffffffff0101000000000000000000000000") self.assertEqual( tx_hex, "0100000000010169c12106097dc2e0526493ef67f21269fe888ef05c7a3a5dacab38e1" "ac8387f14c1d000000ffffffff01010000000000000000034830450220487fb382c497" "4de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf95feb48f8" "45d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e012102a9781d66b61f" "b5a7ef00ac5ad5bc6ffc78be7b44a566e3c87870e1079368df4c4aad4830450220487f" "b382c4974de3f7d834c1b617fe15860828c7f96454490edd6d891556dcc9022100baf9" "5feb48f845d5bfc9882eb6aeefa1bc3790e39f59eaa46ff7f15ae626c53e0100000000" )