def main(): # always remember to setup the network setup('testnet') priv1 = PrivateKey("cN1XE3ESGgdvr4fWsB7L3BcqXncUauF8Fo8zzv4Sm6WrkiGrsxrG") priv2 = PrivateKey("cR8AkcbL2pgBswrHp28AftEznHPPLA86HiTog8MpNCibxwrsUcZ4") p2sh_redeem_script = Script( ['OP_1', priv1.get_public_key().to_hex(), priv2.get_public_key().to_hex(),'OP_2', 'OP_CHECKMULTISIG']) fromAddress = P2wshAddress.from_script(p2sh_redeem_script) toAddress = P2wpkhAddress.from_address("tb1qtstf97nhk2gycz7vl37esddjpxwt3ut30qp5pn") # set values txid = '2042195c40a92353f2ffe30cd0df8d177698560e81807e8bf9174a9c0e98e6c2' vout = 0 amount = 0.01 # create transaction input from tx id of UTXO txin = TxInput(txid, vout) txOut1 = TxOutput(0.0001, toAddress.to_script_pub_key()) txOut2 = TxOutput(0.0098, fromAddress.to_script_pub_key()) tx = Transaction([txin], [txOut1, txOut2], has_segwit=True) sig1 = priv1.sign_segwit_input(tx, 0, p2sh_redeem_script, amount) tx.witnesses.append(Script(['OP_0', sig1, p2sh_redeem_script.to_hex()])) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + tx.serialize()) print("\nTxId:", tx.get_txid())
def test_spend_p2sh_csv_p2pkh(self): redeem_script = Script([ self.seq.for_script(), 'OP_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', self.sk_csv_p2pkh.get_public_key().to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) txout = TxOutput(Decimal('11'), self.another_addr.to_script_pub_key()) tx = Transaction([self.txin_seq], [txout]) sig = self.sk_csv_p2pkh.sign_input(tx, 0, redeem_script) self.txin_seq.script_sig = Script([ sig, self.sk_csv_p2pkh.get_public_key().to_hex(), redeem_script.to_hex() ]) self.assertEqual(tx.serialize(), self.spend_p2sh_csv_p2pkh_result)
def main(): # always remember to setup the network setup('testnet') # # This script spends from a P2SH address containing a P2PK script # # create transaction input from tx id of UTXO (contained 0.1 tBTC) txin = TxInput( '7db363d5a7fabb64ccce154e906588f1936f34481223ea8c1f2c935b0a0c945b', 0) # secret key needed to spend P2PK that is wrapped by P2SH p2pk_sk = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') p2pk_pk = p2pk_sk.get_public_key().to_hex() # create the redeem script - needed to sign the transaction redeem_script = Script([p2pk_pk, 'OP_CHECKSIG']) #TODELETE #txin_script_pub_key = redeem_script.to_p2sh_script_pub_key() to_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') txout = TxOutput(Decimal('0.08'), to_addr.to_script_pub_key()) # no change address - the remaining 0.01 tBTC will go to miners) # create transaction from inputs/outputs -- default locktime is used tx = Transaction([txin], [txout]) # print raw transaction print("\nRaw unsigned transaction:\n" + tx.serialize()) # use the private key corresponding to the address that contains the # UTXO we are trying to spend to create the signature for the txin - # note that the redeem script is passed to replace the scriptSig sig = p2pk_sk.sign_input(tx, 0, redeem_script) #print(sig) # set the scriptSig (unlocking script) txin.script_sig = Script([sig, redeem_script.to_hex()]) signed_tx = tx.serialize() # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + signed_tx) print("\nTxId:", tx.get_txid())
def csv_script(recreate=False): """ creates a P2SH address with a relative csv timelock script Attributes ---------- recreate : boolean False (default) -> used when creating new p2sh addr (save and display) True -> used when spending from p2sh address (returns objects for TX) returns ------- if recreate=False (default - used when creating new p2sh addres) returns nothing - writes p2sh address into data.json - displays p2sh address to the user if recreate=True (used to recreate script when spending form p2sh address) returns csv_script (Script Object), p2sh_addr (P2shAddress Object) """ # load csv script data (pub_key_hash, timelock_period) from data.json data = tools.load_data_json(pub_hash=True, timelock_csv=True, timelock_log=True) pub_key_hash = data['pub_key_hash'] timelock_period = data['timelock_csv'] timelock_str = data['timelock_log'] # initiate script object csv_script = Script([timelock_period, 'OP_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', pub_key_hash, 'OP_EQUALVERIFY', 'OP_CHECKSIG']) # get P2SH address of csv_script p2sh_addr = P2shAddress.from_script(csv_script).to_address() csv_hash = csv_script.to_hex() if recreate: # used when spending from p2sh return csv_script, p2sh_addr # used when creating initial p2sh # - writes p2sh address into data.json # - displays p2sh address (+details) to the user via terminal tools.update_data_json(outputs={'p2sh_address': p2sh_addr, 'csv_hash': csv_hash}) print('\nNew p2sh address with CSV script created') print(' -> timelock period for:', timelock_str, 'blocks') print(' -> script_hash:', csv_hash) print(' -> p2sh_addr:', p2sh_addr, '\n')
def main(): # always remember to setup the network setup('testnet') # # This script spends from a P2SH address containing a CSV+P2PKH script as # created from examples/create_p2sh_csv_p2pkh.py # # We assume that some 11.1 tBTC have been send to that address and that we know # the txid and the specific UTXO index (or vout). # # set values relative_blocks = 20 txid = '76c102821b916a625bd3f0c3c6e35d5c308b7c23e78b8866b06a3a466041db0a' vout = 0 seq = Sequence(TYPE_RELATIVE_TIMELOCK, relative_blocks) # create transaction input from tx id of UTXO (contained 11.1 tBTC) txin = TxInput(txid, vout, sequence=seq.for_input_sequence()) # secret key needed to spend P2PKH that is wrapped by P2SH p2pkh_sk = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') p2pkh_pk = p2pkh_sk.get_public_key().to_hex() p2pkh_addr = p2pkh_sk.get_public_key().get_address() # create the redeem script - needed to sign the transaction redeem_script = Script([ seq.for_script(), 'OP_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # to confirm that address is the same as the one that the funds were sent #addr = P2shAddress.from_script(redeem_script) #print(addr.to_address()) # send/spend to any random address to_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') txout = TxOutput(11, to_addr.to_script_pub_key()) # no change address - the remaining 0.1 tBTC will go to miners) # create transaction from inputs/outputs tx = Transaction([txin], [txout]) # print raw transaction print("\nRaw unsigned transaction:\n" + tx.serialize()) # use the private key corresponding to the address that contains the # UTXO we are trying to spend to create the signature for the txin - # note that the redeem script is passed to replace the scriptSig sig = p2pkh_sk.sign_input(tx, 0, redeem_script) #print(sig) # set the scriptSig (unlocking script) -- unlock the P2PKH (sig, pk) plus # the redeem script, since it is a P2SH txin.script_sig = Script([sig, p2pkh_pk, redeem_script.to_hex()]) signed_tx = tx.serialize() # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + signed_tx) print("\nTxId:", tx.get_txid())
# 14. Add a small fee. A few satoshis is fine. fee = 0.0001 amount = Decimal(btc_to_send) - Decimal(fee) print("Amount:", amount) txout = TxOutput(amount, to_address.to_script_pub_key()) # 15. Create the transaction using the input and output. tx = Transaction([txin], [txout]) # 16. Sign the input. sig = priv.sign_input(tx, 0, redeem_script) # 17. Create the signature. txin.script_sig = Script([sig, pub.to_hex(), redeem_script.to_hex()]) signed_tx = tx.serialize() print("\nTxId:", tx.get_txid()) # 18. Print the raw transaction. tx.get_txid() tx.get_size() tx tx.has_segwit # 19. Submit the transaction to the blockchain. What happens? get_connection() proxy.getrawmempool()
# # 7) display the raw unsigned transaction # if i: print( "raw unsigned transaction:\n" + tx.serialize() ) # # 8) sign the transaction # j = 0 for txin in txins: signature = from_privkey.sign_input( tx, j, redeem_script ) txin.script_sig = Script( [signature, from_pubkey.to_hex(), redeem_script.to_hex()] ) j += 1 # # 9) display the raw signed transaction # if i: print( "raw signed transaction:\n" + tx.serialize() ) fee = int(tx.get_size() * satoshi_per_byte) # # 10) display the transaction id
class TestCreateP2shTransaction(unittest.TestCase): def setUp(self): setup('testnet') self.txin = TxInput( "76464c2b9e2af4d63ef38a77964b3b77e629dddefc5cb9eb1a3645b1608b790f", 0) self.from_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') self.sk = PrivateKey( 'cTALNpTpRbbxTCJ2A5Vq88UxT44w1PE2cYqiB3n4hRvzyCev1Wwo') self.p2pk_sk = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') self.p2pk_redeem_script = Script( [self.p2pk_sk.get_public_key().to_hex(), 'OP_CHECKSIG']) self.txout = TxOutput(to_satoshis(0.09), self.p2pk_redeem_script.to_p2sh_script_pub_key()) self.create_p2sh_and_send_result = '02000000010f798b60b145361aebb95cfcdedd29e6773b4b96778af33ed6f42a9e2b4c4676000000006b483045022100fd3a3fd4aeec5db0f3f9c5c5ef7f60f37920be7464a80edacbc3b6b9d0624173022031ce309330e60b19d39cec8c5597460c840adcdd66f7dbbf896eef3ec42b472f012102d82c9860e36f15d7b72aa59e29347f951277c21cd4d34822acdeeadbcff8a546ffffffff01405489000000000017a9142910fc0b1b7ab6c9789c5a67c22c5bcde5b903908700000000' self.txin_spend = TxInput( '7db363d5a7fabb64ccce154e906588f1936f34481223ea8c1f2c935b0a0c945b', 0) # self.p2pk_sk , self.p2pk_redeem_script from above self.to_addr = self.from_addr self.txout2 = TxOutput(to_satoshis(0.08), self.to_addr.to_script_pub_key()) self.spend_p2sh_result = '02000000015b940c0a5b932c1f8cea231248346f93f18865904e15cecc64bbfaa7d563b37d000000006c47304402204984c2089bf55d5e24851520ea43c431b0d79f90d464359899f27fb40a11fbd302201cc2099bfdc18c3a412afb2ef1625abad8a2c6b6ae0bf35887b787269a6f2d4d01232103a2fef1829e0742b89c218c51898d9e7cb9d51201ba2bf9d9e9214ebb6af32708acffffffff0100127a00000000001976a914fd337ad3bf81e086d96a68e1f8d6a0a510f8c24a88ac00000000' # P2SH(CSV+P2PKH) self.sk_csv_p2pkh = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') self.seq = Sequence(TYPE_RELATIVE_TIMELOCK, 200) self.txin_seq = TxInput( 'f557c623e55f0affc696b742630770df2342c4aac395e0ed470923247bc51b95', 0, sequence=self.seq.for_input_sequence()) self.another_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') self.spend_p2sh_csv_p2pkh_result = '0200000001951bc57b24230947ede095c3aac44223df70076342b796c6ff0a5fe523c657f5000000008a483045022100c123775e69ec27094f7940facb9ad769c09f48a7fc88250a2fce67bd92c9b4cf02204ebdbed84af46e584fe6db9a23c420b7370879e883b555e119465f84bf34d82f012103a2fef1829e0742b89c218c51898d9e7cb9d51201ba2bf9d9e9214ebb6af327081e02c800b27576a914c3f8e5b0f8455a2b02c29c4488a550278209b66988acc80000000100ab9041000000001976a914fd337ad3bf81e086d96a68e1f8d6a0a510f8c24a88ac00000000' def test_signed_send_to_p2sh(self): tx = Transaction([self.txin], [self.txout]) sig = self.sk.sign_input(tx, 0, self.from_addr.to_script_pub_key()) pk = self.sk.get_public_key().to_hex() self.txin.script_sig = Script([sig, pk]) self.assertEqual(tx.serialize(), self.create_p2sh_and_send_result) def test_spend_p2sh(self): tx = Transaction([self.txin_spend], [self.txout2]) sig = self.p2pk_sk.sign_input(tx, 0, self.p2pk_redeem_script) self.txin_spend.script_sig = Script( [sig, self.p2pk_redeem_script.to_hex()]) self.assertEqual(tx.serialize(), self.spend_p2sh_result) def test_spend_p2sh_csv_p2pkh(self): redeem_script = Script([ self.seq.for_script(), 'OP_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', self.sk_csv_p2pkh.get_public_key().to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) txout = TxOutput(to_satoshis(11), self.another_addr.to_script_pub_key()) tx = Transaction([self.txin_seq], [txout]) sig = self.sk_csv_p2pkh.sign_input(tx, 0, redeem_script) self.txin_seq.script_sig = Script([ sig, self.sk_csv_p2pkh.get_public_key().to_hex(), redeem_script.to_hex() ]) self.assertEqual(tx.serialize(), self.spend_p2sh_csv_p2pkh_result)
def buy_lambo(key, lock, from_addr, to_addr): setup(os.getenv("BUY_LAMBO_BTC_NET", "regtest")) # Create a proxy to JSON-RPC api chain = NodeProxy(os.getenv("BUY_LAMBO_RPC_USER", "rpcuser"), os.getenv("BUY_LAMBO_RPC_PASSWORD", "rpcpassword")).get_proxy() # Try executing a command to see if node is running try: chain.getblockcount() except Exception: print("Error: Node isn't working!") return # Check addresses if not chain.validateaddress(from_addr)["isvalid"]: print("Error: `from_addr` is not a valid address!") return if not chain.validateaddress(to_addr)["isvalid"]: print("Error: `to_addr` is not a valid address!") return # Set lock sequence prefix seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, lock) # Get public key (found from private key) private_key = PrivateKey(key) public_key = private_key.get_public_key() # Add address to wallet so we can get utxos from bitcoin core chain.importaddress(from_addr) # Get UTXOs utxos = chain.listunspent(1, 9999999, [from_addr]) # Create inputs txin = [] total_btc = Decimal(0) for utxo in utxos: # Note that for each input we set the correct nSequence txin.append( TxInput(utxo["txid"], utxo["vout"], sequence=seq.for_input_sequence())) total_btc = total_btc + utxo["amount"] if total_btc == 0: return print("\nThere aren't any UTXOs :(.") # Create a fee-less output txout = TxOutput(total_btc - Decimal(0.1), P2pkhAddress(to_addr).to_script_pub_key()) # Create dummy transaction (to calculate size) tx = Transaction([TxInput.copy(inpt) for inpt in txin], [txout], locktime=Locktime(lock).for_transaction()) # create the redeem script - needed to sign the transaction redeem_script = Script([ seq.for_script(), "OP_CHECKLOCKTIMEVERIFY", "OP_DROP", "OP_DUP", "OP_HASH160", public_key.get_address().to_hash160(), "OP_EQUALVERIFY", "OP_CHECKSIG", ]) # use the private key corresponding to the address that contains the # UTXO we are trying to spend to create the signature for the txin - # note that the redeem script is passed to replace the scriptSig for ind, txinput in enumerate(tx.inputs): sig = private_key.sign_input(tx, ind, redeem_script) txinput.script_sig = Script( [sig, public_key.to_hex(), redeem_script.to_hex()]) # Calculate fees sat_per_byte = requests.get( "https://bitcoinfees.earn.com/api/v1/fees/recommended").json( )["fastestFee"] fee = Decimal( max((len(bytes.fromhex(tx.serialize())) * sat_per_byte) / SATOSHIS_PER_BITCOIN, 0)) if fee == 0: print("WARNING: There isn't enough balance to calculate fees.") # Create final tx with correct txout value txout = TxOutput(total_btc - fee, P2pkhAddress(to_addr).to_script_pub_key()) tx = Transaction([TxInput.copy(inpt) for inpt in tx.inputs], [txout], locktime=Locktime(lock).for_transaction()) for ind, txinput in enumerate(tx.inputs): sig = private_key.sign_input(tx, ind, redeem_script) txinput.script_sig = Script( [sig, public_key.to_hex(), redeem_script.to_hex()]) signed_tx = tx.serialize() # print raw transaction print("\nRaw unsigned transaction:\n{}".format( Transaction(txin, [txout]).serialize())) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n{}".format(signed_tx)) print("\nTxId: {}".format(tx.get_txid())) # Check if is valid and send it if chain.testmempoolaccept([signed_tx])[0]["allowed"]: chain.sendrawtransaction(signed_tx) print("\nSent to Block-chain! Have fun with those {} BTC.".format( total_btc - fee)) else: print("\nCan't send (yet)!") print("Reason: `{}`".format( chain.testmempoolaccept([signed_tx])[0]["reject-reason"]))
def spend_p2sh_cltv_p2pkh(proxy, block_height, sender_priv_key, p2sh_addr, rec_addr): """ Spends funds from a P2SH address with an absolute locktime to a P2PKH receiver address. :param proxy: JSON RPC proxy for connecting to the network. :param block_height: Block height the lock is valid for. :param sender_priv_key: Private key of the address locking the funds. :param p2sh_addr: P2SH address containing the funds. :param rec_addr: P2PKH address receiving the funds. """ # mine 100 blocks and send bitcoin to the P2SH address proxy.generatetoaddress(100, p2sh_addr) # mine 100 blocks to make mined bitcoin spendable, emulates 'bitcoin-cli -generate 100' for _ in range(100): proxy.generatetoaddress(1, proxy.getnewaddress()) # retrieve unspent UTXOs for the P2SH address p2sh_addr_unspent = proxy.listunspent(0, 99999999, [p2sh_addr]) # create absolute-block locking sequence for the transaction inputs seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, block_height) # create transaction inputs for unspent UTXOs # and calculate the total unspent bitcoins they contain tx_inputs = [] total_unspent = 0 for utxo in p2sh_addr_unspent: tx_inputs.append( TxInput(utxo['txid'], utxo['vout'], sequence=seq.for_input_sequence())) total_unspent += utxo['amount'] print("Unspent bitcoin in address {} : {}".format(p2sh_addr, total_unspent)) # get the public key of the receiving address for the funds to be sent to rec_pub_key = proxy.getaddressinfo(rec_addr)['pubkey'] rec_pk = PublicKey(rec_pub_key) # calculate fee satoshis_per_kb = requests \ .get('https://api.blockcypher.com/v1/btc/test3') \ .json()['medium_fee_per_kb'] # formula: |inputs| * 180 + 34 * |outputs| +- |inputs| tx_size = len(tx_inputs) * 180 + 34 * 1 + 10 + len(tx_inputs) # we calculate fees in terms of bitcoin fee = (tx_size / 1024) * (satoshis_per_kb / 10e8) # create the transaction output tx_output = TxOutput(to_satoshis(Decimal(total_unspent) - Decimal(fee)), rec_pk.get_address().to_script_pub_key()) # set a lock time in blocks for the transaction lock = Locktime(block_height) # create the transaction tx = Transaction(tx_inputs, [tx_output], lock.for_transaction()) unsigned_tx = tx.serialize() print('Raw unsigned transaction:', unsigned_tx) # we need to rebuild the redeem script from the P2SH private key # make the locking P2PKH address private key sender_sk = PrivateKey(sender_priv_key) # retrieve the public key of the locking address sender_pk = sender_sk.get_public_key() # rebuild the redeem script redeem_script = Script([ seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', sender_pk.get_address().to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # for every input of the transaction for i, txin in enumerate(tx.inputs): # create the signature for redeeming the funds sig = sender_sk.sign_input(tx, i, redeem_script) # and sign the input txin.script_sig = Script( [sig, sender_pk.to_hex(), redeem_script.to_hex()]) signed_tx = tx.serialize() print('Raw signed transaction:', signed_tx) print('Transaction ID:', tx.get_txid()) # verify that the transaction is valid ver = proxy.testmempoolaccept([signed_tx]) if ver[0]['allowed']: # if the transaction is valid send the transaction to the blockchain print('Transaction is valid.') proxy.sendrawtransaction(signed_tx) print('{} Bitcoin sent to address {}'.format( Decimal(total_unspent) - Decimal(fee), rec_addr)) else: # otherwise, display the reason the transaction failed print('Transaction rejected. Reason:', ver[0]['reject-reason'])
def main(): # always remember to setup the network setup('regtest') # # This script creates a P2SH address containing a CHECKLOCKTIMEVERIFY plus a P2PKH locking funds with a key as # well as for an absolute amount of blocks or an absolute amount of seconds since the transaction. # parser = argparse.ArgumentParser( description= 'Give the private key, a future time expressed either in block height or in UNIX Epoch time and ' 'the P2SH address to send the funds') parser.add_argument('key', help="Add the private key.") parser.add_argument( '-param', type=int, help="Add the number of blocks or the time expressed in seconds.") parser.add_argument('-to_address', type=str, help="Add the adress that will sent/spend") args = parser.parse_args() # set values key = args.key absolute_param = args.param send_address = args.to_address # set Locktime seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, absolute_param) locktime = Locktime(absolute_param) # set proxy username = "******" password = "******" proxy = NodeProxy(username, password).get_proxy() # secret key corresponding to the pubkey needed for the P2SH (P2PKH) transaction p2pkh_sk = PrivateKey(key) p2pkh_pk = p2pkh_sk.get_public_key() # get the address (from the public key) p2pkh_addr = p2pkh_pk.get_address() # print("Private key: " + p2pkh_sk. to_wif(compressed=True)) # print("Public key: " + p2pkh_pk.to_hex(compressed=True)) # print("P2PKH Address: " + p2pkh_addr.to_string()) # create the redeem script redeem_script = Script([ seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # accept a P2SH address to get the funds from addr = P2shAddress.from_script(redeem_script) print("The P2SH address to get the funds from is : " + addr.to_string()) # check if the P2SH address has any UTXOs to get funds from proxy.importaddress(addr.to_string(), "P2SH to get the funds from") minconf = 0 maxconf = 99999999 my_list = proxy.listunspent(minconf, maxconf, [addr.to_string()]) # Gather all funds that the P2SH address received to send to the P2PKH address provided txin_list = [] btc_to_send = 0 for i in my_list: txin = TxInput(i['txid'], i['vout'], sequence=seq.for_input_sequence()) txin_list.append(txin) btc_to_send = btc_to_send + i['amount'] if btc_to_send == 0: print("No btc found to send") quit() # accept a P2PKH address to send the funds to to_addr = P2pkhAddress(send_address) print("The P2PKH address to send the funds to is : " + to_addr.to_string()) # calculate the appropriate fees with respect to the size of the transaction response = requests.get("https://mempool.space/api/v1/fees/recommended") fee_per_byte = response.json()['fastestFee'] print("Fastest fee per byte is : %d " % fee_per_byte) # calculate transaction size as described at # https://bitcoin.stackexchange.com/questions/1195/how-to-calculate-transaction-size-before-sending-legacy-non-segwit-p2pkh-p2sh tx_size = len(my_list) * 180 + 34 + 10 + len(my_list) total_fees = tx_size * fee_per_byte / (1024 * 10**8) print('Total fees are : ', total_fees) # Calculate the final amount amount = btc_to_send - total_fees # print(amount) # Create transaction output txout = TxOutput(to_satoshis(amount), to_addr.to_script_pub_key()) # Create transaction after the inputs and the outputs tx = Transaction(txin_list, [txout], locktime.for_transaction()) # For each transaction - when dealing with multiple inputs, you will need to sign all of them for i, txin in enumerate(my_list): sig = p2pkh_sk.sign_input(tx, i, redeem_script) # print(sig) # set the scriptSig (unlocking script) -- unlock the P2PKH (sig, pk) plus # the redeem script, since it is a P2SH txin.script_sig = Script( [sig, p2pkh_pk.to_hex(), redeem_script.to_hex()]) # display the raw signed transaction, ready to be broadcasted signed_tx = tx.serialize() print("\nRaw signed transaction:\n" + signed_tx) # display the raw unsigned transaction print("\nRaw unsigned transaction:\n" + tx.serialize()) # display the transaction id print("\nTxId:", tx.get_txid()) # verify that the transaction is valid and will be accepted by the Bitcoin nodes # if the transaction is valid, send it to the blockchain is_valid = proxy.testmempoolaccept([signed_tx]) # print(is_valid) if is_valid[0]['allowed']: print("Transaction is valid!") print("Sending transaction to blockchain..") proxy.sendrawtransaction(signed_tx) else: print("Transaction not valid") quit()
def main(): # always remember to setup the network setup('regtest') # RPC credentials for communicating with the node rpcuser = '******' rpcpass = '******' proxy = NodeProxy(rpcuser, rpcpass).get_proxy() # set values block_height = 140 # secret key needed to spend P2PKH that is wrapped by P2SH p2pkh_sk = PrivateKey( 'cSbKZh6a6wNUAQ8pr2KLKeZCQ4eJnFmN35wtReaoU4kCP97XQu6W') # this is the P2SH address the funds have been locked in p2shaddress = '2NGWStpuXtke1VXCTgNnzUgWbun7eY2f3nH' # this is the address the funds will be sent to to_addr = P2pkhAddress('mnS1ng5D1hdvLkYAK2oS8R1C4e37aQdVoC') seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, block_height) lock = Locktime(block_height) # import the address as watch-only print('importaddress') proxy.importaddress(p2shaddress, "P2SH absolute timelock", True) # find all UTXOs for this address. 10.000.000 should be enough print('listunspent') list_unspent = proxy.listunspent(0, 9999999, [p2shaddress]) # create transaction inputs for all UTXOs. Calculate the total amount of # bitcoins they contain txin_list = [] total_amount = 0 for i in list_unspent: txin = TxInput(i['txid'], i['vout'], sequence=seq.for_input_sequence()) txin_list.append(txin) total_amount = total_amount + i['amount'] if total_amount == 0: print("No funds to move") sys.exit(0) # derive public key and adddress from the private key p2pkh_pk = p2pkh_sk.get_public_key().to_hex() p2pkh_addr = p2pkh_sk.get_public_key().get_address() # create the redeem script - needed to sign the transaction redeem_script = Script([ seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # get fees using API. Although we may be running in regtest, we'll use the # fees as if we were using testnet (fees are in satoshis) url = 'https://api.blockcypher.com/v1/btc/test3' resp = requests.get(url) fee_per_kb = resp.json()['medium_fee_per_kb'] # calculate transaction size according to: # in*180 + out*34 + 10 plus or minus 'in' # https://bitcoin.stackexchange.com/questions/1195/how-to-calculate-transaction-size-before-sending-legacy-non-segwit-p2pkh-p2sh # we'll play it safe and use the upper bound tx_size = len(txin_list) * 180 + 34 + 10 + len(txin_list) fees = tx_size * fee_per_kb / (1024 * 10**8) print('fees:', fees) # create the output txout = TxOutput( Decimal(total_amount) - Decimal(fees), to_addr.to_script_pub_key()) # create transaction from inputs/outputs tx = Transaction(txin_list, [txout], lock.for_transaction()) # use the private key corresponding to the address that contains the # UTXO we are trying to spend to create the signatures for all txins - # note that the redeem script is passed to replace the scriptSig for i, txin in enumerate(txin_list): sig = p2pkh_sk.sign_input(tx, i, redeem_script) # set the scriptSig (unlocking script) -- unlock the P2PKH (sig, pk) plus # the redeem script, since it is a P2SH txin.script_sig = Script([sig, p2pkh_pk, redeem_script.to_hex()]) # serialize the transaction signed_tx = tx.serialize() # test if the transaction will be accepted by the mempool print('testmempoolaccept') res = proxy.testmempoolaccept([signed_tx]) print(res) if not res[0]['allowed']: print("Transaction not valid") sys.exit(1) # print raw transaction print("\nRaw unsigned transaction:\n" + tx.serialize()) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + signed_tx) print("\nTxId:", tx.get_txid())
# Secret key of P2SH address p2pkh_sk = PrivateKey(priv_key) # Get the P2PKH public key p2pkh_pk = p2pkh_sk.get_public_key().to_hex() # Get the P2PKH address (from the public key) p2pkh_addr = p2pkh_sk.get_public_key().get_address() # Create the redeem script redeem_script = Script([seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG']) # Signature sign = p2pkh_sk.sign_input(p2sh_out_tx, 0, redeem_script) # Unlock transaction's input using signature, P2SH public key and redeem_script txin.script_sig = Script([sign, p2pkh_pk, redeem_script.to_hex()]) # ***** Display the raw signed transaction # Print Raw Signed Transaction r_s_t = p2sh_out_tx.serialize() print('\nRaw Signed Transaction: %s' %r_s_t) # *** Display the transaction ID # Signed Transaction ID r_s_t_id = p2sh_out_tx.get_txid()