From a92e42b4a30f688dd423b194fecfadf33c00194a Mon Sep 17 00:00:00 2001 From: femi Date: Wed, 22 Jul 2026 11:53:32 +0100 Subject: [PATCH 1/2] fix(tests): fail loudly if cost model already updated Add is_cost_model_update_needed() as a standalone check, separate from update_cost_model(). It compares live cost model length against a proposal file for a caller-given set of model names and returns whether an update is still needed. update_cost_model() stays update-only, no gating logic inside it. test_update_cost_models (step2 of the upgrade test) is the only caller that had no pre-check at all. It now asserts an update is needed before proposing one, so it fails loudly instead of silently re-proposing values that don't change anything, which would hide the "cost model not yet updated" test scenario. test_update_in_pv9 and the PlutusV3 builtins test already had their own pre-checks before calling update_cost_model, so they're unaffected. --- cardano_node_tests/tests/test_node_upgrade.py | 14 +++++++++++ .../tests/tests_conway/conway_common.py | 25 +++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/cardano_node_tests/tests/test_node_upgrade.py b/cardano_node_tests/tests/test_node_upgrade.py index 96c10fc30..0c34897e0 100644 --- a/cardano_node_tests/tests/test_node_upgrade.py +++ b/cardano_node_tests/tests/test_node_upgrade.py @@ -132,6 +132,7 @@ def test_update_cost_models( Test updating Plutus cost models after node upgrade. Runs only on step 2 of upgrade testing sequence. + * Check that the cost model update is actually needed at this point * Load cost model proposal from JSON file (PlutusV2 and PlutusV3 models) * Get default governance data (DReps, committee members, pools) * Submit cost model update governance action @@ -142,6 +143,19 @@ def test_update_cost_models( cluster = cluster_singleton temp_template = common.get_test_id(cluster) cost_proposal_file = DATA_DIR / "cost_models_list_185_297_v2_v3.json" + cost_models_to_check = ("PlutusV2", "PlutusV3") + + # This step is expected to run against a cost model that is still short. If it's + # already at the proposed length, the "cost model not yet updated" scenario was + # missed, e.g. the cluster started with it already updated. + assert conway_common.is_cost_model_update_needed( + cluster_obj=cluster, + cost_proposal_file=cost_proposal_file, + cost_models_to_check=cost_models_to_check, + ), ( + "Cost model(s) already at or above the proposed length before the update. " + "The 'cost model not yet updated' test scenario was skipped." + ) governance_data = governance_setup.get_default_governance( cluster_manager=cluster_manager, cluster_obj=cluster diff --git a/cardano_node_tests/tests/tests_conway/conway_common.py b/cardano_node_tests/tests/tests_conway/conway_common.py index 909bacd35..259d0d051 100644 --- a/cardano_node_tests/tests/tests_conway/conway_common.py +++ b/cardano_node_tests/tests/tests_conway/conway_common.py @@ -510,6 +510,31 @@ def propose_pparams_update( ) +def is_cost_model_update_needed( + cluster_obj: clusterlib.ClusterLib, + cost_proposal_file: pl.Path, + cost_models_to_check: tp.Sequence[str], +) -> bool: + """Check whether any of `cost_models_to_check` is still below its proposed length. + + `cost_proposal_file` can bundle cost models that aren't the actual subject of the + calling test, e.g. carried along unchanged because the CLI needs a full file. Only + `cost_models_to_check` is compared, other cost models in the file are ignored. + + Returns: + True if at least one of `cost_models_to_check` is below its proposed length, i.e. + an update is still needed. False if all of them are already at or above it. + """ + with open(cost_proposal_file, encoding="utf-8") as fp: + cost_models_in = json.load(fp) + + live_cost_models = cluster_obj.g_query.get_protocol_params()["costModels"] + return any( + len(live_cost_models.get(name, [])) < len(cost_models_in[name]) + for name in cost_models_to_check + ) + + def update_cost_model( cluster_obj: clusterlib.ClusterLib, name_template: str, From c4bdc7cee7af9190d3704f2b7186d18ea9f914ad Mon Sep 17 00:00:00 2001 From: femi Date: Fri, 24 Jul 2026 07:53:53 +0100 Subject: [PATCH 2/2] fix(tests): sync cost model fixture, fail if no update happened cost_models_list_185_297_v2_v3.json targeted PlutusV3=297, stale since cardonnay bumped local_slow's Conway genesis to the current mainnet value (350) directly. Update the fixture to match. test_update_cost_models (step2) is the step where this update is expected to happen. If the cost model is already at the proposed length going in, that means the "cost model not yet updated" test scenario was missed, so fail loudly with a clear message instead of silently letting it slide. Verified against a real end to end upgrade test run: the cost model was still genuinely short at this point, so the real governance update ran and passed. --- .../data/cost_models_list_185_297_v2_v3.json | 69 ++++++++++++++++--- cardano_node_tests/tests/test_node_upgrade.py | 2 +- 2 files changed, 62 insertions(+), 9 deletions(-) diff --git a/cardano_node_tests/tests/data/cost_models_list_185_297_v2_v3.json b/cardano_node_tests/tests/data/cost_models_list_185_297_v2_v3.json index ea9897e61..8ffde8770 100644 --- a/cardano_node_tests/tests/data/cost_models_list_185_297_v2_v3.json +++ b/cardano_node_tests/tests/data/cost_models_list_185_297_v2_v3.json @@ -409,7 +409,7 @@ 7305, -900, 1716, - 549, + 960, 57, 85848, 0, @@ -419,9 +419,9 @@ 42921, 4, 2, - 24548, - 29498, - 38, + 30623, + 28755, + 75, 1, 898148, 27279, @@ -474,7 +474,7 @@ 7305, -900, 1716, - 549, + 960, 57, 85848, 0, @@ -490,7 +490,7 @@ 7305, -900, 1716, - 549, + 960, 57, 85848, 0, @@ -501,7 +501,7 @@ 7305, -900, 1716, - 549, + 960, 57, 85848, 0, @@ -651,6 +651,59 @@ 1, 1964219, 24520, - 3 + 3, + 607153, + 231697, + 53144, + 0, + 1, + 116711, + 1957, + 4, + 231883, + 10, + 1000, + 24838, + 7, + 1, + 232010, + 32, + 321837444, + 25087669, + 18, + 617887431, + 67302824, + 36, + 356924, + 18413, + 45, + 21, + 219951, + 9444, + 1, + 1000, + 172116, + 183150, + 6, + 24, + 21, + 213283, + 618401, + 1998, + 28258, + 1, + 1000, + 38159, + 2, + 22, + 1000, + 95933, + 1, + 1, + 11, + 1000, + 277577, + 12, + 21 ] } diff --git a/cardano_node_tests/tests/test_node_upgrade.py b/cardano_node_tests/tests/test_node_upgrade.py index 0c34897e0..312da6c39 100644 --- a/cardano_node_tests/tests/test_node_upgrade.py +++ b/cardano_node_tests/tests/test_node_upgrade.py @@ -154,7 +154,7 @@ def test_update_cost_models( cost_models_to_check=cost_models_to_check, ), ( "Cost model(s) already at or above the proposed length before the update. " - "The 'cost model not yet updated' test scenario was skipped." + "The 'cost model not yet updated' test scenario would be missed." ) governance_data = governance_setup.get_default_governance(