Skip to content
Open
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
31 changes: 31 additions & 0 deletions .github/workflows/publish-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,34 @@ jobs:
id: images
run: |
scripts/push-cardano_node_master_images.sh

- name: Ensure published packages are public
# The Antithesis platform pulls component images
# anonymously; ghcr packages default to private on
# first push. Walk the docker-compose image list and
# PATCH each package's visibility to public — idempotent
# for packages already public, no-op for packages that
# don't exist yet (they'll be made public the next run
# after they're first published).
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
# Extract unique component names from the testnet
# compose file (same regex the publish script uses).
mapfile -t NAMES < <(
grep -oP \
'ghcr\.io/cardano-foundation/cardano-node-antithesis/\K[^ :]+' \
testnets/cardano_node_master/docker-compose.yaml |
sort -u
)
for name in "${NAMES[@]}"; do
enc=$(printf '%s' "cardano-node-antithesis/${name}" |
jq -sRr @uri)
echo "Setting visibility=public on $name ..."
gh api --silent --method PATCH \
"/orgs/cardano-foundation/packages/container/${enc}" \
-f visibility=public \
&& echo " → public" \
|| echo " → not yet published or already public; skipping"
done
7 changes: 6 additions & 1 deletion components/asteria-player/aiken/apply-params.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,12 @@ MAX_SPEED_CBOR=d8798201197530 # Speed { distance=1, time=30000 }
MAX_SHIP_FUEL_CBOR=1864 # 100
FUEL_PER_STEP_CBOR=05 # 5

aiken build
# Build with traces stripped — asteria's add_new_ship script is
# heavy enough to overshoot Conway's per-tx CPU step ceiling
# (10_000_000_000) by ~0.006% with the default trace-level.
# `--trace-level silent` removes the runtime allocations that
# wrap every assertion; gameplay-equivalent, costs less.
aiken build --trace-level silent --trace-filter user-defined

# Compute admin_token from the just-built admin_mint hash.
ADMIN_MINT_HASH=$(jq -r '.validators[] | select(.title=="admin_mint.admin_mint.mint") | .hash' plutus.json)
Expand Down
20 changes: 10 additions & 10 deletions components/asteria-player/aiken/plutus-applied.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion components/asteria-player/aiken/plutus.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"plutusVersion": "v3",
"compiler": {
"name": "Aiken",
"version": "v1.1.21+unknown"
"version": "v1.1.19+e525483"
},
"license": "Apache-2.0"
},
Expand Down
33 changes: 30 additions & 3 deletions components/asteria-player/app/PlayerMain.hs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ import Cardano.Node.Client.Submitter (
SubmitResult (..),
Submitter (..),
)
import Cardano.Node.Client.TxBuild (InterpretIO (..), build)
import Cardano.Ledger.Plutus.ExUnits (ExUnits (..))
import Cardano.Node.Client.TxBuild (
BuildOptions (..),
InterpretIO (..),
buildWith,
defaultBuildOptions,
)
import Cardano.Slotting.Slot (SlotNo (..))
import Data.ByteString.Char8 qualified as BS8
import Data.ByteString.Short qualified as SBS
Expand Down Expand Up @@ -234,14 +240,35 @@ attemptSpawn provider submitter wk (aIn, aOut) datum spawnedRef playerId = do
, sspPelletScript = pelletScript
, sspFundingIn = fundingIn
, sspValidTo = validToSlot
, sspPilotAddr = walletAddr wk
}
eval tx =
fmap (Map.map (either (Left . show) Right)) (evaluateTx provider tx)
interpret :: InterpretIO NoQ
interpret = InterpretIO $ \case {}
-- 20 % overshoot mirrors @cardano-cli@'s
-- default before submit. Absorbs the
-- cardano-ledger version drift between this
-- client (CHaP 2026-02-17) and the cluster's
-- cardano-node 10.7.1 (CHaP 2026-04-14):
-- otherwise the asteria spend script
-- overshoots the patched budget by ~751 mem
-- at submit time and fails as
-- @PlutusFailure@.
bumpExUnits (ExUnits m s) =
ExUnits
( fromInteger
(toInteger m * 120 `div` 100)
)
( fromInteger
(toInteger s * 120 `div` 100)
)
opts =
defaultBuildOptions
{ boExUnitsMargin = bumpExUnits
}
built <-
build
buildWith
opts
pp
interpret
eval
Expand Down
4 changes: 2 additions & 2 deletions components/asteria-player/cabal.project
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ repository cardano-haskell-packages
source-repository-package
type: git
location: https://github.com/lambdasistemi/cardano-node-clients
tag: f6a31ca6c169810a46e45648a0868d7a48eb1f02
--sha256: 0fcblvcqdhlj3kjq7jyarj169grmi6csvmrhpja4sc80ann3nihr
tag: f578d6cf11fadf18e9267893c79062c69f322f75
--sha256: 1ljpv1pc1y1gm0c4bb7xvm0jlb1xx4832xykgmn3s8386l266ggm

