diff --git a/README.md b/README.md index c58ec53..1fd599d 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,7 @@ amaru run \ --network "$AMARU_NETWORK" \ --ledger-dir /srv/amaru/ledger.$AMARU_NETWORK.db \ --chain-dir /srv/amaru/chain.$AMARU_NETWORK.db \ - --era-history-file /amaru-runtime/era-history.json \ - --global-parameters-file /amaru-runtime/global-parameters.json \ + --era-history /amaru-runtime/era-history.json \ --peer-address "$AMARU_PEER" ``` @@ -87,9 +86,10 @@ The `amaru-runtime/` directory is part of the deployment contract. It must contain: - `era-history.json`: the custom testnet era history passed to - `--era-history-file`. -- `global-parameters.json`: the custom testnet consensus parameters - passed to `--global-parameters-file`. + `--era-history`. +- `global-parameters.json`: the custom testnet consensus parameters, + exported by the relay as `AMARU_GLOBAL_*` overrides for `amaru run` + (see `amaru run --help-global-parameters`). ## Published images diff --git a/docs/antithesis.md b/docs/antithesis.md index 239d7e9..e257083 100644 --- a/docs/antithesis.md +++ b/docs/antithesis.md @@ -145,8 +145,8 @@ relay entrypoint reads them from `/amaru-runtime` by default: It passes them directly to Amaru: ```text ---era-history-file /amaru-runtime/era-history.json ---global-parameters-file /amaru-runtime/global-parameters.json +--era-history /amaru-runtime/era-history.json +# global-parameters.json is exported as AMARU_GLOBAL_* (amaru run --help-global-parameters) ``` Keep these files aligned with the `testnet.yaml` and genesis files used diff --git a/docs/architecture.md b/docs/architecture.md index 1449543..88bd2c9 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -154,8 +154,8 @@ stateDiagram-v2 The relay passes deployment-provided runtime JSON to `amaru run`: ```text ---era-history-file /amaru-runtime/era-history.json ---global-parameters-file /amaru-runtime/global-parameters.json +--era-history /amaru-runtime/era-history.json +# global-parameters.json is exported as AMARU_GLOBAL_* (amaru run --help-global-parameters) ``` These files must match the custom testnet genesis/config used by the diff --git a/docs/tutorial.md b/docs/tutorial.md index 1f5247c..354ab20 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -44,8 +44,8 @@ testnets/cardano_amaru_epoch360/ The relay entrypoint passes these files to `amaru run` with: ```text ---era-history-file /amaru-runtime/era-history.json ---global-parameters-file /amaru-runtime/global-parameters.json +--era-history /amaru-runtime/era-history.json +# global-parameters.json is exported as AMARU_GLOBAL_* (amaru run --help-global-parameters) ``` Keep them aligned with the genesis/config emitted by the cardano-node diff --git a/flake.lock b/flake.lock index cd56c04..61ac73a 100644 --- a/flake.lock +++ b/flake.lock @@ -36,11 +36,11 @@ "amaru": { "flake": false, "locked": { - "lastModified": 1781023476, - "narHash": "sha256-fVxIU4kiMVyRMj3jzcO5Uqhey5rFEkIx8nGSauWmCfk=", + "lastModified": 1781285605, + "narHash": "sha256-aVzUcJEbn4e0ucS5EZV+867osDm4lIjOnvHoZe36Axo=", "owner": "lambdasistemi", "repo": "amaru", - "rev": "731b39837235178eb183f1b185c5800d8c22e44b", + "rev": "74ffb873ab776921f79b7da6ad1b52b31dbc3e42", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index 757fc33..42af9c3 100644 --- a/flake.nix +++ b/flake.nix @@ -58,7 +58,7 @@ # flake.lock per constitution Principle III. Pinned to feat/testnet-bootstrap: # upstream pragma-org/amaru main plus a minimal, upstreamable delta — # create-snapshots --targets-file/--cardano-db-dir (offline/testnet snapshots), - # runtime --era-history-file/--global-parameters-file, the testnet tvar + # runtime --era-history + AMARU_GLOBAL_* overrides, the testnet tvar # era-history sidecar fix, and short-epoch ledger/consensus guards. amaru = { url = "github:lambdasistemi/amaru/feat/testnet-bootstrap"; diff --git a/nix/checks.nix b/nix/checks.nix index 52988f8..ec7925d 100644 --- a/nix/checks.nix +++ b/nix/checks.nix @@ -400,7 +400,7 @@ in test -d "$final/chain.testnet_42.db" # nonces + bootstrap headers are baked into chain..db by # `amaru bootstrap`; the bundle ships the era-history override for - # `amaru run --era-history-file` at consume time. + # `amaru run --era-history` at consume time. test -f "$final/era-history.json" test -d "$final/ledger.testnet_42.db/live" snapshot_count=0 @@ -474,7 +474,7 @@ in # (epochLength=120) boundary end-to-end: the producer builds a bundle # via create-snapshots + bootstrap, then `amaru run` must open it and # stay alive. The custom epoch length is supplied at runtime via - # --era-history-file (the network built-in is 86400), so this is the + # --era-history (the network built-in is 86400), so this is the # gate for the runtime-testnet-parameters + short-epoch ledger fixes. antithesis-short-epoch-golden = pkgs.runCommand "antithesis-short-epoch-golden" @@ -495,7 +495,7 @@ in set +e timeout 30s amaru --with-json-traces run \ --network testnet_42 \ - --era-history-file $TMPDIR/testnet_42/era-history.json \ + --era-history $TMPDIR/testnet_42/era-history.json \ --ledger-dir $TMPDIR/testnet_42/ledger.testnet_42.db \ --chain-dir $TMPDIR/testnet_42/chain.testnet_42.db \ --listen-address 127.0.0.1:0 \ diff --git a/scripts/amaru-relay-bootstrap.sh b/scripts/amaru-relay-bootstrap.sh index 5a95088..5e435d3 100755 --- a/scripts/amaru-relay-bootstrap.sh +++ b/scripts/amaru-relay-bootstrap.sh @@ -220,10 +220,25 @@ done # the indexer sees it directly with no further wrapping. log "bundle ready at $final, exec'ing amaru run" export AMARU_LOG + +# amaru no longer accepts --global-parameters-file: for a Testnet network the +# global parameters come from individual AMARU_GLOBAL_* cli/env overrides +# (see `amaru run --help-global-parameters`), falling back to the network +# built-in otherwise. Convert the custom testnet's global-parameters.json into +# those env vars; field names map 1:1 to AMARU_GLOBAL_ +# (e.g. consensus_security_param -> AMARU_GLOBAL_CONSENSUS_SECURITY_PARAM). +if [[ -f "$runtime/global-parameters.json" ]]; then + while IFS='=' read -r _k _v; do + [[ -n "$_k" ]] && export "AMARU_GLOBAL_${_k}=${_v}" + done < <(jq -r 'to_entries[] | "\(.key | ascii_upcase)=\(.value)"' "$runtime/global-parameters.json") + log "exported AMARU_GLOBAL_* overrides from $runtime/global-parameters.json" +else + log "WARNING: $runtime/global-parameters.json not found; using network-default global parameters" +fi + exec "$AMARU_BIN" run \ --network "$AMARU_NETWORK" \ --ledger-dir "$final/ledger.$AMARU_NETWORK.db" \ --chain-dir "$final/chain.$AMARU_NETWORK.db" \ - --era-history-file "$runtime/era-history.json" \ - --global-parameters-file "$runtime/global-parameters.json" \ + --era-history "$runtime/era-history.json" \ --peer-address "$AMARU_PEER" diff --git a/scripts/bootstrap-producer.sh b/scripts/bootstrap-producer.sh index 86e73b3..67f5ffb 100755 --- a/scripts/bootstrap-producer.sh +++ b/scripts/bootstrap-producer.sh @@ -111,7 +111,7 @@ tail_phase_log() { ## amaru `bootstrap` consumes this per-snapshot sidecar for custom ## testnets (make_era_history reads history...json next to ## the snapshot dir); the same document is shipped at the bundle root -## as era-history.json so `amaru run --era-history-file` can override +## as era-history.json so `amaru run --era-history` can override ## the network default at consume time. Without it amaru defaults to ## the built-in testnet era-history (epoch_size 86400) and treats every ## short-epoch slot as still-in-epoch-0, producing wrong nonces. See @@ -434,8 +434,8 @@ phase_targets() { # Step 3: amaru create-snapshots. rc=6 on failure. # Drives the db-analyser engine against the local chain DB -# (--cardano-db-dir, so Mithril is skipped) using the explicit targets -# (--targets-file, so Koios is skipped). Materializes one snapshot dir +# (--cardano-node-db, so Mithril is skipped) using the explicit snapshot +# points (--snapshot, so Koios is skipped). Materializes one snapshot dir # per epoch under snapshots//./ with packaged bootstrap # headers, plus epoch metadata under data//epoch-snapshots/epochs/. phase_create_snapshots() { @@ -453,13 +453,24 @@ phase_create_snapshots() { ln -sfn "${CHAIN_DB}/immutable" "${cardano_db}/immutable" local rc=0 - printf '+ amaru create-snapshots (epoch %d + 2)\n' "${first_epoch}" + # amaru >= 4de2db13 replaced --targets-file with a repeated + # --snapshot "::" option (Point = "."); three + # snapshot points, derived from the targets already computed above. + local -a snapshot_args=() + while IFS= read -r _snap; do snapshot_args+=("${_snap}"); done < <( + jq -r '.[] | "--snapshot", "\(.slot).\(.hash)::\(.parent_point)"' "${UNIQUE_TMP}/targets.json" + ) + # amaru >= 4de2db13 treats --epoch as the TARGET epoch (Amaru's start point), + # expanding to the 3 prior snapshots (T-3,T-2,T-1). Our snapshots are the 3 + # latest completed epochs [first_epoch .. first_epoch+2], so target = first_epoch+3. + local target_epoch=$(( first_epoch + 3 )) + printf '+ amaru create-snapshots (target epoch %d, snapshots %d..%d)\n' "${target_epoch}" "${first_epoch}" "$(( first_epoch + 2 ))" log_phase create-snapshots amaru create-snapshots \ --network "${NETWORK}" \ - --epoch "${first_epoch}" \ + --epoch "${target_epoch}" \ --cardano-node-config-dir "${CONFIG_DIR}" \ - --cardano-db-dir "${cardano_db}" \ - --targets-file "${UNIQUE_TMP}/targets.json" \ + --cardano-node-db "${cardano_db}" \ + "${snapshot_args[@]}" \ --snapshot-dir "${snap_root}" \ --dist-dir "${dist_dir}" \ || rc=$? @@ -483,7 +494,7 @@ phase_create_snapshots() { # Step 4: era-history sidecars + bundle era-history.json. rc=6 on failure. # amaru `bootstrap` reads history...json alongside each # snapshot dir for custom testnets (make_era_history); `amaru run` later -# reads era-history.json from the bundle root via --era-history-file. +# reads era-history.json from the bundle root via --era-history. phase_era_sidecars() { local snap_root="${UNIQUE_TMP}/snapshots/${NET_LC}" local slot hash count=0 @@ -499,7 +510,7 @@ phase_era_sidecars() { printf 'no era-history sidecars written\n' >&2 exit 6 fi - # Bundle-level copy for `amaru run --era-history-file` at consume time. + # Bundle-level copy for `amaru run --era-history` at consume time. ensure_era_history_input "${UNIQUE_TMP}/era-history.json" } @@ -525,7 +536,7 @@ phase_bootstrap() { AMARU_BOOTSTRAP_CONFIG_DIR="${UNIQUE_TMP}/bootstrap-config" \ amaru bootstrap \ --network "${NETWORK}" \ - --epoch "${first_epoch}" \ + --epoch "$(( first_epoch + 3 ))" \ --ledger-dir "${ledger_dir}" \ --chain-dir "${chain_dir}" ) 2>"${logdir}/bootstrap.stderr" || rc=$? diff --git a/tests/lib/bootstrap-helpers.bash b/tests/lib/bootstrap-helpers.bash index e3147cf..2f116c7 100644 --- a/tests/lib/bootstrap-helpers.bash +++ b/tests/lib/bootstrap-helpers.bash @@ -264,10 +264,14 @@ start_amaru_run() { local extra=() if [[ -f "$bundle/era-history.json" ]]; then - extra+=(--era-history-file "$bundle/era-history.json") + extra+=(--era-history "$bundle/era-history.json") fi + # amaru replaced --global-parameters-file with individual AMARU_GLOBAL_* + # cli/env overrides; mirror the relay entrypoint by exporting them. if [[ -f "$bundle/global-parameters.json" ]]; then - extra+=(--global-parameters-file "$bundle/global-parameters.json") + while IFS='=' read -r _k _v; do + [[ -n "$_k" ]] && export "AMARU_GLOBAL_${_k}=${_v}" + done < <(jq -r 'to_entries[] | "\(.key | ascii_upcase)=\(.value)"' "$bundle/global-parameters.json") fi amaru --with-json-traces run \ diff --git a/tests/test-bootstrap-producer-history.bats b/tests/test-bootstrap-producer-history.bats index 21a8f9a..ced5f1f 100644 --- a/tests/test-bootstrap-producer-history.bats +++ b/tests/test-bootstrap-producer-history.bats @@ -74,23 +74,24 @@ cmd="\$1" shift case "\$cmd" in create-snapshots) - targets="" snapdir="" + points=() while [[ \$# -gt 0 ]]; do case "\$1" in - --targets-file) targets="\$2"; shift 2 ;; + --snapshot) points+=("\$2"); shift 2 ;; --snapshot-dir) snapdir="\$2"; shift 2 ;; *) shift ;; esac done mkdir -p "\$snapdir" - while IFS=\$'\t' read -r slot hash; do - d="\$snapdir/\$slot.\$hash" + for p in "\${points[@]}"; do + point="\${p%%::*}" + d="\$snapdir/\$point" mkdir -p "\$d/tables" : >"\$d/state" : >"\$d/tables/tvar" printf '[]\n' >"\$d/bootstrap.headers.json" - done < <(jq -r '.[] | "\(.slot)\t\(.hash)"' "\$targets") + done ;; bootstrap) ledger="" diff --git a/tests/test-bootstrap-producer-sparse-boundaries.bats b/tests/test-bootstrap-producer-sparse-boundaries.bats index ddf43dd..e344b26 100644 --- a/tests/test-bootstrap-producer-sparse-boundaries.bats +++ b/tests/test-bootstrap-producer-sparse-boundaries.bats @@ -53,22 +53,23 @@ EOF cmd="$1"; shift case "$cmd" in create-snapshots) - targets=""; snapdir="" + snapdir=""; points=() while [ "$#" -gt 0 ]; do case "$1" in - --targets-file) targets="$2"; shift 2 ;; + --snapshot) points+=("$2"); shift 2 ;; --snapshot-dir) snapdir="$2"; shift 2 ;; *) shift ;; esac done mkdir -p "$snapdir" - while IFS=$'\t' read -r slot hash; do - d="$snapdir/$slot.$hash" + for p in "${points[@]}"; do + point="${p%%::*}" + d="$snapdir/$point" mkdir -p "$d/tables" : >"$d/state" : >"$d/tables/tvar" printf '[]\n' >"$d/bootstrap.headers.json" - done < <(jq -r '.[] | "\(.slot)\t\(.hash)"' "$targets") + done ;; bootstrap) ledger=""; chain=""