Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,18 @@ 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"
```

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

Expand Down
4 changes: 2 additions & 2 deletions docs/antithesis.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,14 @@
# 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";
# pragma-org/amaru main (the fork's testnet-bootstrap work is fully
# upstreamed). Pinned to a validated main commit: 5923f085 bootstraps AND
# follows locally with the epoch125 testnet profile (k*(1/f)*scale_factor
# invariant, scale_factor=5) + the --era-history/AMARU_GLOBAL_* relay CLI.
url = "github:pragma-org/amaru/5923f0858da464256e1664337b478511b6d3fcee";
flake = false;
};
};
Expand Down
7 changes: 4 additions & 3 deletions nix/checks.nix
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ in
test -d "$final/chain.testnet_42.db"
# nonces + bootstrap headers are baked into chain.<net>.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
Expand Down Expand Up @@ -441,6 +441,7 @@ in
set +e
timeout 30s amaru --with-json-traces run \
--network testnet_42 \
--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 \
Expand Down Expand Up @@ -474,7 +475,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"
Expand All @@ -495,7 +496,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 \
Expand Down
19 changes: 17 additions & 2 deletions scripts/amaru-relay-bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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_<UPPER>
# (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"
59 changes: 49 additions & 10 deletions scripts/bootstrap-producer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ tail_phase_log() {
## amaru `bootstrap` consumes this per-snapshot sidecar for custom
## testnets (make_era_history reads history.<slot>.<hash>.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
Expand Down Expand Up @@ -177,6 +177,34 @@ phase_preflight() {
exit 3
fi

# 1.B.2 custom-testnet global parameters -----------------------
# Post pragma-org/amaru#959, `amaru bootstrap` takes a Testnet network's
# GlobalParameters as AMARU_GLOBAL_* cli/env overrides and derives
# epoch_length = k*(1/f)*scale_factor. Without them it falls back to the
# network default epoch length and the snapshot import fails with
# "expected epoch N from the snapshot point, got M". Derive k, 1/f and
# scale_factor from the genesis and export them so create-snapshots and
# bootstrap (children of this process) inherit them. Harmless for built-in
# networks (amaru honours those networks' own parameters, ignoring the env).
local k active inverse scale_factor
k=$(jq -r '.securityParam // empty' "${shelley}")
active=$(jq -r '.activeSlotsCoeff // empty' "${shelley}")
if [[ "${k}" =~ ^[0-9]+$ ]] && [[ -n "${active}" ]]; then
inverse=$(jq -n --argjson f "${active}" '(1 / $f) | round')
if [[ "${inverse}" =~ ^[0-9]+$ ]] && (( inverse > 0 )) \
&& (( EPOCH_LENGTH % (k * inverse) == 0 )); then
scale_factor=$(( EPOCH_LENGTH / (k * inverse) ))
export AMARU_GLOBAL_CONSENSUS_SECURITY_PARAM="${k}"
export AMARU_GLOBAL_ACTIVE_SLOT_COEFF_INVERSE="${inverse}"
export AMARU_GLOBAL_EPOCH_LENGTH_SCALE_FACTOR="${scale_factor}"
printf '+ derived AMARU_GLOBAL_* from genesis: k=%s 1/f=%s scale_factor=%s epoch_length=%s\n' \
"${k}" "${inverse}" "${scale_factor}" "${EPOCH_LENGTH}"
else
printf 'WARNING: epochLength %s is not k*(1/f)*scale_factor (k=%s, 1/f=%s); amaru bootstrap will use defaults and snapshot import may fail\n' \
"${EPOCH_LENGTH}" "${k}" "${inverse}" >&2
fi
fi

# 1.C Conway-fork-slot derivation ------------------------------
# For test-style configs (testnet_42 fixture, antithesis), the
# node config carries TestConwayHardForkAtEpoch; for mainnet/
Expand Down Expand Up @@ -434,8 +462,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/<net>/<slot>.<hash>/ with packaged bootstrap
# headers, plus epoch metadata under data/<net>/epoch-snapshots/epochs/.
phase_create_snapshots() {
Expand All @@ -453,13 +481,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 "<point>::<parent_point>" option (Point = "<slot>.<hash>"); 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=$?
Expand All @@ -483,7 +522,7 @@ phase_create_snapshots() {
# Step 4: era-history sidecars + bundle era-history.json. rc=6 on failure.
# amaru `bootstrap` reads history.<slot>.<hash>.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
Expand All @@ -499,7 +538,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"
}

Expand All @@ -525,7 +564,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=$?
Expand Down
8 changes: 6 additions & 2 deletions tests/lib/bootstrap-helpers.bash
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
11 changes: 6 additions & 5 deletions tests/test-bootstrap-producer-history.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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=""
Expand Down
11 changes: 6 additions & 5 deletions tests/test-bootstrap-producer-sparse-boundaries.bats
Original file line number Diff line number Diff line change
Expand Up @@ -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=""
Expand Down
Loading