From f2970a2b19345da858a967656036be23c9d57c93 Mon Sep 17 00:00:00 2001 From: Ryan Williams Date: Fri, 13 Feb 2026 18:31:42 +0000 Subject: [PATCH] init two scalus validators --- .gitignore | 1 + docker-compose.yml | 1 + scalus/.gitignore | 6 ++ scalus/build.sbt | 15 +++ scalus/compile.sh | 24 +++++ scalus/project/build.properties | 1 + scalus/project/plugins.sbt | 1 + .../src/main/scala/pv11/ArrayValidator.scala | 48 ++++++++++ scalus/src/main/scala/pv11/CompileAll.scala | 53 +++++++++++ .../src/main/scala/pv11/ExpModValidator.scala | 39 ++++++++ scripts/ga/hardfork.sh | 1 + scripts/ga/parameter.sh | 1 + scripts/helper/cardano-cli-wrapper.sh | 1 + scripts/pv11/demo-all.sh | 85 +++++++++++++++++ scripts/pv11/lock-array.sh | 91 ++++++++++++++++++ scripts/pv11/lock-expmod.sh | 92 ++++++++++++++++++ scripts/pv11/unlock-array.sh | 95 +++++++++++++++++++ scripts/pv11/unlock-expmod.sh | 95 +++++++++++++++++++ scripts/query/utxos-for-address.sh | 2 +- 19 files changed, 651 insertions(+), 1 deletion(-) create mode 100644 scalus/.gitignore create mode 100644 scalus/build.sbt create mode 100755 scalus/compile.sh create mode 100644 scalus/project/build.properties create mode 100644 scalus/project/plugins.sbt create mode 100644 scalus/src/main/scala/pv11/ArrayValidator.scala create mode 100644 scalus/src/main/scala/pv11/CompileAll.scala create mode 100644 scalus/src/main/scala/pv11/ExpModValidator.scala create mode 100755 scripts/pv11/demo-all.sh create mode 100755 scripts/pv11/lock-array.sh create mode 100755 scripts/pv11/lock-expmod.sh create mode 100755 scripts/pv11/unlock-array.sh create mode 100755 scripts/pv11/unlock-expmod.sh diff --git a/.gitignore b/.gitignore index c444f1f..0a61630 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ utilities/ node-*/ /scripts/poison /scripts/poison/ +plutus/ # Python virtual environment venv/ diff --git a/docker-compose.yml b/docker-compose.yml index 820782e..e692d15 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,6 +18,7 @@ services: - ./keys:/keys - ./txs:/txs - ./dumps:/dumps + - ./plutus:/plutus - ./utilities:/utilities logging: driver: "json-file" diff --git a/scalus/.gitignore b/scalus/.gitignore new file mode 100644 index 0000000..e82b442 --- /dev/null +++ b/scalus/.gitignore @@ -0,0 +1,6 @@ +target/ +project/target/ +project/project/ +.bsp/ +.metals/ +.idea/ diff --git a/scalus/build.sbt b/scalus/build.sbt new file mode 100644 index 0000000..cfeefc3 --- /dev/null +++ b/scalus/build.sbt @@ -0,0 +1,15 @@ +val scalusVersion = "0.15.0" + +ThisBuild / scalaVersion := "3.3.7" +ThisBuild / scalacOptions ++= Seq("-feature", "-deprecation", "-unchecked") + +addCompilerPlugin("org.scalus" %% "scalus-plugin" % scalusVersion) + +lazy val root = (project in file(".")) + .settings( + name := "pv11-validators", + libraryDependencies ++= Seq( + "org.scalus" %% "scalus" % scalusVersion, + "org.scalus" %% "scalus-cardano-ledger" % scalusVersion + ) + ) diff --git a/scalus/compile.sh b/scalus/compile.sh new file mode 100755 index 0000000..f1dbac3 --- /dev/null +++ b/scalus/compile.sh @@ -0,0 +1,24 @@ +#!/bin/bash +set -euo pipefail + +# Compile PV11 Plutus validators using Scalus 0.15.0 +# Outputs .plutus TextEnvelope JSON files to ../plutus/pv11/ + +script_dir="$(cd "$(dirname "$0")" && pwd)" +cd "$script_dir" + +if ! command -v sbt &> /dev/null; then + echo "Error: sbt not found. Install sbt to compile Scalus validators." + echo "See https://www.scala-sbt.org/download/" + exit 1 +fi + +output_dir="../plutus/pv11" +mkdir -p "$output_dir" + +echo "Compiling PV11 validators with Scalus..." +sbt "run $output_dir" + +echo "" +echo "Compiled validators:" +ls -la "$output_dir/"*.plutus diff --git a/scalus/project/build.properties b/scalus/project/build.properties new file mode 100644 index 0000000..cc68b53 --- /dev/null +++ b/scalus/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.11 diff --git a/scalus/project/plugins.sbt b/scalus/project/plugins.sbt new file mode 100644 index 0000000..8df331e --- /dev/null +++ b/scalus/project/plugins.sbt @@ -0,0 +1 @@ +// No sbt plugins required - Scalus compiler plugin is added via addCompilerPlugin in build.sbt diff --git a/scalus/src/main/scala/pv11/ArrayValidator.scala b/scalus/src/main/scala/pv11/ArrayValidator.scala new file mode 100644 index 0000000..de4e3e4 --- /dev/null +++ b/scalus/src/main/scala/pv11/ArrayValidator.scala @@ -0,0 +1,48 @@ +package pv11 + +import scalus.* +import scalus.uplc.builtin.{Data, BuiltinArray, BuiltinList} +import scalus.uplc.builtin.Data.{FromData, ToData} +import scalus.uplc.builtin.Builtins.* +import scalus.cardano.onchain.plutus.prelude.* +import scalus.cardano.onchain.plutus.v3.* + +/** CIP-138: Array Type validator + * + * Datum is a Plutus Data list of integers stored on-chain. + * Redeemer specifies an index and expected value. + * The validator converts the list to an array (O(1) access), + * looks up the element at the given index, and asserts it + * matches the expected value. + * + * Test case: Array [10, 20, 30, 40, 50], index 2, expect 30 + * + * Note: Array builtins (listToArray, indexArray) are PV11 features. + * This script may need PlutusV4 compilation depending on how the + * Cardano node exposes these builtins. + */ + +case class ArrayRedeemer(index: BigInt, expectedValue: BigInt) derives FromData, ToData + +@Compile object ArrayRedeemer + +@Compile +object ArrayValidator { + inline def validate(scData: Data): Unit = { + val ctx = scData.to[ScriptContext] + ctx.scriptInfo match + case ScriptInfo.SpendingScript(_, datum) => + val d = datum.getOrFail("Missing datum") + // Decode datum as a Plutus Data list of integers + val dataList: BuiltinList[Data] = unListData(d) + // Convert to array for O(1) indexed access (CIP-138) + val arr: BuiltinArray[Data] = listToArray(dataList) + // Decode redeemer + val r = ctx.redeemer.to[ArrayRedeemer] + // Look up element and verify + val element: Data = indexArray(arr, r.index) + val value: BigInt = unIData(element) + require(value == r.expectedValue, "Array element does not match expected value") + case _ => fail("Not a spending script") + } +} diff --git a/scalus/src/main/scala/pv11/CompileAll.scala b/scalus/src/main/scala/pv11/CompileAll.scala new file mode 100644 index 0000000..c5862cc --- /dev/null +++ b/scalus/src/main/scala/pv11/CompileAll.scala @@ -0,0 +1,53 @@ +package pv11 + +import scalus.compiler.Options +import scalus.uplc.PlutusV3 +import java.nio.file.{Files, Path, Paths} + +/** Compiles all PV11 validators and writes .plutus TextEnvelope JSON files. + * + * Usage: sbt run [output-dir] + * Default output: ../plutus/pv11/ + */ +object CompileAll { + private given Options = Options.release + + lazy val expModCompiled = PlutusV3.compile(ExpModValidator.validate) + lazy val arrayCompiled = PlutusV3.compile(ArrayValidator.validate) + + private def writeTextEnvelope(path: Path, plutusVersion: String, cborHex: String): Unit = { + val json = s"""|{ + | "type": "$plutusVersion", + | "description": "", + | "cborHex": "$cborHex" + |}""".stripMargin + Files.writeString(path, json + "\n") + } + + def main(args: Array[String]): Unit = { + val outputDir = if (args.nonEmpty) args(0) else "../plutus/pv11" + Files.createDirectories(Paths.get(outputDir)) + + println("Compiling ExpMod validator (CIP-109: Modular Exponentiation)...") + val expModHex = expModCompiled.program.doubleCborHex + writeTextEnvelope( + Paths.get(s"$outputDir/expmod-validator.plutus"), + "PlutusScriptV3", + expModHex + ) + println(s" Written to $outputDir/expmod-validator.plutus") + println(s" Script size: ${expModCompiled.program.flatEncoded.length} bytes") + + println("Compiling Array validator (CIP-138: Array Type)...") + val arrayHex = arrayCompiled.program.doubleCborHex + writeTextEnvelope( + Paths.get(s"$outputDir/array-validator.plutus"), + "PlutusScriptV3", + arrayHex + ) + println(s" Written to $outputDir/array-validator.plutus") + println(s" Script size: ${arrayCompiled.program.flatEncoded.length} bytes") + + println("Done! All validators compiled successfully.") + } +} diff --git a/scalus/src/main/scala/pv11/ExpModValidator.scala b/scalus/src/main/scala/pv11/ExpModValidator.scala new file mode 100644 index 0000000..3ccdf3e --- /dev/null +++ b/scalus/src/main/scala/pv11/ExpModValidator.scala @@ -0,0 +1,39 @@ +package pv11 + +import scalus.* +import scalus.uplc.builtin.Data +import scalus.uplc.builtin.Data.{FromData, ToData} +import scalus.uplc.builtin.Builtins.* +import scalus.cardano.onchain.plutus.prelude.* +import scalus.cardano.onchain.plutus.v3.* + +/** CIP-109: Modular Exponentiation validator + * + * Datum contains base, exponent, modulus, and expected result. + * The validator computes expModInteger(base, exponent, modulus) + * and asserts the result equals the expected value. + * + * Test case: 3^5 mod 7 = 243 mod 7 = 5 + */ + +case class ExpModDatum( + base: BigInt, + exponent: BigInt, + modulus: BigInt, + expected: BigInt +) derives FromData, ToData + +@Compile object ExpModDatum + +@Compile +object ExpModValidator { + inline def validate(scData: Data): Unit = { + val ctx = scData.to[ScriptContext] + ctx.scriptInfo match + case ScriptInfo.SpendingScript(_, datum) => + val d = datum.getOrFail("Missing datum").to[ExpModDatum] + val result = expModInteger(d.base, d.exponent, d.modulus) + require(result == d.expected, "expModInteger result does not match expected") + case _ => fail("Not a spending script") + } +} diff --git a/scripts/ga/hardfork.sh b/scripts/ga/hardfork.sh index 1d198ba..7c0f9e9 100755 --- a/scripts/ga/hardfork.sh +++ b/scripts/ga/hardfork.sh @@ -52,6 +52,7 @@ echo "Previous Hardfork GA: $PREV_GA_TX_HASH#$PREV_GA_INDEX" echo "Creating and submitting hardfork governance action." cardano_cli conway governance action create-hardfork \ + --testnet \ --governance-action-deposit $(cardano_cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ --deposit-return-stake-verification-key-file $keys_dir/stake.vkey \ --anchor-url "$METADATA_URL" \ diff --git a/scripts/ga/parameter.sh b/scripts/ga/parameter.sh index 8340efa..cba320f 100755 --- a/scripts/ga/parameter.sh +++ b/scripts/ga/parameter.sh @@ -56,6 +56,7 @@ PREV_GA_INDEX=$(echo "$GOV_STATE" | jq -r '.PParamUpdate.govActionIx') echo "Previous Protocol Param Change GA: $PREV_GA_TX_HASH#$PREV_GA_INDEX" cardano_cli conway governance action create-protocol-parameters-update \ + --testnet \ --governance-action-deposit $(cardano_cli conway query gov-state | jq -r '.currentPParams.govActionDeposit') \ --deposit-return-stake-verification-key-file $keys_dir/stake.vkey \ --anchor-url "$METADATA_URL" \ diff --git a/scripts/helper/cardano-cli-wrapper.sh b/scripts/helper/cardano-cli-wrapper.sh index 8d36f01..7866295 100755 --- a/scripts/helper/cardano-cli-wrapper.sh +++ b/scripts/helper/cardano-cli-wrapper.sh @@ -28,6 +28,7 @@ convert_to_container_path() { path=$(echo "$path" | sed "s|^$base_dir/txs|/txs|") path=$(echo "$path" | sed "s|^$base_dir/keys|/keys|") path=$(echo "$path" | sed "s|^$base_dir/dumps|/dumps|") + path=$(echo "$path" | sed "s|^$base_dir/plutus|/plutus|") fi echo "$path" } diff --git a/scripts/pv11/demo-all.sh b/scripts/pv11/demo-all.sh new file mode 100755 index 0000000..98271ac --- /dev/null +++ b/scripts/pv11/demo-all.sh @@ -0,0 +1,85 @@ +#!/bin/bash +set -euo pipefail + +# End-to-end demo of PV11 (van Rossem) hard fork features +# Runs lock/unlock for both validators sequentially + +# Get the script's directory (save before wrapper overrides script_dir) +pv11_dir="$(cd "$(dirname "$0")" && pwd)" +project_root=$(cd "$pv11_dir/../.." && pwd) + +# Source wrapper for colors +source "$pv11_dir/../helper/cardano-cli-wrapper.sh" + +echo -e "${CYAN}============================================${NC}" +echo -e "${CYAN} PV11 (van Rossem) Hard Fork Feature Demo ${NC}" +echo -e "${CYAN}============================================${NC}" +echo "" +echo "This demo will test two PV11 Plutus features:" +echo " 1. CIP-109: Modular Exponentiation (expModInteger)" +echo " 2. CIP-138: Array Type (listToArray, indexArray)" +echo "" + +# Show current UTxOs at script addresses +plutus_dir="$project_root/plutus/pv11" + +if [ -f "$plutus_dir/expmod-validator.plutus" ]; then + EXPMOD_ADDR=$(cardano_cli conway address build --payment-script-file "$plutus_dir/expmod-validator.plutus") + echo -e "${CYAN}ExpMod script address:${NC} $EXPMOD_ADDR" + echo -e "${CYAN}UTxOs at ExpMod validator:${NC}" + cardano_cli conway query utxo --address "$EXPMOD_ADDR" --out-file /dev/stdout + echo "" +fi + +if [ -f "$plutus_dir/array-validator.plutus" ]; then + ARRAY_ADDR=$(cardano_cli conway address build --payment-script-file "$plutus_dir/array-validator.plutus") + echo -e "${CYAN}Array script address:${NC} $ARRAY_ADDR" + echo -e "${CYAN}UTxOs at Array validator:${NC}" + cardano_cli conway query utxo --address "$ARRAY_ADDR" --out-file /dev/stdout + echo "" +fi + +# --- ExpMod Validator --- +echo -e "${YELLOW}--- Step 1/4: Lock ada at ExpMod Validator ---${NC}" +read -p "Press Enter to continue (or Ctrl+C to abort)..." +"$pv11_dir/lock-expmod.sh" +echo "" + +echo -e "${YELLOW}Waiting for transaction to be confirmed...${NC}" +echo "Sleeping 30 seconds for block confirmation..." +sleep 30 +echo "" + +echo -e "${YELLOW}--- Step 2/4: Unlock ADA from ExpMod Validator ---${NC}" +read -p "Press Enter to continue..." +"$pv11_dir/unlock-expmod.sh" +echo "" + +echo -e "${YELLOW}Waiting for transaction to be confirmed...${NC}" +echo "Sleeping 30 seconds for block confirmation..." +sleep 30 +echo "" + +# --- Array Validator --- +echo -e "${YELLOW}--- Step 3/4: Lock ADA at Array Validator ---${NC}" +read -p "Press Enter to continue..." +"$pv11_dir/lock-array.sh" +echo "" + +echo -e "${YELLOW}Waiting for transaction to be confirmed...${NC}" +echo "Sleeping 30 seconds for block confirmation..." +sleep 30 +echo "" + +echo -e "${YELLOW}--- Step 4/4: Unlock ADA from Array Validator ---${NC}" +read -p "Press Enter to continue..." +"$pv11_dir/unlock-array.sh" +echo "" + +echo -e "${GREEN}============================================${NC}" +echo -e "${GREEN} All PV11 feature tests completed! ${NC}" +echo -e "${GREEN}============================================${NC}" +echo "" +echo "Summary:" +echo " CIP-109 (expModInteger): 3^5 mod 7 = 5 ✓" +echo " CIP-138 (Array Type): arr[2] = 30 ✓" diff --git a/scripts/pv11/lock-array.sh b/scripts/pv11/lock-array.sh new file mode 100755 index 0000000..8fa1c97 --- /dev/null +++ b/scripts/pv11/lock-array.sh @@ -0,0 +1,91 @@ +#!/bin/bash +set -euo pipefail + +# Lock ADA at the Array validator script address +# CIP-138: Array Type (listToArray, indexArray) +# Test case: Array [10, 20, 30, 40, 50], index 2, expect 30 + +LOVELACE_AMOUNT=5000000 # 5 ADA + +# Get the script's directory and project root +script_dir=$(dirname "$0") +project_root=$(cd "$script_dir/../.." && pwd) + +# Define directory paths +keys_dir="$project_root/keys" +txs_dir="$project_root/txs/pv11" +plutus_dir="$project_root/plutus/pv11" +script_file="$plutus_dir/array-validator.plutus" + +# Create txs directory if needed +mkdir -p "$txs_dir" + +# Check prerequisites +if [ ! -f "$keys_dir/payment.addr" ]; then + echo "Error: Payment address not found: $keys_dir/payment.addr" + echo "Please run scripts/generate-keys.sh first" + exit 1 +fi + +if [ ! -f "$keys_dir/payment.skey" ]; then + echo "Error: Payment signing key not found: $keys_dir/payment.skey" + exit 1 +fi + +if [ ! -f "$script_file" ]; then + echo "Error: Array validator not found: $script_file" + echo "Run scalus/compile.sh to compile validators first." + exit 1 +fi + +# Source the cardano-cli wrapper +source "$script_dir/../helper/cardano-cli-wrapper.sh" + +# Write datum: list of integers [10, 20, 30, 40, 50] +datum_file="$txs_dir/array-datum.json" +cat > "$datum_file" << 'EOF' +{"list":[{"int":10},{"int":20},{"int":30},{"int":40},{"int":50}]} +EOF + +echo -e "${CYAN}=== Lock ADA at Array Validator (CIP-138) ===${NC}" +echo "Test case: Array [10, 20, 30, 40, 50]" +echo "Amount: $LOVELACE_AMOUNT lovelace" + +# Build script address +echo "Building script address..." +SCRIPT_ADDR=$(cardano_cli conway address build --payment-script-file "$script_file") +echo -e "Script address: ${GREEN}$SCRIPT_ADDR${NC}" + +# Get payment address and UTxO +PAYMENT_ADDR=$(cat "$keys_dir/payment.addr") +echo "Querying UTxOs..." +UTXO=$(cardano_cli conway query utxo --address "$PAYMENT_ADDR" --out-file /dev/stdout | jq -r 'keys[0]') + +if [ -z "$UTXO" ] || [ "$UTXO" = "null" ]; then + echo "Error: No UTxO found at payment address: $PAYMENT_ADDR" + exit 1 +fi +echo "Using UTxO: $UTXO" + +# Build transaction +echo "Building transaction..." +cardano_cli conway transaction build \ + --tx-in "$UTXO" \ + --tx-out "$SCRIPT_ADDR+$LOVELACE_AMOUNT" \ + --tx-out-inline-datum-file "$datum_file" \ + --change-address "$PAYMENT_ADDR" \ + --out-file "$txs_dir/lock-array.unsigned" + +# Sign transaction +echo "Signing transaction..." +cardano_cli conway transaction sign \ + --tx-body-file "$txs_dir/lock-array.unsigned" \ + --signing-key-file "$keys_dir/payment.skey" \ + --out-file "$txs_dir/lock-array.signed" + +# Submit transaction +echo "Submitting transaction..." +cardano_cli conway transaction submit --tx-file "$txs_dir/lock-array.signed" + +echo -e "${GREEN}Success!${NC} Locked $LOVELACE_AMOUNT lovelace at Array validator." +echo "Script address: $SCRIPT_ADDR" diff --git a/scripts/pv11/lock-expmod.sh b/scripts/pv11/lock-expmod.sh new file mode 100755 index 0000000..e875cc1 --- /dev/null +++ b/scripts/pv11/lock-expmod.sh @@ -0,0 +1,92 @@ +#!/bin/bash +set -euo pipefail + +# Lock ADA at the ExpMod validator script address +# CIP-109: Modular Exponentiation (expModInteger) +# Test case: 3^5 mod 7 = 243 mod 7 = 5 + +LOVELACE_AMOUNT=5000000 # 5 ADA + +# Get the script's directory and project root +script_dir=$(dirname "$0") +project_root=$(cd "$script_dir/../.." && pwd) + +# Define directory paths +keys_dir="$project_root/keys" +txs_dir="$project_root/txs/pv11" +plutus_dir="$project_root/plutus/pv11" +script_file="$plutus_dir/expmod-validator.plutus" + +# Create txs directory if needed +mkdir -p "$txs_dir" + +# Check prerequisites +if [ ! -f "$keys_dir/payment.addr" ]; then + echo "Error: Payment address not found: $keys_dir/payment.addr" + echo "Please run scripts/generate-keys.sh first" + exit 1 +fi + +if [ ! -f "$keys_dir/payment.skey" ]; then + echo "Error: Payment signing key not found: $keys_dir/payment.skey" + exit 1 +fi + +if [ ! -f "$script_file" ]; then + echo "Error: ExpMod validator not found: $script_file" + echo "Run scalus/compile.sh to compile validators first." + exit 1 +fi + +# Source the cardano-cli wrapper +source "$script_dir/../helper/cardano-cli-wrapper.sh" + +# Write datum: {base: 3, exponent: 5, modulus: 7, expected: 5} +# 3^5 mod 7 = 243 mod 7 = 5 +datum_file="$txs_dir/expmod-datum.json" +cat > "$datum_file" << 'EOF' +{"constructor":0,"fields":[{"int":3},{"int":5},{"int":7},{"int":5}]} +EOF + +echo -e "${CYAN}=== Lock ADA at ExpMod Validator (CIP-109) ===${NC}" +echo "Test case: 3^5 mod 7 = 5" +echo "Amount: $LOVELACE_AMOUNT lovelace" + +# Build script address +echo "Building script address..." +SCRIPT_ADDR=$(cardano_cli conway address build --payment-script-file "$script_file") +echo -e "Script address: ${GREEN}$SCRIPT_ADDR${NC}" + +# Get payment address and UTxO +PAYMENT_ADDR=$(cat "$keys_dir/payment.addr") +echo "Querying UTxOs..." +UTXO=$(cardano_cli conway query utxo --address "$PAYMENT_ADDR" --out-file /dev/stdout | jq -r 'keys[0]') + +if [ -z "$UTXO" ] || [ "$UTXO" = "null" ]; then + echo "Error: No UTxO found at payment address: $PAYMENT_ADDR" + exit 1 +fi +echo "Using UTxO: $UTXO" + +# Build transaction +echo "Building transaction..." +cardano_cli conway transaction build \ + --tx-in "$UTXO" \ + --tx-out "$SCRIPT_ADDR+$LOVELACE_AMOUNT" \ + --tx-out-inline-datum-file "$datum_file" \ + --change-address "$PAYMENT_ADDR" \ + --out-file "$txs_dir/lock-expmod.unsigned" + +# Sign transaction +echo "Signing transaction..." +cardano_cli conway transaction sign \ + --tx-body-file "$txs_dir/lock-expmod.unsigned" \ + --signing-key-file "$keys_dir/payment.skey" \ + --out-file "$txs_dir/lock-expmod.signed" + +# Submit transaction +echo "Submitting transaction..." +cardano_cli conway transaction submit --tx-file "$txs_dir/lock-expmod.signed" + +echo -e "${GREEN}Success!${NC} Locked $LOVELACE_AMOUNT lovelace at ExpMod validator." +echo "Script address: $SCRIPT_ADDR" diff --git a/scripts/pv11/unlock-array.sh b/scripts/pv11/unlock-array.sh new file mode 100755 index 0000000..f53bc1c --- /dev/null +++ b/scripts/pv11/unlock-array.sh @@ -0,0 +1,95 @@ +#!/bin/bash +set -euo pipefail + +# Unlock ADA from the Array validator +# CIP-138: Array Type (listToArray, indexArray) +# The validator checks that array[2] == 30 + +# Get the script's directory and project root +script_dir=$(dirname "$0") +project_root=$(cd "$script_dir/../.." && pwd) + +# Define directory paths +keys_dir="$project_root/keys" +txs_dir="$project_root/txs/pv11" +plutus_dir="$project_root/plutus/pv11" +script_file="$plutus_dir/array-validator.plutus" + +# Check prerequisites +if [ ! -f "$keys_dir/payment.addr" ]; then + echo "Error: Payment address not found: $keys_dir/payment.addr" + echo "Please run scripts/generate-keys.sh first" + exit 1 +fi + +if [ ! -f "$keys_dir/payment.skey" ]; then + echo "Error: Payment signing key not found: $keys_dir/payment.skey" + exit 1 +fi + +if [ ! -f "$script_file" ]; then + echo "Error: Array validator not found: $script_file" + echo "Run scalus/compile.sh to compile validators first." + exit 1 +fi + +# Source the cardano-cli wrapper +source "$script_dir/../helper/cardano-cli-wrapper.sh" + +echo -e "${CYAN}=== Unlock ADA from Array Validator (CIP-138) ===${NC}" + +# Build script address +SCRIPT_ADDR=$(cardano_cli conway address build --payment-script-file "$script_file") +echo -e "Script address: ${GREEN}$SCRIPT_ADDR${NC}" + +# Query script UTxO +echo "Querying script UTxOs..." +SCRIPT_UTXO=$(cardano_cli conway query utxo --address "$SCRIPT_ADDR" --out-file /dev/stdout | jq -r 'keys[0]') + +if [ -z "$SCRIPT_UTXO" ] || [ "$SCRIPT_UTXO" = "null" ]; then + echo "Error: No UTxO found at script address: $SCRIPT_ADDR" + echo "Run lock-array.sh first to lock ADA at the script." + exit 1 +fi +echo "Script UTxO: $SCRIPT_UTXO" + +# Get collateral UTxO from payment address +PAYMENT_ADDR=$(cat "$keys_dir/payment.addr") +COLLATERAL_UTXO=$(cardano_cli conway query utxo --address "$PAYMENT_ADDR" --out-file /dev/stdout | jq -r 'keys[0]') + +if [ -z "$COLLATERAL_UTXO" ] || [ "$COLLATERAL_UTXO" = "null" ]; then + echo "Error: No UTxO found for collateral at: $PAYMENT_ADDR" + exit 1 +fi +echo "Collateral UTxO: $COLLATERAL_UTXO" + +# Write redeemer: {index: 2, expectedValue: 30} +redeemer_file="$txs_dir/array-redeemer.json" +cat > "$redeemer_file" << 'EOF' +{"constructor":0,"fields":[{"int":2},{"int":30}]} +EOF + +# Build transaction +echo "Building transaction..." +cardano_cli conway transaction build \ + --tx-in "$SCRIPT_UTXO" \ + --tx-in-script-file "$script_file" \ + --tx-in-inline-datum-present \ + --tx-in-redeemer-file "$redeemer_file" \ + --tx-in-collateral "$COLLATERAL_UTXO" \ + --change-address "$PAYMENT_ADDR" \ + --out-file "$txs_dir/unlock-array.unsigned" + +# Sign transaction +echo "Signing transaction..." +cardano_cli conway transaction sign \ + --tx-body-file "$txs_dir/unlock-array.unsigned" \ + --signing-key-file "$keys_dir/payment.skey" \ + --out-file "$txs_dir/unlock-array.signed" + +# Submit transaction +echo "Submitting transaction..." +cardano_cli conway transaction submit --tx-file "$txs_dir/unlock-array.signed" + +echo -e "${GREEN}Success!${NC} Unlocked ADA from Array validator." +echo "The on-chain array[2] == 30 check passed!" diff --git a/scripts/pv11/unlock-expmod.sh b/scripts/pv11/unlock-expmod.sh new file mode 100755 index 0000000..73af506 --- /dev/null +++ b/scripts/pv11/unlock-expmod.sh @@ -0,0 +1,95 @@ +#!/bin/bash +set -euo pipefail + +# Unlock ADA from the ExpMod validator +# CIP-109: Modular Exponentiation (expModInteger) +# The validator checks that expModInteger(3, 5, 7) == 5 + +# Get the script's directory and project root +script_dir=$(dirname "$0") +project_root=$(cd "$script_dir/../.." && pwd) + +# Define directory paths +keys_dir="$project_root/keys" +txs_dir="$project_root/txs/pv11" +plutus_dir="$project_root/plutus/pv11" +script_file="$plutus_dir/expmod-validator.plutus" + +# Check prerequisites +if [ ! -f "$keys_dir/payment.addr" ]; then + echo "Error: Payment address not found: $keys_dir/payment.addr" + echo "Please run scripts/generate-keys.sh first" + exit 1 +fi + +if [ ! -f "$keys_dir/payment.skey" ]; then + echo "Error: Payment signing key not found: $keys_dir/payment.skey" + exit 1 +fi + +if [ ! -f "$script_file" ]; then + echo "Error: ExpMod validator not found: $script_file" + echo "Run scalus/compile.sh to compile validators first." + exit 1 +fi + +# Source the cardano-cli wrapper +source "$script_dir/../helper/cardano-cli-wrapper.sh" + +echo -e "${CYAN}=== Unlock ADA from ExpMod Validator (CIP-109) ===${NC}" + +# Build script address +SCRIPT_ADDR=$(cardano_cli conway address build --payment-script-file "$script_file") +echo -e "Script address: ${GREEN}$SCRIPT_ADDR${NC}" + +# Query script UTxO +echo "Querying script UTxOs..." +SCRIPT_UTXO=$(cardano_cli conway query utxo --address "$SCRIPT_ADDR" --out-file /dev/stdout | jq -r 'keys[0]') + +if [ -z "$SCRIPT_UTXO" ] || [ "$SCRIPT_UTXO" = "null" ]; then + echo "Error: No UTxO found at script address: $SCRIPT_ADDR" + echo "Run lock-expmod.sh first to lock ADA at the script." + exit 1 +fi +echo "Script UTxO: $SCRIPT_UTXO" + +# Get collateral UTxO from payment address +PAYMENT_ADDR=$(cat "$keys_dir/payment.addr") +COLLATERAL_UTXO=$(cardano_cli conway query utxo --address "$PAYMENT_ADDR" --out-file /dev/stdout | jq -r 'keys[0]') + +if [ -z "$COLLATERAL_UTXO" ] || [ "$COLLATERAL_UTXO" = "null" ]; then + echo "Error: No UTxO found for collateral at: $PAYMENT_ADDR" + exit 1 +fi +echo "Collateral UTxO: $COLLATERAL_UTXO" + +# Write redeemer (unit / empty constructor) +redeemer_file="$txs_dir/expmod-redeemer.json" +cat > "$redeemer_file" << 'EOF' +{"constructor":0,"fields":[]} +EOF + +# Build transaction +echo "Building transaction..." +cardano_cli conway transaction build \ + --tx-in "$SCRIPT_UTXO" \ + --tx-in-script-file "$script_file" \ + --tx-in-inline-datum-present \ + --tx-in-redeemer-file "$redeemer_file" \ + --tx-in-collateral "$COLLATERAL_UTXO" \ + --change-address "$PAYMENT_ADDR" \ + --out-file "$txs_dir/unlock-expmod.unsigned" + +# Sign transaction +echo "Signing transaction..." +cardano_cli conway transaction sign \ + --tx-body-file "$txs_dir/unlock-expmod.unsigned" \ + --signing-key-file "$keys_dir/payment.skey" \ + --out-file "$txs_dir/unlock-expmod.signed" + +# Submit transaction +echo "Submitting transaction..." +cardano_cli conway transaction submit --tx-file "$txs_dir/unlock-expmod.signed" + +echo -e "${GREEN}Success!${NC} Unlocked ADA from ExpMod validator." +echo "The on-chain expModInteger(3, 5, 7) == 5 check passed!" diff --git a/scripts/query/utxos-for-address.sh b/scripts/query/utxos-for-address.sh index 743b195..a5f683b 100755 --- a/scripts/query/utxos-for-address.sh +++ b/scripts/query/utxos-for-address.sh @@ -2,7 +2,7 @@ set -euo pipefail # ~~~~~~~~~~~~ CHANGE THIS ~~~~~~~~~~~~ -ADDRESS="addr_test1wz0vzkrzked85ywpsq4ffmx2etvjtnk07lvldrp3d4ht86ckfg639" +ADDRESS="addr_test1wqyr40te8gk6yj05j7x9vhl2ylwrzf83snkhrvzv5medmds6kuhju" # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Get the script's directory and project root