asteria-game: bump compose tag to ac7d5c0 (player driver)
Home /
Cardano Foundation /
antithesis
Apr 24, 9-10 AM (0)
Apr 24, 10-11 AM (0)
Apr 24, 11-12 PM (0)
Apr 24, 12-1 PM (0)
Apr 24, 1-2 PM (0)
Apr 24, 2-3 PM (0)
Apr 24, 3-4 PM (0)
Apr 24, 4-5 PM (0)
Apr 24, 5-6 PM (0)
Apr 24, 6-7 PM (0)
Apr 24, 7-8 PM (0)
Apr 24, 8-9 PM (0)
Apr 24, 9-10 PM (0)
Apr 24, 10-11 PM (0)
Apr 24, 11-12 AM (0)
Apr 25, 12-1 AM (0)
Apr 25, 1-2 AM (0)
Apr 25, 2-3 AM (0)
Apr 25, 3-4 AM (0)
Apr 25, 4-5 AM (0)
Apr 25, 5-6 AM (0)
Apr 25, 6-7 AM (0)
Apr 25, 7-8 AM (0)
Apr 25, 8-9 AM (0)
Apr 25, 9-10 AM (0)
Apr 25, 10-11 AM (0)
Apr 25, 11-12 PM (0)
Apr 25, 12-1 PM (0)
Apr 25, 1-2 PM (0)
Apr 25, 2-3 PM (0)
Apr 25, 3-4 PM (0)
Apr 25, 4-5 PM (0)
Apr 25, 5-6 PM (5)
Apr 25, 6-7 PM (0)
Apr 25, 7-8 PM (0)
Apr 25, 8-9 PM (0)
Apr 25, 9-10 PM (0)
Apr 25, 10-11 PM (0)
Apr 25, 11-12 AM (0)
Apr 26, 12-1 AM (0)
Apr 26, 1-2 AM (0)
Apr 26, 2-3 AM (0)
Apr 26, 3-4 AM (0)
Apr 26, 4-5 AM (0)
Apr 26, 5-6 AM (0)
Apr 26, 6-7 AM (3)
Apr 26, 7-8 AM (3)
Apr 26, 8-9 AM (0)
Apr 26, 9-10 AM (0)
Apr 26, 10-11 AM (0)
Apr 26, 11-12 PM (0)
Apr 26, 12-1 PM (0)
Apr 26, 1-2 PM (1)
Apr 26, 2-3 PM (3)
Apr 26, 3-4 PM (1)
Apr 26, 4-5 PM (0)
Apr 26, 5-6 PM (0)
Apr 26, 6-7 PM (0)
Apr 26, 7-8 PM (0)
Apr 26, 8-9 PM (0)
Apr 26, 9-10 PM (0)
Apr 26, 10-11 PM (0)
Apr 26, 11-12 AM (0)
Apr 27, 12-1 AM (0)
Apr 27, 1-2 AM (0)
Apr 27, 2-3 AM (0)
Apr 27, 3-4 AM (0)
Apr 27, 4-5 AM (0)
Apr 27, 5-6 AM (0)
Apr 27, 6-7 AM (0)
Apr 27, 7-8 AM (0)
Apr 27, 8-9 AM (0)
Apr 27, 9-10 AM (2)
Apr 27, 10-11 AM (0)
Apr 27, 11-12 PM (1)
Apr 27, 12-1 PM (0)
Apr 27, 1-2 PM (0)
Apr 27, 2-3 PM (0)
Apr 27, 3-4 PM (0)
Apr 27, 4-5 PM (0)
Apr 27, 5-6 PM (2)
Apr 27, 6-7 PM (0)
Apr 27, 7-8 PM (0)
Apr 27, 8-9 PM (0)
Apr 27, 9-10 PM (0)
Apr 27, 10-11 PM (0)
Apr 27, 11-12 AM (0)
Apr 28, 12-1 AM (0)
Apr 28, 1-2 AM (0)
Apr 28, 2-3 AM (0)
Apr 28, 3-4 AM (0)
Apr 28, 4-5 AM (0)
Apr 28, 5-6 AM (0)
Apr 28, 6-7 AM (0)
Apr 28, 7-8 AM (0)
Apr 28, 8-9 AM (0)
Apr 28, 9-10 AM (0)
Apr 28, 10-11 AM (0)
Apr 28, 11-12 PM (0)
Apr 28, 12-1 PM (0)
Apr 28, 1-2 PM (0)
Apr 28, 2-3 PM (0)
Apr 28, 3-4 PM (0)
Apr 28, 4-5 PM (0)
Apr 28, 5-6 PM (0)
Apr 28, 6-7 PM (0)
Apr 28, 7-8 PM (0)
Apr 28, 8-9 PM (0)
Apr 28, 9-10 PM (0)
Apr 28, 10-11 PM (0)
Apr 28, 11-12 AM (0)
Apr 29, 12-1 AM (0)
Apr 29, 1-2 AM (0)
Apr 29, 2-3 AM (0)
Apr 29, 3-4 AM (0)
Apr 29, 4-5 AM (0)
Apr 29, 5-6 AM (0)
Apr 29, 6-7 AM (0)
Apr 29, 7-8 AM (1)
Apr 29, 8-9 AM (0)
Apr 29, 9-10 AM (0)
Apr 29, 10-11 AM (2)
Apr 29, 11-12 PM (0)
Apr 29, 12-1 PM (3)
Apr 29, 1-2 PM (0)
Apr 29, 2-3 PM (0)
Apr 29, 3-4 PM (0)
Apr 29, 4-5 PM (0)
Apr 29, 5-6 PM (0)
Apr 29, 6-7 PM (0)
Apr 29, 7-8 PM (0)
Apr 29, 8-9 PM (0)
Apr 29, 9-10 PM (0)
Apr 29, 10-11 PM (0)
Apr 29, 11-12 AM (0)
Apr 30, 12-1 AM (0)
Apr 30, 1-2 AM (0)
Apr 30, 2-3 AM (0)
Apr 30, 3-4 AM (0)
Apr 30, 4-5 AM (0)
Apr 30, 5-6 AM (0)
Apr 30, 6-7 AM (13)
Apr 30, 7-8 AM (0)
Apr 30, 8-9 AM (2)
Apr 30, 9-10 AM (1)
Apr 30, 10-11 AM (8)
Apr 30, 11-12 PM (1)
Apr 30, 12-1 PM (0)
Apr 30, 1-2 PM (0)
Apr 30, 2-3 PM (10)
Apr 30, 3-4 PM (2)
Apr 30, 4-5 PM (0)
Apr 30, 5-6 PM (2)
Apr 30, 6-7 PM (0)
Apr 30, 7-8 PM (1)
Apr 30, 8-9 PM (0)
Apr 30, 9-10 PM (2)
Apr 30, 10-11 PM (0)
Apr 30, 11-12 AM (0)
May 01, 12-1 AM (0)
May 01, 1-2 AM (0)
May 01, 2-3 AM (0)
May 01, 3-4 AM (0)
May 01, 4-5 AM (0)
May 01, 5-6 AM (0)
May 01, 6-7 AM (0)
May 01, 7-8 AM (1)
May 01, 8-9 AM (1)
May 01, 9-10 AM (2)
73 commits this week
Apr 24, 2026
-
May 01, 2026
asteria-game: wire player parallel driver (single-pass loop)
Adds the player workload to the asteria_game testnet's composer
harness. PlayerMain.hs is reshaped from a forever-loop to a
single-pass binary so the Antithesis composer can re-fire it on
its own schedule (a forever loop blocks exclusive scheduling for
serial drivers).
components/asteria-game/composer/stub/parallel_driver_asteria_player.sh:
- Picks ASTERIA_PLAYER_ID in {1,2,3} based on the wallclock so
different timelines exercise different players.
- Player 1 attempts the spawn (PlayerMain gates on id == "1");
players 2 and 3 observe the asteria UTxO without acting,
exercising the read path.
components/asteria-game/app/PlayerMain.hs:
- main: drop the forever loop and the in-process IORef Bool
"have I spawned yet" guard. Spawn idempotence comes from chain
state — once the asteria UTxO has been consumed-and-replaced
with a higher ship_counter, the next attempt's tx is rejected
by the validator as expected, and reported via the existing
asteria_player_ship_spawn_failed_<id> sdkUnreachable assertion.
- Adds asteria_player_pass_errored_<id> and
asteria_player_pass_completed_<id> SDK assertions so the report
can score one pass per fire even when the inner observation
bombs out.
Locally validated on testnets/asteria_game/ compose (3-pass run,
one per player_id):
- bootstrap idempotence still holds (cold deploy + 2 short-circuit)
- player 1 attempts spawn end-to-end (observe → build → sign →
submit → reject); players 2, 3 observe-only
- sdk.jsonl shows ship_counter and move_planned per pass
KNOWN ISSUE — submission is currently rejected by the spacetime
validator with "PlutusV3 script failed: overspending the budget"
(CekError, ~600k cpu over). This is a pre-existing issue in the
lifted PR #67 Aiken validators — the off-chain wiring works
correctly, but the on-chain validator over-spends its execution
units. Tracked as a follow-up; does not block landing this driver
since the wiring + report assertions are independent of validator
correctness.
feat(testnet): add cardano_node_adversary as iteration testnet
New testnet that mirrors cardano_node_master and adds the
long-running cardano-adversary daemon. Created as a separate
iteration loop for the adversary roadmap so:
- The scheduled cron continues to target cardano_node_master only.
Findings on the adversary testnet cannot regress the master
baseline because nothing automatic consumes this testnet.
- New adversarial endpoints (Tier 1.2 chain_sync_thrash,
1.3 slow_loris, Tier 2 / 3 / 4) iterate here first, dispatched
manually via:
gh workflow run "Antithesis on cardano-node testnet" \
--ref <branch> -f test=cardano_node_adversary -f duration=1
- Promotion of any change to cardano_node_master happens only
after multiple branch-dispatched runs against this testnet
produce findings_new ≤ master baseline (currently 9), and
with explicit user approval.
Layout:
- testnets/cardano_node_adversary/ — full clone of master plus
one new `adversary` service. Same producers (p1/p2/p3),
relays (relay1/relay2), tracer, tracer-sidecar, sidecar,
tx-generator, asteria-bootstrap, asteria-player, log-tailer.
- adversary service mounts relay1-state for the control socket
and tracer:ro for chainPoints.log; depends_on relay1 +
tracer-sidecar + configurator.
- Image pinned to ghcr.io/cardano-foundation/cardano-node-antithesis/adversary:cc628d5
(current built tag from PR #104). Will be bumped per follow-up
branches as adversary code evolves.
Docs:
- docs/testnets/cardano-node-adversary.md — overview,
scheduling discipline, promotion criteria.
- docs/testnets/index.md — entry pointing at the new page.
- docs/testnets/cardano-node-master.md — sidecar row updated
to drop the now-relocated adversary driver mention.
- mkdocs.yml — nav entry for the new testnet doc.
components/adversary/ is unchanged (the wrapper image keeps
building from the same tree), and components/sidecar/ is
unchanged.
The helper_sdk_lib.sh on main is byte-identical to
tx-generator's; tx-generator's SDK assertions are ingested by
Antithesis successfully, so we keep it as-is and use the first
branch-dispatched run on this new testnet as the diagnostic
for whether the adversary container's assertions are or aren't
reaching the SDK ingest channel.
asteria-bootstrap: idempotent deploy via Provider UTxO query
PR 2: make rerunning bootstrap safe. Antithesis can restart the
asteria-game container at any time; serial_driver_asteria_bootstrap
will re-fire on each restart. The Haskell binary now skips the
mint+lock if the asteria spend address already carries a UTxO with
the asteriaAdmin token.
Defence layers in place after this PR:
1. Haskell-side detection (this PR): Provider.queryUTxOs at the
asteria spend address; presence of (admin_mint_hash,
"asteriaAdmin") = already deployed → exit 0 with
sdk_sometimes("asteria_bootstrap_already_deployed").
2. Antithesis serial_driver scheduling: exclusive access while
bootstrap runs → no concurrent invocations on the same timeline.
KNOWN GAP — defence layer 3 (Plutus one-shot) is still on the
todo list. PR #67's admin_mint validator is the always-true
placeholder, so there is no chain-level uniqueness guarantee yet.
A future PR replaces admin_mint with a parameterised one-shot
that consumes a seed OutputReference; until then the indexer
race window between detection and submission, while small under
serial_driver scheduling, is non-zero. See spec FR-010 / User
Story 4.
New: composer/stub/serial_driver_asteria_bootstrap.sh — exec
/bin/asteria-bootstrap. Antithesis discovers it under
/opt/antithesis/test/v1/stub/ (already mounted via the same
docker-image build).
chore: use reconnect tx-generator image
fix: pin tx-generator reconnect dependency
fix: isolate amaru bootstrap chaindb reads
chore: use hardened tx generator image
fix: harden tx generator composer drivers
docs(adversary-roadmap): mark Tier 1.1 done, stub Tier 1.2 spec link
Updates the roadmap to reflect what shipped today: - PR A (#88), PR B (clients #103), PR C (clients #106), PR D (this repo #99) all marked landed with PR / commit links. - Tier 1.1 (chain_sync_flap) marked done. - Tier 1.2 (chain_sync_thrash) marked next, with a link to the speckit spec being filed in clients (specs/037-cardano-adversary-thrash) and the tracking issue clients#107. - Status table at the top so a reader can see the state of every tier without scrolling the prose. - Tickets section reorganised: closed issues marked ✅ inline.
fix: use antithesis-compatible node digest pin
asteria-game: rename component + lift PR #67 source for bootstrap+player
PR 1 of 2 toward the real asteria workload. Scope-limited to the
rename + Haskell source lift + nix scaffolding so the binaries
build alongside the existing utxo-indexer. Bootstrap is iteration
5b — *not safe for repeat invocation* — that gap is explicitly the
subject of PR 2.
Rename:
components/asteria-stub/ → components/asteria-game/
service asteria-stub → asteria-game
volume asteria-stub-db → asteria-game-db
Lift from cardano-foundation/cardano-node-antithesis#67 (asteria-spawn-v2):
components/asteria-game/aiken/ (validators + apply-params)
components/asteria-game/src/Asteria/ (game state, datums, validators, wallet, providers, RNG, SDK)
components/asteria-game/app/{BootstrapMain.hs, PlayerMain.hs}
components/asteria-game/asteria-game.cabal (renamed package)
components/asteria-game/cabal.project (cardano-node-clients SRP bumped to PR #98 head 5707836b)
Build infra:
flake.nix — extends prior asteria-stub flake with haskell.nix /
iohk-nix overlays so local Haskell packages compile, while
keeping the upstream cardano-node-clients flake input that
supplies the prebuilt utxo-indexer (PR #98 supervisor).
nix/project.nix — lifted from PR #67, package renamed.
nix/docker-image.nix — bundles utxo-indexer + asteria-bootstrap
+ asteria-game (player) execs + composer scripts + bash/jq/
socat; entrypoint stays utxo-indexer.
KNOWN GAP — admin_mint validator is the always-true placeholder
PR #67 ships. Without an on-chain one-shot guarantee, every
container restart could mint another admin NFT. Bootstrap is *not*
wired into compose in this PR for that reason. PR 2 patches the
Aiken admin_mint to take an OutputReference parameter, runs
apply-params at bootstrap-time, and adds defence-in-depth detection
in Bootstrap.hs.
Composer scripts (composer/stub/{parallel_driver_heartbeat,
eventually_alive, finally_alive, helper_sdk}.sh) unchanged from
the green stub baseline so this PR stays bisect-safe and in
property terms identical to commit 3b6fb0e (PR #74's merged head).
chore(adversary): bump compose tag + retire adversary-CI workflow
Bumps the compose pin to a328953 (this branch's tip pre-this-commit) so publish-images can resolve the tag and rebuild the new wrapper image. The publish-images run on commit a328953 skipped the adversary because its compose still pointed at 15daf1b which never existed on origin. Deletes .github/workflows/adversary-CI.yaml — the workflow built the now-deleted standalone Haskell binary and fails outright since that source is gone. The cardano-node-clients side runs all of the daemon's CI; this repo only needs publish-images + the end-to-end Compose smoke test.
chore(adversary): pin compose tag to this commit (15daf1b → final)
chore(adversary): bump compose tag to 9bc9b23 (post-CI-cleanup)
asteria-game: rename component + lift PR #67 source for bootstrap+player
PR 1 of 2 toward the real asteria workload. Scope-limited to the
rename + Haskell source lift + nix scaffolding so the binaries
build alongside the existing utxo-indexer. Bootstrap is iteration
5b — *not safe for repeat invocation* — that gap is explicitly the
subject of PR 2.
Rename:
components/asteria-stub/ → components/asteria-game/
service asteria-stub → asteria-game
volume asteria-stub-db → asteria-game-db
Lift from cardano-foundation/cardano-node-antithesis#67 (asteria-spawn-v2):
components/asteria-game/aiken/ (validators + apply-params)
components/asteria-game/src/Asteria/ (game state, datums, validators, wallet, providers, RNG, SDK)
components/asteria-game/app/{BootstrapMain.hs, PlayerMain.hs}
components/asteria-game/asteria-game.cabal (renamed package)
components/asteria-game/cabal.project (cardano-node-clients SRP bumped to PR #98 head 5707836b)
Build infra:
flake.nix — extends prior asteria-stub flake with haskell.nix /
iohk-nix overlays so local Haskell packages compile, while
keeping the upstream cardano-node-clients flake input that
supplies the prebuilt utxo-indexer (PR #98 supervisor).
nix/project.nix — lifted from PR #67, package renamed.
nix/docker-image.nix — bundles utxo-indexer + asteria-bootstrap
+ asteria-game (player) execs + composer scripts + bash/jq/
socat; entrypoint stays utxo-indexer.
KNOWN GAP — admin_mint validator is the always-true placeholder
PR #67 ships. Without an on-chain one-shot guarantee, every
container restart could mint another admin NFT. Bootstrap is *not*
wired into compose in this PR for that reason. PR 2 patches the
Aiken admin_mint to take an OutputReference parameter, runs
apply-params at bootstrap-time, and adds defence-in-depth detection
in Bootstrap.hs.
Composer scripts (composer/stub/{parallel_driver_heartbeat,
eventually_alive, finally_alive, helper_sdk}.sh) unchanged from
the green stub baseline so this PR stays bisect-safe and in
property terms identical to commit 3b6fb0e (PR #74's merged head).
chore: quiet amaru relay logs
asteria-game: rename component + lift PR #67 source for bootstrap+player
PR 1 of 2 toward the real asteria workload. Scope-limited to the
rename + Haskell source lift + nix scaffolding so the binaries
build alongside the existing utxo-indexer. Bootstrap is iteration
5b — *not safe for repeat invocation* — that gap is explicitly the
subject of PR 2.
Rename:
components/asteria-stub/ → components/asteria-game/
service asteria-stub → asteria-game
volume asteria-stub-db → asteria-game-db
Lift from cardano-foundation/cardano-node-antithesis#67 (asteria-spawn-v2):
components/asteria-game/aiken/ (validators + apply-params)
components/asteria-game/src/Asteria/ (game state, datums, validators, wallet, providers, RNG, SDK)
components/asteria-game/app/{BootstrapMain.hs, PlayerMain.hs}
components/asteria-game/asteria-game.cabal (renamed package)
components/asteria-game/cabal.project (cardano-node-clients SRP bumped to PR #98 head 5707836b)
Build infra:
flake.nix — extends prior asteria-stub flake with haskell.nix /
iohk-nix overlays so local Haskell packages compile, while
keeping the upstream cardano-node-clients flake input that
supplies the prebuilt utxo-indexer (PR #98 supervisor).
nix/project.nix — lifted from PR #67, package renamed.
nix/docker-image.nix — bundles utxo-indexer + asteria-bootstrap
+ asteria-game (player) execs + composer scripts + bash/jq/
socat; entrypoint stays utxo-indexer.
KNOWN GAP — admin_mint validator is the always-true placeholder
PR #67 ships. Without an on-chain one-shot guarantee, every
container restart could mint another admin NFT. Bootstrap is *not*
wired into compose in this PR for that reason. PR 2 patches the
Aiken admin_mint to take an OutputReference parameter, runs
apply-params at bootstrap-time, and adds defence-in-depth detection
in Bootstrap.hs.
Composer scripts (composer/stub/{parallel_driver_heartbeat,
eventually_alive, finally_alive, helper_sdk}.sh) unchanged from
the green stub baseline so this PR stays bisect-safe and in
property terms identical to commit 3b6fb0e (PR #74's merged head).
chore(adversary): bump compose tag to 9bc9b23 (post-CI-cleanup)
chore(adversary): bump compose tag + retire adversary-CI workflow
Bumps the compose pin to a328953 (this branch's tip pre-this-commit) so publish-images can resolve the tag and rebuild the new wrapper image. The publish-images run on commit a328953 skipped the adversary because its compose still pointed at 15daf1b which never existed on origin. Deletes .github/workflows/adversary-CI.yaml — the workflow built the now-deleted standalone Haskell binary and fails outright since that source is gone. The cardano-node-clients side runs all of the daemon's CI; this repo only needs publish-images + the end-to-end Compose smoke test.
docs: mark amaru nodes relay-only
fix(ci): verify surge upload via sentinel and retry transient errors
PR #88's preview deployed an empty subdomain (cf-cna-pr-88.surge.sh returns 404) because surge.cli exited 0 after an ECONNRESET mid-upload. The job was marked successful and the comment was posted with a URL that points at nothing. Make the deploy step trustworthy: - Write a unique sentinel file into the upload tree before pushing. - After surge exits 0, curl https://<domain>/<sentinel> and require HTTP 200; treat anything else as a failed deploy. - Wrap the surge+verify pair in a 3-attempt retry loop with linear backoff (5s, 10s, 15s) so transient surge.sh ECONNRESETs don't fail the workflow. - set -euo pipefail at the top of the step so future drift is caught earlier. Resolves the cf-cna-pr-88 false-positive class of failure.
feat: add amaru bootstrap antithesis testnet