def test_legacy_tx(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) tx_in = simple.p2pkh_input( outpoint=outpoint, sig=helpers.P2PKH['human']['ins'][0]['signature'], pubkey=helpers.P2PKH['human']['ins'][0]['pubkey'], sequence=helpers.P2PKH['human']['ins'][0]['sequence']) tx_out = simple.output( helpers.P2PKH['human']['outs'][0]['value'], helpers.P2PKH['human']['outs'][0]['addr']) tx_return_output = txn.make_op_return_output( helpers.P2PKH['human']['outs'][1]['memo']) tx = simple.legacy_tx([tx_in], [tx_out, tx_return_output]) self.assertEqual(tx, helpers.P2PKH['ser']['tx']['signed'])
def test_witness_tx(self): outpoint = simple.outpoint( tx_id=helpers.P2WPKH['human']['ins'][0]['hash'], index=helpers.P2WPKH['human']['ins'][0]['index']) (tx_in, witness) = simple.p2wpkh_input_and_witness( outpoint=outpoint, sig=helpers.P2WPKH['human']['witnesses'][0]['signature'], pubkey=helpers.P2WPKH['human']['witnesses'][0]['pubkey'], sequence=helpers.P2WPKH['human']['ins'][0]['sequence']) tx_out = simple.output( value=helpers.P2WPKH['human']['outs'][0]['value'], address=helpers.P2WPKH['human']['outs'][0]['addr']) tx = simple.witness_tx(tx_ins=[tx_in], tx_outs=[tx_out], tx_witnesses=[witness], lock_time=helpers.P2WPKH['human']['locktime']) self.assertEqual(tx, helpers.P2WPKH['ser']['tx']['signed'])
def make_partial_tx(outpoint: Outpoint, output_value: int, output_address: str, lock_time: int = 0) -> Tx: '''Creates an unsigned partial tx Args: outpoint (riemann.tx.Outpoint): the outpoint to spend sequence (int): tx nSequence output_value (int): the number of satoshi to receive output_address (str): the seller's address lock_time (int): the tx's lock time ''' tx_ins = [simple.unsigned_input(outpoint, sequence=0xFFFFFFFD)] tx_outs = [simple.output(output_value, output_address)] return cast( Tx, simple.unsigned_witness_tx(tx_ins=tx_ins, tx_outs=tx_outs, lock_time=lock_time))
def test_witness_tx_exception(self): outpoint = simple.outpoint( tx_id=helpers.P2WPKH['human']['ins'][0]['hash'], index=helpers.P2WPKH['human']['ins'][0]['index']) (tx_in, witness) = simple.p2wpkh_input_and_witness( outpoint=outpoint, sig=helpers.P2WPKH['human']['witnesses'][0]['signature'], pubkey=helpers.P2WPKH['human']['witnesses'][0]['pubkey'], sequence=helpers.P2WPKH['human']['ins'][0]['sequence']) tx_out = simple.output( value=helpers.P2WPKH['human']['outs'][0]['value'], address=helpers.P2WPKH['human']['outs'][0]['addr']) witness = txn.InputWitness.from_bytes(b'\x02\x02\xab\xab\x01\xab') tx = simple.witness_tx(tx_ins=[tx_in], tx_outs=[tx_out], tx_witnesses=[witness]) self.assertEqual(tx.lock_time, b'\x00' * 4) self.assertEqual(tx.version, b'\x01' + b'\x00' * 3)
def createSingleFundingTransaction(network, funder_outpoint, funder_amount, funder_pubkey, fundee_pubkey): """network -> bitcoin or zcash script -> { stack_script : , redeem_script : if spending a P2SH, then this should be set } funder_outpoint -> specific tx output consisting of (txid, output-index) funder_amount -> amount from unspent tx funder_pubkey -> pub key for the funder fundee_pubkey -> pub key of the fundee (or counterparty) """ # create the multi-signature address # fee = 10000 msig_addr, funding_redeem_script = createMultiSigAddress(funder_pubkey, fundee_pubkey) print("Output address: ", msig_addr) print("Redeem script: ", funding_redeem_script) # for closing # create tx input _redeem_script = bytes.fromhex("48304502210090587b6201e166ad6af0227d3036a9454223d49a1f11839c1a362184340ef0240220577f7cd5cca78719405cbf1de7414ac027f0239ef6e214c90fcaab0454d84b3b012103535b32d5eb0a6ed0982a0479bbadc9868d9836f6ba94dd5a63be16d875069184") #tx_ins = [simple.unsigned_input(outpoint=funder_outpoint, redeem_script=_redeem_script)] tx_ins = [tb.make_legacy_input(outpoint=funder_outpoint, stack_script=b"", redeem_script=_redeem_script, sequence=0xFFFFFFFF)] print("Input: ", tx_ins) tx_outs = [simple.output(address=msig_addr, value=funder_amount)] print("Output: ", tx_outs) if network == "bitcoin": unsigned_tx = simple.unsigned_legacy_tx(tx_ins, tx_outs) elif network == "zcash": unsigned_tx = simple.unsigned_legacy_tx(tx_ins, tx_outs) script_code1 = b'\x19' + addresses.to_output_script(msig_addr) # TODO: computing sighash_all => verify that this is done correctly sighash = unsigned_tx.sighash_all(index=0, script=script_code1, prevout_value=utils.i2le_padded(funder_amount, 8)) # TODO: add signing of the sighash print("sighash hex: ", sighash.hex()) # NOTE: for dual-funded channel, funder_bal = funder_amount + fundee_amount funding_tx = {'funding_tx_id': unsigned_tx.tx_id.hex(), 'funding_bal': funder_amount, 'funding_addr': str(msig_addr)} return funding_tx, unsigned_tx.hex(), funding_redeem_script
def undo_split(tx_id: str, num_auctions: int, change_addr: str, control_addr_keypair: Tuple[str, str]) -> tx.Tx: ''' undoes a split tx. NOT FOR SHUTTING DOWN AUCTIONS Args: tx_id: the tx_id of the split tx num_auctions: the number of non-change outputs of the split tx change_addr: the address to send leftovers to control_addr_keypair: the keypair of the controlling address ''' tx_ins = [ simple.unsigned_input(simple.outpoint(tx_id, i)) for i in range(num_auctions) ] tx_outs = [simple.output(600, change_addr)] unsplit_tx = simple.unsigned_witness_tx(tx_ins, tx_outs) pubkeyhash = rutils.hash160(bytes.fromhex(control_addr_keypair[1])) prevout_script = b'\x19\x76\xa9\x14' + pubkeyhash + b'\x88\xac' tx_witnesses = [] for i in range(num_auctions): sighash_bytes = unsplit_tx.sighash_all( index=i, script=prevout_script, prevout_value=rutils.i2le_padded(550, 8), anyone_can_pay=False) sig = utils.sign_hash(sighash_bytes, control_addr_keypair[0]) sig = '{}{}'.format(sig, '01') # Build the witness wit = tx.make_witness( [bytes.fromhex(sig), bytes.fromhex(control_addr_keypair[1])]) tx_witnesses.append(wit) return cast(tx.Tx, unsplit_tx.copy(tx_witnesses=tx_witnesses))
# flake8: noqa from riemann import simple # Spend a P2PKH output: tx_ins = [simple.unsigned_input(outpoint)] # Spend a P2SH output tx_ins += [simple.unsigned_input( outpoint=outpoint, redeem_script=redeem_script)] # Make an output tx_outs = [simple.output(value, address)] # Build the transaction tx = simple.unsigned_tx(tx_ins, tx_outs) sighash_0 = tx.sighash_single(0, p2pkh_pk_script) sighash_1 tx.sighash_all(1, redeem_script, anyone_can_pay=True)
# Receiver (made up private key that controls absolutely nothing) receiver_privkey_hex = '9a597c337b95fb037e3e1e4b719b1fd8d3914e69c22464bee63954eda03b56c3' # noqa: E501 receiver_pubkey = '02ef21caa25eca974d3bdd73c034d6943cbf145a700d493adaa6f496bd87c5b33b' # noqa: E501 receiver_addr = addr.make_p2wpkh_address(bytes.fromhex(receiver_pubkey)) # Sender Input tx_id = 'ff7ff97060bfa1763dd9d4101b322157e841a4de865ddc28b1f71500f45c8135' index = 0 sender_outpoint = simple.outpoint(tx_id, index) sender_value = 1000 fee = 10 sender_input = simple.unsigned_input(sender_outpoint, sequence=sequence) # Sender Output sender_output = simple.output(value=sender_value - fee, address=receiver_addr) # OP_RETURN output riemann_note = 'made with ❤ by riemann'.encode('utf-8') op_return_output = tx_builder.make_op_return_output(riemann_note) unsigned_tx = simple.unsigned_legacy_tx( tx_ins=[sender_input], tx_outs=[sender_output, op_return_output], version=version, lock_time=locktime) sighash_all = 0x01 sighash = unsigned_tx.sighash_all( index=0, script=addr.to_output_script(sender_addr))
def make_btc_shutdown_txns(auction_tx_id: str, idxs: List[int], add_funds_tx_id: str, add_funds_idx: int, add_funds_value: int, control_addr: str, control_addr_keypair: Tuple[str, str], change_addr: str, eth_addr: str, fee: int = 7700) -> List[str]: ''' Shuts down an auction by winning them with the owner keypair Args: tx_id: the split tx for the auction set idxs: the unpurchased indexes add_funds_tx_id: a prevout tx id to fund these transactions add_funds_idx: the prevout index add_funds_value: the prevout value control_addr: the input prevout's controlling address control_addr_keypair: the priv/pub keypair as a tuple of hex change_addr: where to send leftover funds eth_addr: where to deliver auction proceeds fee: the tx fee to pay ''' prev = (add_funds_tx_id, add_funds_idx) val = add_funds_value shutdown_txns = [] pubkeyhash = rutils.hash160(bytes.fromhex(control_addr_keypair[1])) prevout_script = b'\x19\x76\xa9\x14' + pubkeyhash + b'\x88\xac' for i in range(len(idxs)): tx_ins = [ simple.unsigned_input(simple.outpoint(auction_tx_id, idxs[i])), simple.unsigned_input(simple.outpoint(*prev)) ] out_val = val + 550 - fee addr = control_addr if i < len(idxs) - 1 else change_addr tx_outs = [ simple.output(out_val, addr), tx.make_op_return_output(bytes.fromhex(eth_addr[2:])) ] shutdown_tx = simple.unsigned_witness_tx(tx_ins, tx_outs) tx_witnesses = [] sighash_bytes = shutdown_tx.sighash_all( index=0, script=prevout_script, prevout_value=rutils.i2le_padded(550, 8), anyone_can_pay=False) sig = utils.sign_hash(sighash_bytes, control_addr_keypair[0]) sig = '{}{}'.format(sig, '01') # Build the witness wit = tx.make_witness( [bytes.fromhex(sig), bytes.fromhex(control_addr_keypair[1])]) tx_witnesses.append(wit) sighash_bytes_2 = shutdown_tx.sighash_all( index=1, script=prevout_script, prevout_value=rutils.i2le_padded(val, 8), anyone_can_pay=False) sig_2 = utils.sign_hash(sighash_bytes_2, control_addr_keypair[0]) sig_2 = '{}{}'.format(sig_2, '01') # Build the witness wit_2 = tx.make_witness( [bytes.fromhex(sig_2), bytes.fromhex(control_addr_keypair[1])]) tx_witnesses.append(wit_2) prev = (shutdown_tx.tx_id.hex(), 0) val = out_val shutdown_txns.append(shutdown_tx.copy(tx_witnesses=tx_witnesses).hex()) return shutdown_txns
# Use a real timelock! timeout = 'deadbeef' # string formatting to fill parameters filled_in_redeem_script = htlc_redeem_script.format( secret_hash=secret_hash, pkh0=utils.hash160(bytes.fromhex(fake_pk_execute)).hex(), timeout=timeout, pkh1=utils.hash160(bytes.fromhex(fake_pk_refund)).hex()) # DON'T SEND MONEY TO THIS EXAMPLE ADDRESS!!! # t 3fKPy737rsshnQJ7iRoXw3XujCB7tjuiUt htlc_address = addr.make_sh_address(filled_in_redeem_script) # how to send money there output = simple.output(500000, htlc_address) # --- HOW TO SPEND --- # fill in the sig/pubkey/secret filled_in_execute_script = htlc_stack_script_execute.format( sig=fake_sig, pk=fake_pk_execute, secret=secret) filled_in_refund_script = htlc_stack_script_refund.format( sig=fake_sig, pk=fake_pk_refund) # make inputs with the stack script and redeem script fake_outpoint = simple.empty_outpoint() execute_input = simple.p2sh_input( outpoint=fake_outpoint,
tx_outpoint = simple.outpoint(tx_id, tx_index) # Generate TxIn tx_in = simple.unsigned_input(tx_outpoint, sequence=0xFFFFFFFE) # Generate TxOut # Address to receive bitcoin receiving_address = 'bc1qss5rslea60lftfe7pyk32s9j9dtr7z7mrqud3g' # Bitcoin (satoshis) to send input_value = 100000 # Allocate Bitcoin (satoshis) for miner tx_fee = 3100 tx_out = simple.output(input_value - tx_fee, receiving_address) # Completely optional memo tx_return_output = tb.make_op_return_output( 'made with ❤ by riemann'.encode('utf-8')) # Generate Unsigned Tx # Create unsigned transaction tx = simple.unsigned_tx([tx_in], [tx_out, tx_return_output]) # Generate Signed Tx # https://blockchain.info/tx/1e7acd3d4715054c8fb0fdea25c5c704986006d2c6f30b0782e9b36a7ee072ef # With the p2pkh output script from address, create the the sighash to be signed sighash = tx.sighash_all(index=0, script=addresses.to_output_script(address))
# Make inputs for our tx # We're spending the 1st output of a45216... # And the 0th output of ae9ee9... tx_in_1 = simple.unsigned_input( simple.outpoint( 'a45216a60855f053d63eb78a91429f85c6218541e876be95b17f8743635a0d3e', 1)) # noqa: E501 tx_in_2 = simple.unsigned_input( simple.outpoint( 'ae9ee9ddeae0f0de07837f25b638ac8a723104753008d9c672e57b1d58e1c863', 0)) # noqa: E501 # Make an output for our tx. # Our prevouts are worth 0.01845001 and 0.00002 ZEC # We want to pay 0.0001 ZEC tx_out = simple.output(1845001 + 2000 - 10000, 't1fRswMu1vopHpWVisgxTtkJSVs8ZCrDZtz') # noqa: E501 # Make the transaction unsigned_tx = simple.unsigned_legacy_tx([tx_in_1, tx_in_2], [tx_out]) # Calculate the sighashes sighash_1 = unsigned_tx.sighash_all(index=0, script_code=script_code_1, prevout_value=utils.i2le_padded( 1845001, 8)) sighash_2 = unsigned_tx.sighash_all(index=1, script_code=script_code_2, prevout_value=utils.i2le_padded(2000, 8)) # Sign the transaction with your private keys elsewhere pubkey_1 = ''
def pay_address(value: int, address: str) -> tx.TxOut: ''' Create an output paying `value` to `address` ''' return simple.output(value, address)
def p2htlc_output(value: int, secret_hash: bytes, redeemer_pkh: bytes, timeout: int, funder_pkh: bytes) -> tx.TxOut: '''Parameterizes the script, and creates an output paying that address''' address = htlc_address(secret_hash, redeemer_pkh, timeout, funder_pkh) return simple.output(value, address)