diff --git a/cardano_node_tests/tests/data/cost_models_list_185_330_v2_v3.json b/cardano_node_tests/tests/data/cost_models_list_185_330_v2_v3.json new file mode 100644 index 000000000..6c6b4fd0d --- /dev/null +++ b/cardano_node_tests/tests/data/cost_models_list_185_330_v2_v3.json @@ -0,0 +1,689 @@ +{ + "PlutusV1": [ + 205665, + 812, + 1, + 1, + 1000, + 571, + 0, + 1, + 1000, + 24177, + 4, + 1, + 1000, + 32, + 117366, + 10475, + 4, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 100, + 100, + 23000, + 100, + 19537, + 32, + 175354, + 32, + 46417, + 4, + 221973, + 511, + 0, + 1, + 89141, + 32, + 497525, + 14068, + 4, + 2, + 196500, + 453240, + 220, + 0, + 1, + 1, + 1000, + 28662, + 4, + 2, + 245000, + 216773, + 62, + 1, + 1060367, + 12586, + 1, + 208512, + 421, + 1, + 187000, + 1000, + 52998, + 1, + 80436, + 32, + 43249, + 32, + 1000, + 32, + 80556, + 1, + 57667, + 4, + 1000, + 10, + 197145, + 156, + 1, + 197145, + 156, + 1, + 204924, + 473, + 1, + 208896, + 511, + 1, + 52467, + 32, + 64832, + 32, + 65493, + 32, + 22558, + 32, + 16563, + 32, + 76511, + 32, + 196500, + 453240, + 220, + 0, + 1, + 1, + 69522, + 11687, + 0, + 1, + 60091, + 32, + 196500, + 453240, + 220, + 0, + 1, + 1, + 196500, + 453240, + 220, + 0, + 1, + 1, + 806990, + 30482, + 4, + 1927926, + 82523, + 4, + 265318, + 0, + 4, + 0, + 85931, + 32, + 205665, + 812, + 1, + 1, + 41182, + 32, + 212342, + 32, + 31220, + 32, + 32696, + 32, + 43357, + 32, + 32247, + 32, + 38314, + 32, + 9462713, + 1021, + 10 + ], + "PlutusV2": [ + 205665, + 812, + 1, + 1, + 1000, + 571, + 0, + 1, + 1000, + 24177, + 4, + 1, + 1000, + 32, + 117366, + 10475, + 4, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 23000, + 100, + 100, + 100, + 23000, + 100, + 19537, + 32, + 175354, + 32, + 46417, + 4, + 221973, + 511, + 0, + 1, + 89141, + 32, + 497525, + 14068, + 4, + 2, + 196500, + 453240, + 220, + 0, + 1, + 1, + 1000, + 28662, + 4, + 2, + 245000, + 216773, + 62, + 1, + 1060367, + 12586, + 1, + 208512, + 421, + 1, + 187000, + 1000, + 52998, + 1, + 80436, + 32, + 43249, + 32, + 1000, + 32, + 80556, + 1, + 57667, + 4, + 1000, + 10, + 197145, + 156, + 1, + 197145, + 156, + 1, + 204924, + 473, + 1, + 208896, + 511, + 1, + 52467, + 32, + 64832, + 32, + 65493, + 32, + 22558, + 32, + 16563, + 32, + 76511, + 32, + 196500, + 453240, + 220, + 0, + 1, + 1, + 69522, + 11687, + 0, + 1, + 60091, + 32, + 196500, + 453240, + 220, + 0, + 1, + 1, + 196500, + 453240, + 220, + 0, + 1, + 1, + 1159724, + 392670, + 0, + 2, + 806990, + 30482, + 4, + 1927926, + 82523, + 4, + 265318, + 0, + 4, + 0, + 85931, + 32, + 205665, + 812, + 1, + 1, + 41182, + 32, + 212342, + 32, + 31220, + 32, + 32696, + 32, + 43357, + 32, + 32247, + 32, + 38314, + 32, + 35892428, + 10, + 9462713, + 1021, + 10, + 38887044, + 32947, + 10, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1 + ], + "PlutusV3": [ + 100788, + 420, + 1, + 1, + 1000, + 173, + 0, + 1, + 1000, + 59957, + 4, + 1, + 11183, + 32, + 201305, + 8356, + 4, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 16000, + 100, + 100, + 100, + 16000, + 100, + 94375, + 32, + 132994, + 32, + 61462, + 4, + 72010, + 178, + 0, + 1, + 22151, + 32, + 91189, + 769, + 4, + 2, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 1000, + 42921, + 4, + 2, + 24548, + 29498, + 38, + 1, + 898148, + 27279, + 1, + 51775, + 558, + 1, + 39184, + 1000, + 60594, + 1, + 141895, + 32, + 83150, + 32, + 15299, + 32, + 76049, + 1, + 13169, + 4, + 22100, + 10, + 28999, + 74, + 1, + 28999, + 74, + 1, + 43285, + 552, + 1, + 44749, + 541, + 1, + 33852, + 32, + 68246, + 32, + 72362, + 32, + 7243, + 32, + 7391, + 32, + 11546, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 90434, + 519, + 0, + 1, + 74433, + 32, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 1, + 85848, + 123203, + 7305, + -900, + 1716, + 549, + 57, + 85848, + 0, + 1, + 955506, + 213312, + 0, + 2, + 270652, + 22588, + 4, + 1457325, + 64566, + 4, + 20467, + 1, + 4, + 0, + 141992, + 32, + 100788, + 420, + 1, + 1, + 81663, + 32, + 59498, + 32, + 20142, + 32, + 24588, + 32, + 20744, + 32, + 25933, + 32, + 24623, + 32, + 43053543, + 10, + 53384111, + 14333, + 10, + 43574283, + 26308, + 10, + 16000, + 100, + 16000, + 100, + 962335, + 18, + 2780678, + 6, + 442008, + 1, + 52538055, + 3756, + 18, + 267929, + 18, + 76433006, + 8868, + 18, + 52948122, + 18, + 1995836, + 36, + 3227919, + 12, + 901022, + 1, + 166917843, + 4307, + 36, + 284546, + 36, + 158221314, + 26549, + 36, + 74698472, + 36, + 333849714, + 1, + 254006273, + 72, + 2174038, + 72, + 2261318, + 64571, + 4, + 207616, + 8310, + 4, + 1293828, + 28716, + 63, + 0, + 1, + 1006041, + 43623, + 251, + 0, + 1, + 100181, + 726, + 719, + 0, + 1, + 100181, + 726, + 719, + 0, + 1, + 100181, + 726, + 719, + 0, + 1, + 107878, + 680, + 0, + 1, + 95336, + 1, + 281145, + 18848, + 0, + 1, + 180194, + 159, + 1, + 1, + 158519, + 8942, + 0, + 1, + 159378, + 8813, + 0, + 1, + 107490, + 3298, + 1, + 106057, + 655, + 1, + 1964219, + 24520, + 3, + 607153, + 231697, + 53144, + 0, + 1, + 116711, + 1957, + 4, + 231883, + 10, + 1000, + 24838, + 7, + 1, + 232010, + 32, + 321837444, + 25087669, + 18, + 617887431, + 67302824, + 36, + 219951, + 9444, + 1, + 1163050, + 1470, + 1, + 194713, + 1, + 1000, + 43200, + 1 + ] +} diff --git a/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_1.plutus b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_1.plutus new file mode 100644 index 000000000..2540e0227 --- /dev/null +++ b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_1.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "expensiveDropListPolicyScript_V3_110_1", + "cborHex": "58db0101003323232223003002323001001229001a4d2290029112999ab9a330083357b00066012004601200226600e00e008264c66ae71241106d6b44726f704c697374506f6c696379008000646002002444a64666ae68d5d18018a999ab9a357460042944540045400454ccd5cd19b87357420046ae840044cc8cc010010004d5d10011aba200114a06460020024520034bd60488cd5d000119802002000a0070014820203027a4706471e540b0034805b003480b30034810b00348163003481bb00348210070034826807003482c0070034831807000006000c001" +} diff --git a/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_2.plutus b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_2.plutus new file mode 100644 index 000000000..6128398e9 --- /dev/null +++ b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_2.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "expensiveDropListPolicyScript_V3_110_2", + "cborHex": "58db0101003323232223003002323001001229001a4d2290029112999ab9a330083357b00066012004601200226600e00e008264c66ae71241106d6b44726f704c697374506f6c696379008000646002002444a64666ae68d5d18018a999ab9a357460042944540045400454ccd5cd19b87357420046ae840044cc8cc010010004d5d10011aba200114a06460020024520034bd60488cd5d000119802002000a0070014828eafe2c6778f5353580b0034805b003480b30034810b00348163003481bb00348210070034826807003482c0070034831807000006000c001" +} diff --git a/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_3.plutus b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_3.plutus new file mode 100644 index 000000000..2dd5bdf49 --- /dev/null +++ b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_3.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "expensiveDropListPolicyScript_V3_110_3", + "cborHex": "59025e0101003323232223003002323001001229001a4d2290029112999ab9a330083357b00066012004601200226600e00e008264c66ae71241106d6b44726f704c697374506f6c696379008000646002002444a64666ae68d5d18018a999ab9a357460042944540045400454ccd5cd19b87357420046ae840044cc8cc010010004d5d10011aba200114a06460020024520034bd60488cd5d000119802002000a007001483f3fffffffffffffffc07003480a3003480ab003480b3003480bb003480c3003480cb003480d3003480db003480e3003480eb003480f3003480fb003481030034810b003481130034811b003481230034812b003481330034813b003481430034814b003481530034815b003481630034816b003481730034817b003481830034818b003481930034819b003481a3003481ab003481b3003481bb003481c3003481cb003481d3003481db003481e3003481eb003481f3003481fb00348200070034820807003482100700348218070034822007003482280700348230070034823807003482400700348248070034825007003482580700348260070034826807003482700700348278070034828007003482880700348290070034829807003482a007003482a807003482b007003482b807003482c007003482c807003482d007003482d807003482e007003482e807003482f007003482f807003483000700348308070034831007003483180700348320070034832807003483300700348338070034834007003483480700348350070034835807003483600700348368070034837007003483780700000000000000000000000000c00180001" +} diff --git a/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_4.plutus b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_4.plutus new file mode 100644 index 000000000..e468ac457 --- /dev/null +++ b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_4.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "expensiveDropListPolicyScript_V3_110_4", + "cborHex": "59025e0101003323232223003002323001001229001a4d2290029112999ab9a330083357b00066012004601200226600e00e008264c66ae71241106d6b44726f704c697374506f6c696379008000646002002444a64666ae68d5d18018a999ab9a357460042944540045400454ccd5cd19b87357420046ae840044cc8cc010010004d5d10011aba200114a06460020024520034bd60488cd5d000119802002000a007001483fbfffffffffffffffc07003480a3003480ab003480b3003480bb003480c3003480cb003480d3003480db003480e3003480eb003480f3003480fb003481030034810b003481130034811b003481230034812b003481330034813b003481430034814b003481530034815b003481630034816b003481730034817b003481830034818b003481930034819b003481a3003481ab003481b3003481bb003481c3003481cb003481d3003481db003481e3003481eb003481f3003481fb00348200070034820807003482100700348218070034822007003482280700348230070034823807003482400700348248070034825007003482580700348260070034826807003482700700348278070034828007003482880700348290070034829807003482a007003482a807003482b007003482b807003482c007003482c807003482d007003482d807003482e007003482e807003482f007003482f807003483000700348308070034831007003483180700348320070034832807003483300700348338070034834007003483480700348350070034835807003483600700348368070034837007003483780700000000000000000000000000c00180001" +} diff --git a/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_5.plutus b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_5.plutus new file mode 100644 index 000000000..a95c12b50 --- /dev/null +++ b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/expensiveDropListPolicyScript_V3_110_5.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "expensiveDropListPolicyScript_V3_110_5", + "cborHex": "59025e0101003323232223003002323001001229001a4d2290029112999ab9a330083357b00066012004601200226600e00e008264c66ae71241106d6b44726f704c697374506f6c696379008000646002002444a64666ae68d5d18018a999ab9a357460042944540045400454ccd5cd19b87357420046ae840044cc8cc010010004d5d10011aba200114a06460020024520034bd60488cd5d000119802002000a0070014820202020202020202000b003480a3003480ab003480b3003480bb003480c3003480cb003480d3003480db003480e3003480eb003480f3003480fb003481030034810b003481130034811b003481230034812b003481330034813b003481430034814b003481530034815b003481630034816b003481730034817b003481830034818b003481930034819b003481a3003481ab003481b3003481bb003481c3003481cb003481d3003481db003481e3003481eb003481f3003481fb00348200070034820807003482100700348218070034822007003482280700348230070034823807003482400700348248070034825007003482580700348260070034826807003482700700348278070034828007003482880700348290070034829807003482a007003482a807003482b007003482b807003482c007003482c807003482d007003482d807003482e007003482e807003482f007003482f807003483000700348308070034831007003483180700348320070034832807003483300700348338070034834007003483480700348350070034835807003483600700348368070034837007003483780700000000000000000000000000c00180001" +} diff --git a/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/succeedingDropListPolicyScript_V3_110.plutus b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/succeedingDropListPolicyScript_V3_110.plutus new file mode 100644 index 000000000..74ecb0d93 --- /dev/null +++ b/cardano_node_tests/tests/data/plutus/v3/batch6/1.1.0/succeedingDropListPolicyScript_V3_110.plutus @@ -0,0 +1,5 @@ +{ + "type": "PlutusScriptV3", + "description": "succeedingDropListPolicyScript_V3_110", + "cborHex": "5901110101003323232223003002323001001229001a4d2290029112999ab9a330083357b00066012004601200226600e00e008264c66ae71241106d6b44726f704c697374506f6c696379008000646002002444a64666ae68d5d18018a999ab9a357460042944540045400454ccd5cd19b87357420046ae840044cc8cc010010004d5d10011aba200114a06460020024520034bd60488cd5d0001198020020008c8ca0070014800200300160070014803a00300260070014808a0038003003800a401b001800b003800a4146278006000c00e002900060018003003800a4148278006000c0000400d2016c00d202cc00d2042c00d2058c00d206ec00d208401c00d209a0180080801a416003801a418c0380001" +} diff --git a/cardano_node_tests/tests/plutus_common.py b/cardano_node_tests/tests/plutus_common.py index 810d50c93..f094baa60 100644 --- a/cardano_node_tests/tests/plutus_common.py +++ b/cardano_node_tests/tests/plutus_common.py @@ -16,6 +16,8 @@ SCRIPTS_V1_DIR = PLUTUS_DIR / "v1" SCRIPTS_V2_DIR = PLUTUS_DIR / "v2" SCRIPTS_V3_DIR = PLUTUS_DIR / "v3" +SCRIPTS_V3_BATCH6_110_DIR = SCRIPTS_V3_DIR / "batch6" / "1.1.0" + SEPC256K1_ECDSA_DIR = PLUTUS_DIR / "sepc256k1_ecdsa" SEPC256K1_SCHNORR_DIR = PLUTUS_DIR / "sepc256k1_schnorr" @@ -285,7 +287,18 @@ class PlutusScriptData: # ----- Succeeding bitwise tests ----- # +# These are used to fill in the execution costs of scripts where we don't yet +# know what the cost is. We're not currently checking the costs (and it seems +# to be difficult when the script fails anyway), so the values here don't really +# matter. + +UNKNOWN_PER_TIME = 1_000_000 +UNKNOWN_PER_SPACE = 100_000 UNKNOWN_FIXED_COST = 777_777 +UNDETERMINED_COST = ExecutionCost( + per_time=UNKNOWN_PER_TIME, per_space=UNKNOWN_PER_SPACE, fixed_cost=UNKNOWN_FIXED_COST +) + MINTING_ANDBYTESTRING_PLUTUS_V3 = SCRIPTS_V3_DIR / "succeedingAndByteStringPolicyScriptV3.plutus" MINTING_ANDBYTESTRING_V3 = PlutusScriptData( @@ -441,10 +454,6 @@ class PlutusScriptData: "failingWriteBitsPolicyScriptV3_19.plutus", ) -# We're not currently checking the costs (and it seems to be difficult when the -# script fails anyway), so the values here don't really matter. -UNDETERMINED_COST = ExecutionCost(per_time=1_000_000, per_space=100_000, fixed_cost=1234) - FAILING_MINTING_BITWISE_SCRIPTS_V3 = tuple( PlutusScriptData( @@ -464,6 +473,36 @@ class PlutusScriptData: SUCCEEDING_MINTING_RIPEMD_160_SCRIPTS_V3 = (MINTING_RIPEMD_160_V3,) +# ------ Batch 6 builtins (Plutus V3 only) ------ # + +MINTING_DROPLIST_PLUTUS_V3 = ( + SCRIPTS_V3_BATCH6_110_DIR / "succeedingDropListPolicyScript_V3_110.plutus" +) +MINTING_DROPLIST_V3 = PlutusScriptData( + script_file=MINTING_DROPLIST_PLUTUS_V3, + script_type=clusterlib.ScriptTypes.PLUTUS_V3, + execution_cost=UNDETERMINED_COST, +) + +SUCCEEDING_MINTING_BATCH6_SCRIPTS_V3 = (MINTING_DROPLIST_V3,) + +OVERSPENDING_BATCH6_SCRIPT_FILES_V3 = ( + "expensiveDropListPolicyScript_V3_110_1.plutus", + "expensiveDropListPolicyScript_V3_110_2.plutus", + "expensiveDropListPolicyScript_V3_110_3.plutus", + "expensiveDropListPolicyScript_V3_110_4.plutus", + "expensiveDropListPolicyScript_V3_110_5.plutus", +) + +OVERSPENDING_MINTING_BATCH6_SCRIPTS_V3 = tuple( + PlutusScriptData( + script_file=SCRIPTS_V3_BATCH6_110_DIR / n, + script_type=clusterlib.ScriptTypes.PLUTUS_V3, + execution_cost=UNDETERMINED_COST, + ) + for n in OVERSPENDING_BATCH6_SCRIPT_FILES_V3 +) + @dataclasses.dataclass(frozen=True, order=True) class PlutusOp: diff --git a/cardano_node_tests/tests/tests_plutus_v3/test_mint_build.py b/cardano_node_tests/tests/tests_plutus_v3/test_mint_build.py index aeee0a374..6175cbce6 100644 --- a/cardano_node_tests/tests/tests_plutus_v3/test_mint_build.py +++ b/cardano_node_tests/tests/tests_plutus_v3/test_mint_build.py @@ -1,7 +1,10 @@ """Tests for minting with Plutus using `transaction build`.""" +import enum import logging +import os import pathlib as pl +import typing as tp import allure import pytest @@ -20,6 +23,16 @@ LOGGER = logging.getLogger(__name__) DATA_DIR = pl.Path(__file__).parent.parent / "data" +UPGRADE_TESTS_STEP = int(os.environ.get("UPGRADE_TESTS_STEP") or 0) + +# Minimum protocol version required for batch5 built-in functions +BATCH5_PROT_VERSION = 10 +# Minimum protocol version required for batch6 built-in functions +BATCH6_PROT_VERSION = 11 +# Cost model length including batch5 built-in functions +BATCH5_COST_MODEL_LEN = 297 +# Cost model length including batch6 built-in functions +BATCH6_COST_MODEL_LEN = 330 pytestmark = [ common.SKIPIF_PLUTUSV3_UNUSABLE, @@ -27,8 +40,14 @@ ] +class Outcomes(enum.StrEnum): + SUCCESS = "success" + ERROR = "error" + OVERSPEND = "overspend" + + @pytest.fixture -def cluster( +def cluster_plutus( cluster_manager: cluster_management.ClusterManager, ) -> clusterlib.ClusterLib: """Mark whole governance and Plutus as "locked".""" @@ -43,29 +62,39 @@ def cluster( return cluster_obj -@pytest.fixture def update_cost_model( + cluster_obj: clusterlib.ClusterLib, cluster_manager: cluster_management.ClusterManager, - cluster: clusterlib.ClusterLib, + temp_template: str, + prot_version: int, + cost_model_len: int, ) -> None: - """Update cost model to include values for the batch5 of Plutus Core built-in functions.""" - pparams = cluster.g_query.get_protocol_params() - if len(pparams["costModels"]["PlutusV3"]) >= 297: + """Update cost model to include values for new Plutus Core built-in functions.""" + if prot_version == BATCH5_PROT_VERSION: + if cost_model_len >= BATCH5_COST_MODEL_LEN: + return + cost_proposal_file = DATA_DIR / "cost_models_list_185_297_v2_v3.json" + elif prot_version == BATCH6_PROT_VERSION: + if cost_model_len >= BATCH6_COST_MODEL_LEN: + return + cost_proposal_file = DATA_DIR / "cost_models_list_185_330_v2_v3.json" + else: + LOGGER.warning( + "Unsupported protocol version %s for updating cost model, skipping update.", + prot_version, + ) return - temp_template = common.get_test_id(cluster) - cost_proposal_file = DATA_DIR / "cost_models_list_185_297_v2_v3.json" - pool_user = common.get_registered_pool_user( name_template=temp_template, cluster_manager=cluster_manager, - cluster_obj=cluster, + cluster_obj=cluster_obj, ) governance_data = governance_setup.get_default_governance( - cluster_manager=cluster_manager, cluster_obj=cluster + cluster_manager=cluster_manager, cluster_obj=cluster_obj ) conway_common.update_cost_model( - cluster_obj=cluster, + cluster_obj=cluster_obj, name_template=temp_template, governance_data=governance_data, cost_proposal_file=cost_proposal_file, @@ -73,142 +102,288 @@ def update_cost_model( ) -class TestPlutusBatch5V3Builtins: - """Tests for batch5 of Plutus Core built-in functions.""" +def run_scenario( + cluster_obj: clusterlib.ClusterLib, + temp_template: str, + payment_addrs: list[clusterlib.AddressRecord], + plutus_v_record: plutus_common.PlutusScriptData, + outcome: Outcomes, + is_cost_model_ok: bool, + is_prot_version_ok: bool, +): + """Run an e2e test for a Plutus builtin.""" + payment_addr = payment_addrs[0] + issuer_addr = payment_addrs[1] - success_scripts = ( - *plutus_common.SUCCEEDING_MINTING_RIPEMD_160_SCRIPTS_V3, - *plutus_common.SUCCEEDING_MINTING_BITWISE_SCRIPTS_V3, + lovelace_amount = 2_000_000 + token_amount = 5 + script_fund = 10_000_000 + + minting_cost = plutus_common.compute_cost( + execution_cost=plutus_v_record.execution_cost, + protocol_params=cluster_obj.g_query.get_protocol_params(), ) - fail_scripts = plutus_common.FAILING_MINTING_BITWISE_SCRIPTS_V3 - @pytest.fixture - def payment_addrs( - self, - update_cost_model: None, # noqa: ARG002 - cluster_manager: cluster_management.ClusterManager, - cluster: clusterlib.ClusterLib, - ) -> list[clusterlib.AddressRecord]: - """Create new payment address.""" - addrs = common.get_payment_addrs( - name_template=common.get_test_id(cluster), - cluster_manager=cluster_manager, - cluster_obj=cluster, - num=2, - fund_idx=[0], - amount=700_000_000, - ) - return addrs + # Step 1: fund the token issuer and create UTXO for collaterals - def run_scenario( - self, - cluster_obj: clusterlib.ClusterLib, - payment_addrs: list[clusterlib.AddressRecord], - plutus_v_record: plutus_common.PlutusScriptData, - success_expected: bool, - ): - """Run an e2e test for a Plutus builtin.""" - temp_template = common.get_test_id(cluster_obj) + mint_utxos, collateral_utxos, _tx_output_step1 = mint_build._fund_issuer( + cluster_obj=cluster_obj, + temp_template=temp_template, + payment_addr=payment_addr, + issuer_addr=issuer_addr, + minting_cost=minting_cost, + amount=script_fund, + ) - payment_addr = payment_addrs[0] - issuer_addr = payment_addrs[1] + # Step 2: mint the "qacoin" - lovelace_amount = 2_000_000 - token_amount = 5 - script_fund = 10_000_000 + policyid = cluster_obj.g_transaction.get_policyid(plutus_v_record.script_file) + asset_name = f"qacoin{clusterlib.get_rand_str(4)}".encode().hex() + token = f"{policyid}.{asset_name}" + mint_txouts = [clusterlib.TxOut(address=issuer_addr.address, amount=token_amount, coin=token)] - minting_cost = plutus_common.compute_cost( - execution_cost=plutus_v_record.execution_cost, - protocol_params=cluster_obj.g_query.get_protocol_params(), + plutus_mint_data = [ + clusterlib.Mint( + txouts=mint_txouts, + script_file=plutus_v_record.script_file, + collaterals=collateral_utxos, + redeemer_file=plutus_common.REDEEMER_42, ) + ] - # Step 1: fund the token issuer and create UTXO for collaterals + tx_files_step2 = clusterlib.TxFiles( + signing_key_files=[issuer_addr.skey_file], + ) + txouts_step2 = [ + clusterlib.TxOut(address=issuer_addr.address, amount=lovelace_amount), + *mint_txouts, + ] - mint_utxos, collateral_utxos, _tx_output_step1 = mint_build._fund_issuer( + try: + tx_output_step2 = clusterlib_utils.build_and_submit_tx( cluster_obj=cluster_obj, - temp_template=temp_template, - payment_addr=payment_addr, - issuer_addr=issuer_addr, - minting_cost=minting_cost, - amount=script_fund, + name_template=f"{temp_template}_step2", + src_address=payment_addr.address, + build_method=clusterlib_utils.BuildMethods.BUILD, + tx_files=tx_files_step2, + txins=mint_utxos, + txouts=txouts_step2, + mint=plutus_mint_data, ) + except clusterlib.CLIError as excp: + str_excp = str(excp) + if ( + not is_prot_version_ok + and "not available in language PlutusV3 at and protocol version" in str_excp + ): + return + if (not is_cost_model_ok or outcome == Outcomes.OVERSPEND) and ( + "The machine terminated part way through evaluation due to " + "overspending the budget." in str_excp + ): + return + if outcome == Outcomes.ERROR and "The machine terminated because of an error" in str_excp: + return + raise - # Step 2: mint the "qacoin" - - policyid = cluster_obj.g_transaction.get_policyid(plutus_v_record.script_file) - asset_name = f"qacoin{clusterlib.get_rand_str(4)}".encode().hex() - token = f"{policyid}.{asset_name}" - mint_txouts = [ - clusterlib.TxOut(address=issuer_addr.address, amount=token_amount, coin=token) - ] - - plutus_mint_data = [ - clusterlib.Mint( - txouts=mint_txouts, - script_file=plutus_v_record.script_file, - collaterals=collateral_utxos, - redeemer_file=plutus_common.REDEEMER_42, - ) - ] + out_utxos = cluster_obj.g_query.get_utxo(tx_raw_output=tx_output_step2) + token_utxo = clusterlib.filter_utxos(utxos=out_utxos, address=issuer_addr.address, coin=token) + assert token_utxo and token_utxo[0].amount == token_amount, "The token was not minted" - tx_files_step2 = clusterlib.TxFiles( - signing_key_files=[issuer_addr.skey_file], - ) - txouts_step2 = [ - clusterlib.TxOut(address=issuer_addr.address, amount=lovelace_amount), - *mint_txouts, - ] - - try: - tx_output_step2 = clusterlib_utils.build_and_submit_tx( - cluster_obj=cluster_obj, - name_template=f"{temp_template}_step2", - src_address=payment_addr.address, - build_method=clusterlib_utils.BuildMethods.BUILD, - tx_files=tx_files_step2, - txins=mint_utxos, - txouts=txouts_step2, - mint=plutus_mint_data, - ) - except clusterlib.CLIError as excp: - if success_expected: - raise - if "The machine terminated because of an error" in str(excp): - return - raise - - out_utxos = cluster_obj.g_query.get_utxo(tx_raw_output=tx_output_step2) - token_utxo = clusterlib.filter_utxos( - utxos=out_utxos, address=issuer_addr.address, coin=token - ) - assert token_utxo and token_utxo[0].amount == token_amount, "The token was not minted" + +def run_plutusv3_builtins_test( + cluster_manager: cluster_management.ClusterManager, + cluster_obj: clusterlib.ClusterLib, + temp_template: str, + variant: str, + success_scripts: tp.Iterable[plutus_common.PlutusScriptData], + fail_scripts: tp.Iterable[plutus_common.PlutusScriptData], + overspend_scripts: tp.Iterable[plutus_common.PlutusScriptData], + is_cost_model_ok: bool, + is_prot_version_ok: bool, + subtests: pytest_subtests.SubTests, +): + """Run minting tests with the tested Plutus Core built-in functions.""" + payment_addrs = common.get_payment_addrs( + name_template=temp_template, + cluster_manager=cluster_manager, + cluster_obj=cluster_obj, + num=2, + fund_idx=[0], + caching_key="plutusv3_builtins_batch_testing", + amount=700_000_000, + min_amount=300_000_000, + ) + + cases = ( + (success_scripts, Outcomes.SUCCESS), + (fail_scripts, Outcomes.ERROR), + (overspend_scripts, Outcomes.OVERSPEND), + ) + + for scripts, outcome in cases: + for script in scripts: + script_stem = script.script_file.stem + with subtests.test(variant=f"{variant}_{script_stem}"): + run_scenario( + cluster_obj=cluster_obj, + temp_template=f"{temp_template}_{script_stem}", + payment_addrs=payment_addrs, + plutus_v_record=script, + outcome=outcome, + is_cost_model_ok=is_cost_model_ok, + is_prot_version_ok=is_prot_version_ok, + ) + + +class TestPlutusV3Builtins: + """Tests for new batches of Plutus Core built-in functions.""" + + batch5_success_scripts = ( + *plutus_common.SUCCEEDING_MINTING_RIPEMD_160_SCRIPTS_V3, + *plutus_common.SUCCEEDING_MINTING_BITWISE_SCRIPTS_V3, + ) + batch5_fail_scripts = plutus_common.FAILING_MINTING_BITWISE_SCRIPTS_V3 + batch5_overspend_scripts = () + + batch6_success_scripts = plutus_common.SUCCEEDING_MINTING_BATCH6_SCRIPTS_V3 + batch6_fail_scripts = () + batch6_overspend_scripts = plutus_common.OVERSPENDING_MINTING_BATCH6_SCRIPTS_V3 @allure.link(helpers.get_vcs_link()) @pytest.mark.long @pytest.mark.team_plutus + @pytest.mark.upgrade_step1 + @pytest.mark.upgrade_step2 @pytest.mark.upgrade_step3 - def test_plutusv3_builtins( + def test_plutusv3_builtins( # noqa: C901 self, - update_cost_model: None, # noqa: ARG002 - cluster: clusterlib.ClusterLib, - payment_addrs: list[clusterlib.AddressRecord], + cluster_manager: cluster_management.ClusterManager, + cluster_plutus: clusterlib.ClusterLib, subtests: pytest_subtests.SubTests, ): - """Test minting with the batch5 of Plutus Core built-in functions.""" - for script in self.success_scripts: - with subtests.test(script=script.script_file.stem): - self.run_scenario( - cluster_obj=cluster, - payment_addrs=payment_addrs, - plutus_v_record=script, - success_expected=True, - ) + """Test minting with the new batches of Plutus Core built-in functions. - for script in self.fail_scripts: - with subtests.test(script=script.script_file.stem): - self.run_scenario( - cluster_obj=cluster, - payment_addrs=payment_addrs, - plutus_v_record=script, - success_expected=False, - ) + * Query initial protocol parameters + * Run tests with the old cost model, if applicable + * Update cost model to include new built-in functions + * Run tests with the updated cost model + + Expect correct behavior (errors or success) depending on whether the cost model + includes the new built-in functions or not, and whether the protocol version supports them. + + All batches are tested in a single test as each batch needs cost model update, and it would + not be practical to update cost model multiple times in separate tests. + """ + cluster = cluster_plutus + temp_template = common.get_test_id(cluster) + + pparams_init = cluster.g_query.get_protocol_params() + cost_model_len_init = len(pparams_init["costModels"]["PlutusV3"]) + prot_version = pparams_init["protocolVersion"]["major"] + + is_batch5_cost_model_ok = cost_model_len_init >= BATCH5_COST_MODEL_LEN + is_batch5_prot_version_ok = prot_version >= BATCH5_PROT_VERSION + is_batch6_cost_model_ok = cost_model_len_init >= BATCH6_COST_MODEL_LEN + is_batch6_prot_version_ok = prot_version >= BATCH6_PROT_VERSION + + def _get_variant(batch: int) -> str: + if batch == 5: + prot_part = "prot_ok" if is_batch5_prot_version_ok else "prot_nok" + elif batch == 6: + prot_part = "prot_ok" if is_batch6_prot_version_ok else "prot_nok" + else: + err = f"Unsupported batch number {batch}" + raise ValueError(err) + + return f"batch{batch}_{prot_part}" + + # Step 1: run tests with the old cost model + + # Run tests only when the corresponding cost model isn't up-to-date, + # otherwise we would be repeating the same tests in Step 3. + + if cost_model_len_init < BATCH5_COST_MODEL_LEN: + batch5_variant_old = f"old_{_get_variant(batch=5)}" + run_plutusv3_builtins_test( + cluster_manager=cluster_manager, + cluster_obj=cluster, + temp_template=f"{temp_template}_{batch5_variant_old}", + variant=batch5_variant_old, + success_scripts=self.batch5_success_scripts, + fail_scripts=self.batch5_fail_scripts, + overspend_scripts=self.batch5_overspend_scripts, + is_cost_model_ok=is_batch5_cost_model_ok, + is_prot_version_ok=is_batch5_prot_version_ok, + subtests=subtests, + ) + + if cost_model_len_init < BATCH6_COST_MODEL_LEN: + batch6_variant_old = f"old_{_get_variant(batch=6)}" + run_plutusv3_builtins_test( + cluster_manager=cluster_manager, + cluster_obj=cluster, + temp_template=f"{temp_template}_{batch6_variant_old}", + variant=batch6_variant_old, + success_scripts=self.batch6_success_scripts, + fail_scripts=self.batch6_fail_scripts, + overspend_scripts=self.batch6_overspend_scripts, + is_cost_model_ok=is_batch6_cost_model_ok, + is_prot_version_ok=is_batch6_prot_version_ok, + subtests=subtests, + ) + + # Step 2: update cost model, if not already updated + + if UPGRADE_TESTS_STEP and UPGRADE_TESTS_STEP < 3: + LOGGER.info( + "Skipping cost model update on step %s of upgrade testing", UPGRADE_TESTS_STEP + ) + cost_model_len_updated = cost_model_len_init + else: + update_cost_model( + cluster_obj=cluster, + cluster_manager=cluster_manager, + temp_template=temp_template, + prot_version=prot_version, + cost_model_len=cost_model_len_init, + ) + cost_model_len_updated = len( + cluster.g_query.get_protocol_params()["costModels"]["PlutusV3"] + ) + if prot_version >= BATCH6_PROT_VERSION: + assert cost_model_len_updated >= BATCH6_COST_MODEL_LEN + elif prot_version >= BATCH5_PROT_VERSION: + assert cost_model_len_updated >= BATCH5_COST_MODEL_LEN + + # Step 3: run tests with the updated cost model + + if cost_model_len_updated >= BATCH5_COST_MODEL_LEN: + batch5_variant_updated = f"upd_{_get_variant(batch=5)}" + run_plutusv3_builtins_test( + cluster_manager=cluster_manager, + cluster_obj=cluster, + temp_template=f"{temp_template}_{batch5_variant_updated}", + variant=batch5_variant_updated, + success_scripts=self.batch5_success_scripts, + fail_scripts=self.batch5_fail_scripts, + overspend_scripts=self.batch5_overspend_scripts, + is_cost_model_ok=True, + is_prot_version_ok=is_batch5_prot_version_ok, + subtests=subtests, + ) + + if cost_model_len_updated >= BATCH6_COST_MODEL_LEN: + batch6_variant_updated = f"upd_{_get_variant(batch=6)}" + run_plutusv3_builtins_test( + cluster_manager=cluster_manager, + cluster_obj=cluster, + temp_template=f"{temp_template}_{batch6_variant_updated}", + variant=batch6_variant_updated, + success_scripts=self.batch6_success_scripts, + fail_scripts=self.batch6_fail_scripts, + overspend_scripts=self.batch6_overspend_scripts, + is_cost_model_ok=True, + is_prot_version_ok=is_batch6_prot_version_ok, + subtests=subtests, + )