def test_signed_SIGSINGLE_tx_2in_2_out(self): # note that this would have failed due to absurdly high fees but we # ignore it for our purposes tx = Transaction([self.sig_txin1, self.sig_txin2], [self.sig_txout1, self.sig_txout2]) sig = self.sig_sk1.sign_input( tx, 0, Script([ 'OP_DUP', 'OP_HASH160', self.sig_from_addr1.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]), SIGHASH_SINGLE) sig2 = self.sig_sk2.sign_input( tx, 1, Script([ 'OP_DUP', 'OP_HASH160', self.sig_from_addr2.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]), SIGHASH_SINGLE) pk = self.sig_sk1.get_public_key().to_hex() pk2 = self.sig_sk2.get_public_key().to_hex() self.sig_txin1.script_sig = Script([sig, pk]) self.sig_txin2.script_sig = Script([sig2, pk2]) self.assertEqual(tx.serialize(), self.sign_sighash_single_2in_2out_result)
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_signed_low_s_SIGALL_tx_1_input_2_outputs(self): tx = Transaction([self.txin], [self.txout, self.change_low_s_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.core_tx_signed_low_s_SIGALL_result)
def test_multiple_input_multiple_ouput(self): tx = Transaction( [self.txin1_multiple, self.txin2_multiple, self.txin3_multiple], [ self.output1_multiple, self.output2_multiple, self.output3_multiple ], has_segwit=True, witnesses=[]) sig1 = self.sk1.sign_input(tx, 0, self.p2pkh_addr.to_script_pub_key()) pk1 = self.sk1.get_public_key().to_hex() self.txin1_multiple.script_sig = Script([sig1, pk1]) tx.witnesses.append(Script([])) sig_p2sh1 = self.sk1.sign_segwit_input(tx, 1, self.p2wsh_redeem_script, self.txin2_multiple_amount) sig_p2sh2 = self.sk2.sign_segwit_input(tx, 1, self.p2wsh_redeem_script, self.txin2_multiple_amount) pk2 = self.p2wsh_redeem_script.to_hex() tx.witnesses.append(Script(['OP_0', sig_p2sh1, sig_p2sh2, pk2])) sig3 = self.sk1.sign_segwit_input(tx, 2, self.p2pkh_addr.to_script_pub_key(), self.txin3_multiple_amount) pk3 = self.sk1.get_public_key().to_hex() tx.witnesses.append(Script([sig3, pk3])) print(tx.serialize()) self.assertEqual(tx.serialize(), self.multiple_input_multiple_ouput_result)
def test_spend_p2wpkh(self): tx = Transaction([self.txin_spend], [self.txout2], has_segwit=True) sig = self.sk.sign_segwit_input(tx, 0, self.p2pkh_redeem_script, self.txin_spend_amount) pk = self.sk.get_public_key().to_hex() tx.witnesses = [Script([sig, pk])] self.assertEqual(tx.serialize(), self.spend_p2pkh_result)
def get_trx_amount_fees(total_amount, trxin_set, p2pkh_addr_to_obj): """ Calculate fees with approximation as to the size of the transactionself. Trying not introduce side effects to the harvested input transactions objects. """ # set amount first without fees txout_just_for_size_calc = TxOutput(total_amount, p2pkh_addr_to_obj.to_script_pub_key()) tx_just_for_size_calc = Transaction(trxin_set, [txout_just_for_size_calc]) # https://live.blockcypher.com/btc-testnet/ # High Priority (1-2 blocks) Medium Priority (3-6 blocks) Low Priority (7+ blocks) # 0.00059 BTC/KB 0.00001 BTC/KB 0.00001 BTC/KB trxsize_bytes = len(tx_just_for_size_calc.serialize().encode('utf-8')) trx_KB = (trxsize_bytes / 1024) # * 0.00001 # Choose Medium Fee trx_KB *= (1 + ESTIMATE_OF_PERCENTAGE_SIGNING_BLOAT_IN_TRX_SIZE) trx_fees_in_btc = trx_KB * 0.00001 total_amount = total_amount print("Size in KB: " + str(trx_KB) + ", estimated btc fees: " + str(trx_fees_in_btc) + ", total amount to be transferred: " + str(total_amount) + "\n") return trx_fees_in_btc
def test_siganyonecanpay_none_send(self): """ SIGHASH_NONE | SIGHASH_ANYONECANPAY:signs only the txin_index input """ tx = Transaction([self.txin1_siganyonecanpay_none], [self.txout1_siganyonecanpay_none], has_segwit=True) pk = self.sk.get_public_key().to_hex() sig_signone = self.sk.sign_segwit_input( tx, 0, self.p2pkh_redeem_script, self.txin1_siganyonecanpay_none_amount, SIGHASH_NONE | SIGHASH_ANYONECANPAY) tx.witnesses = [Script([sig_signone, pk])] tx.inputs.append(self.txin2_siganyonecanpay_none) tx.outputs.append(self.txout2_siganyonecanpay_none) sig = self.sk.sign_segwit_input(tx, 1, self.p2pkh_redeem_script, self.txin2_siganyonecanpay_none_amount, SIGHASH_ALL) tx.witnesses.append(Script([sig, pk])) self.assertEqual(tx.serialize(), self.test_siganyonecanpay_none_send_result)
def test_signed_send_to_p2wsh(self): # Non-segregated witness transaction tx = Transaction([self.txin1], [self.txout1]) sig = self.sk1.sign_input(tx, 0, self.p2pkh_addr.to_script_pub_key()) pk = self.sk1.get_public_key().to_hex() self.txin1.script_sig = Script([sig, pk]) self.assertEqual(tx.serialize(), self.create_send_to_p2pkh_result)
def test_send_to_non_std(self): tx = Transaction([self.txin], [self.txout, self.change_txout]) from_addr = P2pkhAddress('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r') sig = self.sk.sign_input(tx, 0, 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_non_std_tx_result)
def main(): # always remember to setup the network setup('testnet') # create transaction input from tx id of UTXO (contained 0.4 tBTC) txin = TxInput( 'fb48f4e23bf6ddf606714141ac78c3e921c8c0bebeb7c8abb2c799e9ff96ce6c', 0) # create transaction output using P2PKH scriptPubKey (locking script) addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') txout = TxOutput( Decimal('0.1'), Script([ 'OP_DUP', 'OP_HASH160', addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ])) # create another output to get the change - remaining 0.01 is tx fees # note that this time we used to_script_pub_key() to create the P2PKH # script change_addr = P2pkhAddress('mmYNBho9BWQB2dSniP1NJvnPoj5EVWw89w') change_txout = TxOutput(Decimal('0.29'), change_addr.to_script_pub_key()) #change_txout = TxOutput(Decimal('0.29'), Script(['OP_DUP', 'OP_HASH160', # change_addr.to_hash160(), # 'OP_EQUALVERIFY', 'OP_CHECKSIG'])) # create transaction from inputs/outputs -- default locktime is used tx = Transaction([txin], [txout, change_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 sign the input sk = PrivateKey('cRvyLwCPLU88jsyj94L7iJjQX5C2f8koG4G2gevN4BeSGcEvfKe9') # note that we pass the scriptPubkey as one of the inputs of sign_input # because it is used to replace the scriptSig of the UTXO we are trying to # spend when creating the transaction digest from_addr = P2pkhAddress('myPAE9HwPeKHh8FjKwBNBaHnemApo3dw6e') sig = sk.sign_input( tx, 0, Script([ 'OP_DUP', 'OP_HASH160', from_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ])) #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)
def test_signed_tx_1_input_2_outputs(self): tx = Transaction([self.txin], [self.txout, self.change_txout]) sig = self.sk.sign_input( tx, 0, Script(['OP_DUP', 'OP_HASH160', self.from_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG']) ) pk = self.sk.get_public_key().to_hex() self.txin.script_sig = Script([sig, pk]) self.assertEqual(tx.serialize(), self.core_tx_signed_result)
def test_signed_low_s_SIGSINGLE_tx_1_input_2_outputs(self): tx = Transaction([self.sig_txin1], [self.sig_txout1, self.sig_txout2] ) sig = self.sig_sk1.sign_input( tx, 0, self.sig_from_addr1.to_script_pub_key(), SIGHASH_SINGLE) pk = self.sig_sk1.get_public_key().to_hex() self.sig_txin1.script_sig = Script([sig, pk]) self.assertEqual(tx.serialize(), self.sig_sighash_single_result)
def btc_payment(source_address, outputs, fee_satoshi_kb, network='mainnet'): try: setup(network) outputs_list = [] p2sh_num = 0 p2pkh_num = 0 total_amount_to_spend = _calculate_total_amount(outputs) print(total_amount_to_spend) txin = [] utxo_amount = 0 for address, value in outputs.items(): addr_type = _check_address_type(address) addr = '' if addr_type is P2PKH_ADDRESS: addr = P2pkhAddress(address) txout = TxOutput( Decimal(value) / Decimal(SATOSHIS_PER_BITCOIN), Script([ 'OP_DUP', 'OP_HASH160', addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ])) outputs_list.append(txout) p2pkh_num += 1 elif addr_type is P2SH_ADDRESS: addr = P2shAddress(address) txout = TxOutput( Decimal(value) / Decimal(SATOSHIS_PER_BITCOIN), Script(['OP_HASH160', addr.to_hash160(), 'OP_EQUAL'])) outputs_list.append(txout) p2sh_num += 1 utxo_set, fee = _get_unspent_transactions(source_address, total_amount_to_spend, p2pkh_num, p2sh_num, fee_satoshi_kb) for utxo in utxo_set: txin.append(TxInput(utxo['txid'], utxo['vout'])) utxo_amount += utxo['amount'] change = utxo_amount - fee - total_amount_to_spend change_addr = P2pkhAddress(source_address) change_txout = TxOutput( Decimal(change) / Decimal(SATOSHIS_PER_BITCOIN), Script([ 'OP_DUP', 'OP_HASH160', change_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ])) outputs_list.append(change_txout) tx = Transaction(txin, outputs_list) return tx.serialize(), utxo_set except UnspentTransactionsError: raise UnspentTransactionsError except: raise BtcPaymentError("Problem during creation of raw transaction")
def test_spend_p2wsh(self): tx = Transaction([self.txin_spend], [self.txout2], has_segwit=True) sig1 = self.sk1.sign_segwit_input(tx, 0, self.p2wsh_redeem_script, self.txin_spend_amount) sig2 = self.sk2.sign_segwit_input(tx, 0, self.p2wsh_redeem_script, self.txin_spend_amount) pk = self.p2wsh_redeem_script.to_hex() tx.witnesses = [ Script(['OP_0', sig1, sig2, pk]) ] #print(tx.serialize()) self.assertEqual(tx.serialize(), self.spend_p2pkh_result)
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 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') # # 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']) txout = TxOutput(Decimal('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 spend_all(): """ creates & broadcasts a transactions that spend all UTXOs from the P2SH""" # loads script data (Script, p2sh_addr) script, p2sh_addr = csv_script(recreate=True) # load transaction data(PrivateKey, timelock, P2pkhAddresses) from data.json data = tools.load_data_json(priv=True, timelock_tx=True, p2pk=True) priv_key = data['priv_key'] tx_lock = data['timelock_tx'] p2pkh_addr = data['p2pk_addr'] # query cli to detect transactions send to the p2sh adddress # gathers txid, vout, and amount of p2sh's UTXOs to create TxInputs p2sh_utxos, p2sh_balance = [], 0 wallet_txs = tools.talk_to_cli('bitcoin-cli listtransactions * 900', True) for tx in json.loads(wallet_txs): if tx['address'] == p2sh_addr and tx['category'] == 'send': p2sh_utxos.append(TxInput(tx['txid'], tx['vout'], sequence=tx_lock)) p2sh_balance += (-tx['amount']) # confirm that bitcoin-cli was able to locate transactions to p2sh address if not p2sh_utxos: errors.missing_utxos() # prints error msg & raises systemExit # check current network fees and compute fee estimate resp = requests.get('https://api.blockcypher.com/v1/btc/test3').json() fee_per_kb = resp['medium_fee_per_kb'] # per Output: 34 bytes | per Input: 200 bytes (estimate) script_size = 1 * 34 + len(p2sh_utxos) * 200 fee = (script_size * fee_per_kb) / 100000000 if fee >= p2sh_balance: fee = tools.user_custom_fee(fee, p2sh_balance) # create and sign transaction tx_out = TxOutput((p2sh_balance-fee), p2pkh_addr.to_script_pub_key()) # no change address, spending entire balance tx = Transaction(p2sh_utxos, [tx_out]) pub_key = priv_key.get_public_key().to_hex() for i, txin in enumerate(p2sh_utxos): sig = priv_key.sign_input(tx, i, script) txin.script_sig = Script([sig, pub_key, script.to_hex()]) tx_signed, tx_id = tx.serialize(), tx.get_txid() # writes tx_id into data.json and displays tx_signed (+details) to the user tools.update_data_json(outputs={'tx_id': tx_id, 'tx_signed': tx_signed}) print('\nSpending from P2SH transaction') print(' -> to_addr:', p2pkh_addr.to_address()) print(' -> amount:', p2sh_balance-fee) print(' -> fee:', fee) print(' -> tx_id:', tx_id) print(' -> tx_signed:',tx_signed, '\n') # broadcast signed transaction over bitcoin-cli r = tools.talk_to_cli(f'bitcoin-cli sendrawtransaction {tx_signed}', True) if len(r) == 64: print('\nTransaction broadcasted via bitcoin-cli successfully\n')
def main(): # always remember to setup the network setup('testnet') # same params as regest, which the node should run # create transaction input from tx id of UTXO (contained 0.4 tBTC) txin = TxInput( 'e2d08a63a540000222d6a92440436375d8b1bc89a2638dc5366833804287c83f', 1) # create transaction output using P2PKH scriptPubKey (locking script) addr = P2pkhAddress('msXP94TBncQ9usP6oZNpGweE24biWjJs2d') # locking script expects 2 numbers that when added equal 5 (silly example) txout = TxOutput(0.9, Script(['OP_ADD', 'OP_5', 'OP_EQUAL'])) # create another output to get the change - remaining 0.01 is tx fees # note that this time we used to_script_pub_key() to create the P2PKH # script change_addr = P2pkhAddress('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r') change_txout = TxOutput(2, change_addr.to_script_pub_key()) # create transaction from inputs/outputs -- default locktime is used tx = Transaction([txin], [txout, change_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 sign the input sk = PrivateKey('cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN87JcbXMTcA') # note that we pass the scriptPubkey as one of the inputs of sign_input # because it is used to replace the scriptSig of the UTXO we are trying to # spend when creating the transaction digest from_addr = P2pkhAddress('mrCDrCybB6J1vRfbwM5hemdJz73FwDBC8r') sig = sk.sign_input( tx, 0, Script([ 'OP_DUP', 'OP_HASH160', from_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ])) #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)
def test_p2pkh_and_p2wpkh_to_p2pkh(self): tx = Transaction([self.txin_spend_p2pkh, self.txin_spend_p2wpkh], [self.txout3], has_segwit=True,witnesses = []) # spend_p2pkh sig1 = self.sk.sign_input(tx, 0, self.p2pkh_addr.to_script_pub_key()) pk1 = self.sk.get_public_key().to_hex() self.txin_spend_p2pkh.script_sig = Script([sig1, pk1]) tx.witnesses.append(Script([])) # spend_p2wpkh sig2 = self.sk.sign_segwit_input(tx, 1, self.p2pkh_redeem_script, self.txin_spend_p2wpkh_amount) pk2 = self.sk.get_public_key().to_hex() tx.witnesses.append(Script([sig2, pk2])) self.assertEqual(tx.serialize(), self.p2pkh_and_p2wpkh_to_p2pkh_result)
def test_sigsingle_send(self): """ SIGHASH_SINGLE:signs all inputs but only txin_index output """ tx = Transaction([self.txin1_sigsingle], [self.txout1_sigsingle], has_segwit=True,witnesses = []) pk = self.sk.get_public_key().to_hex() sig_signone = self.sk.sign_segwit_input(tx, 0, self.p2pkh_redeem_script, self.txin1_sigsingle_amount, SIGHASH_SINGLE) tx.witnesses.append(Script([sig_signone, pk])) tx.outputs.append(self.txout2_sigsingle) self.assertEqual(tx.serialize(), self.test_sigsingle_send_result)
def test_signed_low_s_SIGNONE_tx_1_input_2_outputs(self): tx = Transaction([self.txin], [self.txout, self.change_low_s_txout]) sig = self.sk.sign_input( tx, 0, Script(['OP_DUP', 'OP_HASH160', self.from_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG']), SIGHASH_NONE) pk = self.sk.get_public_key().to_hex() self.txin.script_sig = Script([sig, pk]) # check correct raw tx self.assertEqual(tx.serialize(), self.core_tx_signed_low_s_SIGNONE_result) # check correct calculation of txid self.assertEqual(tx.get_txid(), self.core_tx_signed_low_s_SIGNONE_txid)
def test_signone_send(self): """ SIGHASH_NONE:signs all of the inputs """ # First, only txin1 and txout1 are added to the transaction. tx = Transaction([self.txin1_signone], [self.txout1_signone], has_segwit=True,witnesses = []) pk = self.sk.get_public_key().to_hex() sig_signone = self.sk.sign_segwit_input(tx, 0, self.p2pkh_redeem_script, self.txin1_signone_amount, SIGHASH_NONE) tx.witnesses.append(Script([sig_signone, pk])) # Adding additional output signatures will not be affected tx.outputs.append(self.txout2_signone) self.assertEqual(tx.serialize(), self.test_signone_send_result)
def main(): # always remember to setup the network setup('testnet') # send 2 P2PKH inputs to 1 P2WPKH output # create transaction inputs from tx ids of UTXOs (contained 0.002 tBTC) txin = TxInput('eddfaa3d5a1c9a2a2961638aa4e28871b09ed9620f9077482248f368d46d8205', 1) txin2 = TxInput('cf4b2987c06b9dd2ba6770af31a4942a4ea3e7194c0d64e8699e9fda03f50551', 1) # create transaction output using P2WPKH scriptPubKey (locking script) addr = P2wpkhAddress('tb1qlffsz7cgzmyzhklleu97afru7vwjytux4z4zsl') txout = TxOutput(to_satoshis(0.0019), addr.to_script_pub_key()) #txout = TxOutput(to_satoshis(0.0019), Script([0, addr.to_hash()]) ) # create transaction from inputs/outputs -- default locktime is used # note that this is not a segwit transaction since we don't spend segwit tx = Transaction([txin, txin2], [txout]) #, has_segwit=True) # print raw transaction print("\nRaw unsigned transaction:\n" + tx.serialize()) # use the private keys corresponding to the address that contains the # UTXOs we are trying to spend to sign the input sk = PrivateKey('cTALNpTpRbbxTCJ2A5Vq88UxT44w1PE2cYqiB3n4hRvzyCev1Wwo') sk2 = PrivateKey('cVf3kGh6552jU2rLaKwXTKq5APHPoZqCP4GQzQirWGHFoHQ9rEVt') # note that we pass the scriptPubkey as one of the inputs of sign_input # because it is used to replace the scriptSig of the UTXO we are trying to # spend when creating the transaction digest from_addr = P2pkhAddress('n4bkvTyU1dVdzsrhWBqBw8fEMbHjJvtmJR') sig = sk.sign_input( tx, 0, Script(['OP_DUP', 'OP_HASH160', from_addr.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG']) ) from_addr2 = P2pkhAddress('mmYNBho9BWQB2dSniP1NJvnPoj5EVWw89w') sig2 = sk2.sign_input( tx, 1, from_addr2.to_script_pub_key() ) # get public key as hex pk = sk.get_public_key().to_hex() pk2 = sk2.get_public_key().to_hex() # set the scriptSig (unlocking script) txin.script_sig = Script([sig, pk]) txin2.script_sig = Script([sig2, pk2]) signed_tx = tx.serialize() # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + signed_tx)
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 createTxState(tx_in: TxInput, pubkey_left: PublicKey, pubkey_right: PublicKey, pubkey_pay_right: PublicKey, pubkey_mulsig_left: PublicKey, pubkey_mulsig_right: PublicKey, lock_val: float, left_val: float, right_val: float, T: int, delta: int) -> Transaction: """ Move coins from left user balance to a new "lock" output. Before: 'a' coins to L, 'b' coins to R. After: 'a - c' coins to L, 'b' coins to R, 'c' coins locked. :param tx_in: reference to channel open transaction :param pubkey_left: public key owned by left user to receive his coins from channel :param pubkey_right: public key owned by right user to receive his coins from channel :param pubkey_pay_right: public key owned by right user for payment after time T :param pubkey_mulsig_left: public key owned by left user for refund if enable-refund tx is published :param pubkey_mulsig_right: public key owned by right user for refund if enable-refund tx is published :param lock_val: amount of coins to lock: 'c' :param left_val: coins or left user: '******' :param right_val: coins or right user: '******' :param T: locked funds can pe paid after this time wherever right user wants :param delta: upper bound on time for transaction to be confirmed by the network :return: tx_state """ out_lock_script = getTxStateLockScript(T, delta, pubkey_pay_right, pubkey_mulsig_left, pubkey_mulsig_right) tx_out_lock = TxOutput(lock_val, out_lock_script) tx_out_left = TxOutput(left_val, P2pkhAddress(pubkey_left.get_address().to_string()).to_script_pub_key()) tx_out_right = TxOutput(right_val, P2pkhAddress(pubkey_right.get_address().to_string()).to_script_pub_key()) tx = Transaction([tx_in], [tx_out_lock, tx_out_left, tx_out_right]) return tx
def createTxPayAndSign(tx_state_input: TxInput, id_state_pay_right: Id, tx_state_lock_script: Script, id_pay_receiver: Id, lock_coins: float, fee: float) -> Transaction: """ Right can spend locked coins after time T wherever he wants :param tx_state_input: tx_state locked output reference :param id_state_pay_right: id for signing spend of tx_state.out_lock by right user :param tx_state_lock_script: lock script of tx_state.out_lock (for creating a signature) :param id_pay_receiver: id that will own coins if transaction will be published :param lock_coins: coins locked in tx_state :param fee: coins paid to miners :return: transaction for pay to right user, valid after time T """ out_pay = TxOutput(lock_coins - fee, id_pay_receiver.p2pkh) tx_pay = Transaction([tx_state_input], [out_pay]) signature = id_state_pay_right.private_key.sign_input( tx_pay, 0, tx_state_lock_script) tx_state_input.script_sig = Script([ signature, id_state_pay_right.public_key.to_hex(), 'OP_0', 'OP_0', 'OP_0', 'OP_0', 'OP_0', 'OP_0' ]) return tx_pay
def createTxInstPay(tx_ep_input: TxInput, tx_state_input: TxInput, id_state_inst_pay_left: Id, tx_state_lock_script: Script, inst_pay_lock_script: Script, lock_coins: float, fee: float, eps: float) -> (Transaction, str): """ Left user creates tx_inst_pay and signature for tx_state which funds this tx_inst_pay :param tx_ep_input: enable-payment transaction output reference :param tx_state_input: tx_state locked output reference :param id_state_inst_pay_left: id for signing spend of tx_state.out_lock by left user :param tx_state_lock_script: lock script of tx_state.out_lock (for creating a signature) :param inst_pay_lock_script: ScriptPubKey for new transactio, for example, p2pkh (to right user pubkey hash) :param lock_coins: coins locked in tx_state :param fee: coins paid to miners :param eps: coins from enable-refund transaction :return: tx for instant payment and signature of left user for it """ out_inst_pay = TxOutput(lock_coins + eps - fee, inst_pay_lock_script) tx_inst_pay = Transaction([tx_ep_input, tx_state_input], [out_inst_pay]) # should be also signed by right for 2/2 multisig sig_state_left = id_state_inst_pay_left.private_key.sign_input( tx_inst_pay, 0, tx_state_lock_script) return tx_inst_pay, sig_state_left
def createTxRefund(tx_er_input: TxInput, tx_state_input: TxInput, id_er: Id, id_state_ref_left: Id, tx_state_lock_script: Script, id_refund: Id, lock_coins: float, fee: float, eps: float, rel_lock: int) -> (Transaction, str): """ Left user creates transaction for refund based on tx_state and tx_er, and signs it :param tx_er_input: enable-refund transaction output reference :param tx_state_input: tx_state locked output reference :param id_er: id that owns output of enable-refund transaction :param id_state_ref_left: id for signing spend of tx_state.out_lock by left user :param tx_state_lock_script: lock script of tx_state.out_lock (for creating a signature) :param id_refund: id that will own coins if transaction will be published :param lock_coins: coins locked in tx_state :param fee: coins paid to miners :param eps: coins from enable-refund transaction :param rel_lock: relative lock on tx_er_input (for creating a signature) :return: tx_refund, signed by left user """ out_refund = TxOutput(lock_coins + eps - fee, id_refund.p2pkh) tx_refund = Transaction([tx_er_input, tx_state_input], [out_refund]) er_in_lock_script = getEnableTxOutputLockScript(id_er.public_key, rel_lock) sig_er_in = id_er.private_key.sign_input(tx_refund, 0, er_in_lock_script) tx_er_input.script_sig = Script([sig_er_in, id_er.public_key.to_hex()]) # should be also signed by right for 2/2 multisig sig_state_left = id_state_ref_left.private_key.sign_input( tx_refund, 1, tx_state_lock_script) return tx_refund, sig_state_left
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 main(): # always remember to setup the network setup('testnet') # the key that corresponds to the P2WPKH address priv = PrivateKey("cVdte9ei2xsVjmZSPtyucG43YZgNkmKTqhwiUA8M4Fc3LdPJxPmZ") pub = priv.get_public_key() fromAddress = pub.get_segwit_address() print(fromAddress.to_string()) # amount is needed to sign the segwit input fromAddressAmount = to_satoshis(0.01) # UTXO of fromAddress txid = '13d2d30eca974e8fa5da11b9608fa36905a22215e8df895e767fc903889367ff' vout = 0 toAddress = P2pkhAddress('mrrKUpJnAjvQntPgz2Z4kkyr1gbtHmQv28') # create transaction input from tx id of UTXO txin = TxInput(txid, vout) # the script code required for signing for p2wpkh is the same as p2pkh script_code = Script([ 'OP_DUP', 'OP_HASH160', pub.to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # create transaction output txOut = TxOutput(to_satoshis(0.009), toAddress.to_script_pub_key()) # create transaction without change output - if at least a single input is # segwit we need to set has_segwit=True tx = Transaction([txin], [txOut], has_segwit=True) print("\nRaw transaction:\n" + tx.serialize()) sig = priv.sign_segwit_input(tx, 0, script_code, fromAddressAmount) tx.witnesses.append(Script([sig, pub.to_hex()])) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + tx.serialize()) print("\nTxId:", tx.get_txid())
def main(): # always remember to setup the network setup('testnet') priv0 = PrivateKey("cN1XE3ESGgdvr4fWsB7L3BcqXncUauF8Fo8zzv4Sm6WrkiGrsxrG") pub = priv0.get_public_key() fromAddress = pub.get_segwit_address() priv1 = PrivateKey("cN1XE3ESGgdvr4fWsB7L3BcqXncUauF8Fo8zzv4Sm6WrkiGrsxrG") # P2SH Script: OP_M <Public key 1> <Public key 2> ... OP_N OP_CHECKMULTISIG p2sh_redeem_script = Script( ['OP_1', priv1.get_public_key().to_hex(), 'OP_1', 'OP_CHECKMULTISIG']) toAddress = P2wshAddress.from_script(p2sh_redeem_script) # set values txid = 'd222d91e2da368ac38e84aa615c557e4caeacce02aa5dbca10d840fd460fc938' vout = 0 amount = Decimal('0.01764912') # create transaction input from tx id of UTXO txin = TxInput(txid, vout) redeem_script1 = Script([ 'OP_DUP', 'OP_HASH160', priv0.get_public_key().to_hash160(), 'OP_EQUALVERIFY', 'OP_CHECKSIG' ]) # create transaction output txOut1 = TxOutput(Decimal('0.0001'), toAddress.to_script_pub_key()) txOut2 = TxOutput(Decimal('0.01744912'), fromAddress.to_script_pub_key()) # create transaction tx = Transaction([txin], [txOut1, txOut2], has_segwit=True) print("\nRaw transaction:\n" + tx.serialize()) sig1 = priv0.sign_segwit_input(tx, 0, redeem_script1, amount) tx.witnesses.append(Script([sig1, pub.to_hex()])) # print raw signed transaction ready to be broadcasted print("\nRaw signed transaction:\n" + tx.serialize()) print("\nTxId:", tx.get_txid())