Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Contributing to Crucible Simulator

See CONTRIBUTING.md for the process (issues, branches, PRs, review expectations). This page is the map for what there is to contribute, aligned with the repository’s structure — the same surface the issue templates describe.

Where things live

AreaPathWhat lives there
Domain modelcrates/coreaccounts, tokens, commitments, balances, operations, transactions, events, errors
State enginecrates/statestore, commitment lifecycle, nullifiers, transitions, rollback, snapshots, Merkle
Flow enginecrates/flowsthe five flows, authorization, validation, ProofProvider boundary
High-level APIcrates/simulatorConfiguration, Environment, Simulator (examples and benches live on the root package)
Fixturescrates/fixtures + fixtures/ + schemas/typed fixtures, loader, scenario runner, the corpus, the schemas
CLIclithe stateful crucible binary
Boundariescrates/adapters/*Soroban adapter, testnet configuration + runner
Root packageexamples/, tests/, benches/runnable examples, defining-property suites, criterion benchmarks

Rules of the house

  1. Determinism is sacred. Never introduce system entropy, unordered collections into anything serialized or hashed, or platform-dependent behavior. If your change alters the state-root scheme, commitment IDs, or event/transaction output, existing deterministic anchors (Merkle root regression tests, fixture outcomes) must be regenerated deliberately and called out in the PR.
  2. Privacy boundary. Private values (amounts, commitment values, balances) never enter events, proofs, or published output. Tests may assert on inspect_private_*; output may not leak it.
  3. Atomicity. A failed operation must leave no partial state. Failed operations are still recorded (as Rejected/Failed transactions with an operation_rejected event) — do not regress that to silent errors.
  4. One operation, one ledger. Flows advance at most one ledger step per executed operation.
  5. Do not raise sha2 past 0.10 on its own. This crate’s digests are a published interface: crucible-prover pins a simulator revision and compiles it, and it also depends on stellar-xdr 28, which requires sha2 0.10. Raising sha2 here resolves two SHA-256 implementations into that consumer’s binary and is not a change one repository can make. The analysis, the reproduction, and the acceptance test for a future bump are in crucible-prover/docs/dependency-policy.md. Any change to the hashed encoding itself must be paired with regenerated known-answer vectors in crates/core/src/hashing.rs, which pin the digests by value.

Great first contributions

  • A new failure fixture — every bug you find becomes fixtures/failures/*.json with an expected_error, and the corpus-replay test keeps it green forever.
  • A determinism or invariant test — the suites under tests/ on the root package (tests/determinism, tests/state, tests/regression, tests/flows) are where defining properties are pinned.
  • Flow edge cases — the issue template names the success/failure surface; flow unit tests in crates/flows/src/<flow>.rs are the pattern to follow.
  • Docs — every doc under docs/ matches a spec section; stale docs are bugs.

Local development loop

cargo fmt --all -- --check   # formatting
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace      # everything, including the fuzz suite
cargo bench -p crucible            # objective performance targets