diff --git a/cardano_node_tests/tests/test_scripts.py b/cardano_node_tests/tests/test_scripts.py index c255d2f8e..348a498f0 100644 --- a/cardano_node_tests/tests/test_scripts.py +++ b/cardano_node_tests/tests/test_scripts.py @@ -2170,7 +2170,7 @@ def test_script_reference_utxo( fund_amount = 4_500_000 amount = 2_000_000 - # create multisig script + # Create multisig script if script_version == "simple_v1": invalid_before = None invalid_hereafter = None @@ -2202,7 +2202,7 @@ def test_script_reference_utxo( slot_type_arg=clusterlib.MultiSlotTypeArgs.AFTER, ) - # create reference UTxO + # Create reference UTxO reference_utxo, tx_out_reference = clusterlib_utils.create_reference_utxo( temp_template=temp_template, cluster_obj=cluster, @@ -2213,12 +2213,12 @@ def test_script_reference_utxo( ) assert reference_utxo.reference_script - # create script address + # Create script address script_address = cluster.g_address.gen_payment_addr( addr_name=temp_template, payment_script_file=multisig_script ) - # send funds to script address + # Send funds to script address tx_out_to = multisig_tx( cluster_obj=cluster, temp_template=f"{temp_template}_to", @@ -2229,12 +2229,12 @@ def test_script_reference_utxo( use_build_cmd=use_build_cmd, ) - # send funds from script address + # Send funds from script address destinations = [clusterlib.TxOut(address=dst_addr.address, amount=amount)] tx_files = clusterlib.TxFiles( signing_key_files=[dst_addr.skey_file], ) - # empty `txins` means Tx inputs will be selected automatically by ClusterLib magic + # Empty `txins` means Tx inputs will be selected automatically by ClusterLib magic script_txins = [ clusterlib.ScriptTxIn( txins=[], @@ -2272,7 +2272,7 @@ def test_script_reference_utxo( invalid_before=invalid_before, ) - # check final balances + # Check final balances out_utxos = cluster.g_query.get_utxo(tx_raw_output=tx_out_from) assert ( clusterlib.filter_utxos(utxos=out_utxos, address=script_address)[0].amount @@ -2287,10 +2287,9 @@ def test_script_reference_utxo( dbsync_utils.check_tx(cluster_obj=cluster, tx_raw_output=tx_out_reference) dbsync_utils.check_tx(cluster_obj=cluster, tx_raw_output=tx_out_to) - # TODO: check reference script in db-sync (the `tx_out_from`) + dbsync_utils.check_tx(cluster_obj=cluster, tx_raw_output=tx_out_from) # check expected script type - # TODO: moved the check to the end of the test because of XFAIL if ( script_type_str == "SimpleScriptV1" and reference_utxo.reference_script["script"]["type"] == "SimpleScriptV2" diff --git a/cardano_node_tests/utils/dbsync_utils.py b/cardano_node_tests/utils/dbsync_utils.py index 962ce83a9..171f06033 100644 --- a/cardano_node_tests/utils/dbsync_utils.py +++ b/cardano_node_tests/utils/dbsync_utils.py @@ -4,6 +4,7 @@ import json import logging import time +from pathlib import Path from typing import Any from typing import Callable from typing import Dict @@ -17,6 +18,7 @@ from cardano_node_tests.utils import clusterlib_utils from cardano_node_tests.utils import configuration from cardano_node_tests.utils import dbsync_queries +from cardano_node_tests.utils import helpers LOGGER = logging.getLogger(__name__) @@ -153,6 +155,7 @@ class TxRecord(NamedTuple): collateral_outputs: List[clusterlib.UTXOData] reference_inputs: List[clusterlib.UTXOData] scripts: List[ScriptRecord] + reference_scripts: List[ScriptRecord] redeemers: List[RedeemerRecord] metadata: List[MetadataRecord] reserve: List[ADAStashRecord] @@ -555,6 +558,20 @@ def get_tx_record(txhash: str) -> TxRecord: # noqa: C901 for r in dbsync_queries.query_scripts(txhash=txhash) ] + reference_scripts = [] + if reference_inputs: + for reference_input in reference_inputs: + reference_scripts.extend( + [ + ScriptRecord( + hash=r.hash.hex(), + type=str(r.type), + serialised_size=int(r.serialised_size) if r.serialised_size else 0, + ) + for r in dbsync_queries.query_scripts(txhash=reference_input.utxo_hash) + ] + ) + redeemers = [] if txdata.last_row.redeemer_count: redeemers = [ @@ -598,6 +615,7 @@ def get_tx_record(txhash: str) -> TxRecord: # noqa: C901 collateral_outputs=collateral_outputs, reference_inputs=reference_inputs, scripts=scripts, + reference_scripts=reference_scripts, redeemers=redeemers, metadata=metadata, reserve=reserve, @@ -829,7 +847,7 @@ def _txout_has_inline_datum(txout: clusterlib.TxOut) -> bool: return False -def check_tx( +def check_tx( # noqa: C901 cluster_obj: clusterlib.ClusterLib, tx_raw_output: clusterlib.TxRawOutput, retry_num: int = 3 ) -> Optional[TxRecord]: """Check a transaction in db-sync.""" @@ -1060,6 +1078,29 @@ def check_tx( f"({tx_raw_output.required_signer_hashes} != {db_required_signer_hashes})" ) + # Check reference scripts txins + reference_script_hashes = [] + + for r in tx_raw_output.script_txins: + if r.reference_txin and r.reference_txin.reference_script: + script_file = Path(f"{helpers.get_timestamped_rand_str()}.script") + with open(script_file, "w", encoding="utf-8") as outfile: + json.dump(r.reference_txin.reference_script["script"], outfile) + + reference_script_hashes.append( + cluster_obj.g_transaction.get_policyid(script_file=script_file) + ) + + db_reference_script_hashes = {r.hash for r in response.reference_scripts if r.hash} + + # A script is added to `script` table only the first time it is seen, so the record + # can be empty for the current transaction + if db_reference_script_hashes: + assert set(reference_script_hashes).issubset(db_reference_script_hashes), ( + "Reference scripts txins don't match " + f"({set(reference_script_hashes)} != {db_reference_script_hashes})" + ) + return response