From e8b88c4107e9126813655285a274de8088839781 Mon Sep 17 00:00:00 2001 From: Jerry Date: Fri, 2 Sep 2022 20:24:36 -0700 Subject: [PATCH] Get cost model from context --- examples/plutus/forty_two/forty_two.py | 19 +++++++++++++++---- pycardano/backend/base.py | 4 ++++ pycardano/backend/blockfrost.py | 14 +++++--------- pycardano/backend/ogmios.py | 6 ++++++ pycardano/txbuilder.py | 12 +++++++++--- test/pycardano/backend/test_ogmios.py | 1 + test/pycardano/util.py | 1 + 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/examples/plutus/forty_two/forty_two.py b/examples/plutus/forty_two/forty_two.py index ffbd3903..d89a5f82 100644 --- a/examples/plutus/forty_two/forty_two.py +++ b/examples/plutus/forty_two/forty_two.py @@ -26,7 +26,9 @@ def get_env_val(key): payment_vkey = PaymentVerificationKey.from_signing_key(payment_skey) chain_context = BlockFrostChainContext( - project_id=get_env_val("BLOCKFROST_ID"), network=NETWORK + project_id=get_env_val("BLOCKFROST_ID"), + network=NETWORK, + base_url="https://cardano-preview.blockfrost.io/api", ) @@ -67,7 +69,7 @@ def create_collateral(target_address, skey): script_hex = f.read() forty_two_script = cbor2.loads(bytes.fromhex(script_hex)) -script_hash = plutus_script_hash(forty_two_script) +script_hash = plutus_script_hash(PlutusV1Script(forty_two_script)) script_address = Address(script_hash, network=NETWORK) @@ -94,11 +96,20 @@ def create_collateral(target_address, skey): # Put integer 42 (the secret that unlocks the fund) in the redeemer. redeemer = Redeemer(RedeemerTag.SPEND, 42) -utxo_to_spend = chain_context.utxos(str(script_address))[0] +utxo_to_spend = None +for utxo in chain_context.utxos(str(script_address)): + if utxo.output.datum_hash == datum_hash(datum): + utxo_to_spend = utxo + break + +if utxo_to_spend is None: + raise Exception("Can't find utxo to spend! Please try again later.") builder = TransactionBuilder(chain_context) -builder.add_script_input(utxo_to_spend, forty_two_script, datum, redeemer) +builder.add_script_input( + utxo_to_spend, PlutusV1Script(forty_two_script), datum, redeemer +) # Send 5 ADA to taker address. The remaining ADA (~4.7) will be sent as change. take_output = TransactionOutput(taker_address, 5000000) diff --git a/pycardano/backend/base.py b/pycardano/backend/base.py index 8a562bb2..c94caa20 100644 --- a/pycardano/backend/base.py +++ b/pycardano/backend/base.py @@ -97,6 +97,10 @@ class ProtocolParameters: coins_per_utxo_byte: int = None + cost_models: Dict[str, Dict[str, int]] = None + """A dict contains cost models for Plutus. The key will be "PlutusV1", "PlutusV2", etc. + The value will be a dict of cost model parameters.""" + @typechecked class ChainContext: diff --git a/pycardano/backend/blockfrost.py b/pycardano/backend/blockfrost.py index ab864c25..0cfcb25a 100644 --- a/pycardano/backend/blockfrost.py +++ b/pycardano/backend/blockfrost.py @@ -1,4 +1,3 @@ -import argparse import os import tempfile import time @@ -28,13 +27,6 @@ __all__ = ["BlockFrostChainContext"] -def _namespace_to_dict(namespace: argparse.Namespace) -> dict: - return { - k: _namespace_to_dict(v) if isinstance(v, argparse.Namespace) else v - for k, v in vars(namespace).items() - } - - class BlockFrostChainContext(ChainContext): """A `BlockFrost `_ API wrapper for the client code to interact with. @@ -119,8 +111,12 @@ def protocol_param(self) -> ProtocolParameters: max_val_size=int(params.max_val_size), collateral_percent=int(params.collateral_percent), max_collateral_inputs=int(params.max_collateral_inputs), - coins_per_utxo_word=int(params.coins_per_utxo_word) or int(params.coins_per_utxo_size), + coins_per_utxo_word=int(params.coins_per_utxo_word) + or int(params.coins_per_utxo_size), coins_per_utxo_byte=int(params.coins_per_utxo_size), + cost_models={ + k: v.to_dict() for k, v in params.cost_models.to_dict().items() + }, ) return self._protocol_param diff --git a/pycardano/backend/ogmios.py b/pycardano/backend/ogmios.py index 2ada593e..37c5a906 100644 --- a/pycardano/backend/ogmios.py +++ b/pycardano/backend/ogmios.py @@ -121,8 +121,14 @@ def protocol_param(self) -> ProtocolParameters: "coinsPerUtxoWord", ALONZO_COINS_PER_UTXO_WORD ), coins_per_utxo_byte=result.get("coinsPerUtxoByte", 0), + cost_models=result.get("costModels", {}), ) + if "plutus:v1" in param.cost_models: + param.cost_models["PlutusV1"] = param.cost_models.pop("plutus:v1") + if "plutus:v2" in param.cost_models: + param.cost_models["PlutusV2"] = param.cost_models.pop("plutus:v2") + args = {"query": "genesisConfig"} result = self._request(method, args) param.min_utxo = result["protocolParameters"]["minUtxoValue"] diff --git a/pycardano/txbuilder.py b/pycardano/txbuilder.py index 09c4c66a..c4ad2c85 100644 --- a/pycardano/txbuilder.py +++ b/pycardano/txbuilder.py @@ -384,10 +384,16 @@ def script_data_hash(self) -> Optional[ScriptDataHash]: if self.datums or self.redeemers: cost_models = {} for s in self.all_scripts: - if isinstance(s, PlutusV1Script): - cost_models[0] = PLUTUS_V1_COST_MODEL + if isinstance(s, PlutusV1Script) or type(s) == bytes: + cost_models[0] = ( + self.context.protocol_param.cost_models.get("PlutusV1") + or PLUTUS_V1_COST_MODEL + ) if isinstance(s, PlutusV2Script): - cost_models[1] = PLUTUS_V2_COST_MODEL + cost_models[1] = ( + self.context.protocol_param.cost_models.get("PlutusV2") + or PLUTUS_V2_COST_MODEL + ) return script_data_hash( self.redeemers, list(self.datums.values()), CostModels(cost_models) ) diff --git a/test/pycardano/backend/test_ogmios.py b/test/pycardano/backend/test_ogmios.py index 6bc5fb24..3c5c7735 100644 --- a/test/pycardano/backend/test_ogmios.py +++ b/test/pycardano/backend/test_ogmios.py @@ -125,6 +125,7 @@ def test_protocol_param(self): max_collateral_inputs=5, coins_per_utxo_word=1, coins_per_utxo_byte=1, + cost_models={}, ) == self.chain_context.protocol_param ) diff --git a/test/pycardano/util.py b/test/pycardano/util.py index 475bef29..36c65892 100644 --- a/test/pycardano/util.py +++ b/test/pycardano/util.py @@ -45,6 +45,7 @@ class FixedChainContext(ChainContext): max_collateral_inputs=3, coins_per_utxo_word=34482, coins_per_utxo_byte=4310, + cost_models={}, ) _genesis_param = GenesisParameters(