> ## Documentation Index
> Fetch the complete documentation index at: https://docs.leafage.chaintable.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Contributing

> Repository map, build and test commands, commit conventions, and where to start contributing

Leafage's code is spread across five repositories, each of which can be developed and tested independently. This page helps you determine where a change belongs and how to get it running locally.

## Repository map

| Repository                                                               | Language | What you want to change                                                  |
| ------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------ |
| [go-ethereum](https://github.com/Chaintable/go-ethereum)                 | Go       | Block execution, hook distribution, `trace_debankBlock`, history pruning |
| [pipeline](https://github.com/Chaintable/pipeline)                       | Go       | Tracing logic, data structures, S3 / Kafka writes, Leader election       |
| [leafage-evm](https://github.com/Chaintable/leafage-evm)                 | Rust     | State storage, EVM execution, RPC methods, executors for new chains      |
| [consistency-checker](https://github.com/Chaintable/consistency-checker) | Go       | Consistency decisions, fork marking, node state, external notifications  |
| [nodex-proxy](https://github.com/Chaintable/nodex-proxy)                 | Go       | Routing, load balancing, rate limiting, observability                    |
| [leafage-documents](https://github.com/Chaintable/leafage-documents)     | MDX      | This documentation site                                                  |

### Which repository a change belongs to

| Need                                                     | Repository                                                                        |
| -------------------------------------------------------- | --------------------------------------------------------------------------------- |
| Add a new RPC method                                     | leafage-evm (implementation) + nodex-proxy (routing and rate limiting, if needed) |
| Collect a new execution data field                       | pipeline (types and collection) + execution client (if a new hook is needed)      |
| Change fork decisions or external notification semantics | consistency-checker                                                               |
| Change the State / Archive routing rules                 | `utils/pick_nodes.go` in nodex-proxy                                              |
| Reduce query node disk usage                             | `leafage-evm-storage` in leafage-evm                                              |
| Support a new chain                                      | See [Adding a new chain](/en/guides/new-chain)                                    |

<Warning>
  Before changing a cross-repository interface (Kafka messages, S3 keys, etcd keys, error codes), read the [interface contracts](/en/architecture/interfaces#compatibility-rules). These formats are hard-coded in multiple repositories; a one-sided change silently breaks the data path.
</Warning>

## Local development

### Prerequisites

| Component         | Requirements                                       |
| ----------------- | -------------------------------------------------- |
| Go repositories   | Go 1.23+ (1.22+ for nodex-proxy), golangci-lint    |
| leafage-evm       | Rust 1.79+, clang, Git LFS (needed to run benches) |
| Integration tests | Docker, AWS credentials (or MinIO), Kafka, etcd    |

### Build and test

The three Go repositories share the same Makefile targets:

```bash theme={null}
make build   # go build ./...
make test    # go test -count=1 -shuffle=on ./...
make race    # race detection
make lint    # golangci-lint run --timeout=5m
make ci      # full pre-commit checks
```

leafage-evm:

```bash theme={null}
cargo build --release
cargo test
cargo clippy --all-targets -- -D warnings
cargo fmt --all
```

Execution client forks keep the upstream build and CI entry points (`make all` and `go run ./build/ci.go ...` for go-ethereum); see their `AGENTS.md` for details.

### Run a minimal setup

Most changes can be validated without connecting to production infrastructure. Use HTTP mode to connect the write node and the query node directly, skipping Kafka and S3:

```bash theme={null}
# Write node, exposing the trace namespace
geth --http --http.api=eth,debug,trace --http.addr=0.0.0.0

# Query node, polling the write node's trace_debankBlock
leafage-evm standalone \
  --db-path /tmp/leafage \
  --listen-addr 0.0.0.0:8659 \
  --chain-cfg 1 \
  --rpc-addr http://127.0.0.1:8545
```

See the [quickstart](/en/quickstart) for the full steps.

## Commit conventions

### Execution client forks

Follow the upstream go-ethereum conventions: commit messages use `<package(s)>: description`, and PR titles use the same format. The full pre-commit checklist is in the repository's `AGENTS.md`.

Two hard constraints: **keep changes small and focused** (no drive-by refactoring, no renaming of unrelated code), and **do not add or remove dependencies casually**. The fork has to track upstream releases over the long term, and unrelated changes amplify merge conflicts.

### Other repositories

* Cut feature branches from `main` and keep PRs small and focused
* Run `make ci` locally before committing (or fmt + clippy + test for Rust)
* New behavior needs tests; read the existing tests before changing a critical path, for example `check/critical_path_test.go` in consistency-checker

## Context for AI agents

If you are assisting with these repositories from inside an agent, these entry points save the most time:

| Repository             | Read first                                                                                            |
| ---------------------- | ----------------------------------------------------------------------------------------------------- |
| Execution client forks | `AGENTS.md` (pre-commit checklist), `git diff <upstream tag> HEAD --stat` (to see what the fork adds) |
| pipeline               | `CLAUDE.md`, `docs/architecture.md`, `docs/protocol.md`                                               |
| leafage-evm            | `docs/Architecture.md`, `docs/StateManage.md`, `docs/Database.md`                                     |
| consistency-checker    | `README_cn.md`, `Process` in `check/check.go`                                                         |
| nodex-proxy            | `docs/architecture_cn.md`, `utils/pick_nodes.go`                                                      |

A few pitfalls that are easy to hit:

* **Do not infer cross-component behavior from a single repository's README.** Some READMEs diverge from the implementation (S3 key format, method naming, license statements); the code is authoritative, and the [interface contracts](/en/architecture/interfaces) on this site have been checked against the code.
* **Read the tests before changing critical paths such as `Process` or `OnCommit`**; they encode idempotency and retry semantics that are easy to miss by reading the implementation alone.
* **etcd key and S3 key construction is scattered across multiple repositories**; when searching, locate it with `fmt.Sprintf` / `format!` plus a fragment of the key name.

## Where to start contributing

<AccordionGroup>
  <Accordion title="Documentation and examples">
    Fill in missing configuration documentation in the component repositories, fix divergences between READMEs and the implementation, and add troubleshooting steps for common failures. These changes are low risk but highly valuable to users.
  </Accordion>

  <Accordion title="Observability">
    Fill in metrics missing along the path (for example S3 fetch failure rate, catch-up progress), or build Grafana dashboards for existing metrics. The data path is long, and a missing metric at any link makes troubleshooting harder.
  </Accordion>

  <Accordion title="New chain support">
    Adding an `EvmExecutor` on the read side is a clearly bounded change with limited impact; follow the existing implementations in `leafage-evm-chains`. See [Adding a new chain](/en/guides/new-chain).
  </Accordion>

  <Accordion title="Performance">
    The storage layer and execution hot path of leafage-evm have a clear way to be measured: use `leafage-bench` to compare the `eth_call` latency distribution before and after a change.
  </Accordion>
</AccordionGroup>

## Maintaining this documentation site

This site is built on Mintlify; the content is MDX and the navigation lives in `docs.json`.

```bash theme={null}
npm ci                # Install the pinned version of the Mintlify CLI
npm run dev           # Local preview at http://localhost:3000
npm run check         # Strict build validation + internal link check + accessibility check
```

GitHub Actions runs the same set of checks automatically on pull requests. New pages must also be added to the `groups` of the matching language under `navigation.languages` in `docs.json` (`cn` for Chinese, `en` for English), otherwise they will not appear in the sidebar. Chinese and English pages correspond one to one (English lives under `en/`); update both when you change either. See the repository's `AGENTS.md` and `README.md` for writing conventions.
