def test_txout_locking( self, cluster: clusterlib.ClusterLib, payment_addrs: List[clusterlib.AddressRecord], use_inline_datum: bool, use_reference_script: bool, request: FixtureRequest, ): """Test combinations of inline datum and datum file + reference script and script file. * create the necessary Tx outputs * check that the expected amount was locked at the script address * spend the locked UTxO * check that the expected UTxOs were correctly spent """ temp_template = f"{common.get_test_id(cluster)}_{request.node.callspec.id}" amount = 2_000_000 plutus_op = PLUTUS_OP_ALWAYS_SUCCEEDS # for mypy assert plutus_op.execution_cost assert plutus_op.datum_file assert plutus_op.redeemer_cbor_file redeem_cost = plutus_common.compute_cost( execution_cost=plutus_op.execution_cost, protocol_params=cluster.get_protocol_params() ) # Step 1: fund the Plutus script script_utxos, collateral_utxos, reference_utxos, __ = _fund_script( temp_template=temp_template, cluster=cluster, payment_addr=payment_addrs[0], dst_addr=payment_addrs[1], plutus_op=plutus_op, amount=amount, redeem_cost=redeem_cost, use_inline_datum=use_inline_datum, use_reference_script=use_reference_script, ) plutus_txins = [ clusterlib.ScriptTxIn( txins=script_utxos, script_file=plutus_op.script_file if not use_reference_script else "", reference_txin=reference_utxos[0] if use_reference_script else None, reference_type=clusterlib.ScriptTypes.PLUTUS_V2 if use_reference_script else "", collaterals=collateral_utxos, execution_units=( plutus_op.execution_cost.per_time, plutus_op.execution_cost.per_space, ), redeemer_cbor_file=plutus_op.redeemer_cbor_file, inline_datum_present=use_inline_datum, datum_file=plutus_op.datum_file if not use_inline_datum else "", ) ] tx_files_redeem = clusterlib.TxFiles( signing_key_files=[payment_addrs[1].skey_file], ) txouts_redeem = [ clusterlib.TxOut(address=payment_addrs[1].address, amount=amount), ] tx_output_redeem = cluster.build_raw_tx_bare( out_file=f"{temp_template}_step2_tx.body", txouts=txouts_redeem, tx_files=tx_files_redeem, fee=redeem_cost.fee + FEE_REDEEM_TXSIZE, script_txins=plutus_txins, ) tx_signed_redeem = cluster.sign_tx( tx_body_file=tx_output_redeem.out_file, signing_key_files=tx_files_redeem.signing_key_files, tx_name=f"{temp_template}_step2", ) dst_init_balance = cluster.get_address_balance(payment_addrs[1].address) cluster.submit_tx( tx_file=tx_signed_redeem, txins=[t.txins[0] for t in tx_output_redeem.script_txins if t.txins], ) assert ( cluster.get_address_balance(payment_addrs[1].address) == dst_init_balance + amount ), f"Incorrect balance for destination address `{payment_addrs[1].address}`" script_utxos_lovelace = [u for u in script_utxos if u.coin == clusterlib.DEFAULT_COIN] for u in script_utxos_lovelace: assert not cluster.get_utxo( txin=f"{u.utxo_hash}#{u.utxo_ix}", coins=[clusterlib.DEFAULT_COIN] ), f"Inputs were NOT spent for `{u.address}`" if use_reference_script: assert cluster.get_utxo( txin=f"{reference_utxos[0].utxo_hash}#{reference_utxos[0].utxo_ix}", coins=[clusterlib.DEFAULT_COIN], ), "Reference input was spent"
def test_lock_tx_datum_as_witness( self, cluster: clusterlib.ClusterLib, payment_addrs: List[clusterlib.AddressRecord] ): """Test unlock a Tx output with a datum as witness. Expect failure. """ __: Any # mypy workaround temp_template = common.get_test_id(cluster) amount = 2_000_000 plutus_op = PLUTUS_OP_ALWAYS_SUCCEEDS # for mypy assert plutus_op.execution_cost assert plutus_op.datum_file assert plutus_op.redeemer_cbor_file redeem_cost = plutus_common.compute_cost( execution_cost=plutus_op.execution_cost, protocol_params=cluster.get_protocol_params() ) script_utxos, collateral_utxos, __, __ = _fund_script( temp_template=temp_template, cluster=cluster, payment_addr=payment_addrs[0], dst_addr=payment_addrs[1], plutus_op=plutus_op, amount=amount, redeem_cost=redeem_cost, use_inline_datum=True, ) plutus_txins = [ clusterlib.ScriptTxIn( txins=script_utxos, script_file=plutus_op.script_file, collaterals=collateral_utxos, execution_units=( plutus_op.execution_cost.per_time, plutus_op.execution_cost.per_space, ), redeemer_cbor_file=plutus_op.redeemer_cbor_file, datum_file=plutus_op.datum_file, ) ] tx_files_redeem = clusterlib.TxFiles( signing_key_files=[payment_addrs[1].skey_file], ) txouts_redeem = [ clusterlib.TxOut(address=payment_addrs[1].address, amount=amount), ] tx_output_redeem = cluster.build_raw_tx_bare( out_file=f"{temp_template}_step2_tx.body", txouts=txouts_redeem, tx_files=tx_files_redeem, fee=redeem_cost.fee + FEE_REDEEM_TXSIZE, script_txins=plutus_txins, ) tx_signed_redeem = cluster.sign_tx( tx_body_file=tx_output_redeem.out_file, signing_key_files=tx_files_redeem.signing_key_files, tx_name=f"{temp_template}_step2", ) with pytest.raises(clusterlib.CLIError) as excinfo: cluster.submit_tx( tx_file=tx_signed_redeem, txins=[t.txins[0] for t in tx_output_redeem.script_txins if t.txins], ) err_str = str(excinfo.value) assert "NonOutputSupplimentaryDatums" in err_str, err_str
def test_reference_locking( self, cluster: clusterlib.ClusterLib, payment_addrs: List[clusterlib.AddressRecord], ): """Test locking a Tx output with a Plutus script and spending the locked UTxO. * create a Tx output with an inline datum at the script address * create a Tx output with a reference script * check that the expected amount was locked at the script address * spend the locked UTxO using the reference UTxO * check that the expected amount was spent * check that the reference UTxO was not spent """ temp_template = common.get_test_id(cluster) amount = 2_000_000 protocol_params = cluster.get_protocol_params() plutus_op = plutus_common.PlutusOp( script_file=plutus_common.ALWAYS_SUCCEEDS_PLUTUS_V2, datum_file=plutus_common.DATUM_42_TYPED, redeemer_cbor_file=plutus_common.REDEEMER_42_CBOR, execution_cost=plutus_common.ALWAYS_SUCCEEDS_V2_COST, ) # Step 1: fund the Plutus script # for mypy assert plutus_op.execution_cost assert plutus_op.datum_file script_address = cluster.gen_payment_addr( addr_name=f"{temp_template}_addr", payment_script_file=plutus_op.script_file) redeem_cost = plutus_common.compute_cost( execution_cost=plutus_op.execution_cost, protocol_params=protocol_params) # create a Tx output with a datum hash at the script address tx_files_fund = clusterlib.TxFiles( signing_key_files=[payment_addrs[0].skey_file], ) txouts_fund = [ clusterlib.TxOut( address=script_address, amount=amount + redeem_cost.fee + FEE_REDEEM_TXSIZE, inline_datum_file=plutus_op.datum_file, ), # for reference script clusterlib.TxOut( address=payment_addrs[1].address, amount=2_000_000, reference_script_file=plutus_op.script_file, ), # for collateral clusterlib.TxOut(address=payment_addrs[1].address, amount=redeem_cost.collateral), ] tx_output_fund = cluster.send_tx( src_address=payment_addrs[0].address, tx_name=f"{temp_template}_step1", txouts=txouts_fund, tx_files=tx_files_fund, # TODO: workaround for https://github.com/input-output-hk/cardano-node/issues/1892 witness_count_add=2, join_txouts=False, ) txid_fund = cluster.get_txid(tx_body_file=tx_output_fund.out_file) script_utxos = cluster.get_utxo(txin=f"{txid_fund}#0", coins=[clusterlib.DEFAULT_COIN]) reference_utxos = cluster.get_utxo(txin=f"{txid_fund}#1") collateral_utxos = cluster.get_utxo(txin=f"{txid_fund}#2") assert script_utxos, "No script UTxO" assert reference_utxos, "No reference UTxO" assert collateral_utxos, "No collateral UTxO" assert ( script_utxos[0].amount == amount + redeem_cost.fee + FEE_REDEEM_TXSIZE ), f"Incorrect balance for script address `{script_utxos[0].address}`" assert (script_utxos[0].inline_datum_hash and script_utxos[0].inline_datum ), "Inline datum not present on script UTxO" assert reference_utxos[ 0].reference_script, "Reference script not present on reference UTxO" # Step 2: spend the "locked" UTxO # for mypy assert plutus_op.execution_cost assert plutus_op.datum_file assert plutus_op.redeemer_cbor_file reference_utxo = reference_utxos[0] plutus_txins = [ clusterlib.ScriptTxIn( txins=script_utxos, reference_txin=reference_utxo, reference_type=clusterlib.ScriptTypes.PLUTUS_V2, collaterals=collateral_utxos, execution_units=( plutus_op.execution_cost.per_time, plutus_op.execution_cost.per_space, ), inline_datum_present=True, redeemer_cbor_file=plutus_op.redeemer_cbor_file, ), ] tx_files_redeem = clusterlib.TxFiles( signing_key_files=[payment_addrs[1].skey_file], ) txouts_redeem = [ clusterlib.TxOut(address=payment_addrs[1].address, amount=amount), ] tx_output_redeem = cluster.build_raw_tx_bare( out_file=f"{temp_template}_step2_tx.body", txouts=txouts_redeem, tx_files=tx_files_redeem, fee=redeem_cost.fee + FEE_REDEEM_TXSIZE, script_txins=plutus_txins, ) tx_signed_redeem = cluster.sign_tx( tx_body_file=tx_output_redeem.out_file, signing_key_files=tx_files_redeem.signing_key_files, tx_name=f"{temp_template}_step2", ) dst_init_balance = cluster.get_address_balance( payment_addrs[1].address) cluster.submit_tx( tx_file=tx_signed_redeem, txins=[ t.txins[0] for t in tx_output_redeem.script_txins if t.txins ], ) assert ( cluster.get_address_balance( payment_addrs[1].address) == dst_init_balance + amount ), f"Incorrect balance for destination address `{payment_addrs[1].address}`" script_utxos_lovelace = [ u for u in script_utxos if u.coin == clusterlib.DEFAULT_COIN ] for u in script_utxos_lovelace: assert not cluster.get_utxo( txin=f"{u.utxo_hash}#{u.utxo_ix}", coins=[clusterlib.DEFAULT_COIN ]), f"Inputs were NOT spent for `{u.address}`" assert cluster.get_utxo( txin=f"{reference_utxo.utxo_hash}#{reference_utxo.utxo_ix}", coins=[clusterlib.DEFAULT_COIN], ), "Reference input was spent"