def main(): # always remember to setup the network setup('testnet') # could also instantiate from existing WIF key priv = PrivateKey.from_wif( 'cVdte9ei2xsVjmZSPtyucG43YZgNkmKTqhwiUA8M4Fc3LdPJxPmZ') # compressed is the default print("\nPrivate key WIF:", priv.to_wif(compressed=True)) # get the public key pub = priv.get_public_key() # compressed is the default print("Public key:", pub.to_hex(compressed=True)) # get address from public key address = pub.get_segwit_address() # print the address and hash - default is compressed address print("Native Address:", address.to_string()) segwit_hash = address.to_hash() print("Segwit Hash:", segwit_hash) print("Segwit Version:", address.get_type()) # test to_string addr2 = P2wpkhAddress.from_hash(segwit_hash) print("Created P2wpkhAddress from Segwit Hash and calculate address:") print("Native Address:", addr2.to_string()) # # display P2SH-P2WPKH # # create segwit address addr3 = PrivateKey.from_wif( 'cTmyBsxMQ3vyh4J3jCKYn2Au7AhTKvqeYuxxkinsg6Rz3BBPrYKK').get_public_key( ).get_segwit_address() # wrap in P2SH address addr4 = P2shAddress.from_script(addr3.to_script_pub_key()) print("P2SH(P2WPKH):", addr4.to_string()) # # display P2WSH # p2wpkh_key = PrivateKey.from_wif( 'cNn8itYxAng4xR4eMtrPsrPpDpTdVNuw7Jb6kfhFYZ8DLSZBCg37') script = Script([ 'OP_1', p2wpkh_key.get_public_key().to_hex(), 'OP_1', 'OP_CHECKMULTISIG' ]) p2wsh_addr = P2wshAddress.from_script(script) print("P2WSH of P2PK:", p2wsh_addr.to_string()) # # display P2SH-P2WSH # p2sh_p2wsh_addr = P2shAddress.from_script(p2wsh_addr.to_script_pub_key()) print("P2SH(P2WSH of P2PK):", p2sh_p2wsh_addr.to_string())
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 # until a certain block_height is reached # # set values block_height = 140 seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, block_height) # secret key corresponding to the pubkey needed for the P2SH (P2PKH) transaction p2pkh_sk = PrivateKey('cSbKZh6a6wNUAQ8pr2KLKeZCQ4eJnFmN35wtReaoU4kCP97XQu6W') # get the 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']) # create a P2SH address from a redeem script addr = P2shAddress.from_script(redeem_script) print(addr.to_string())
def create_HODL_address(key, lock, is_priv=False): setup(os.getenv("BUY_LAMBO_BTC_NET", "regtest")) # Get public key (given or found from private key) public_key = PrivateKey(key).get_public_key() if is_priv else PublicKey(key) # Get address from public key address_from_key = public_key.get_address() # Set lock sequence prefix seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, lock) # create the redeem script - needed to sign the transaction redeem_script = Script( [ seq.for_script(), "OP_CHECKLOCKTIMEVERIFY", "OP_DROP", "OP_DUP", "OP_HASH160", address_from_key.to_hash160(), "OP_EQUALVERIFY", "OP_CHECKSIG", ] ) # create a P2SH address from a redeem script addr = P2shAddress.from_script(redeem_script) print("Time-locked address: {}".format(addr.to_string()))
def main(): # always remember to setup the network setup('testnet') # # This script creates a P2SH address containing a CHECKSEQUENCEVERIFY plus # a P2PKH locking funds with a key as well as for 20 blocks # # set values relative_blocks = 20 seq = Sequence(TYPE_RELATIVE_TIMELOCK, relative_blocks) # secret key corresponding to the pubkey needed for the P2SH (P2PKH) transaction p2pkh_sk = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') # get the 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_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # create a P2SH address from a redeem script addr = P2shAddress.from_script(redeem_script) print(addr.to_string())
def test_p2sh_p2wpkh_creation_pubkey(self): addr = PrivateKey.from_wif( 'cTmyBsxMQ3vyh4J3jCKYn2Au7AhTKvqeYuxxkinsg6Rz3BBPrYKK' ).get_public_key().get_segwit_address() p2sh_addr = P2shAddress.from_script(addr.to_script_pub_key()) self.assertTrue(p2sh_addr.to_string(), self.correct_p2sh_p2wpkh_address)
def create_spending_signed_trx(p2pkh_addr_to_str, priv_key_from_obj): """ Gather related data and generate the single transation that transfers the btc value of the found UTXO transactions. """ p2pkh_addr_to_obj = P2pkhAddress(p2pkh_addr_to_str) seq_number_in_hex = Common.get_seq_hex_from_conf( Common.get_relative_time_seconds_blocks()) redeem_script = Common.get_redeem_script_from_conf( get_redeem_pub_key_obj()) p2sh_paid_to_addr = P2shAddress.from_script(redeem_script).to_address() utxo_results = get_input_trx_from_utxo(priv_key_from_obj, p2sh_paid_to_addr, seq_number_in_hex, redeem_script) # No sense in creating a transaction with 0 UTXOs if utxo_results[0] > 0 and len(utxo_results[1]) > 0: signed_tx = get_signed_trx(utxo_results, p2pkh_addr_to_obj, priv_key_from_obj, redeem_script) # print raw signed transaction ready to be broadcasted print("\nSigned raw transaction:\n" + signed_tx) trasmit_finalized_trx(signed_tx) else: print("\nNo UTXOs found. Nothing to do!\n")
def main(): #Connect to the regtest setup('regtest') proxy = NodeProxy('user', 'bitcoin').get_proxy() #Accept a Public Key from User and derive a P2PKH address from it pk = PublicKey.from_hex(input('Please input your Public Key\n')) pk_p2pkh_addr = pk.get_address() #Accept future absolute block amount from User current_blocks = proxy.getblockcount() absolute_blocks = int( input( f'\nPlease input the future block height. The current block height is: {current_blocks}\n' )) #Set the timelock sequence and create a redeemScript accordingly redeem_script = Script([ absolute_blocks, 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', pk_p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) #Generate a P2SH Address from the redeemScript and show it p2sh_addr = P2shAddress.from_script(redeem_script) print( f'\nThe P2SH Address is:\n{p2sh_addr.to_string()} Now, go on and send some funds to it.\n' )
def test_p2sh_p2wsh_creation_1multisig(self): p2wpkh_key = PrivateKey.from_wif( 'cNn8itYxAng4xR4eMtrPsrPpDpTdVNuw7Jb6kfhFYZ8DLSZBCg37') script = Script([ 'OP_1', p2wpkh_key.get_public_key().to_hex(), 'OP_1', 'OP_CHECKMULTISIG' ]) p2wsh_addr = P2wshAddress.from_script(script) p2sh_p2wsh_addr = P2shAddress.from_script( p2wsh_addr.to_script_pub_key()) self.assertTrue(p2sh_p2wsh_addr.to_string(), self.correct_p2sh_p2wsh_address)
def get_redeem_script_from_conf(cls, pub_key_obj): """ Great when method name are self explanatory """ csv_args = cls.get_relative_time_seconds_blocks() seq_number_in_hex = Sequence(TYPE_RELATIVE_TIMELOCK, csv_args) print("seconds to wait: " + str(csv_args[0]) + ", blocks to wait: " + str(csv_args[1])) print('sequence number in little endian format: ' + seq_number_in_hex) redeem_script = cls.get_redeem_script(seq_number_in_hex, pub_key_obj) to_P2SH_addr = P2shAddress.from_script(redeem_script) print('Redeem script generated P2SH addr: ' + to_P2SH_addr.to_address() + "\n") return redeem_script
def main(): # always remember to setup the network setup('testnet') # the key that corresponds to the P2WPKH address priv = PrivateKey('cNho8fw3bPfLKT4jPzpANTsxTsP8aTdVBD6cXksBEXt4KhBN7uVk') pub = priv.get_public_key() # the p2sh script and the corresponding address redeem_script = pub.get_segwit_address().to_script_pub_key() p2sh_addr = P2shAddress.from_script(redeem_script) # the UTXO of the P2SH-P2WPKH that we are trying to spend inp = TxInput('95c5cac558a8b47436a3306ba300c8d7af4cd1d1523d35da3874153c66d99b09', 0) # exact amount of UTXO we try to spent amount = 0.0014 # the address to send funds to to_addr = P2pkhAddress('mvBGdiYC8jLumpJ142ghePYuY8kecQgeqS') # the output sending 0.001 -- 0.0004 goes to miners as fee -- no change out = TxOutput(to_satoshis(0.001), to_addr.to_script_pub_key()) # create a tx with at least one segwit input tx = Transaction([inp], [out], has_segwit=True) # script code is the script that is evaluated for a witness program type; each # witness program type has a specific template for the script code # script code that corresponds to P2WPKH (it is the classic P2PKH) script_code = pub.get_address().to_script_pub_key() # calculate signature using the appropriate script code # remember to include the original amount of the UTXO sig = priv.sign_segwit_input(tx, 0, script_code, to_satoshis(amount)) # script_sig is the redeem script passed as a single element inp.script_sig = Script([redeem_script.to_hex()]) # finally, the unlocking script is added as a witness tx.witnesses.append(Script([sig, pub.to_hex()])) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + tx.serialize())
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 get_redeem_script_from_conf(cls, pub_key_obj): """ Return a P2SH address for a redemption scription encaptulating CHECKSEQUENCEVERIFY + P2PKH script with a paying to public address possibly locked up to x blocks read from program.conf [relative_blocks_to_wait] """ blocks_wait = Common.get_conf_wait_blocks() seq_number_in_hex = Sequence(TYPE_RELATIVE_TIMELOCK, blocks_wait) redeem_script = cls.get_redeem_csv_script(seq_number_in_hex, pub_key_obj) to_P2SH_addr = P2shAddress.from_script(redeem_script) print('Redeem script generated P2SH addr: ' + to_P2SH_addr.to_string() + "\n") return redeem_script
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 public key, a future time expressed either in block height or in UNIX Epoch time and ' 'the P2SH address will be displayed') parser.add_argument('pubkey', help="Add the public key.") parser.add_argument('-param', type=int, help="Add the number of blocks or the time expressed in seconds.") args = parser.parse_args() # set values key = args.pubkey absolute_param = args.param p2pkh_pk = PublicKey(key) # set Locktime seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, absolute_param) locktime = Locktime(absolute_param) # get the address (from the public key) p2pkh_addr = p2pkh_pk.get_address() # 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']) # create a P2SH address from a redeem script addr = P2shAddress.from_script(redeem_script) print("The P2SH address is : " + addr.to_string())
def main() : setup('testnet') relative_blocks = 20 seq = Sequence(TYPE_RELATIVE_TIMELOCK, relative_blocks) p2pkh_sk = PrivateKey('cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') p2pkh_addr = p2pkh_sk.get_public_key().get_address() print("Address : " + p2pkh_addr.to_string()) redeem_script = Script([seq.for_script(), 'OP_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160' , p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG']) addr = P2shAddress.from_script(redeem_script) print(addr.to_string())
def create_p2sh(proxy, block_height=10, address_pubk=None): """ Creates a P2SH address with an absolute block locktime. :param proxy: JSON RPC proxy for connecting to the network. :param block_height: Block height the lock is valid for. Default value is 10. :param address_pubk: Public key of the address locking the funds. If None, a new address will be created. """ # if a public key is not specified, create a new address and display its keys for future use if not address_pubk: print('Public key not provided. Created a new address.') address = proxy.getnewaddress() print('Address:', address) address_privk = proxy.dumpprivkey(address) print('Private key:', address_privk) address_pubk = proxy.getaddressinfo(address)['pubkey'] print('Public key:', address_pubk) # create the public key object p2pkh_pk = PublicKey(address_pubk) # create sequence for the redeem script seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, block_height) # create the redeem script redeem_script = Script([ seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_pk.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # create the P2SH address from the redeem script p2sh_addr = P2shAddress.from_script(redeem_script) # insert the P2SH address into the wallet proxy.importaddress(p2sh_addr.to_string()) # display the P2SH address print('Created P2SH address:', p2sh_addr.to_string())
def get_priv_key(address): # read master secret from hsm_secret hsm_secret = open(expanduser('~/.lightning/bitcoin/hsm_secret'), 'rb').read() # derive the bip32_seed salt = bytes([0]) or b'\x00' bip32_seed = Hkdf(salt, hsm_secret, hash=hashlib.sha256).expand(b'bip32 seed') master = network.keys.bip32_seed(bip32_seed) index = 0 while True: # derive an index subkey = master.subkey_for_path('0/0/' + str(index)) setup('mainnet') # create segwit address segwit = PrivateKey.from_wif( subkey.wif()).get_public_key().get_segwit_address() # wrap in P2SH address wrapped_p2sh = P2shAddress.from_script(segwit.to_script_pub_key()) if wrapped_p2sh.to_string() == address: break index += 1 plugin.log('found the address at index {}'.format(index), level="info") return master.subkey_for_path('0/0/' + str(index))
def create_p2sh(): ''' This method creates a P2SH address containing a CHECKLOCKTIMEVERIFY plus a P2PKH locking funds with a key up to specific blockchain height Arguments: pubKey: public key for the P2PKH part of the redeem script lockBlocks: absolute lock (set to blockchain height) Returns: lock_block_height: the specific blockchain height lock (in blocks) new_addr_privk: the private key of created P2SH address p2sh_addr: the new P2SH address ''' # Setup the network setup('regtest') # Initialize proxy for RPC calls rpcuser = "******" rpcpassword = "******" rpc_con = AuthServiceProxy("http://%s:%[email protected]:18443" % (rpcuser, rpcpassword)) # ***** Accept a public (or optionally a private) key for the P2PKH part of # the redeem script # Create a new Bitcoin Address (P2PKH) # Call the node's getnewaddress JSON-RPC method # Returns the address' Public Key new_addr_pubk = rpc_con.getnewaddress() # ***** Accept a future time expressed either in block height or in UNIX # Epoch time # Numbers of blockchain height corresponding to absolute lock time lock_block_height = 103 # Get the corresponding private key from the wallet # Call the node's dumpprivkey JSON-RPC method new_addr_privk = rpc_con.dumpprivkey(new_addr_pubk) # Get information about current blockchain height # Call the node's getblockcount JSON-RPC method current_block_height = rpc_con.getblockcount() if (lock_block_height < current_block_height): print( '\n***BEWARE*** Given lock (%d blocks) is lower than current blockchain height (%d blocks)' % (lock_block_height, current_block_height)) else: print('Current blockchain height: %d blocks' % current_block_height) print('Fund\'s lock is set to: %d blocks' % lock_block_height) # Setting up an appropriate sequence to provide the script seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, lock_block_height) # Secret key corresponding to the pubkey needed for the P2SH (P2PKH) transaction p2pkh_sk = PrivateKey(new_addr_privk) # Get the P2PKH address (from the public key) p2pkh_addr = p2pkh_sk.get_public_key().get_address() redeem_script = Script([ seq.for_script(), 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # Create a P2SH address from a redeem script p2sh_addr = P2shAddress.from_script(redeem_script) # VERY IMPORTANT: I must insert P2SH address into my wallet rpc_con.importaddress(p2sh_addr.to_address()) # ***** Display the P2SH address print( '\nNewly created P2SH address with absolute lock set to %d blockchain height:' % lock_block_height) print(p2sh_addr.to_address()) return (lock_block_height, new_addr_privk, p2sh_addr.to_address())
# Redeem script is a special type of script. # - The hash of the redeem script used to lock the outputs of a transaction. # - Then the redeem script used to unlock these UTXOs. redeem_script = Script([seq.for_script(), 'OP_CHECKSEQUENCEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', address.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG']) # Script code explanation: # - add on top of the stack the relative_blocks number (10) and the check if this sequence have been verified, ie the locktime have been pass. (T/F) # - drop the top element of the stack # - duplicate the and get its hash # - also get the address hash and check if are equal # - then check if the signature is valid # 5. What is the P2SH address for that script? (Get the hash from the redeem_script) help(P2shAddress) p2sh_addr = P2shAddress.from_script(redeem_script) print(p2sh_addr.to_string()) # 6. Send some bitcoin to that P2SH address. # / Important Notes / # Until this point no interaction with bitcoin network have been made! # At this time I have to start a regtest node and then I have to proceed with bitcoin transfer, # either using cli (bitcoin-cli), either programmatically through python. # Also note, that I need to already have an address and sufficient funds in order to send btc # to this address or else I would get an error. # To create a new address and get enough btc, I can execute the following commands: # $ bitcoin-cli getnewaddress "temp"
# # 1) accept a future time, expressed either in block height or in UNIX Epoch time, # and a private key (to recreate the redeem script as above and also use to unlock the P2PKH part) # from_privkey = PrivateKey( 'cSyZjejfhK5gaVYoG9pgfdMrZzw7rXufpiG4oDaYShanJhwpqGcE' ) from_pubkey = from_privkey.get_public_key() from_address = from_pubkey.get_address() from_hash = from_address.to_hash160() redeem_script = Script( [BLOCKHEIGHT, 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', from_hash, 'OP_EQUALVERIFY', 'OP_CHECKSIG'] ) # # 2) accept a P2SH address to get the funds from (the one created by the first script) # from_p2sh = P2shAddress.from_script( redeem_script ) print( " source: " + from_p2sh.to_string() ) # # 3) check if the P2SH address has any UTXOs to get funds from # # support multiple unknown funding transactions utxos = {} funds = Decimal(0) txids = proxy.listreceivedbyaddress( 0, True, True, from_p2sh.to_string() )[0]['txids'] for txid in txids: tx = proxy.gettransaction( txid )
def test_p2shaddress_to_script_pub_key(self): script = Script([self.pub.to_hex(), 'OP_CHECKSIG']) fromScript = Script.to_p2sh_script_pub_key(script).to_hex() addr = P2shAddress.from_script(script) fromP2shAddress = addr.to_script_pub_key().to_hex() self.assertTrue(fromScript, fromP2shAddress)
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()
pubkey = privkey.get_public_key() # # 2) accept a future time expressed either in block height or in UNIX Epoch time # blockheight = proxy.getblockcount() + 1 print("future time in absolute block height: " + str(blockheight)) # get address from public key address = pubkey.get_address() # get hash of address hash = address.to_hash160() # create redeem script script = Script([ blockheight, 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', hash, 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) print("redeem script: " + str(script.get_script())) # get P2SH address P2SHaddress = P2shAddress.from_script(script) # # 3) display the P2SH address # print("p2sh address: " + P2SHaddress.to_string())
def main(): # always remember to setup the network setup('testnet') # # This script creates a P2SH address containing a P2PK script and sends # some funds to it # # # create transaction output using P2SH scriptPubKey (locking script) # (the recipient will give us the final address but for now we create it # for demonstration purposes) # # secret key corresponding to the pubkey needed for the P2SH (P2PK) transaction p2pk_sk = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') p2pk_pk = p2pk_sk.get_public_key().to_hex() redeem_script = Script([p2pk_pk, 'OP_CHECKSIG']) #TESTE_SUZANA addressObj = P2shAddress.from_script(redeem_script) print("addressObj=" + addressObj.to_address()) #TESTE_SUZANA # you can initially spend a specific UTXO that you know (e.g. with the txid after you send some funds to the address). Then if everything works you can use the address to find all tx in that address and spend them. Make sure the timelock works and that you can spend the funds as expected. # The 2nd program should display the raw signed transaction that is to be sent to a bitcoin node plus _send_ the transaction to a node. The last part is not possible with the bitcoin-utils library since I have not impl. a node proxy yet. So you have to use another lib or finish with the cli commands (commented out of course) that I have to run in order to send the raw tx to a bitcoin node. # The P2SH addr could be recalculated in 2nd program since we have the redeem script! Providing the P2SH addr saves you from this small calculation and 'connects' the 2 programs :-) # Re fees, I would rather you calculate the 'appropriate' fee and explain in comments how/why you did it this way. Ideally, you would consult an online service to get an estimate of the appropriate fee. This is minor for assignment purposes but major for production systems. #https://bitcoin.stackexchange.com/questions/83650/how-does-nsequence-check-sequence-verify-work #The 2nd program requires a private key as well... that is what unlock the funds. ##### NAO PRECISA PARA O ASSIGNMENT DAQUI EM DIANTE ####### # create transaction input from tx id of UTXO (contained 0.1 tBTC) txin = TxInput( '76464c2b9e2af4d63ef38a77964b3b77e629dddefc5cb9eb1a3645b1608b790f', 0) # address we are spending from from_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') # secret key of address that we are trying to spent sk = PrivateKey('cTALNpTpRbbxTCJ2A5Vq88UxT44w1PE2cYqiB3n4hRvzyCev1Wwo') #SUZANA ---- ASSINA COM P2SH do SCRIPT txout = TxOutput(0.09, redeem_script.to_p2sh_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 sig = sk.sign_input(tx, 0, from_addr.to_script_pub_key()) #print(sig) # get public key as hex pk = sk.get_public_key() pk = pk.to_hex() #print (pk) # set the scriptSig (unlocking script) txin.script_sig = Script([sig, pk]) 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 test_p2sh_creation(self): script = Script([self.pub.to_hex(), 'OP_CHECKSIG']) addr = P2shAddress.from_script(script) self.assertTrue(addr.to_string(), self.p2sh_address)
def generate(): # Tells the library what network we are using setup() if not mnemonic_phrase: # Generate mnemonic from random 192-bit entropy entropy_bytes = Bip39EntropyGenerator( Bip39EntropyBitLen.BIT_LEN_192).Generate() mnemonic = Bip39MnemonicGenerator.FromEntropy(entropy_bytes) print("Generated random mnemonic:\n" + mnemonic) else: print("Using included mnemonic.") mnemonic = mnemonic_phrase # Get seed bytes from mnemonic seed_bytes = Bip39SeedGenerator(mnemonic).Generate() bip44_mst = Bip44.FromSeed( seed_bytes, Bip44Coins.BITCOIN) # Could add in multi currency support # Derive account 0 for Bitcoin: m/44'/0'/0' bip44_acc = bip44_mst.Purpose() \ .Coin() \ .Account(0) # Derive the external chain: m/44'/0'/0'/0 bip44_change = bip44_acc.Change(Bip44Changes.CHAIN_EXT) with open(output_dest, 'w') as output_file: # Open the output file output_file.write("address, public_key" + (", private_key" if privates else "") + "\n") # Go through each address for i in range(number): bip44_addr = bip44_change.AddressIndex(i) # create segwit address addr3 = PrivateKey.from_wif(bip44_addr.PrivateKey().ToWif( )).get_public_key().get_segwit_address() # wrap in P2SH address addr4 = P2shAddress.from_script(addr3.to_script_pub_key()) if addr4.to_string() == compare: print("Found it!") print("Path: m/44'/0'/0'/0/" + str(i)) break #print("P2SH(P2WPKH):", addr4.to_string()) if (i % int(number / 10)) == 0: print('Finished {}'.format(i)) out = "{0}, {1}".format(addr4.to_string(), bip44_addr.PublicKey().ToExtended() ) # Public addresses not including private if (privates): # Include the private keys out = "{0}, {1}, {2}".format( addr4.to_string(), bip44_addr.PublicKey().RawCompressed().ToHex(), bip44_addr.PrivateKey().ToWif()) #bip44_addr.PublicKey().ToAddress() # This is the regular address (not P2SH(P2WPKH)) # Print extended keys and address if (verbose): print(out) output_file.write(out + "\n")
def main(): #Connect to the regtest network setup('regtest') proxy = NodeProxy('user', 'bitcoin').get_proxy() #Accept absolute future block amount User current_blocks = proxy.getblockcount() absolute_blocks = int( input( f'\nPlease input the future block height. The current block height is: {current_blocks}.\nIt must match the one in the redeem script from which the P2SH address (with the locked funds) was derived\n' )) #Accept the Private Key from User sk = PrivateKey( input( '\nPlease enter your Private Key (used to create the address from which the P2SH Address was derived)\n' )) #Accept the P2SH Address with the funds p2sh_addr = input( '\nPlease enter the P2SH address which has the locked funds\n') #Import the address into the wallet proxy.importaddress(f'{p2sh_addr}') print( f'\nThe P2SH address {p2sh_addr} has been imported into the wallet.\n') #Get all UTXOs for this address all_utxos = proxy.listunspent(1, 9999999, [f'{p2sh_addr}']) print(f'\nAll the UTXO Objects for this address are:\n{all_utxos}\n') #Calculate total funds available. Aggregate all UTXO amounts. def totalFunds(): total = Decimal(0) for utxo in all_utxos: total += Decimal(utxo["amount"]) return total total_funds = totalFunds() print("Total funds available: ", total_funds) #Instantiate the timelock sequence seq = Sequence(TYPE_ABSOLUTE_TIMELOCK, absolute_blocks) #Create an array of inputs from these UTXOs def getInputs(): inputs = [] count = 0 for utxo in all_utxos: #create inputs and append them into an array #First, create an input utxo = all_utxos[count] txin = TxInput(utxo["txid"], utxo["vout"], sequence=seq.for_input_sequence()) #then, append it to the array inputs.append(txin) ++count return inputs inputs = getInputs() print(f'The inputs created from these outputs are:\n {inputs}') #Use User's Secret Key (Accepted above) to recreate the Public Key pk = sk.get_public_key() #We recreate the P2PKH Addr to recreate the other half of the redeemScript p2pkh_addr = pk.get_address() #We recreate the redeem script redeem_script = Script([ absolute_blocks, 'OP_CHECKLOCKTIMEVERIFY', 'OP_DROP', 'OP_DUP', 'OP_HASH160', p2pkh_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) #Confirm that the P2SH address is the same one to which funds were sent by receating the P2SH from this redeem script addr = P2shAddress.from_script(redeem_script).to_string() print( f'\nCheck if this is the address with the locked funds:\n{addr} vs what you input above {p2sh_addr}' ) #Accept the receiving P2PKH from User destination_addr = P2pkhAddress( input( '\nPlease enter the address you want to send the locked funds to:\n' )) #Calculate txn size to estimate fee from inputs only so we subtract it from funds tx_test = Transaction(inputs, [], Locktime(absolute_blocks).for_transaction()) tx_size = tx_test.get_size() # 0.0001 is an appropriate fee per byte so we use that est_tx_fee = tx_size / 1000 * 0.0001 #Create a txout transferring total locked funds (minus estimated fees). txout = TxOutput(to_satoshis(total_funds - Decimal(est_tx_fee)), destination_addr.to_script_pub_key()) #Create Txn. Passing in the inputs, output, and the future absolute lock time tx = Transaction(inputs, [txout], Locktime(absolute_blocks).for_transaction()) #Print the newly created txn print(f'\nThe raw unsigned txn is: {tx.serialize()}\n') #Calulate the Appropriate Transaction Fee According to Txn Size. #First, get the fee estimate from network. Useful only for mainnet and testnet. def getFee(): fee = proxy.estimatesmartfee(5, "ECONOMICAL") if fee["errors"]: print( 'Network data not enough to calculate fee. Setting default fee: 0.0001 BTC' ) return 0.0001 else: return fee["feerate"] #Then, calculate the size of our Txn and then multiply it by the per-byte fee est_fee = getFee() #per byte tx_size = tx.get_size() print(f'\nThe transaction size is:\n{tx_size} bytes') tx_fee = tx_size / 1000 * est_fee print(f'\nThe recommended fee for this transaction is:\n{tx_fee}') #Need to sign all inputs def signInputs(): input_index = 0 for input in inputs: #Use the Secret Key corresponding to the P2SH to create the signature for the txn/ sign all inputs #Redeem script is passed to replace the scriptSig inputSig = sk.sign_input(tx, input_index, redeem_script) input.script_sig = Script( [inputSig, pk.to_hex(), redeem_script.to_hex()]) ++input_index signInputs() signed_tx = tx.serialize() #Print the signed raw txn, ready to be checked for validity print(f"\nRaw signed transaction:\n{signed_tx}") print( f"\nTransaction ready to be broadcast. Transaction Id: {tx.get_txid()}" ) #Test for validity isValid = proxy.testmempoolaccept([f'{signed_tx}']) print(f'\nTransaction validity check result:\n{isValid}') #Broadcast txn #needs signed_tx if isValid[0]["allowed"]: if input('\nSend transaction to network? Y / N: ') == 'Y': sent_tx_id = proxy.sendrawtransaction(f'{signed_tx}') print( f'\n***The transaction with id {sent_tx_id} has been sent to the network***' ) else: print( f'\nUser decided not to send the funds and exited the program.' ) exit() else: reason = isValid[0]["reject-reason"] print(f'\nThe signed raw transaction is invalid. Reason: {reason}')
def main(): # always remember to setup the network setup('testnet') # # This script creates a P2SH address containing a P2PK script and sends # some funds to it # # # create transaction output using P2SH scriptPubKey (locking script) # (the recipient will give us the final address but for now we create it # for demonstration purposes) # # secret key corresponding to the pubkey needed for the P2SH (P2PK) transaction p2pk_sk = PrivateKey( 'cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') p2pk_pk = p2pk_sk.get_public_key().to_hex() redeem_script = Script([p2pk_pk, 'OP_CHECKSIG']) #TESTE_SUZANA addressObj = P2shAddress.from_script(redeem_script) print("addressObj=" + addressObj.to_address()) #TESTE_SUZANA # create transaction input from tx id of UTXO (contained 0.1 tBTC) txin = TxInput( '76464c2b9e2af4d63ef38a77964b3b77e629dddefc5cb9eb1a3645b1608b790f', 0) # address we are spending from from_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') # secret key of address that we are trying to spent sk = PrivateKey('cTALNpTpRbbxTCJ2A5Vq88UxT44w1PE2cYqiB3n4hRvzyCev1Wwo') #SUZANA ---- ASSINA COM P2SH do SCRIPT txout = TxOutput(0.09, redeem_script.to_p2sh_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 sig = sk.sign_input(tx, 0, from_addr.to_script_pub_key()) #print(sig) # get public key as hex pk = sk.get_public_key() pk = pk.to_hex() #print (pk) # set the scriptSig (unlocking script) txin.script_sig = Script([sig, pk]) signed_tx = tx.serialize() # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + signed_tx) print("\nTxId:", tx.get_txid())