Skip to content

Technical Reference

Terramike edited this page Oct 3, 2026 · 4 revisions

Technical Reference

Current as of v0.14.1. For commands, see Command Reference. For the trust boundary, see Security.

Proposal envelope: xrpl-proposal/5

xrpl-trade writes a complete, autofilled, unsigned transaction envelope and never submits it. The proposal hash binds:

  • Format, network, account, action, creation time, and policy version.
  • The named profile and its canonical profile fingerprint.
  • The SHA-256 digest of the exact policy file bytes.
  • The canonical XRPL binary serialization of the complete transaction.

The signer derives summaries from the transaction; stored summaries are not trusted. Old envelope formats must be rebuilt. Policy edits require review and xrpl-sign sync-profile --profile <name> before new proposals use that profile.

Signing profiles

~/.xrpl/profiles.json contains named profiles binding account, network, credential reference, absolute policy path, policy digest, and state selection. The file must pass protected-file checks. Mainnet requires a named profile with an environment credential supplied through the secure vault; mainnet cannot use local seed files or CLI overrides to reclassify a credential.

The signer verifies profile and policy schemas and digests before credential access. Per-account/network spend state uses a stable namespace so profile renames or edits cannot reset accounting. Testnet-only adhoc signing is a development path, not a Muse mainnet boundary.

Policy checks

Policy schema version is 4. Unknown fields, invalid values, unsupported networks/types, and non-finite fee limits are rejected. Core gates include:

  • Strict transaction-type and per-type field allowlists.
  • Exact approved issuer/pair matching for offers.
  • Per-asset per-transaction and rolling 24-hour spend caps; missing limits fail closed.
  • Funded-depth book analysis at one validated ledger index, with both sides, spread, and depth checks.
  • Expiring offers and validated destination-tag enforcement.
  • Validated master-key or RegularKey authorization for the signing account.
  • Full 64-character proposal digest before profile credential access.

NFT reads pin ownership and offer data to one validated ledger snapshot. The buy ceremony reports issuer/minter separately from seller/current owner. All external display text is sanitized before terminal output.

NFT staging and pinning

nft-stage validates and hashes artwork locally. The human reviews the full stage digest independently. nft-pin-and-propose --stage <id> --approve-stage <full-stage-sha256> checks that independent digest before reading Pinata credentials or uploading. Muse must bind the reviewed stage ID and digest to the human-approved operation; the CLI flag by itself is not approval. The bytes uploaded are the same bytes that were hashed. Pinning is an external, potentially irreversible write; if a later step fails, content can remain pinned without an on-ledger NFT.

The configured media directory is accepted only when its protecting configuration passes owner-only checks. A same-user agent can still alter files if the deployed Muse boundary does not prevent it; see Security.

Spend reservations and reliable submission

Signing reserves spend under a lock and binds it to the signed transaction hash and LastLedgerSequence before submission. A reservation remains pending while the result is ambiguous and does not age out automatically.

  • Validated success confirms the spend.
  • Validated failure releases the transaction amount but retains the fee as confirmed XRP spend.
  • Proven non-inclusion releases a reservation only when a successful lookup explicitly reports txnNotFound and server-reported complete-ledger history covers the entire submission-to-expiry range.
  • Any incomplete history, timeout, tooBusy, malformed response, or other uncertainty preserves the reservation.

Reconciliation groups work by transaction so a multi-asset operation does not charge its fee more than once. See XRPL reliable transaction submission.

Recovery and migration

Corrupt state never becomes an empty balance sheet. xrpl-sign recover-state holds the state lock, checks the original full SHA-256, validates a reviewed replacement, preserves the original bytes, and refuses to omit known valid obligations. Malformed or omitted liabilities require explicit reconstruction from audit and validated ledger data.

For legacy accounting, use:

xrpl-sign migrate-state --profile <name> --legacy-state default \
  --state-sha256 <full-source-sha256> \
  --approve-migration <full-reviewed-sha256>

Use --legacy-state giveaway for giveaway accounting. The command checks identity, locks source and destination, validates and copies entries, retains the source, and writes a migration receipt. Unresolved legacy obligations block profile accounting until they are reconciled or reviewed and migrated.

doctor

xrpl-trade doctor is read-only. It checks local profiles, signer/helper hashes, protected files, accounting readability, and unresolved reservations without network or credential access. It always reports the actual Muse vault approval and protected-execution boundary as unverified; it cannot certify the deployment.

Files

~/.xrpl/
  config.json          public address + network settings
  profiles.json        named profile bindings (owner-only)
  policy.json          strict v4 policy
  approved.json        vetted pairs and payment destinations
  proposals/           hash-bound pending proposals
  accounts/<key>/      stable per-account/network accounting state
  audit.log            operational signing/reconciliation record
  local-wallet-testnet.json  typed testnet credential (never mainnet)
  local-giveaway-testnet.json  typed testnet giveaway credential

Mainnet seeds remain in Muse's secure credential vault. Legacy seed files must be migrated out before mainnet signing. Giveaway testnet credentials are separately typed and tagged; local giveaway seeds are refused for mainnet.

Tests

The CI workflow runs all deterministic tests/test_*.py suites on Ubuntu/Linux. The optional manual testnet stage uses temporary homes and faucet wallets only. The workflow passed deterministic and faucet-only testnet suites for the remediation branch, including payment and NFT end-to-end checks. CI does not verify a deployed Muse vault or mainnet safety.

Run on Linux:

python tests/run_tests.py
python tests/run_tests.py --testnet  # explicit live faucet-only testnet runs

Prioritized follow-up features

The security remediation does not yet include richer transaction receipts that distinguish actual fills, remaining offers, fees, and unknown outcomes; a direct NFT offer-cancellation command; or giveaway round commitments that freeze entrants and the future-ledger choice before a draw. These remain proposed additions, not current guarantees.

Spec conventions (STE100)

Specs for this project are written in ASD Simplified Technical English (STE100): one meaning per word, one instruction per sentence, so an AI agent parses the spec with no human in the loop to resolve ambiguity. (Karpathy-suggested approach.)

  • Use it for: specs, tool descriptions, error messages, inter-agent instructions, system prompts.
  • Do not use it for: creative or marketing copy — STE is deliberately flat and literal.
  • Two modes: strict (hard caps, one-word-one-meaning) for normative specs and safety text; STE-flavored (structure only, lexical rules advisory) for prose such as READMEs and changelogs.
  • Tooling: the asd-ste100 skill — rewrite plus a stdlib linter (scripts/ste-lint.py).
  • Rule: the linter checks form, not meaning. It cannot verify that a rewrite preserved intent. Always show the diff on rewrites handed to subagents or merged as specs.

Wiki


Propose → approve → sign. Nothing moves without your hash.

Clone this wiki locally