phase 1: full read path — bip39 + cip-3 + cip-1852 + koios + age-mnemonic + rmcp
end-to-end working wallet: paste 24-word mnemonic, age-encrypt at rest,
on unlock derive root + payment + stake keys, build cip-19 base address,
serve four tools over mcp stdio (wallet.address, wallet.network,
wallet.balance, wallet.utxos).
deps added: ed25519-bip32 0.4 (pallas only ships raw ed25519, not the
cardano variant of bip32 hd derivation), cryptoxide 0.4 for pbkdf2-hmac-sha512,
age 0.10 for at-rest mnemonic encryption, rpassword 7 for tty-only passphrase
prompts, toml 0.9 for config.toml.
new modules:
- crates/aldabra-core/src/derive.rs — payment + stake key derivation, hash
- crates/aldabra-chain/src/koios.rs — real reqwest impl, asset aggregation
- crates/aldabra-mcp/src/{bootstrap,config,tools}.rs
caught one bug pre-flight: get_balance was clobbering same-asset
quantities across utxos instead of summing. fixed + regression test.
headless support via ALDABRA_PASSPHRASE env (mcp clients own stdin so
the rpassword prompt path can't run). docker secret / systemd
EnvironmentFile sources it in production.
dockerfile: multi-stage rust:1.95-bookworm → debian:bookworm-slim, tini
as pid1, non-root aldabra user, /var/lib/aldabra owned 700.
29 unit tests + 1 ignored live-koios test. preprod smoke test exercised
initialize → tools/list → tools/call wallet.address end-to-end via
piped json-rpc; correct preprod address came back from canonical
abandon-art mnemonic.
phase 2 (send) is next.
This commit is contained in:
parent
edc976e5d9
commit
2b4fdff0c0
14 changed files with 4389 additions and 167 deletions
72
Dockerfile
Normal file
72
Dockerfile
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
# aldabra — Cardano lite wallet over MCP.
|
||||
#
|
||||
# Multi-stage:
|
||||
# 1. builder — rust toolchain, cargo build --release
|
||||
# 2. runtime — debian:bookworm-slim, just the binary + ca-certs.
|
||||
#
|
||||
# Built in CI and
|
||||
# published as a container image (aldabra/mcp). Pulled
|
||||
# anywhere we want the MCP server available — usually as a sidecar
|
||||
# spawned by an MCP client (e.g. Claude Code).
|
||||
#
|
||||
# Required env at runtime:
|
||||
# ALDABRA_DATA directory containing mnemonic.age (must
|
||||
# already exist; bootstrap separately on
|
||||
# first install)
|
||||
# ALDABRA_NETWORK mainnet | preview | preprod (default preprod)
|
||||
# ALDABRA_KOIOS_BASE defaults to public Koios for the network
|
||||
# ALDABRA_PASSPHRASE unlocks mnemonic.age. Source from a docker
|
||||
# secret or systemd EnvironmentFile — never
|
||||
# commit it.
|
||||
|
||||
FROM rust:1.95-bookworm AS builder
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Cache deps separately from source. Copy manifests + dummy bins so
|
||||
# `cargo build` resolves and downloads everything before the real
|
||||
# source rebuilds invalidate the layer.
|
||||
COPY Cargo.toml ./
|
||||
COPY crates/aldabra-core/Cargo.toml crates/aldabra-core/
|
||||
COPY crates/aldabra-chain/Cargo.toml crates/aldabra-chain/
|
||||
COPY crates/aldabra-mcp/Cargo.toml crates/aldabra-mcp/
|
||||
|
||||
RUN mkdir -p crates/aldabra-core/src crates/aldabra-chain/src crates/aldabra-mcp/src && \
|
||||
echo 'fn main() {}' > crates/aldabra-mcp/src/main.rs && \
|
||||
echo '' > crates/aldabra-core/src/lib.rs && \
|
||||
echo '' > crates/aldabra-chain/src/lib.rs && \
|
||||
cargo build --release --bin aldabra || true && \
|
||||
rm -rf crates/*/src
|
||||
|
||||
COPY crates ./crates
|
||||
|
||||
# Touch every src file so cargo notices and rebuilds. The dummy-source
|
||||
# trick above leaves stale build artifacts otherwise.
|
||||
RUN find crates -name '*.rs' -exec touch {} +
|
||||
|
||||
RUN cargo build --release --bin aldabra && \
|
||||
strip target/release/aldabra
|
||||
|
||||
FROM debian:bookworm-slim AS runtime
|
||||
|
||||
# rustls-tls needs ca-certificates to verify Koios's TLS cert.
|
||||
# tini for proper signal forwarding when running as PID 1.
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends ca-certificates tini && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /build/target/release/aldabra /usr/local/bin/aldabra
|
||||
|
||||
# Default data dir — mount a volume here in compose / k8s / docker run.
|
||||
ENV ALDABRA_DATA=/var/lib/aldabra
|
||||
RUN mkdir -p /var/lib/aldabra && chmod 700 /var/lib/aldabra
|
||||
|
||||
# Non-root user for runtime. Mnemonic.age is owner-readable only
|
||||
# (chmod 600 from the bootstrap path), so the runtime UID must own
|
||||
# the data dir.
|
||||
RUN groupadd -r aldabra && useradd -r -g aldabra -d /var/lib/aldabra aldabra && \
|
||||
chown -R aldabra:aldabra /var/lib/aldabra
|
||||
USER aldabra
|
||||
|
||||
# tini handles SIGTERM and reaps zombies.
|
||||
ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/aldabra"]
|
||||
Loading…
Add table
Add a link
Reference in a new issue