source-repository-package
type: git
Expand Down
19 changes: 6 additions & 13 deletions components/asteria-player/src/Asteria/Game.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import Cardano.Node.Client.TxBuild (
attachScript,
collateral,
mint,
payTo,
payTo',
spend,
spendScript,
Expand Down Expand Up @@ -78,10 +77,6 @@ data SpawnShipParams = SpawnShipParams
, sspPelletScript :: Script ConwayEra
, sspFundingIn :: TxIn
, sspValidTo :: SlotNo
, sspPilotAddr :: Addr
-- ^ Where the new PILOT NFT lands. Conventional asteria
-- off-chain code sends it to the player's wallet so the
-- pilot doubles as proof of ship ownership.
}

{- | Hard-coded spawn position. Asteria's add_new_ship rule
Expand Down Expand Up @@ -160,13 +155,11 @@ spawnShipProgram SpawnShipParams{..} = do
-- Pellet mint: initial_fuel FUEL via MintFuel redeemer.
mint sspFuelPolicy (Map.singleton fuelName initialFuel) MintFuel
validTo sspValidTo
-- The PILOT NFT is left for the balancer to fold
-- into the player's change output, matching the
-- 3-output spawn-tx shape used on mainnet. This
-- relies on the residual-multi-asset folding
-- added in cardano-node-clients balanceTx; see
-- lambdasistemi/cardano-node-clients PR #77.
_ <- payTo' sspAsteriaAddr asteriaOutValue asteriaDatum'
-- The pilot NFT goes to the player's wallet (proof of ship
-- ownership). 1.5 ADA covers the multi-asset min-utxo.
let pilotOutValue =
MaryValue (Coin 1_500_000) $
MultiAsset $
Map.singleton sspShipyardPolicy $
Map.singleton pName 1
_ <- payTo sspPilotAddr pilotOutValue
payTo' sspShipAddr shipOutValue shipDatum
22 changes: 12 additions & 10 deletions components/configurator/configurator.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -152,17 +152,19 @@ fi

echo "removing /configs/keys"; rm -rf /configs/keys

