Skip to content

Commit ebda271

Browse files
sae: Add README.md to describe C-Chain wrapper design (#5342)
1 parent 9ea99ca commit ebda271

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

vms/saevm/cchain/README.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# C-Chain VM (`cchain`)
2+
3+
`cchain` is the C-Chain VM. It is a thin chain-specific harness around [saevm](../), the generic EVM framework that implements [ACP-194](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/194-streaming-asynchronous-execution). `saevm` does the heavy lifting of block execution, settlement, gas accounting, and EVM gossip. `cchain` adds what makes the chain *the C-Chain*, transactions for moving assets between Primary Network chains, Warp messaging, and validator-voted chain parameters.
4+
5+
## Architecture
6+
7+
The C-Chain is composed of three major components:
8+
9+
1. **AvalancheGo**[networking](../../../network), [consensus](../../../snow), validator-set management, and the external API surface.
10+
2. **SAE** — the generic EVM implementation.
11+
3. **C-Chain** (this package) — the wrapper that adds C-Chain-specific behavior.
12+
13+
```mermaid
14+
flowchart TB
15+
subgraph avago["AvalancheGo"]
16+
consensus["Consensus"]
17+
network["Network"]
18+
apiserver["API Server"]
19+
end
20+
21+
subgraph sae["SAE"]
22+
execution["Execution"]
23+
p2pn["P2P Network"]
24+
rpc["/rpc"]
25+
ws["/ws"]
26+
end
27+
28+
subgraph cchain["C-Chain"]
29+
hook["Hooks"]
30+
warp["Warp"]
31+
db[("Database")]
32+
mempool[("Mempool")]
33+
avax["/avax"]
34+
end
35+
36+
network <--> consensus
37+
network --> p2pn
38+
consensus --> execution
39+
apiserver --> rpc
40+
apiserver --> ws
41+
apiserver --> avax
42+
execution --> hook
43+
44+
hook --> warp
45+
p2pn --> warp
46+
47+
hook --> mempool
48+
p2pn --> mempool
49+
avax --> mempool
50+
51+
hook --> db
52+
warp --> db
53+
mempool --> db
54+
```
55+
56+
Hooks are the seam through which SAE calls into C-Chain-specific code. SAE invokes them throughout a block's lifecycle, most notably:
57+
58+
- **Build** — construct custom header fields and embed cross-chain transactions into the block body.
59+
- **Verify** — enforce validation rules on header fields, embedded transactions, and Warp predicates.
60+
- **Execute** — apply cross-chain transaction state effects and persist emitted Warp messages.
61+
62+
## What `cchain` adds
63+
64+
### Block format changes
65+
66+
`cchain` modifies the standard Ethereum block format. The C-Chain transitioned to this VM from coreth on the same database and block format, so historical blocks must keep parsing and hashing identically and vestigial fields cannot be removed.
67+
68+
#### Block header changes
69+
70+
The block header gains the following extra fields:
71+
72+
- `extDataHash` — keccak256 of the block's cross-chain transaction data.
73+
- `extDataGasUsed` — gas used by cross-chain transactions. No longer used.
74+
- `blockGasCost` — block-level required priority fee. No longer used.
75+
- `timestampMilliseconds` — millisecond-precise timestamp.
76+
- `minDelayExcess` — ACP-226 minimum-delay vote tracker.
77+
- `targetExponent` — ACP-176 gas-target vote tracker.
78+
- `minPriceExponent` — ACP-283 minimum-gas-price vote tracker.
79+
- `settledHeight` — height of the block this header settles.
80+
- `settledGasUnix` — seconds component of the settled block's gas time.
81+
- `settledGasNumerator` — sub-second numerator of the settled block's gas time.
82+
- `settledExcess` — gas excess after executing the settled block.
83+
84+
The block header removes a field:
85+
86+
- `withdrawalsHash` — Avalanche has no beacon-chain withdrawals.
87+
88+
The existing `extra` header field is repurposed to carry the Warp predicate verification results described under [Warp messaging](#warp-messaging).
89+
90+
#### Block body changes
91+
92+
The block body adds two extra fields:
93+
94+
- `version` — legacy format version. Always 0, enforced at parse time.
95+
- `extData` — the encoded cross-chain transactions described under [Cross-chain transactions](#cross-chain-transactions).
96+
97+
The block body removes a field:
98+
99+
- `withdrawals` — Avalanche has no beacon-chain withdrawals.
100+
101+
### Cross-chain transactions
102+
103+
The Primary Network chains, P, X, and C, exchange assets through pair-wise [shared databases](../../../chains/atomic). Each pair of chains has its own database, readable and writable by both chains in the pair.
104+
105+
```mermaid
106+
flowchart TB
107+
P((P-Chain))
108+
X((X-Chain))
109+
C((C-Chain))
110+
111+
PX[("P&X Database")]
112+
CP[("C&P Database")]
113+
CX[("C&X Database")]
114+
115+
P --> PX
116+
X --> PX
117+
P --> CP
118+
C --> CP
119+
X --> CX
120+
C --> CX
121+
```
122+
123+
A cross-chain transfer happens in two steps. An **Export** transaction on the source chain burns the asset and writes a UTXO into the shared store between the source and destination chains. The UTXO specifies who is allowed to consume it. An **Import** transaction, issued by that party on the destination chain, consumes the UTXO and credits funds to addresses of the Import issuer's choice. A transaction's shared-database writes are applied after the block containing it executes, which under SAE is after acceptance.
124+
125+
`cchain` defines both transaction types and their validation rules, and runs a dedicated mempool that gossips them in a bandwidth-optimized way using bloom filters.
126+
127+
#### How transactions enter the mempool
128+
129+
Cross-chain transactions reach the mempool from three independent sources. Every source funnels into the same add path, which checks signatures, state validity, and conflicts.
130+
131+
```mermaid
132+
flowchart LR
133+
rpc["/avax"]
134+
pushgossip["Outbound push gossiper"]
135+
push["Inbound push gossip"]
136+
pull["Pull gossip responses"]
137+
mempool[("Mempool")]
138+
139+
rpc --> pushgossip
140+
rpc --> mempool
141+
push --> mempool
142+
pull --> mempool
143+
```
144+
145+
The entry paths in detail:
146+
147+
- **User RPC submission.** The `/avax` JSON-RPC endpoint receives a transaction and forwards it to the mempool, also enqueuing it on the push gossiper. This is the only path that registers transactions with the push gossiper.
148+
- **Inbound push gossip.** A peer pushes a transaction over the transaction gossip protocol, and the transaction is routed to the same add path.
149+
- **Pull gossip responses.** Periodically, `cchain` sends a bloom filter representing the current state of the mempool to a peer. The peer returns transactions not referenced in the bloom filter, and those transactions are forwarded to the same add path.
150+
151+
Transactions leave the mempool in only three ways. A conflicting higher-fee transaction replaces them, a full pool evicts the lowest-fee transaction in favor of a higher-fee arrival, or an executed block consumes their UTXOs.
152+
153+
### Warp messaging
154+
155+
The C-Chain participates in cross-subnet [Warp messaging](../../platformvm/warp) on both sides, sending messages to other chains and receiving messages from them. Four pieces are involved:
156+
157+
- A custom precompile that lets EVM contracts emit and consume Warp messages.
158+
- Incoming Warp messages encoded in the access list, so the hook implementation can verify them prior to EVM execution.
159+
- [Predicate verification](../../evm/predicate) results encoded into the block header's `extra`.
160+
- The [ACP-118](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/118-warp-signature-request) p2p protocol for collecting BLS signatures from peer validators on outbound messages.
161+
162+
The [warp](warp/README.md) package documents the full message lifecycle, what makes a message signable, and the storage compatibility constraints.
163+
164+
### Validator-voted parameters
165+
166+
Three chain parameters are set by validator vote. Each block moves each parameter toward the builder's configured value. Because block production is stake-weighted, this yields a stake-weighted voting mechanism over the long run.
167+
168+
- **Gas target per second** ([ACP-176](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/176-dynamic-evm-gas-limit-and-price-discovery-updates)) — the throughput target. The rest of ACP-176, gas accounting and the excess tracker, lives in SAE. `cchain` contributes only the target value.
169+
- **Minimum block delay** ([ACP-226](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/226-dynamic-minimum-block-times)) — a lower bound on the time between consecutive blocks. Prevents block production faster than the network can maintain.
170+
- **Minimum gas price** ([ACP-283](https://github.com/avalanche-foundation/ACPs/tree/main/ACPs/283-dynamic-minimum-gas-price)) — a floor on the gas price for transactions to be included in a block.
171+
172+
## References
173+
174+
- [config.md](config.md) — node operator configuration for this VM.
175+
- [warp](warp/README.md) — Warp message lifecycle, signability rules, and storage constraints.

0 commit comments

Comments
 (0)