Skip to content

Commit d61865c

Browse files
committed
feat(plutus): add E2E tests for array builtins (CIP-0138, Batch 6)
Implement end-to-end tests for PlutusV3 array builtin functions: - indexArray: O(1) array element access - lengthOfArray: O(1) array length retrieval - listToArray: O(n) list-to-array conversion **Test Organization:** - Created TestPlutusBatch6V3Builtins class (array builtins are Plutus Core Batch 6, not Batch 5) - Follows established pattern from bitwise/RIPEMD-160 tests - Parametrized tests for all 3 array scripts - Marked as smoke tests for quick validation **Script Definitions (plutus_common.py):** - MINTING_INDEXARRAY_V3 (299 bytes) - MINTING_LENGTHOFARRAY_V3 (286 bytes) - MINTING_LISTTOARRAY_V3 (360 bytes) - All use minting policy pattern (standard for pure builtin testing) **Scripts Generated From:** - plutus-scripts-e2e PR #12 (yura/add-array-builtin-scripts branch) - Validators use hardcoded test data (no external redeemer parameters) ⚠️ **IMPORTANT: Array builtins require Protocol Version 11** Tests are currently **BLOCKED** until PV11 support is added to cardano-node-tests. Tests will skip with message: "Array builtins require PV11+ (currently not supported)" Expected timeline: PV11 support in testnet cluster beginning of next week (per Martin). Initial execution costs set to (0, 0) placeholders. Will be updated with actual measured values once PV11 cluster is available. - plutus-private#1920: Array builtin validators (implemented in plutus-scripts-e2e) - plutus-private#1921: E2E tests for array builtins (this implementation) - plutus-private#1922: Related array builtin work - CIP-0138: Array builtins specification - Plutus Core Spec: Batch 6 builtin functions - plutus-scripts-e2e PR #12: mkoura/plutus-scripts-e2e#12
1 parent 6859336 commit d61865c

File tree

5 files changed

+179
-0
lines changed

5 files changed

+179
-0
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "PlutusScriptV3",
3+
"description": "succeedingIndexArrayPolicyScriptV3",
4+
"cborHex": "585d01010032293370e900319abdb357b460050034800b003480130034801b003480230034802b0000240093263357389201126d6b496e6465784172726179506f6c69637900800526191800800914800d2f58122335740004660080080021"
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "PlutusScriptV3",
3+
"description": "succeedingLengthOfArrayPolicyScriptV3",
4+
"cborHex": "585501010032293370e90031abd9357b4600500348053003480a3003480f300013263357389201156d6b4c656e6774684f664172726179506f6c69637900800526191800800914800d2f58122335740004660080080021"
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"type": "PlutusScriptV3",
3+
"description": "succeedingListToArrayPolicyScriptV3",
4+
"cborHex": "587b01010032232993370e90041abd9001a50c99b874832004cd5ed800a40014a13370e90500319abdb0014801899319ab9c4901136d6b4c697374546f4172726179506f6c696379008005261abda3002801a419003801a412007801a41b009801a41400d8000191800800914800d2f581223357400046600800800201"
5+
}

cardano_node_tests/tests/plutus_common.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,35 @@ class PlutusScriptData:
464464

465465
SUCCEEDING_MINTING_RIPEMD_160_SCRIPTS_V3 = (MINTING_RIPEMD_160_V3,)
466466

467+
# Array builtin scripts (CIP-0138, Plutus Core Batch 6)
468+
# NOTE: Array builtins require Protocol Version 11+
469+
MINTING_INDEXARRAY_PLUTUS_V3 = SCRIPTS_V3_DIR / "succeedingIndexArrayPolicyScriptV3.plutus"
470+
MINTING_INDEXARRAY_V3 = PlutusScriptData(
471+
script_file=MINTING_INDEXARRAY_PLUTUS_V3,
472+
script_type=clusterlib.ScriptTypes.PLUTUS_V3,
473+
execution_cost=ExecutionCost(per_time=0, per_space=0, fixed_cost=UNKNOWN_FIXED_COST),
474+
)
475+
476+
MINTING_LENGTHOFARRAY_PLUTUS_V3 = SCRIPTS_V3_DIR / "succeedingLengthOfArrayPolicyScriptV3.plutus"
477+
MINTING_LENGTHOFARRAY_V3 = PlutusScriptData(
478+
script_file=MINTING_LENGTHOFARRAY_PLUTUS_V3,
479+
script_type=clusterlib.ScriptTypes.PLUTUS_V3,
480+
execution_cost=ExecutionCost(per_time=0, per_space=0, fixed_cost=UNKNOWN_FIXED_COST),
481+
)
482+
483+
MINTING_LISTTOARRAY_PLUTUS_V3 = SCRIPTS_V3_DIR / "succeedingListToArrayPolicyScriptV3.plutus"
484+
MINTING_LISTTOARRAY_V3 = PlutusScriptData(
485+
script_file=MINTING_LISTTOARRAY_PLUTUS_V3,
486+
script_type=clusterlib.ScriptTypes.PLUTUS_V3,
487+
execution_cost=ExecutionCost(per_time=0, per_space=0, fixed_cost=UNKNOWN_FIXED_COST),
488+
)
489+
490+
SUCCEEDING_MINTING_ARRAY_SCRIPTS_V3 = (
491+
MINTING_INDEXARRAY_V3,
492+
MINTING_LENGTHOFARRAY_V3,
493+
MINTING_LISTTOARRAY_V3,
494+
)
495+
467496

468497
@dataclasses.dataclass(frozen=True, order=True)
469498
class PlutusOp:

