Conversation
…eguide.md) Add deep architecture context for AI coding agents working in this repo. Covers execution flow, message/program lifecycle, gas model, queues, lazy pages, ethexe contracts, no_std boundary, and build commands. - CLAUDE.md: Claude Code context - AGENTS.md: OpenAI Codex / generic agents context - .gemini/styleguide.md: expanded with architecture for Gemini Code Assist Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces dedicated documentation files to improve the integration and effectiveness of AI coding assistants within the repository. By providing structured context on the project's architecture, build pipelines, and development workflows, these changes ensure that AI tools can better understand and navigate the codebase, ultimately streamlining development and review processes. Highlights
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces two new documentation files, AGENTS.md and CLAUDE.md, which provide architectural context, build commands, and development guidelines for AI coding agents. The content of both files is identical. Feedback focuses on the maintenance burden of duplicating this extensive documentation across two files and requests clarification on the specified nightly toolchain date, which appears to be a future date and could cause confusion regarding the project's MSRV.
AGENTS.md
Outdated
| ## Project Overview | ||
|
|
||
| Gear Protocol — a Substrate-based platform for running WebAssembly smart contracts (programs) with an actor-model message-passing architecture. The main network is **Vara**. The repo also contains **ethexe**, a layer that runs Gear programs on Ethereum. | ||
|
|
||
| - Rust edition 2024, MSRV 1.91, nightly toolchain (2025-10-20) | ||
| - 114-crate Cargo workspace; default member is `node/cli` (the Vara node binary) | ||
| - `ethexe/` is excluded from the main workspace and has its own Cargo.toml + Solidity contracts (Foundry/Forge) | ||
| - Sails framework lives in a separate repo (github.com/gear-tech/sails), not here | ||
|
|
||
| ## Build & Development Commands | ||
|
|
||
| ### Setup | ||
| ```bash | ||
| make init # Install wasm target + cargo tools (hakari, nextest, etc.) | ||
| ``` | ||
|
|
||
| ### Build | ||
| ```bash | ||
| make gear # Build workspace (debug) | ||
| make node # Build Vara node (debug) | ||
| make node-release # Build Vara node (release) | ||
| make examples # Build example WASM programs | ||
| ``` | ||
|
|
||
| ### Test | ||
| ```bash | ||
| # Workspace tests (uses cargo nextest): | ||
| make test # All workspace tests (excludes gcli, gsdk, fuzzer) | ||
| cargo nextest run -p <crate-name> # Single crate | ||
| cargo nextest run -p <crate-name> -E 'test(name)' # Single test by name filter | ||
| make test-pallet # Pallet tests only | ||
| make test-doc # Doc tests (uses cargo test, not nextest) | ||
|
|
||
| # Ethexe tests: | ||
| cargo nextest run -p "ethexe-*" --no-fail-fast | ||
|
|
||
| # gsdk/gcli tests require a built node: | ||
| make test-gsdk # Builds node-release first | ||
| make test-gcli # Builds node-release first | ||
| ``` | ||
|
|
||
| ### Lint & Format | ||
| ```bash | ||
| make fmt # Format (rustfmt) | ||
| make fmt-check # Check formatting | ||
| make clippy # Clippy for workspace + examples | ||
| make typos # Check for typos (requires typos-cli) | ||
| make pre-commit # Full pre-commit: fmt, typos, hakari, clippy, test, check-runtime-imports | ||
| ``` | ||
|
|
||
| ### Ethexe Contracts (Solidity/Forge) | ||
| ```bash | ||
| make ethexe-contracts-pre-commit # Clean, format, build, test, copy ABIs | ||
| forge test --root ethexe/contracts -vvv | ||
| ``` | ||
|
|
||
| ### Workspace Hakari | ||
| ```bash | ||
| make workspace-hack # Regenerate workspace-hack (cargo hakari generate + post-process) | ||
| ``` | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### Execution Flow | ||
|
|
||
| ``` | ||
| User extrinsic (upload_program / send_message / send_reply) | ||
| → pallet-gear validates, reserves gas+value, queues StoredDispatch | ||
| → run() inherent fires each block (mandatory, unsigned) | ||
| → QueueRunner dequeues dispatches one by one | ||
| → core-processor loads program, creates Ext context | ||
| → core-backend instantiates WASM in sandbox (Wasmer/Wasmtime) | ||
| → Program calls gstd/gcore syscalls → dispatched to host fns | ||
| → lazy-pages intercepts SIGSEGV for on-demand memory paging | ||
| → Execution produces journal notes (outgoing messages, state changes, gas burns) | ||
| → pallet-gear applies journal: route messages, update waitlist/mailbox, transfer value | ||
| ``` | ||
|
|
||
| ### Message Lifecycle | ||
|
|
||
| Messages have four dispatch kinds: **Init**, **Handle**, **Reply**, **Signal**. | ||
|
|
||
| Type progression through the system: | ||
| 1. Created as packets (`InitPacket`, `HandlePacket`, `ReplyPacket`) | ||
| 2. Converted to typed messages (`InitMessage`, `HandleMessage`, etc.) | ||
| 3. Wrapped in `Dispatch` with `DispatchKind` | ||
| 4. Stored as `StoredDispatch` (gasless, persistent) in the message queue | ||
| 5. Dequeued as `IncomingDispatch` (with gas limit) for execution | ||
| 6. `ContextStore` preserves execution state across async boundaries (initialized actors, reservation nonce, local nonce) | ||
|
|
||
| Reply/signal messages carry `MessageDetails` — either `ReplyDetails` (origin message + ReplyCode) or `SignalDetails` (origin message + SignalCode). | ||
|
|
||
| ### Program Lifecycle | ||
|
|
||
| ``` | ||
| [not exists] → upload_program → Active(Uninitialized { message_id }) | ||
| → init succeeds → Active(Initialized) | ||
| → init fails → Terminated(inheritor) | ||
| → gr_exit called → Exited(inheritor) | ||
| → expiration_block reached → removed | ||
| ``` | ||
|
|
||
| `ActiveProgram` fields: `code_id`, `state` (Uninitialized/Initialized), `allocations_tree_len`, `memory_infix` (lazy-page storage namespace), `gas_reservation_map`, `expiration_block`. | ||
|
|
||
| ### Gas Model | ||
|
|
||
| UTXO-like gas tree (`GasTree`) where each message owns a gas node: | ||
| - `GasCounter` tracks `(left, burned)` — `charge()` deducts and records burn, `reduce()` deducts without burn (for sends) | ||
| - `ValueCounter` tracks value (u128) transfers alongside gas | ||
| - `GasAllowanceCounter` enforces block-level gas budget | ||
| - Tree operations: `create`, `split`, `split_with_value`, `cut`, `consume`, `lock`/`unlock` | ||
| - Lock IDs: `Mailbox`, `Waitlist`, `Reservation`, `DispatchStash` | ||
| - Imbalance types (`PositiveImbalance`/`NegativeImbalance`) for accounting correctness | ||
| - `ReservableTree` trait adds gas reservation management (programs can reserve gas for future use) | ||
|
|
||
| ### Queues: Waitlist, Mailbox, TaskPool | ||
|
|
||
| **Message Queue** (gear-messenger): FIFO linked-list of `StoredDispatch` — processed each block by `run()`. | ||
|
|
||
| **Waitlist** (gear-messenger): Programs waiting for a reply. Keyed by `(ActorId, MessageId) → StoredDispatch`. When a reply arrives, the dispatch is woken and re-queued. | ||
|
|
||
| **Mailbox** (gear-messenger): Messages addressed to user accounts. Keyed by `(AccountId, MessageId) → UserStoredMessage`. Users call `claim_value` extrinsic to collect value. Messages have rent (gas-based TTL via `MailboxThreshold`). | ||
|
|
||
| **TaskPool** (gear-scheduler): Delayed actions keyed by `(BlockNumber, Task)`. Task types: delayed message send, wake from waitlist, mailbox expiry removal, reservation cleanup, program stall timeout. | ||
|
|
||
| **Interaction**: Queue → execution → may create Waitlist entry (async reply) or Mailbox entry (user-bound message) → TaskPool schedules cleanup/wake at future block. | ||
|
|
||
| ### Lazy Pages | ||
|
|
||
| Signal-based demand paging for WASM program memory: | ||
| 1. `initialize_for_program()` protects non-stack WASM pages via `mprotect` | ||
| 2. When program accesses a protected page → SIGSEGV fires | ||
| 3. Signal handler loads page data from `LazyPagesStorage`, unprotects the page | ||
| 4. Tracks `accessed_pages` and `write_accessed_pages` for state diff computation | ||
| 5. `PagePrefix` ([u8; 32]) namespaces pages per program via `memory_infix` | ||
|
|
||
| This avoids loading entire program memory upfront — only touched pages are loaded from storage. | ||
|
|
||
| ### Pallet-Gear Extrinsics | ||
|
|
||
| | Extrinsic | Purpose | | ||
| |-----------|---------| | ||
| | `upload_code` | Store WASM code blob (CodeId = blake2 hash) | | ||
| | `upload_program` | Create program + enqueue Init dispatch. ProgramId = blake2(code + salt) | | ||
| | `send_message` | Enqueue Handle dispatch to a program | | ||
| | `send_reply` | Reply to a message in caller's mailbox | | ||
| | `claim_value` | Remove message from mailbox, transfer attached value | | ||
| | `claim_value_to_inheritor` | Traverse exited/terminated inheritance chain to recover stuck balance | | ||
| | `run` | **Mandatory inherent** — processes message queue within block gas limits. Once per block. | | ||
|
|
||
| ### Builtin Actors | ||
|
|
||
| Native Rust actors registered in `pallet-gear-builtin` — no WASM, no gas metering, instant execution. Implement `BuiltinActor` trait with `handle()` and `max_gas()`. Actor IDs derived from `blake2(b"built/in" ++ builtin_id)`. | ||
|
|
||
| Available builtins: BLS12-381 verification, staking proxy, message proxy, Ethereum bridge. | ||
|
|
||
| ### Voucher System | ||
|
|
||
| `pallet-gear-voucher` lets sponsors pre-fund gas for specific users/programs. `VoucherInfo` stores: owner, spender, balance, optional program whitelist, duration, code_uploading flag. Voucher IDs are nonce-based H256. Vouchers can only pay for gas on whitelisted programs — not general transfers. | ||
|
|
||
| ### Ethexe (Ethereum Execution Layer) | ||
|
|
||
| Separate workspace that runs Gear programs on Ethereum via three Solidity contracts: | ||
|
|
||
| **Router**: Central authority. Validators commit state transition batches (`commitBatch`). Handles code validation requests, program creation, computation/validation settings. Manages validator set and signing thresholds. | ||
|
|
||
| **Mirror**: One per Gear program on Ethereum. Stores `stateHash` + `nonce`. `sendMessage()` for user→program messages. `performStateTransition()` applies validated state changes from Router. Handles value claiming and program exit. | ||
|
|
||
| **Middleware**: Validator coordination via Symbiotic framework. Manages operator/vault staking, era transitions, slashing, reward distribution. | ||
|
|
||
| **ethexe runtime** (`ethexe/runtime/`): Gear runtime compiled to `no_std` WASM for EVM context. Differences from Vara: no Substrate pallets, no signaling syscalls, no reservation operations, simplified host function interface via `RuntimeInterface` trait. | ||
|
|
||
| Contract ABIs must be copied after Forge build: `make ethexe-contracts-pre-commit` handles this (copies from `ethexe/contracts/out/` to `ethexe/ethereum/abi/`). | ||
|
|
||
| ### no_std Boundary | ||
|
|
||
| ``` | ||
| WASM program (no_std): gstd → gcore → gsys, gprimitives, gear-core-errors | ||
| ↕ syscall FFI boundary | ||
| Native runtime (std): core-backend → core-processor → pallets → runtime/vara | ||
| ``` | ||
|
|
||
| `no_std` crates use `extern crate alloc` for Vec/BTreeMap/Arc. `std` feature is excluded by `wasm-builder` during program compilation. `ethexe` feature flag in gstd/gcore disables certain syscalls unavailable in the Ethereum context. | ||
|
|
||
| ### WASM Builder | ||
|
|
||
| `utils/wasm-builder` hooks into `build.rs` to compile Gear programs: | ||
| 1. Reads `CARGO_MANIFEST_DIR` and feature flags | ||
| 2. Compiles to `wasm32-unknown-unknown` with nightly toolchain | ||
| 3. Applies `wasm-instrument` for gas metering and stack height checks | ||
| 4. Optimizes via `wasm-optimizer` | ||
| 5. Set `__GEAR_WASM_BUILDER_NO_BUILD=1` or `SKIP_WASM_BUILD=1` to skip (used in doc tests) | ||
|
|
||
| ### Testing (gtest) | ||
|
|
||
| `gtest` simulates a local blockchain. Key abstractions: | ||
| - `System` — singleton runtime environment (one per thread) | ||
| - `Program` — deployed program handle with `send_bytes()`, `read_state()` | ||
| - `System::run_next_block()` — increments block, processes TaskPool then message Queue | ||
| - `Log` — message log builder for assertions | ||
| - `BlockRunResult` — contains succeed/failed/panicked message ID sets | ||
| - `WasmProgram` trait — mock programs with custom `init()`/`handle()`/`state()` for unit testing without WASM | ||
|
|
||
| ### Key Error Categories | ||
|
|
||
| `gear-core-errors` defines `ExtError` with sub-enums: | ||
| - `ExecutionError` (100s): NotEnoughGas, NotEnoughValue, NoReplyContext, NoSignalContext | ||
| - `MemoryError` (200s): RuntimeAllocOutOfBounds, AccessOutOfBounds | ||
| - `MessageError` (300s): MaxMessageSizeExceed, DuplicateReply, DuplicateWaking, OutgoingMessagesAmountLimitExceeded, InsufficientValue/GasLimit | ||
| - `ReservationError` (500s): InvalidReservationId, ReservationsLimitReached, ZeroReservationDuration | ||
|
|
||
| Errors are encoded as little-endian u32. Code `0xffff` is reserved for SyscallUsage, `600` is deprecated (ProgramRent). | ||
|
|
||
| ## Code Conventions | ||
|
|
||
| - `rustfmt.toml`: `imports_granularity = "Crate"`, `format_code_in_doc_comments = true` | ||
| - CI uses `[skip-ci]` (not `[skip ci]`) in commit messages to get green status checks while skipping workflows | ||
| - `cargo nextest` is the test runner (not `cargo test`), except for doc tests | ||
| - `cargo hakari` manages workspace dependency deduplication — run `make workspace-hack` after dependency changes |
There was a problem hiding this comment.
The architectural context, build commands, and code conventions provided in this file are nearly identical to those in CLAUDE.md. Duplicating this extensive content across multiple files creates a maintenance burden. Any future updates to this shared information will require changes in both files, increasing the risk of inconsistencies and potential regressions if one file is updated and the other is overlooked.
Consider consolidating this shared information into a single source of truth, perhaps using a markdown include mechanism if supported by the AI agent's context ingestion, or by clearly designating one file as primary and outlining a process for synchronizing changes.
References
- Maintainability is important, especially when duplication can lead to future regressions or inconsistencies. (link)
AGENTS.md
Outdated
|
|
||
| Gear Protocol — a Substrate-based platform for running WebAssembly smart contracts (programs) with an actor-model message-passing architecture. The main network is **Vara**. The repo also contains **ethexe**, a layer that runs Gear programs on Ethereum. | ||
|
|
||
| - Rust edition 2024, MSRV 1.91, nightly toolchain (2025-10-20) |
There was a problem hiding this comment.
The specification nightly toolchain (2025-10-20) for the MSRV is potentially ambiguous. A "nightly toolchain" typically refers to a continuously updated version, while a specific future date like 2025-10-20 suggests a fixed target or a placeholder. This could lead to confusion for an AI agent (and human developers) trying to determine the correct development environment.
Please clarify if this date represents a future target MSRV, a placeholder, or if the intention is to use the latest nightly toolchain. If it's the latter, specifying a fixed date might be misleading. This comment also applies to CLAUDE.md.
References
- Clarity in documentation is crucial for correctness and avoiding misleading information, especially for AI agents. (link)
- AGENTS.md now references CLAUDE.md as single source of truth instead of duplicating all content - Clarify "nightly toolchain" wording to "pinned nightly nightly-2025-10-20 (see rust-toolchain.toml)" across all files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
All three files cover: execution flow, message/program lifecycle, gas model (GasTree), queues (waitlist/mailbox/taskpool), lazy pages, pallet extrinsics, builtin actors, voucher system, ethexe contracts (Router/Mirror/Middleware), no_std boundary, WASM builder pipeline, gtest abstractions, and error categories.
Test plan
[skip-ci]
🤖 Generated with Claude Code