From c43bda0d3676afae144db6a627ddbdba5e0f5a5b Mon Sep 17 00:00:00 2001 From: Sasha Mitchell Date: Fri, 25 Sep 2026 23:08:17 +0700 Subject: [PATCH] Parse Ogmios protocol ratios instead of evaluating them as Python. --- pycardano/backend/ogmios_v6.py | 18 ++++-- .../pycardano/backend/test_ogmios_v6_ratio.py | 56 +++++++++++++++++++ 2 files changed, 69 insertions(+), 5 deletions(-) create mode 100644 test/pycardano/backend/test_ogmios_v6_ratio.py diff --git a/pycardano/backend/ogmios_v6.py b/pycardano/backend/ogmios_v6.py index b0ff21cc..492b224f 100644 --- a/pycardano/backend/ogmios_v6.py +++ b/pycardano/backend/ogmios_v6.py @@ -162,18 +162,26 @@ def _fetch_protocol_param(self) -> ProtocolParameters: ), key_deposit=protocol_parameters.stake_credential_deposit.lovelace, pool_deposit=protocol_parameters.stake_pool_deposit.lovelace, - pool_influence=eval(protocol_parameters.stake_pool_pledge_influence), - monetary_expansion=eval(protocol_parameters.monetary_expansion), - treasury_expansion=eval(protocol_parameters.treasury_expansion), + pool_influence=self._fraction_parser( + protocol_parameters.stake_pool_pledge_influence + ), + monetary_expansion=self._fraction_parser( + protocol_parameters.monetary_expansion + ), + treasury_expansion=self._fraction_parser( + protocol_parameters.treasury_expansion + ), decentralization_param=None, # type: ignore[arg-type] extra_entropy=protocol_parameters.extra_entropy, protocol_major_version=protocol_parameters.version.get("major"), protocol_minor_version=protocol_parameters.version.get("minor"), min_utxo=None, # type: ignore[arg-type] - price_mem=eval( + price_mem=self._fraction_parser( protocol_parameters.script_execution_prices.get("memory") ), - price_step=eval(protocol_parameters.script_execution_prices.get("cpu")), + price_step=self._fraction_parser( + protocol_parameters.script_execution_prices.get("cpu") + ), max_tx_ex_mem=protocol_parameters.max_execution_units_per_transaction.get( "memory" ), diff --git a/test/pycardano/backend/test_ogmios_v6_ratio.py b/test/pycardano/backend/test_ogmios_v6_ratio.py new file mode 100644 index 00000000..2ad3b708 --- /dev/null +++ b/test/pycardano/backend/test_ogmios_v6_ratio.py @@ -0,0 +1,56 @@ +from types import SimpleNamespace +from unittest.mock import MagicMock, patch + +import pytest + +from pycardano.backend.ogmios_v6 import OgmiosV6ChainContext + + +def _ogmios_params(**overrides): + params = dict( + min_fee_constant=SimpleNamespace(lovelace=155381), + min_fee_coefficient=44, + min_stake_pool_cost=SimpleNamespace(lovelace=0), + max_block_body_size={"bytes": 65536}, + max_transaction_size={"bytes": 16384}, + max_block_header_size={"bytes": 1100}, + stake_credential_deposit=SimpleNamespace(lovelace=0), + stake_pool_deposit=SimpleNamespace(lovelace=0), + stake_pool_pledge_influence="1/10", + monetary_expansion="1/10", + treasury_expansion="1/10", + extra_entropy="neutral", + version={"major": 9, "minor": 0}, + script_execution_prices={"memory": "721/10000000", "cpu": "577/10000"}, + max_execution_units_per_transaction={"memory": 1, "cpu": 1}, + max_execution_units_per_block={"memory": 1, "cpu": 1}, + max_value_size={"bytes": 4000}, + collateral_percentage=150, + max_collateral_inputs=3, + min_utxo_deposit_coefficient=4310, + plutus_cost_models={}, + max_ref_script_size={"bytes": 200000}, + min_fee_ref_scripts=None, + ) + params.update(overrides) + return SimpleNamespace(**params) + + +def _fetch(params): + ctx = OgmiosV6ChainContext() + client = MagicMock() + client.query_protocol_parameters.execute.return_value = (params, None) + client.__enter__.return_value = client + with patch("pycardano.backend.ogmios_v6.OgmiosClient", return_value=client): + return ctx._fetch_protocol_param() + + +def test_protocol_ratio_rejects_a_python_expression(): + with pytest.raises(ValueError): + _fetch(_ogmios_params(monetary_expansion="1+1")) + + +def test_protocol_ratio_parses_a_fraction(): + parsed = _fetch(_ogmios_params()) + assert parsed.monetary_expansion == 0.1 + assert parsed.price_mem == 721 / 10000000