Pull-mirror of github.com/Sulkta-Coop/aldabra. Canonical lives on GitHub; this is a LAN-fast read-only cache.
Find a file
Kayos a0daadf38e fix(dao): audit punch list — H-1 to H-4 + M-2 + pallas bump
Lands the high-priority fixes from the 2026-05-06 audit before any
mainnet submit of the new vote/cosign/advance/destroy txs.

## H-1: Locked→Finished gate (MCP tool)

`dao_proposal_advance_unsigned` now refuses LockedToFinished unless
`tx_lower_ms > executing_end`. During the executing period the
validator demands gstMoved=true (governor input present); builder
doesn't include the governor input, so a tx in that window would
fee-burn. The proper Locked→Finished + GAT-mint flow is Phase 4c-bis;
this gate keeps us out of the broken middle.

## H-2 + H-4: strict-boundary + tx-upper-inside-period (MCP tool)

Validator's pgetRelation is strict on PAfter (`period_end < lb`)
and demands `ub <= period_end` on PWithin. Tool now picks PWithin
only when `tx_lower_ms >= period_start && tx_upper_ms <= period_end`,
PAfter only when `tx_lower_ms > period_end` strictly, and explicit-
errors on the boundary-straddling case (when tx validity range
crosses out of the target period). Same logic mirrored for the
VotingReady→Locked + VotingReady→Finished branches.

## H-3: vote builder lower-bound preflight (MCP tool)

`dao_proposal_vote_unsigned` previously checked only validity_upper
vs voting_end_ms. Validator demands BOTH `voting_start <= lb` AND
`ub <= voting_end`. Vote-too-early would hit "too early or invalid"
script error. New preflight on tx_lower_ms vs voting_start.

## M-2: DRep deposit pulled from ProtocolParams

Hardcoded constant (500 ADA) was wrong if the protocol changes
drep_deposit OR if the DRep was originally registered at a different
deposit amount (deregistration must match registration). Added
`drep_deposit_lovelace: u64` to ProtocolParams (default 500 ADA),
governance.rs build_signed_drep_registration / deregistration now
read from params instead of the constant. Constant kept for
backward compat with a doc note pointing at the params field.

## Pallas fork bump 507fd9da → 8091abd1

M-4 from the audit landed on the fork: voting_procedures builder
debug_assert_ne!s against empty CBOR map (0xa0) and docs the
upstream NonEmptyKeyValuePairs::decode footgun.

L-1 from the audit was a false finding — the audit subagent
misread the constants. PROPOSAL_CREATE_*_EX_UNITS are already at
the post-2026-05-05-H-2 values (5M mem / 2G steps per spend, 2M / 1G
per mint). The new builders alias these correctly. No change needed.
2026-05-06 08:06:44 -07:00
.cargo build: strip Gitea token from pallas patch URLs + add cargo config 2026-05-06 07:45:37 -07:00
crates fix(dao): audit punch list — H-1 to H-4 + M-2 + pallas bump 2026-05-06 08:06:44 -07:00
docs rename: sulkta-wallet → aldabra (per Cobb 2026-05-04) 2026-05-04 10:11:23 -07:00
.dockerignore phase 1: full read path — bip39 + cip-3 + cip-1852 + koios + age-mnemonic + rmcp 2026-05-04 11:09:00 -07:00
.gitignore phase 1 scaffold: cargo workspace + 3 crates + roadmap + architecture 2026-05-04 10:02:32 -07:00
Cargo.lock fix(dao): audit punch list — H-1 to H-4 + M-2 + pallas bump 2026-05-06 08:06:44 -07:00
Cargo.toml build: switch aldabra-pallas patch URLs to SSH 2026-05-06 07:55:32 -07:00
Dockerfile phase 1: full read path — bip39 + cip-3 + cip-1852 + koios + age-mnemonic + rmcp 2026-05-04 11:09:00 -07:00
LICENSE phase 1 scaffold: cargo workspace + 3 crates + roadmap + architecture 2026-05-04 10:02:32 -07:00
README.md rename: sulkta-wallet → aldabra (per Cobb 2026-05-04) 2026-05-04 10:11:23 -07:00
ROADMAP.md rename: sulkta-wallet → aldabra (per Cobb 2026-05-04) 2026-05-04 10:11:23 -07:00

aldabra

Rust-native Cardano lite wallet with an MCP-server interface — built for LLM-first usage (send, receive, mint, Plutus interaction).

Status: Phase 1 scaffold (2026-05-04). Compiles, structure in place, real wallet primitives still landing. See ROADMAP.md.

Why

The existing Cardano MCP servers are either read-only doc gateways (Jimmyh-world/Cardano_MCP) or built on Blockfrost (web3-mcp) which is a centralized API we deliberately don't depend on. Sulkta runs its own Koios + Ogmios endpoints on Rackham; we want a wallet that talks directly to those.

Also: it's the first Sulkta Rust project — useful as a workout for crafting-table's Rust toolchain (per Sulkta-Coop/lucy-infra spec-crafting-table.md).

Architecture

Three crates in a Cargo workspace:

Crate Responsibility
aldabra-core Pure crypto + types. Mnemonic → root key (CIP-3), root → payment + stake key (CIP-1852), address construction, signing. No I/O, no network. This is the security boundary.
aldabra-chain Pluggable backends for chain queries. ChainBackend trait, with Koios as the phase-1 implementation. Ogmios + submission paths in phase 2.
aldabra-mcp Binary. MCP server speaking stdio. Glues core + chain together, exposes tools to the LLM client.
            ┌─────────────────────────────┐
LLM client  │       aldabra-mcp (bin)      │  stdio
─────────►  │   tool handlers, lifecycle  │  ────►
            └──────────┬──────────────────┘
                       │
              ┌────────┴────────┐
              ▼                 ▼
       ┌──────────────┐  ┌──────────────┐
       │ aldabra-core  │  │ aldabra-chain │
       │ keys, sign   │  │ Koios/Ogmios │
       └──────────────┘  └──────────────┘

MCP tools (target)

Phase 1:

  • wallet.address — derived base address at account 0, index 0
  • wallet.balance — ADA + native asset balance at the wallet's address
  • wallet.utxos — list UTXOs

Phase 2:

  • wallet.send — build, sign, submit a payment (ADA or native)
  • wallet.tx_status — poll a submitted tx hash

Phase 3:

  • wallet.mint — mint a CIP-25 / CIP-68 native asset
  • wallet.policy.create — generate a policy script (timelock, multisig)

Phase 4:

  • wallet.script.attach — attach an inline datum + reference script
  • wallet.script.spend — spend a Plutus-locked UTXO with redeemer
  • wallet.stake.delegate — delegate to a pool

Build

# Local (requires rustc 1.75+)
cargo build --release

# Through crafting-table (preferred — validates the toolchain there)
crafting-table build aldabra

Run

# Direct invocation (smoke test only — does nothing useful in phase 1)
./target/release/aldabra

# As an MCP server registered with Claude Code:
# add to ~/.claude.json:
#   "aldabra": {
#     "command": "/path/to/aldabra",
#     "env": {
#       "ALDABRA_DATA": "/mnt/cache/appdata/aldabra"
#     }
#   }

Security model

  • Mnemonic source: interactive bootstrap on first run, paste once, encrypted at rest with age. Never written to disk in plaintext.
  • Derived keys: in-memory only, ZeroizeOnDrop on every container.
  • Network exposure: stdio MCP transport — never opens a TCP socket. Only the spawning client process can reach it.
  • Multi-network: mainnet by default, but --network preview / --network preprod for testing without real ADA.

See also