# Bump Alonzo ExUnits limits to fit asteria's add_new_ship script,
# which exceeds the cardano-cli default maxTxExUnits.steps of
# 10_000_000_000 by a few hundred thousand steps. 14B / 14M is
# comfortable headroom; matching maxBlockExUnits scales by 4x as
# the upstream defaults do.
echo "bumping Alonzo maxTxExUnits + maxBlockExUnits for asteria"
# Match mainnet's per-tx ExUnits ceilings so Plutus scripts that
# already run on mainnet — like asteria's @add_new_ship@ — fit
# under the antithesis cluster's budget too. The default Alonzo
# genesis ships 10M/10B, but mainnet (Conway, epoch 627+) uses
# 16_500_000 mem and 10_000_000_000 steps. Block ceilings scale
# accordingly; we follow mainnet on mem and keep the upstream 4x
# block-vs-tx step ratio.
echo "matching mainnet maxTxExUnits + maxBlockExUnits"
for ag in /configs/*/configs/alonzo-genesis.json; do
jq '.maxTxExUnits.exUnitsMem = 14000000
| .maxTxExUnits.exUnitsSteps = 14000000000
| .maxBlockExUnits.exUnitsMem = 80000000
| .maxBlockExUnits.exUnitsSteps = 64000000000' "$ag" | write_file "$ag"
jq '.maxTxExUnits.exUnitsMem = 16500000
| .maxTxExUnits.exUnitsSteps = 10000000000
| .maxBlockExUnits.exUnitsMem = 62000000
| .maxBlockExUnits.exUnitsSteps = 40000000000' "$ag" | write_file "$ag"
done

pools=$(ls -d /configs/*)
Expand Down
62 changes: 54 additions & 8 deletions scripts/push-cardano_node_master_images.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ REGISTRY="ghcr.io/cardano-foundation/cardano-node-antithesis"
TEST="testnets/cardano_node_master"
# -----------------------------------------------------------

# Track every entry we couldn't process (missing git tag, missing
# component directory, …). The job MUST fail at the end if any
# entry was skipped — silent skips previously left CI green while
# the antithesis testnet ran against stale registry images.
SKIPPED=()

# 1. Extract "name tag" pairs (e.g. configurator 5967670)
mapfile -t ENTRIES < <(
grep -oP 'ghcr\.io/cardano-foundation/cardano-node-antithesis/\K[^ ]+' "$TEST/docker-compose.yaml" |
Expand Down Expand Up @@ -37,18 +43,42 @@ for entry in "${ENTRIES[@]}"; do
echo "Processing: $NAME (tag: $TAG)"
echo "=================================================="

# ---- Resolve tag → commit ----
# ---- Already-published fast path ----
# If the registry already serves $NAME:$TAG, we don't need to
# rebuild — the testnet will pull what's there. This handles
# legacy components whose original git commit has since been
# rebased away: the image is still served, we just can't build
# it again. No need to resolve $TAG against the repo at all.
if docker manifest inspect "$REGISTRY/$NAME:$TAG" >/dev/null 2>&1; then
echo "→ $NAME:$TAG already in registry. Skipping rebuild."
continue
fi

# ---- Need to build → must resolve tag to a commit ----
# Try the tag as a bare ref (git tag, commit SHA, or local
# branch) first, then fall back to @origin/<tag>@ — fresh
# clones expose feature branches only as remote-tracking
# refs.
COMMIT=$(git -C "$CLONE_DIR" rev-list -n 1 "$TAG" 2>/dev/null || true)
if [[ -z "$COMMIT" ]]; then
echo "Error: Tag '$TAG' not found in repo. Skipping $NAME."
COMMIT=$(git -C "$CLONE_DIR" rev-list -n 1 "origin/$TAG" 2>/dev/null || true)
fi
if [[ -z "$COMMIT" ]]; then
echo "Error: Tag '$TAG' is NOT in the registry AND cannot be" >&2
echo " resolved against this repo (tried '$TAG' and" >&2
echo " 'origin/$TAG') — nothing to build and nothing" >&2
echo " to publish." >&2
SKIPPED+=("$NAME:$TAG (not in registry, tag not resolvable)")
continue
fi
echo "→ Tag $TAG resolves to commit ${COMMIT:0:8}"

# ---- Skip if both tags already published ----
if docker manifest inspect "$REGISTRY/$NAME:$TAG" >/dev/null 2>&1 \
&& docker manifest inspect "$REGISTRY/$NAME:$COMMIT" >/dev/null 2>&1; then
echo "→ $NAME:$TAG and $NAME:$COMMIT already in registry. Skipping."
# ---- Skip if commit-tagged image is also already published ----
if docker manifest inspect "$REGISTRY/$NAME:$COMMIT" >/dev/null 2>&1; then
echo "→ $NAME:$COMMIT already in registry. Re-tagging as $NAME:$TAG."
docker pull "$REGISTRY/$NAME:$COMMIT"
docker tag "$REGISTRY/$NAME:$COMMIT" "$REGISTRY/$NAME:$TAG"
docker push "$REGISTRY/$NAME:$TAG"
continue
fi

Expand All @@ -57,7 +87,8 @@ for entry in "${ENTRIES[@]}"; do

# ---- Verify component directory exists ----
if [[ ! -d "$BUILD_DIR" ]]; then
echo "Warning: Directory $BUILD_DIR does not exist. Skipping $NAME."
echo "Warning: Directory $BUILD_DIR does not exist." >&2
SKIPPED+=("$NAME:$TAG (component directory missing at commit ${COMMIT:0:8})")
continue
fi

Expand Down Expand Up @@ -92,4 +123,19 @@ done

echo
echo "All components processed."
echo "Images available at: $REGISTRY/<name>:<tag> and $REGISTRY/<name>:<commit>"
echo "Images available at: $REGISTRY/<name>:<tag> and $REGISTRY/<name>:<commit>"

if (( ${#SKIPPED[@]} > 0 )); then
echo
echo "FAIL: ${#SKIPPED[@]} entr(y/ies) were skipped — the testnet docker-compose.yaml" >&2
echo " references images that this script could not build/push:" >&2
for entry in "${SKIPPED[@]}"; do
echo " - $entry" >&2
done
echo >&2
echo "Fix the offending image: tag in testnets/cardano_node_master/docker-compose.yaml" >&2
echo "to a value that resolves via 'git rev-list -n 1 <tag>' (a real git tag, branch, or" >&2
echo "commit SHA living in this repo) and that has the corresponding components/<name>/" >&2
echo "build context at that commit." >&2
exit 1
fi
7 changes: 4 additions & 3 deletions testnets/cardano_node_master/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ services:
container_name: configurator
volumes:
- ./testnet.yaml:/testnet.yaml # source of configurations
- ../../components/configurator/configurator.sh:/configurator.sh:ro
- p1-configs:/configs/1 # configs for p1
- p2-configs:/configs/2 # configs for p2
- p3-configs:/configs/3 # configs for p3
Expand Down Expand Up @@ -202,7 +203,7 @@ services:
# ----------------------------------------------

asteria-bootstrap:
image: ghcr.io/cardano-foundation/cardano-node-antithesis/asteria-player:dev
image: ghcr.io/cardano-foundation/cardano-node-antithesis/asteria-player:asteria-spawn-v2
container_name: asteria-bootstrap
hostname: asteria-bootstrap.example
# Override the image's `sleep-forever` entrypoint so the
Expand All @@ -222,7 +223,7 @@ services:
condition: service_started

asteria-player-1:
image: ghcr.io/cardano-foundation/cardano-node-antithesis/asteria-player:dev
image: ghcr.io/cardano-foundation/cardano-node-antithesis/asteria-player:asteria-spawn-v2
container_name: asteria-player-1
hostname: asteria-player-1.example
entrypoint: ["/bin/parallel_driver_asteria_player"]
Expand All @@ -241,7 +242,7 @@ services:
condition: service_completed_successfully

asteria-player-2:
image: ghcr.io/cardano-foundation/cardano-node-antithesis/asteria-player:dev
image: ghcr.io/cardano-foundation/cardano-node-antithesis/asteria-player:asteria-spawn-v2
container_name: asteria-player-2
hostname: asteria-player-2.example
entrypoint: ["/bin/parallel_driver_asteria_player"]
Expand Down
Loading