cardano_node_tests/tests/tests_plutus_v3/test_mint_build.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,138 @@ def test_plutusv3_builtins(
212212
plutus_v_record=script,
213213
success_expected=False,
214214
)
215+
216+
217+
class TestPlutusBatch6V3Builtins:
218+
"""Tests for batch6 of Plutus Core built-in functions (CIP-0138).
219+
220+
Array builtins (indexArray, lengthOfArray, listToArray) require Protocol Version 11.
221+
NOTE: These tests are blocked until PV11 support is added to cardano-node-tests.
222+
"""
223+
224+
success_scripts = plutus_common.SUCCEEDING_MINTING_ARRAY_SCRIPTS_V3
225+
226+
@pytest.fixture
227+
def skip_bootstrap(
228+
self,
229+
cluster: clusterlib.ClusterLib,
230+
) -> None:
231+
pparams = cluster.g_query.get_protocol_params()
232+
# Array builtins require PV11 - currently not supported in cardano-node-tests
233+
if pparams["protocolVersion"]["major"] < 11:
234+
pytest.skip("Array builtins require PV11+ (currently not supported in cardano-node-tests)")
235+
236+
@pytest.fixture
237+
def payment_addrs(
238+
self,
239+
skip_bootstrap: None, # noqa: ARG002
240+
cluster_manager: cluster_management.ClusterManager,
241+
cluster: clusterlib.ClusterLib,
242+
) -> list[clusterlib.AddressRecord]:
243+
"""Create new payment address."""
244+
addrs = common.get_payment_addrs(
245+
name_template=common.get_test_id(cluster),
246+
cluster_manager=cluster_manager,
247+
cluster_obj=cluster,
248+
num=2,
249+
fund_idx=[0],
250+
amount=100_000_000,
251+
)
252+
return addrs
253+
254+
def run_scenario(
255+
self,
256+
cluster_obj: clusterlib.ClusterLib,
257+
payment_addrs: list[clusterlib.AddressRecord],
258+
plutus_v_record: plutus_common.PlutusScriptData,
259+
):
260+
"""Run an e2e test for a Plutus array builtin."""
261+
temp_template = common.get_test_id(cluster_obj)
262+
263+
payment_addr = payment_addrs[0]
264+
issuer_addr = payment_addrs[1]
265+
266+
lovelace_amount = 2_000_000
267+
token_amount = 5
268+
script_fund = 10_000_000
269+
270+
minting_cost = plutus_common.compute_cost(
271+
execution_cost=plutus_v_record.execution_cost,
272+
protocol_params=cluster_obj.g_query.get_protocol_params(),
273+
)
274+
275+
# Step 1: fund the token issuer and create UTXO for collaterals
276+
277+
mint_utxos, collateral_utxos, tx_output_step1 = mint_build._fund_issuer(
278+
cluster_obj=cluster_obj,
279+
temp_template=temp_template,
280+
payment_addr=payment_addr,
281+
issuer_addr=issuer_addr,
282+
minting_cost=minting_cost,
283+
amount=script_fund,
284+
)
285+
286+
# Step 2: mint the "qacoin"
287+
288+
policyid = cluster_obj.g_transaction.get_policyid(plutus_v_record.script_file)
289+
asset_name = f"qacoin{clusterlib.get_rand_str(4)}".encode().hex()
290+
token = f"{policyid}.{asset_name}"
291+
mint_txouts = [
292+
clusterlib.TxOut(address=issuer_addr.address, amount=token_amount, coin=token)
293+
]
294+
295+
plutus_mint_data = [
296+
clusterlib.Mint(
297+
txouts=mint_txouts,
298+
script_file=plutus_v_record.script_file,
299+
collaterals=collateral_utxos,
300+
redeemer_file=plutus_common.REDEEMER_42,
301+
)
302+
]
303+
304+
tx_files_step2 = clusterlib.TxFiles(
305+
signing_key_files=[issuer_addr.skey_file],
306+
)
307+
txouts_step2 = [
308+
clusterlib.TxOut(address=issuer_addr.address, amount=lovelace_amount),
309+
*mint_txouts,
310+
]
311+
312+
tx_output_step2 = clusterlib_utils.build_and_submit_tx(
313+
cluster_obj=cluster_obj,
314+
name_template=f"{temp_template}_step2",
315+
src_address=payment_addr.address,
316+
use_build_cmd=True,
317+
tx_files=tx_files_step2,
318+
txins=mint_utxos,
319+
txouts=txouts_step2,
320+
mint=plutus_mint_data,
321+
)
322+
323+
out_utxos = cluster_obj.g_query.get_utxo(tx_raw_output=tx_output_step2)
324+
token_utxo = clusterlib.filter_utxos(
325+
utxos=out_utxos, address=issuer_addr.address, coin=token
326+
)
327+
assert token_utxo and token_utxo[0].amount == token_amount, "The token was not minted"
328+
329+
@allure.link(helpers.get_vcs_link())
330+
@pytest.mark.parametrize(
331+
"script",
332+
success_scripts,
333+
ids=(s.script_file.stem for s in success_scripts),
334+
)
335+
@pytest.mark.team_plutus
336+
@pytest.mark.smoke
337+
def test_array_builtins(
338+
self,
339+
skip_bootstrap: None, # noqa: ARG002
340+
cluster: clusterlib.ClusterLib,
341+
payment_addrs: list[clusterlib.AddressRecord],
342+
script: plutus_common.PlutusScriptData,
343+
):
344+
"""Test array builtin functions (indexArray, lengthOfArray, listToArray)."""
345+
self.run_scenario(
346+
cluster_obj=cluster,
347+
payment_addrs=payment_addrs,
348+
plutus_v_record=script,
349+
)

0 commit comments

Comments
 (0)