diff --git a/AGENTS.md b/AGENTS.md index 85bf9befb2d..0839fd01a29 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,13 +4,7 @@ This file provides guidance to AI coding agents (Claude Code, and other AGENTS.m ## Build -Required on Linux/macOS: use the Nix devshell, which sets up the compiler, Conan, ccache, and (optionally) Rust automatically. - -```bash -nix develop -``` - -For alternate devshell variants (specific compiler, no-compiler, coverage), see [docs/build/nix.md](./docs/build/nix.md). For the manual build steps, CMake options, and protocol codegen commands, see [BUILD.md](./BUILD.md) (`## Steps`, `## Options`, `## Code generation`). +For the build steps, CMake options, and protocol codegen commands, see [BUILD.md](./BUILD.md) (`## Steps`, `## Options`, `## Code generation`). Nix development shells are available in the repo (not required) — see [docs/build/nix.md](./docs/build/nix.md) for setup and variants. Rust crate tests (independent of the CMake build): `cargo test --manifest-path crates/Cargo.toml --workspace` (CI uses `cargo nextest`). @@ -21,7 +15,7 @@ Unit tests are a custom framework built into the `xrpld` binary itself (not Boos - A suite's `--unittest` name is built from the arguments to its `BEAST_DEFINE_TESTSUITE`/`BEAST_DEFINE_TESTSUITE_PRIO` macro (usually at the bottom of the test file), in reverse order and joined with `.`: `BEAST_DEFINE_TESTSUITE(Credentials, app, xrpl)` → `xrpl.app.Credentials`. - `--unittest-arg` does nothing — don't use it. - Tests that run offline in under a minute should be automatic `--unittest` suites; anything else is a manual/integration test. -- New tests should be written using `gtest` under `src/tests/` unless that isn't possible, in which case fall back to the legacy Beast framework under `src/test/`. `tests/` (top-level) holds integration tests exercised against `libxrpl`/`xrpld`. +- New tests should be written using `gtest` under `src/tests/` unless that isn't possible, in which case fall back to the legacy Beast framework under `src/test/` (see [src/test/AGENTS.md](./src/test/AGENTS.md) for conventions specific to that directory). `tests/` (top-level) holds integration tests exercised against `libxrpl`/`xrpld`. ## Lint/Format @@ -29,14 +23,14 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md#pre-commit-hooks) for `pre-commit` setup ## Code Style -New file placement and header levelization: see [CONTRIBUTING.md](./CONTRIBUTING.md#before-making-a-pull-request). Braces, whitespace, member order, and other conventions: see [docs/CodingStyle.md](./docs/CodingStyle.md). `XRPL_ASSERT`/`UNREACHABLE` contracts: see [CONTRIBUTING.md](./CONTRIBUTING.md#contracts-and-instrumentation). Commit messages: see [CONTRIBUTING.md](./CONTRIBUTING.md#good-commit-messages). +New file placement and header levelization: see [CONTRIBUTING.md](./CONTRIBUTING.md#before-making-a-pull-request). Braces, whitespace, member order, and other conventions: see [docs/CodingStyle.md](./docs/CodingStyle.md). `XRPL_ASSERT`/`UNREACHABLE` contracts: see [CONTRIBUTING.md](./CONTRIBUTING.md#contracts-and-instrumentation). Commit messages: see [CONTRIBUTING.md](./CONTRIBUTING.md#good-commit-messages). New public functions/methods need a Doxygen-style comment. + +Comments should explain _why_, not _what_/_how_ — the code already shows that. Only describe what/how when the code itself would otherwise be confusing (a non-obvious workaround, a subtle invariant, a surprising constraint). ## Architecture -Paths below reflect the current layout; update this section if modularization moves a subsystem to a different directory. +See [ARCHITECTURE.md](./ARCHITECTURE.md) for the directory-by-directory map of the codebase. + +## Keeping docs current -- `include/xrpl/` + `src/libxrpl/` — the core protocol library: ledger, shamap, consensus, crypto, json, resource, nodestore, rdb, peerfinder, and `tx/` (transaction application: `Transactor.cpp`, `applySteps.cpp`, invariants, payment paths). `tx/transactors/` has one file per transaction type, grouped by subsystem: `escrow/`, `vault/`, `lending/`, `sponsor/`, `nft/`, `token/` (MPT), `payment_channel/`, `permissioned_domain/`, `dex/`, `oracle/`, `did/`, `credentials/`, `bridge/`, `check/`, `delegate/`, `account/`, `system/`. Any change to transaction-processing behavior must be gated behind an Amendment. -- `src/xrpld/` — the server application built on top of `libxrpl`: `app`, `core`, `overlay` (P2P networking), `peerfinder`, `perflog`, `rpc`, `shamap`. `main` builds an `ApplicationImp` implementing `Application`; most components hold a reference to it (`app_`), giving broad cross-component access — expect to trace call chains through `Application&`. -- `src/test/` — unit tests mirroring the subsystems above, plus `jtx/` (the transaction-building test DSL — e.g. `jtx/escrow.h`, `jtx/vault.h`, `jtx/sponsor.h`, `jtx/permissioned_dex.h`) and `unit_test/` (the custom test framework itself, derived from Beast). -- `src/tests/` — unit tests for `libxrpl` written in `gtest`, gradually replacing the `src/test` equivalents. -- `crates/` — a Rust workspace (only built with `-Dxrpld -Drust=ON`) bridged into C++ via `cxxbridge`/the `cxx` crate; currently just a `hello_world` interop scaffold. Requires the Rust toolchain pinned in `rust-toolchain.toml` (the Nix devshell provides it automatically). +When you add or change a convention, or touch a subsystem that has its own `AGENTS.md`, `README.md`, or `ARCHITECTURE.md`, update that documentation in the same change rather than leaving it stale. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md new file mode 100644 index 00000000000..c2e1d22c3bd --- /dev/null +++ b/ARCHITECTURE.md @@ -0,0 +1,9 @@ +# Architecture + +Paths below reflect the current layout; update this doc if modularization moves a subsystem to a different directory. + +- `include/xrpl/` + `src/libxrpl/` — the core protocol library: ledger, shamap, consensus, crypto, json, resource, nodestore, rdb, peerfinder, and `tx/` (transaction application: `Transactor.cpp`, `applySteps.cpp`, invariants, payment paths — see [src/libxrpl/tx/AGENTS.md](./src/libxrpl/tx/AGENTS.md) for amendment-gating conventions). `tx/transactors/` has one file per transaction type, grouped by subsystem: `escrow/`, `vault/`, `lending/`, `sponsor/`, `nft/`, `token/` (MPT), `payment_channel/`, `permissioned_domain/`, `dex/`, `oracle/`, `did/`, `credentials/`, `bridge/`, `check/`, `delegate/`, `account/`, `system/`. +- `src/xrpld/` — the server application built on top of `libxrpl`: `app`, `core`, `overlay` (P2P networking), `peerfinder`, `perflog`, `rpc`, `shamap`. `main` builds an `ApplicationImp` implementing `Application`; most components hold a reference to it (`app_`), giving broad cross-component access — expect to trace call chains through `Application&`. +- `src/test/` — unit tests mirroring the subsystems above, plus `jtx/` (the transaction-building test DSL — e.g. `jtx/escrow.h`, `jtx/vault.h`, `jtx/sponsor.h`, `jtx/permissioned_dex.h`) and `unit_test/` (the custom test framework itself, derived from Beast). +- `src/tests/` — unit tests for `libxrpl` written in `gtest`, gradually replacing the `src/test` equivalents. +- `crates/` — a Rust workspace (only built with `-Dxrpld -Drust=ON`) bridged into C++ via `cxxbridge`/the `cxx` crate; currently just a `hello_world` interop scaffold. Requires the Rust toolchain pinned in `rust-toolchain.toml` (the Nix devshell provides it automatically). diff --git a/include/xrpl/consensus/AGENTS.md b/include/xrpl/consensus/AGENTS.md new file mode 100644 index 00000000000..553c7953bc5 --- /dev/null +++ b/include/xrpl/consensus/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — consensus + +See [README.md](./README.md) for a short pointer, and [docs/consensus.md](../../../docs/consensus.md) for the full consensus design. diff --git a/include/xrpl/consensus/CLAUDE.md b/include/xrpl/consensus/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/include/xrpl/consensus/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/include/xrpl/nodestore/AGENTS.md b/include/xrpl/nodestore/AGENTS.md new file mode 100644 index 00000000000..f941557f831 --- /dev/null +++ b/include/xrpl/nodestore/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — nodestore + +See [README.md](./README.md) for backend and benchmark design. diff --git a/include/xrpl/nodestore/CLAUDE.md b/include/xrpl/nodestore/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/include/xrpl/nodestore/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/include/xrpl/shamap/AGENTS.md b/include/xrpl/shamap/AGENTS.md new file mode 100644 index 00000000000..355032f3faf --- /dev/null +++ b/include/xrpl/shamap/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — shamap + +See [README.md](./README.md) for the SHAMap design. diff --git a/include/xrpl/shamap/CLAUDE.md b/include/xrpl/shamap/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/include/xrpl/shamap/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/libxrpl/ledger/helpers/AGENTS.md b/src/libxrpl/ledger/helpers/AGENTS.md new file mode 100644 index 00000000000..951b0975566 --- /dev/null +++ b/src/libxrpl/ledger/helpers/AGENTS.md @@ -0,0 +1,7 @@ +# AGENTS.md — ledger/helpers + +A helper that takes an `SLE`/`std::shared_ptr` should `XRPL_ASSERT` that it's non-null and of the expected ledger-entry type at entry, and keep a real runtime check/error-return alongside the assert (asserts compile out in release builds) — the established idiom in this directory is `std::expected<..., TER>`, returning `std::unexpected(tec*)` on failure. Don't invent a new error-handling idiom for this. + +Prefer a single amendment-enabled block and a single disabled block over scattering `rules.enabled(...)` checks through a function, even if the two blocks are similar. When a file or function checks more than one amendment, name local enablement booleans per-amendment (e.g. `fix340Enabled` for `fixCleanup3_4_0`), not a generic `fixEnabled`. + +Only use `UNREACHABLE` for genuinely impossible paths, not to avoid writing a test for one that's reachable but rare. When a branch marked `UNREACHABLE` is excluded from coverage, wrap it in `LCOV_EXCL_START`/`LCOV_EXCL_STOP`. diff --git a/src/libxrpl/ledger/helpers/CLAUDE.md b/src/libxrpl/ledger/helpers/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/libxrpl/ledger/helpers/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/libxrpl/tx/AGENTS.md b/src/libxrpl/tx/AGENTS.md index e2261fc1adf..b95d34b1a80 100644 --- a/src/libxrpl/tx/AGENTS.md +++ b/src/libxrpl/tx/AGENTS.md @@ -1,5 +1,15 @@ # AGENTS.md — tx -See the repo-level [AGENTS.md](../../../AGENTS.md) for general build/test/style guidance. +## When an amendment is required -Any change to transaction-processing behavior must be gated behind an amendment. New amendments (and fixes, i.e. `fix*` amendments) are added to [`include/xrpl/protocol/detail/features.macro`](../../../include/xrpl/protocol/detail/features.macro), as an `XRPL_FEATURE(...)` or `XRPL_FIX(...)` entry added to the top of the list (the list is kept in reverse chronological order). Once the pre-amendment code path for a retired amendment is removed, move its entry to `XRPL_RETIRE_FEATURE(...)`/`XRPL_RETIRE_FIX(...)` instead of deleting it. +A change needs an amendment if it affects transaction processing, ledger objects, or anything else about the binary format or hash of the ledger. An amendment is optional if a change only affects what transactions get proposed for consensus (e.g. fee escalation). Otherwise, don't use one. + +New amendments (and fixes, i.e. `fix*` amendments) are added to [`include/xrpl/protocol/detail/features.macro`](../../../include/xrpl/protocol/detail/features.macro), as an `XRPL_FEATURE(...)` or `XRPL_FIX(...)` entry added to the top of the list (the list is kept in reverse chronological order). Once the pre-amendment code path for a retired amendment is removed, move its entry to `XRPL_RETIRE_FEATURE(...)`/`XRPL_RETIRE_FIX(...)` instead of deleting it. + +When adding a new amendment or transaction type, check its interaction with: invariants, fees, Deposit Auth, Batch transaction inclusion/exclusion, Permission Delegation inclusion/exclusion, Freeze/Deep Freeze (IOU) and Lock (MPT), Clawback, Credentials and Permissioned Domain, the case where the submitting account is the asset's issuer, and numeric over/underflow. Stick to existing paradigms rather than inventing new ones — consistency between features matters more than a locally "better" design. + +New (or deleted) invariant checks must be amendment-gated: they introduce (or remove) a way for a transaction to fail, and an un-gated change risks validators disagreeing on a transaction's result, i.e. a network fork. + +See [transactors/AGENTS.md](./transactors/AGENTS.md) for conventions on writing the amendment-gated code itself. + +A change to transaction/signing behavior that's visible through the public API also needs an `API-CHANGELOG.md` entry — see [../../xrpld/rpc/AGENTS.md](../../xrpld/rpc/AGENTS.md) for the full rule. diff --git a/src/libxrpl/tx/transactors/AGENTS.md b/src/libxrpl/tx/transactors/AGENTS.md new file mode 100644 index 00000000000..75218aceb06 --- /dev/null +++ b/src/libxrpl/tx/transactors/AGENTS.md @@ -0,0 +1,13 @@ +# AGENTS.md — transactors + +Prefer a single object-level invariant over duplicating the same delta/balance check in every transactor that touches an object — e.g. one invariant asserting a Vault's pseudo-account balance and `assetsAvailable` always move together, rather than repeating that check in `VaultDeposit`, `VaultWithdraw`, `VaultClawback`, `LoanSet`, etc. + +## Gating amendment-dependent code + +Prefer a single amendment-enabled block and a single disabled block over scattering `rules.enabled(...)` checks through a function, even if the two blocks are similar. + +When a file or function checks more than one amendment, name local enablement booleans per-amendment (e.g. `fix340Enabled` for `fixCleanup3_4_0`), not a generic `fixEnabled` — it becomes ambiguous once a second amendment is checked in the same scope. + +## `UNREACHABLE` and test coverage + +Only use `UNREACHABLE` for genuinely impossible paths, not to avoid writing a test for one that's reachable but rare. When a branch marked `UNREACHABLE` is excluded from coverage, wrap it in `LCOV_EXCL_START`/`LCOV_EXCL_STOP`. diff --git a/src/libxrpl/tx/transactors/CLAUDE.md b/src/libxrpl/tx/transactors/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/libxrpl/tx/transactors/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/test/AGENTS.md b/src/test/AGENTS.md new file mode 100644 index 00000000000..2743e428aa5 --- /dev/null +++ b/src/test/AGENTS.md @@ -0,0 +1,5 @@ +# AGENTS.md — test + +See [README.md](./README.md) for basic `--unittest` invocation. + +Shared test setup/helper code used by more than one test file belongs in `jtx/`, not copy-pasted across test files. diff --git a/src/test/CLAUDE.md b/src/test/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/test/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/xrpld/app/consensus/AGENTS.md b/src/xrpld/app/consensus/AGENTS.md new file mode 100644 index 00000000000..292de6b67a7 --- /dev/null +++ b/src/xrpld/app/consensus/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — consensus + +See [README.md](./README.md) for a short pointer, and [docs/consensus.md](../../../../docs/consensus.md) for the full consensus design. diff --git a/src/xrpld/app/consensus/CLAUDE.md b/src/xrpld/app/consensus/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/xrpld/app/consensus/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/xrpld/app/ledger/AGENTS.md b/src/xrpld/app/ledger/AGENTS.md new file mode 100644 index 00000000000..7f9125f61f9 --- /dev/null +++ b/src/xrpld/app/ledger/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — ledger + +See [README.md](./README.md) for ledger lifecycle and fetch-pack design. diff --git a/src/xrpld/app/ledger/CLAUDE.md b/src/xrpld/app/ledger/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/xrpld/app/ledger/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/xrpld/overlay/AGENTS.md b/src/xrpld/overlay/AGENTS.md new file mode 100644 index 00000000000..c4566819be8 --- /dev/null +++ b/src/xrpld/overlay/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — overlay + +See [README.md](./README.md) for the peer-protocol handshake, clustering, gossip, and monitoring design. diff --git a/src/xrpld/overlay/CLAUDE.md b/src/xrpld/overlay/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/xrpld/overlay/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/xrpld/peerfinder/AGENTS.md b/src/xrpld/peerfinder/AGENTS.md new file mode 100644 index 00000000000..d53d8f1e775 --- /dev/null +++ b/src/xrpld/peerfinder/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md — peerfinder + +See [README.md](./README.md) for the peer-discovery design. diff --git a/src/xrpld/peerfinder/CLAUDE.md b/src/xrpld/peerfinder/CLAUDE.md new file mode 120000 index 00000000000..47dc3e3d863 --- /dev/null +++ b/src/xrpld/peerfinder/CLAUDE.md @@ -0,0 +1 @@ +AGENTS.md \ No newline at end of file diff --git a/src/xrpld/rpc/AGENTS.md b/src/xrpld/rpc/AGENTS.md index 14fdd7a03ea..5934e5ed423 100644 --- a/src/xrpld/rpc/AGENTS.md +++ b/src/xrpld/rpc/AGENTS.md @@ -1,5 +1,5 @@ # AGENTS.md — rpc -See the repo-level [AGENTS.md](../../../AGENTS.md) for general build/test/style guidance. +See [README.md](./README.md) for the RPC subsystem design. -Any change to a public RPC method's behavior (new/changed/removed fields, parameters, or error conditions) needs a corresponding entry in [`API-CHANGELOG.md`](../../../API-CHANGELOG.md), under the `## Unreleased` section (`### Additions`, `### Deprecations`, etc. as appropriate). +Any change to publicly-visible API behavior — RPC/WebSocket fields, parameters, or error conditions, or transaction/signing behavior surfaced through the API even from outside this directory — needs an entry in [`API-CHANGELOG.md`](../../../API-CHANGELOG.md) under `## Unreleased` (`### Additions`, `### Deprecations`, etc. as appropriate).