def test_p2wsh_input_and_witness(self): helper_witness = helpers.P2WSH['human']['witnesses'][0] outpoint = simple.outpoint( tx_id=helpers.P2WSH['human']['ins'][0]['hash'], index=helpers.P2WSH['human']['ins'][0]['index']) (tx_in, witness) = simple.p2wsh_input_and_witness( outpoint=outpoint, stack=helper_witness['stack'], witness_script=helper_witness['wit_script'], sequence=helpers.P2WSH['human']['ins'][0]['sequence']) self.assertEqual(tx_in, helpers.P2WSH['ser']['ins'][0]['input']) self.assertEqual(witness, helpers.P2WSH['ser']['tx']['witness']) helper_witness = helpers.P2WSH['human']['witnesses'][0] outpoint = simple.outpoint( tx_id=helpers.P2WSH['human']['ins'][0]['hash'], index=helpers.P2WSH['human']['ins'][0]['index']) (tx_in, witness) = simple.p2wsh_input_and_witness( outpoint=outpoint, stack=helper_witness['stack'], witness_script=helper_witness['wit_script'], sequence=None) self.assertEqual( tx_in, helpers.INPUT_FOR_WITNESS_SEQUENCE_GUESSING)
def test_p2sh_input_and_witness(self): outpoint = simple.outpoint( helpers.P2SH_PD1['human']['ins'][0]['hash'], helpers.P2SH_PD1['human']['ins'][0]['index']) (tx_p2sh_input, witness) = simple.p2sh_input_and_witness( outpoint=outpoint, stack_script=helpers.P2SH_PD1['human']['ins'][0]['stack_script'], redeem_script=helpers.P2SH_PD1['human']['ins'][0]['redeem_script'], sequence=helpers.P2SH_PD1['human']['ins'][0]['sequence']) self.assertTrue(tx_p2sh_input.is_p2sh()) self.assertEqual(witness, b'\x00') self.assertEqual(tx_p2sh_input.stack_script, helpers.P2SH_PD1['ser']['ins'][0]['stack_script']) self.assertEqual(tx_p2sh_input.redeem_script, helpers.P2SH_PD1['ser']['ins'][0]['redeem_script']) self.assertEqual(tx_p2sh_input, helpers.P2SH_PD1['ser']['ins'][0]['input']) # Seems weird but tests sequence guessing outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) (tx_in, witness) = simple.p2sh_input_and_witness( outpoint=outpoint, stack_script=helpers.P2PKH['human']['ins'][0]['stack_script'], redeem_script='', sequence=None) self.assertEqual(tx_in, helpers.P2PKH['ser']['ins'][0]['input']) self.assertEqual(witness, b'\x00')
def partial(tx_id: str, index: int, prevout_value: int, recipient_addr: str, output_value: int, lock_time: int, keypair: KeyPair) -> Tx: ''' Makes a partial_tx from human readable information Args: tx_id (str): txid of parent tx index (int): index of input in parent tx prevout_value (int): value in satoshi of the input recipient_addr (str): address of the recipient output_value (int): value in satoshi of the output lock_time (int): desired lock_time in bitcoin format keypair (tuple(str, str)): privkey as hex, pubkey as hex Returns: (riemann.tx.Tx): The signed transaction ''' outpoint = simple.outpoint(tx_id, index) pub = bytes.fromhex(keypair[1]) pkh = rutils.hash160(pub) output_script = b'\x19\x76\xa9\x14' + pkh + b'\x88\xac' # Assume PKH unsigned = make_partial_tx(outpoint=outpoint, output_value=output_value, output_address=recipient_addr, lock_time=lock_time) signed = sign_partial_tx(partial_tx=unsigned, keypair=keypair, prevout_script=output_script, prevout_value=rutils.i2le_padded( prevout_value, 8)) return signed
def createCommitmentTransaction(funding_tx, cust_pubkey, rev_pubkey, merch_pubkey, cust_amount, merch_amount): funding_tx_id = funding_tx.get("funding_tx_id") funding_bal = funding_tx.get("funding_bal") funding_addr = funding_tx.get('funding_address') print("<= Create Commitment Transaction =>") # compute the funding tx outpoint funding_tx_outpoint = simple.outpoint(funding_tx_id, 0) # get the funding tx outpoint as the transaction input tx_ins = [simple.unsigned_input(funding_tx_outpoint)] # the commitment tx has two outputs: (1) customer and (2) merchant cust_redeem_script = ln_redeem_script.format(rev_pubkey=rev_pubkey, merch_pubkey=merch_pubkey, cust_pubkey=cust_pubkey, timeout=uint32_to_bytes(1440)) # 1 day - timeout if debug: print("Cust redeem script: ", cust_redeem_script) cust_address = addresses.make_p2sh_address(cust_redeem_script) tx_out_1 = simple.output(cust_amount, cust_address) # customer encoded_merch_pubkey = bytes.fromhex(merch_pubkey) merch_address = addresses.make_p2pkh_address(encoded_merch_pubkey) tx_out_2 = simple.output(merch_amount, merch_address) # merchant unsigned_tx = simple.unsigned_legacy_tx(tx_ins, [tx_out_1, tx_out_2]) # script code of prevout being spent (from funding tx) prevout_script_code = b'\x19' + addresses.to_output_script(funding_addr) sighash = unsigned_tx.sighash_all(index=0, script_code=prevout_script_code, prevout_value=utils.i2le_padded(funding_bal, 8)) print("sighash hex: ", sighash.hex()) return unsigned_tx.hex()
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 setUTXOs(self, txid, index, utxo_amount, scriptsig): if self.input_utxo_specified: return # assume these are specified correctly for now self.outpoint = simple.outpoint(txid, index) self.utxo_amount = utxo_amount self.scriptsig = bytes.fromhex(scriptsig) self.input_utxo_specified = True
def test_unsigned_input(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) self.assertEqual(simple.unsigned_input(outpoint=outpoint), outpoint.to_bytes() + b'\x00' + b'\xFE\xFF\xFF\xFF') self.assertEqual( simple.unsigned_input(outpoint=outpoint, sequence=0x1234abcd), outpoint.to_bytes() + b'\x00' + b'\xcd\xab\x34\x12')
def test_decred_simple(self): outpoint = simple.outpoint( tx_id=helpers.DCR['human']['ins'][0]['hash'], index=helpers.DCR['human']['ins'][0]['index'], tree=helpers.DCR['human']['ins'][0]['tree']) self.assertEqual( simple.unsigned_input( outpoint=outpoint, sequence=helpers.DCR['human']['ins'][0]['sequence']), helpers.DCR['ser']['tx']['in_unsigned'])
def test_p2pkh_input(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) self.assertEqual( simple.p2pkh_input( outpoint=outpoint, sig=helpers.P2PKH['human']['ins'][0]['signature'], pubkey=helpers.P2PKH['human']['ins'][0]['pubkey'], ), helpers.P2PKH['ser']['ins'][0]['input'])
def test_unsigned_input(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) self.assertEqual( simple.unsigned_input( outpoint=outpoint), outpoint.to_bytes() + b'\x00' + b'\xFE\xFF\xFF\xFF') self.assertEqual( simple.unsigned_input( outpoint=outpoint, sequence=0x1234abcd), outpoint.to_bytes() + b'\x00' + b'\xcd\xab\x34\x12') self.assertEqual( simple.unsigned_input( outpoint=outpoint, redeem_script='11AA OP_CHECKSEQUENCEVERIFY'), outpoint.to_bytes() + b'\x00' + b'\xaa\x11\x00\x00') self.assertEqual( simple.unsigned_input( outpoint=outpoint, redeem_script='11AA OP_CHECKSEQUENCEVERIFY', sequence=0x1234abcd), outpoint.to_bytes() + b'\x00' + b'\xcd\xab\x34\x12') riemann.select_network('decred_main') outpoint = simple.outpoint( tx_id=helpers.DCR['human']['ins'][0]['hash'], index=helpers.DCR['human']['ins'][0]['index'], tree=helpers.DCR['human']['ins'][0]['tree']) self.assertEqual( simple.unsigned_input( outpoint=outpoint, sequence=helpers.DCR['human']['ins'][0]['sequence']), helpers.DCR['ser']['tx']['in_unsigned'])
def test_p2pkh_input_and_witness(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) (tx_in, witness) = simple.p2pkh_input_and_witness( outpoint=outpoint, sig=helpers.P2PKH['human']['ins'][0]['signature'], pubkey=helpers.P2PKH['human']['ins'][0]['pubkey'], sequence=helpers.P2PKH['human']['ins'][0]['sequence']) self.assertEqual(tx_in, helpers.P2PKH['ser']['ins'][0]['input']) self.assertEqual(witness, b'\x00')
def test_unsigned_witness_tx(self): outpoint = simple.outpoint( tx_id=helpers.P2WPKH['human']['ins'][0]['hash'], index=helpers.P2WPKH['human']['ins'][0]['index']) tx_in = simple.unsigned_input( outpoint=outpoint, sequence=helpers.P2WPKH['human']['ins'][0]['sequence']) tx_out = simple.output( helpers.P2WPKH['human']['outs'][0]['value'], helpers.P2WPKH['human']['outs'][0]['addr']) tx = simple.unsigned_witness_tx( tx_ins=[tx_in], tx_outs=[tx_out]) self.assertEqual(tx, helpers.P2WPKH['ser']['tx']['unsigned'])
def test_unsigned_legacy_tx(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) tx_in = simple.unsigned_input( outpoint=outpoint, 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.unsigned_legacy_tx(tx_ins=[tx_in], tx_outs=[tx_out, tx_return_output]) self.assertEqual(tx, helpers.P2PKH['ser']['tx']['unsigned'])
def spend_utxo(tx_id: str, index: int) -> tx.TxIn: ''' Make an input spending a TXO. TXOs are specified by the ID of the tx that created them, and their index in that txn's `vout`. This creates an Input using that information Args: tx_id: the id of the tx that created the output index: the index of the output in the previous txn's `vout` Return: An input spending the specified TXO ''' return simple.unsigned_input( outpoint=simple.outpoint(tx_id, index), sequence=0xFFFFFFFE) # disable RBF and nSeq timelocks, allow nlocktime
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 test_unsigned_input(self): outpoint = simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']) self.assertEqual(simple.unsigned_input(outpoint=outpoint), outpoint.to_bytes() + b'\x00' + b'\xFE\xFF\xFF\xFF') self.assertEqual( simple.unsigned_input(outpoint=outpoint, sequence=0x1234abcd), outpoint.to_bytes() + b'\x00' + b'\xcd\xab\x34\x12') self.assertEqual( simple.unsigned_input(outpoint=outpoint, redeem_script='11AA OP_CHECKSEQUENCEVERIFY'), outpoint.to_bytes() + b'\x00' + b'\xaa\x11\x00\x00') self.assertEqual( simple.unsigned_input(outpoint=outpoint, redeem_script='11AA OP_CHECKSEQUENCEVERIFY', sequence=0x1234abcd), outpoint.to_bytes() + b'\x00' + b'\xcd\xab\x34\x12')
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))
def generate_small_utxos( tx_id: str, index: int, prevout_value: int, recipient_addr: str, num_outputs: int, fee: int, change_addr: str, size: int = 550) -> Tx: ''' Makes new utxos. All utxos have the same address (i.e. the same keypair) Args: tx_id (str): txid of parent tx index (int): index of input in parent tx prevout_value (int): value in satoshi of the input recipient_addr (str): address of the recipient num_outputs (int): how many new small UTXOs to make fee (int): fee to pay in satoshi change_addr (str): address to send change to Returns: (rieman.tx.Tx): The unsigned tx making num_outputs new UTXOs ''' # Make the input outpoint = simple.outpoint(tx_id, index) tx_ins = [simple.unsigned_input(outpoint)] # make small outputs tx_outs = [simple.output(size, recipient_addr) for i in range(num_outputs)] # Make a change output change = prevout_value - (size * num_outputs) - fee tx_outs.append(simple.output(change, change_addr)) return cast(Tx, simple.unsigned_witness_tx(tx_ins, tx_outs))
public_key = '02bfb0a1108262227c8415aa90edc6c1a10e1e447ae58587c537926ef7069a38ca' # Generate address from public key address = addresses.make_pkh_address(bytes.fromhex(public_key)) # Generate Unsigned TxIn # https://blockchain.info/tx/264b157c1c733bb42c42f2932702921ea23ac93259ca058cdf36311e36295188 # Previous transaction hash tx_id = '264b157c1c733bb42c42f2932702921ea23ac93259ca058cdf36311e36295188' # UTXO index to use tx_index = 0 # Generate 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)
def test_outpoint(self): self.assertEqual( simple.outpoint( tx_id=helpers.P2PKH['human']['ins'][0]['hash'], index=helpers.P2PKH['human']['ins'][0]['index']), helpers.P2PKH['ser']['ins'][0]['outpoint'])
prevout_addr_1 = 't1S3kN4zusjHtDEwfdaCMgk132bqo9DaYW4' prevout_addr_2 = 't1VQCUYzApF5eWf4UFAGdWwaFEpBfG2su1A' # This is the script code of the prevout being spent # We length prefix it # Needed for sighash later script_code_1 = b'\x19' + addr.to_output_script(prevout_addr_1) script_code_2 = b'\x19' + addr.to_output_script(prevout_addr_2) # 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])
# Sender (made up private key that controls absolutely nothing) sender_privkey_hex = '372f913c52d7a6dfdfda9261e666a70e60f694f47c83fae388035fabbb168d63' # noqa: E501 sender_pubkey = '02a004b949e4769ed341064829137b18992be884da5932c755e48f9465c1069dc2' # noqa: E501 sender_addr = addr.make_p2wpkh_address(bytes.fromhex(sender_pubkey)) # 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,
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