From 62b1b932f91df0c4bc61fe137676f98f71896d49 Mon Sep 17 00:00:00 2001 From: KtorZ Date: Fri, 9 Aug 2024 19:04:25 +0200 Subject: [PATCH] Write down first e2e script context test for v3. --- crates/uplc/src/tx/eval.rs | 11 +- .../script_context/v3/.gitignore | 8 + .../script_context/v3/README.md | 191 ++++++++++++++++++ .../script_context/v3/aiken.lock | 7 + .../script_context/v3/aiken.toml | 5 + .../v3/ctx/spend_1/resolved_inputs.template | 1 + .../script_context/v3/ctx/spend_1/tx.template | 34 ++++ .../script_context/v3/lib/aiken | 1 + .../script_context/v3/plutus.json | 45 +++++ .../script_context/v3/test.sh | 53 +++++ .../script_context/v3/validators/spend_1.ak | 69 +++++++ 11 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 examples/acceptance_tests/script_context/v3/.gitignore create mode 100644 examples/acceptance_tests/script_context/v3/README.md create mode 100644 examples/acceptance_tests/script_context/v3/aiken.lock create mode 100644 examples/acceptance_tests/script_context/v3/aiken.toml create mode 100644 examples/acceptance_tests/script_context/v3/ctx/spend_1/resolved_inputs.template create mode 100644 examples/acceptance_tests/script_context/v3/ctx/spend_1/tx.template create mode 120000 examples/acceptance_tests/script_context/v3/lib/aiken create mode 100644 examples/acceptance_tests/script_context/v3/plutus.json create mode 100755 examples/acceptance_tests/script_context/v3/test.sh create mode 100644 examples/acceptance_tests/script_context/v3/validators/spend_1.ak diff --git a/crates/uplc/src/tx/eval.rs b/crates/uplc/src/tx/eval.rs index dc9c1a61..636fa47d 100644 --- a/crates/uplc/src/tx/eval.rs +++ b/crates/uplc/src/tx/eval.rs @@ -4,7 +4,7 @@ use super::{ Error, }; use crate::{ - ast::{FakeNamedDeBruijn, NamedDeBruijn, Program}, + ast::{Data, FakeNamedDeBruijn, NamedDeBruijn, Program}, machine::cost_model::ExBudget, tx::script_context::{DataLookupTable, ScriptVersion, TxInfoV1, TxInfoV2, TxInfoV3}, PlutusData, @@ -44,7 +44,14 @@ pub fn eval_redeemer( } .apply_data(redeemer.data.clone()) .apply_data(script_context.to_plutus_data()), - ScriptContext::V3 { .. } => program.apply_data(script_context.to_plutus_data()), + ScriptContext::V3 { .. } => { + program + // FIXME: Temporary, but needed until https://github.com/aiken-lang/aiken/pull/977 + // is implemented. + .apply_data(Data::constr(0, vec![])) + .apply_data(Data::constr(0, vec![])) + .apply_data(script_context.to_plutus_data()) + } }; let mut eval_result = if let Some(costs) = cost_mdl_opt { diff --git a/examples/acceptance_tests/script_context/v3/.gitignore b/examples/acceptance_tests/script_context/v3/.gitignore new file mode 100644 index 00000000..3d2d091c --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/.gitignore @@ -0,0 +1,8 @@ +# Aiken compilation artifacts +artifacts/ +# Aiken's project working directory +build/ +# Aiken's default documentation export +docs/ +*.cbor +*.log diff --git a/examples/acceptance_tests/script_context/v3/README.md b/examples/acceptance_tests/script_context/v3/README.md new file mode 100644 index 00000000..5dfbffc3 --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/README.md @@ -0,0 +1,191 @@ +# V3 Script Context Tests + +This project contains a few handcrafted Plutus V3 validators and transactions +whose sole purpose is to test the interpretation of the `ScriptContext` from +within an Aiken's validators. + +So validators are meant to work hand-in-hand with an associated context. +Because we can't have fully static context (since they contain the validator +and its hash), we define _templates_. + +Everything is a bit clunky, but steps have been captured in a `test.sh` script +for convenience. + +## How to use + +``` +./test.sh [VALIDATOR_TITLE] +``` + +## Test Coverage + +- Purpose + - [x] spend + - [ ] mint + - [ ] withdraw + - [ ] publish + - [ ] voting + - [ ] proposing + +- Transaction body + - [x] inputs + - reference inputs + - [x] none + - [ ] some + - outputs + - [ ] none + - [ ] some + - [x] fee + - [ ] mint + - certificates + - [ ] none + - some + - Register credential + - [ ] no deposit + - [ ] with deposit + - Unregister credential + - [ ] no deposit + - [ ] with deposit + - [ ] Delegate + - [ ] Register & delegate credential + - [ ] Register drep + - [ ] Unregister drep + - [ ] Update drep + - [ ] Register pool + - [ ] Retire pool + - [ ] Delegate CC + - [ ] Retire CC + - withdrawals + - [ ] none + - [ ] some + - [ ] validity range + - extra signatories + - [x] none + - [ ] some + - [ ] redeemers + - [ ] datums + - votes + - [ ] none + - [ ] some + - proposal procedures + - [ ] none + - [ ] some + - current treasury + - [ ] with + - [ ] without + - treasury donation + - [ ] with + - [ ] without + +- Address + - [ ] type-0 (key | key) + - [ ] type-1 (script | key) + - [ ] type-2 (key | script) + - [ ] type-3 (script | script) + - [ ] type-4 (key | ptr) + - [ ] type-5 (script | ptr) + - [ ] type-6 (key | ø) + - [x] type-7 (key | ø) + +- Value + - [x] only ada + - [ ] multi-assets + +- Output datum + - [ ] none + - [ ] hash + - [x] inline + +- Output script + - [x] none + - [ ] inline + +- Governance Action + - parameter change + - [ ] with action id + - [ ] without action id + - hardfork initiation + - [ ] with action id + - [ ] without action id + - treasuryWithdrawals + - [ ] with constitution + - [ ] without constitution + - no confidence + - [ ] with action id + - [ ] without action id + - update committee + - [ ] with action id + - [ ] without action id + - new constitution + - [ ] with action id + - [ ] without action id + - [ ] info action + +- Vote + - [ ] No + - [ ] Yes + - [ ] Abstain + +- Voter + - [ ] CC + - [ ] DRep + - [ ] SPO + +- ChangedParameters + - [ ] 0: coin + - [ ] 1 : coin + - [ ] 2 : uint .size 4 + - [ ] 3 : uint .size 4 + - [ ] 4 : uint .size 2 + - [ ] 5 : coin + - [ ] 6 : coin + - [ ] 7 : epoch_interval + - [ ] 8 : uint .size 2 + - [ ] 9 : nonnegative_interval + - [ ] 10 : unit_interval + - [ ] 11 : unit_interval + - [ ] 16 : coin + - [ ] 17 : coin + - [ ] 18 : costmdls + - [ ] 19 : ex_unit_prices + - [ ] 20 : ex_units + - [ ] 21 : ex_units + - [ ] 22 : uint .size 4 + - [ ] 23 : uint .size 2 + - [ ] 24 : uint .size 2 + - [ ] 25 : pool_voting_thresholds + - [ ] 26 : drep_voting_thresholds + - [ ] 27 : uint .size 2 + - [ ] 28 : epoch_interval + - [ ] 29 : epoch_interval + - [ ] 30 : coin + - [ ] 31 : coin + - [ ] 32 : epoch_interval + - [ ] 33 : nonnegative_interval} + +- Constitution + - [ ] with guardrail script + - [ ] without guardrail script + +- Value + - [x] pure ada + - [ ] native assets + +- Credential + - [ ] key + - [x] script + +- Delegatee + - [ ] pool + - [ ] drep + - [ ] pool + drep + +- DRep + - [ ] key + - [ ] script + - [ ] abstain + - [ ] no confidence + +- Boundary + - [ ] closed + - [ ] open diff --git a/examples/acceptance_tests/script_context/v3/aiken.lock b/examples/acceptance_tests/script_context/v3/aiken.lock new file mode 100644 index 00000000..6e350cda --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/aiken.lock @@ -0,0 +1,7 @@ +# This file was generated by Aiken +# You typically do not need to edit this file + +requirements = [] +packages = [] + +[etags] diff --git a/examples/acceptance_tests/script_context/v3/aiken.toml b/examples/acceptance_tests/script_context/v3/aiken.toml new file mode 100644 index 00000000..58af499e --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/aiken.toml @@ -0,0 +1,5 @@ +name = "script_context/v3" +version = "0.0.0" +plutus = "v3" +license = "Apache-2.0" +description = "Aiken contracts for project 'script_context/v3'" diff --git a/examples/acceptance_tests/script_context/v3/ctx/spend_1/resolved_inputs.template b/examples/acceptance_tests/script_context/v3/ctx/spend_1/resolved_inputs.template new file mode 100644 index 00000000..c00435a2 --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/ctx/spend_1/resolved_inputs.template @@ -0,0 +1 @@ +81a300581d70{{ VALIDATOR_HASH }}011a3b9aca00028201d818{{ DATUM }} diff --git a/examples/acceptance_tests/script_context/v3/ctx/spend_1/tx.template b/examples/acceptance_tests/script_context/v3/ctx/spend_1/tx.template new file mode 100644 index 00000000..f5b64f71 --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/ctx/spend_1/tx.template @@ -0,0 +1,34 @@ +[ + { 0: + [ [h'0000000000000000000000000000000000000000000000000000000000000000', 0] + ] + + , 1: + [ [h'6011111111111111111111111111111111111111111111111111111111', 1000000000] + ] + + , 2: 42 + + , 11: h'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' + + , 13: + [ [h'0000000000000000000000000000000000000000000000000000000000000000', 0] + ] + + , 16: + [ h'6000000000000000000000000000000000000000000000000000000000', 1000000000 + ] + + , 17: 1 + }, + + { 5: [[0, 0, 121([]), [1000000, 100000000]]] + + , 7: [h'{{ VALIDATOR }}'] + + }, + + true, + + null +] diff --git a/examples/acceptance_tests/script_context/v3/lib/aiken b/examples/acceptance_tests/script_context/v3/lib/aiken new file mode 120000 index 00000000..6c2c415d --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/lib/aiken @@ -0,0 +1 @@ +../../../../../../stdlib/lib/aiken \ No newline at end of file diff --git a/examples/acceptance_tests/script_context/v3/plutus.json b/examples/acceptance_tests/script_context/v3/plutus.json new file mode 100644 index 00000000..130de03b --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/plutus.json @@ -0,0 +1,45 @@ +{ + "preamble": { + "title": "script_context/v3", + "description": "Aiken contracts for project 'script_context/v3'", + "version": "0.0.0", + "plutusVersion": "v3", + "compiler": { + "name": "Aiken", + "version": "v1.0.31-alpha+32a3d90" + }, + "license": "Apache-2.0" + }, + "validators": [ + { + "title": "spend_1.spend", + "datum": { + "title": "_tmp1", + "schema": { + "$ref": "#/definitions/Void" + } + }, + "redeemer": { + "title": "_tmp2", + "schema": { + "$ref": "#/definitions/Void" + } + }, + "compiledCode": "590cb3010100323232323232323232323232322533333300e00115332330073001300937540042a66601660146ea8008494cccccc04000454ccc020c008c028dd50008a99980618059baa00112533300932533300a3371e9112078ec148ea647cf9969446891af31939c5d57b275a2455706782c6183ef0b62f100375c602060226022602260226022602260226022602260226022601a6ea8c004c034dd50010a99980519baf3374a900119807a6127d8799f5820000000000000000000000000000000000000000000000000000000000000000000ff003300f3374a900019807a6103d87980004bd7025eb80c040c044c044c034dd50010a9980599b9649108696e707574733a200037326664646464646002002444a6664666603400626464646464646601800400266e2922010128000025333016337100069007099b80483c80400c54ccc058cdc4001a410004266e00cdc0241002800690068b299980c800899b8a4881035b5d2900005133714911035b5f2000333300800133714911025d2900005223330090090023006001223330090090020013758602e0046eb4c054004c8cdd81ba83015001374e602c0026ea800c4c94ccc05c0044cdc52441027b7d00003133714911037b5f200032323300100100322533301a00110031533301a301d0011323330090093019001337149101023a2000333009009301a001004301c0011323330090093019001337149101023a2000333009009301a001300633003003301e002301c0013371491102207d000033756006264a66602e002266e29221025b5d00003133714911035b5f2000333300600133714911015d000032233300700700230040012233300700700200137580066e292201022c2000133005375a0040022646466e2922010268270000132333001001337006e3400920013371491101270000322253330153371000490000800899191919980300319b8000548004cdc599b80002533301833710004900a0a40c02903719b8b33700002a66603066e2000520141481805206e0043370c004901019b8300148080cdc70020011bae00222223233001001005225333017001100515333017301a0011330033019001005133004301900133002002301a001223233001001003225333010300a00113371491101300000315333010337100029000099b8a489012d003300200233702900000089980299b8400148050cdc599b803370a002900a240c00066002002444a66601a66e2400920001001133300300333708004900a19b8b3370066e14009201448180004c004c034dd5180098069baa00248900132533300f001007132533301030130021323232325333010300a375a602c602e0042646464646464a66602c66e1d20043018375460380042a6646602e600260326ea800854ccc05ccdc7804244120000000000000000000000000000000000000000000000000000000000000000000153330173375e6e98010dd3299980ba5014bd6f7b6300991919800800a5eb7bdb180894ccc0780044cc07ccdd82601014000374c00697adef6c60132323232533301e33720910100002133023337609801014000374c00e00a2a66603c66e3d22100002133023337609801014000374c00e00626604666ec0dd48011ba600133006006003375660400066eb8c078008c088008c080004c8cc0040052f5bded8c044a66603a00226603c66ec130010140004c01051a3b9aca00004bd6f7b630099191919299980e99b90489000021330223376098010140004c01051a3b9aca00000051533301d3371e9101000021330223376098010140004c01051a3b9aca0000003133022337606ea4008dd4000998030030019bad301f003375c603a0046042004603e00226464a666032600660366ea8c07c00854ccc064c00cc06cdd50008a99980e9bac301f3020301c3754602060386ea804454ccc074dd6180f98101810181018101810181018101810180e1baa3010301c37540222a66603266e1d2054375a603e60406040604060386ea8c040c070dd50088a99980c99baf374c6603c66ec130012bd87a9fd8799f5820000000000000000000000000000000000000000000000000000000000000000000ffff004c0103d87980004bd6f7b630180f981018101810181018101810181018101810180e1baa3010301c37540222a66603266ebd300101a000301f3020302030203020302030203020302030203020301c3754602060386ea80445288a9980d24932657870656374205b5d203d3d20646963742e746f5f7061697273286374782e7472616e73616374696f6e2e646174756d73290016153301a491ff6578706563740a2020202020205b0a202020202020202050616972285370656e64280a202020202020202020204f75747075745265666572656e6365207b0a2020202020202020202020207472616e73616374696f6e5f69643a20232230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c0a2020202020202020202020206f75747075745f696e6465783a20302c0a202020202020202020207d2c0a2020202020202020292c0a2020202020202020766f6964292c0a2020202020205d203d3d206374782e7472616e73616374696f6e2e0972656465656d6572730016153301a49120657870656374203432203d3d206374782e7472616e73616374696f6e2e6665650016153301a4912d657870656374205b5d203d206374782e7472616e73616374696f6e2e65787472615f7369676e61746f726965730016153301a4912c657870656374205b5d203d206374782e7472616e73616374696f6e2e7265666572656e63655f696e707574730016016016301e301f001301a375400c2a660309213e657870656374207265736f6c7665645f696e7075745f76616c7565203d3d2076616c75652e66726f6d5f6c6f76656c61636528313030303030303030302900161533018491626578706563740a2020202020207472616e73616374696f6e5f6964203d3d20232230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030220016370e9001009009180d980e000980d8011bab301900130190023017001301337540060186eb8c054004c044dd5180a0011809980a00098079baa001008301100137586002601a6ea8c004c034dd50010a99805a49dd6578706563740a2020202020205370656e64696e67280a20202020202020204f75747075745265666572656e6365207b0a202020202020202020207472616e73616374696f6e5f69643a20232230303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030303030222c0a202020202020202020206f75747075745f696e6465783a20302c0a20202020202020207d2c0a2020202020202020536f6d6528766f6964292c0a20202020202029203d3d206374782e696e666f0016153300b491666578706563740a20202020202023223738656331343865613634376366393936393434363839316166333139333963356435376232373561323435353730363738326336313833656630623632663122203d3d206374782e7472616e73616374696f6e2e6964001623010001149854cc0292411856616c696461746f722072657475726e65642066616c73650013656006006006006006006006370e90000028028028028028a99802a481ff657870656374205b0a202020202020496e707574207b0a20202020202020206f75747075745f7265666572656e63653a204f75747075745265666572656e6365207b207472616e73616374696f6e5f69642c206f75747075745f696e6465783a2030207d2c0a20202020202020206f75747075743a204f7574707574207b0a20202020202020202020616464726573732c0a2020202020202020202076616c75653a207265736f6c7665645f696e7075745f76616c75652c0a20202020202020202020646174756d3a20496e6c696e65446174756d285f292c0a202020202020202020207265666572656e63655f7363726970743a204e6f6e652c0a2020202f20202020207d2c0a2020202020207d2c0a202020205d203d206374782e7472616e73616374696f6e2e696e70757473001615330044916d6578706563742041646472657373207b0a2020202020207061796d656e745f63726564656e7469616c3a2053637269707443726564656e7469616c285f292c0a2020202020207374616b655f63726564656e7469616c3a204e6f6e652c0a202020207d203d2061646472657373001615330034910b5f746d70323a20566f6964001615330024910b5f746d70313a20566f696400165734ae7155ceaab9e5573eae815d0aba257481", + "hash": "accffdf337e522a7f4d1fccd4de2099db8e4ea268a09e9896e198f21" + } + ], + "definitions": { + "Void": { + "title": "Unit", + "description": "The nullary constructor.", + "anyOf": [ + { + "dataType": "constructor", + "index": 0, + "fields": [] + } + ] + } + } +} \ No newline at end of file diff --git a/examples/acceptance_tests/script_context/v3/test.sh b/examples/acceptance_tests/script_context/v3/test.sh new file mode 100755 index 00000000..1ed0c14c --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/test.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash + +TITLE=$1 +if [ -z $TITLE ]; then + echo -e "\033[31mMissing argument: \033[1mVALIDATOR_TITLE\033[0m" + echo "" + echo -e "\033[1mUsage: \033[0m" + echo " test.sh {ACCEPTANCE_TEST}" + echo "" + echo -e "\033[1mExample: \033[0m" + echo " test.sh basic" + exit 1 +fi + +AIKEN=${2:-"cargo run -r --quiet --"} + +if ! command -v jq &> /dev/null +then + echo "\033[1mjq\033[0m missing from system but required." + exit 1 +fi + +if ! command -v cbor-diag &> /dev/null +then + echo "\033[1mcbor-diag\033[0m missing from system but required." + exit 1 +fi + +$AIKEN build --filter-traces all -t verbose +if [ $? -ne 0 ]; then + exit $? +fi + +BLUEPRINT=$(jq ".validators[] | select(.title|contains(\"$TITLE\"))" plutus.json) + +VALIDATOR_HASH=$(echo $BLUEPRINT | jq -r .hash) +VALIDATOR=$(echo $BLUEPRINT | jq -r .compiledCode) + +DATUM=$(cbor-diag --to hex --from diag <<< "h'$(cat ctx/$TITLE/datum.cbor)'") + +sed "s/{{ VALIDATOR_HASH }}/$VALIDATOR_HASH/" ctx/$TITLE/resolved_inputs.template \ + | sed "s/{{ DATUM }}/$DATUM/" \ + > ctx/$TITLE/resolved_inputs.cbor + +sed "s/{{ VALIDATOR }}/$VALIDATOR/" ctx/$TITLE/tx.template \ + | sed "s/{{ VALIDATOR_HASH }}/$VALIDATOR_HASH/" \ + | cbor-diag --to hex --from diag \ + > ctx/$TITLE/tx.cbor + +$AIKEN tx simulate \ + ctx/$TITLE/tx.cbor \ + ctx/inputs.cbor \ + ctx/$TITLE/resolved_inputs.cbor diff --git a/examples/acceptance_tests/script_context/v3/validators/spend_1.ak b/examples/acceptance_tests/script_context/v3/validators/spend_1.ak new file mode 100644 index 00000000..a25f5e6d --- /dev/null +++ b/examples/acceptance_tests/script_context/v3/validators/spend_1.ak @@ -0,0 +1,69 @@ +use aiken/dict +use aiken/transaction.{ + InlineDatum, Input, Output, OutputReference, ScriptContext, Spend, Spending, +} +use aiken/transaction/credential.{Address, ScriptCredential} +use aiken/transaction/value + +validator { + fn spend(_tmp1: Void, _tmp2: Void, ctx: ScriptContext) { + let void: Data = Void + + expect + #"78ec148ea647cf9969446891af31939c5d57b275a2455706782c6183ef0b62f1" == ctx.transaction.id + + expect + Spending( + OutputReference { + transaction_id: #"0000000000000000000000000000000000000000000000000000000000000000", + output_index: 0, + }, + Some(void), + ) == ctx.info + + trace @"inputs": ctx.transaction.inputs + + expect [ + Input { + output_reference: OutputReference { transaction_id, output_index: 0 }, + output: Output { + address, + value: resolved_input_value, + datum: InlineDatum(_), + reference_script: None, + }, + }, + ] = ctx.transaction.inputs + + expect + transaction_id == #"0000000000000000000000000000000000000000000000000000000000000000" + + expect resolved_input_value == value.from_lovelace(1000000000) + + expect Address { + payment_credential: ScriptCredential(_), + stake_credential: None, + } = address + + expect [] = ctx.transaction.reference_inputs + + expect [] = ctx.transaction.extra_signatories + + expect 42 == ctx.transaction.fee + + expect + [ + Pair(Spend( + OutputReference { + transaction_id: #"0000000000000000000000000000000000000000000000000000000000000000", + output_index: 0, + }, + ), + void), + ] == ctx.transaction.redeemers + + expect [] == dict.to_pairs(ctx.transaction.datums) + + True + } +}