Skip to content

Commit 43a6a26

Browse files
committed
Refactor documentation for data availability layers and node operations
- Updated Celestia guide to clarify prerequisites, installation, and configuration for connecting Evolve chains to Celestia. - Enhanced Local DA documentation with installation instructions, configuration options, and use cases for development and testing. - Expanded troubleshooting guide with detailed diagnostic commands, common issues, and solutions for node operations. - Created comprehensive upgrades guide covering minor and major upgrades, version compatibility, and rollback procedures. - Added aggregator node documentation detailing configuration, block production settings, and monitoring options. - Introduced attester node overview with configuration and use cases for low-latency applications. - Removed outdated light node documentation. - Improved formatting and clarity in ev-reth chainspec reference for better readability.
1 parent 09ad049 commit 43a6a26

10 files changed

Lines changed: 1493 additions & 214 deletions

File tree

docs/ev-abci/overview.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ ev-abci implements the Executor interface, translating ev-node's calls into ABCI
3737

3838
## Key Differences from CometBFT
3939

40-
| Aspect | CometBFT | ev-abci |
41-
|--------|----------|---------|
42-
| Validators | Multiple validators with staking | Single sequencer |
43-
| Consensus | BFT consensus rounds | Sequencer produces blocks |
44-
| Finality | Instant (BFT) | Soft (P2P) → Hard (DA) |
45-
| Block time | ~6s typical | Configurable (100ms+) |
46-
| Vote extensions | Supported | Not supported |
40+
| Aspect | CometBFT | ev-abci |
41+
|-----------------|----------------------------------|---------------------------|
42+
| Validators | Multiple validators with staking | Single sequencer |
43+
| Consensus | BFT consensus rounds | Sequencer produces blocks |
44+
| Finality | Instant (BFT) | Soft (P2P) → Hard (DA) |
45+
| Block time | ~6s typical | Configurable (100ms+) |
46+
| Vote extensions | Supported | Not supported |
4747

4848
## Benefits
4949

Lines changed: 277 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,279 @@
11
# Custom Precompiles
22

3-
<!-- TODO: Create custom precompiles guide (ev-reth specific)
4-
- What are precompiles
5-
- ev-reth custom precompiles:
6-
- Mint precompile
7-
- Others as they exist
8-
- Adding custom precompiles to ev-reth
9-
- Chainspec activation configuration
10-
- Reference: ev-reth repository
11-
-->
3+
ev-reth supports custom EVM precompiled contracts for chain-specific functionality. This guide covers the built-in precompiles and how to add custom ones.
4+
5+
## What Are Precompiles?
6+
7+
Precompiles are special contracts at predefined addresses that execute native code instead of EVM bytecode. They're used for:
8+
9+
- Computationally expensive operations (cryptography, hashing)
10+
- Chain-specific functionality (minting, governance)
11+
- Operations impossible or inefficient in Solidity
12+
13+
## Built-in ev-reth Precompiles
14+
15+
### Mint Precompile
16+
17+
Allows an authorized address to mint native tokens. Useful for bridging scenarios.
18+
19+
**Address:** `0x0000000000000000000000000000000000000100`
20+
21+
**Configuration (chainspec):**
22+
23+
```json
24+
{
25+
"config": {
26+
"evolve": {
27+
"mintPrecompile": {
28+
"admin": "0xBridgeContract",
29+
"address": "0x0000000000000000000000000000000000000100"
30+
}
31+
}
32+
}
33+
}
34+
```
35+
36+
**Interface:**
37+
38+
```solidity
39+
interface IMint {
40+
/// @notice Mint native tokens to a recipient
41+
/// @param recipient Address to receive tokens
42+
/// @param amount Amount to mint (in wei)
43+
function mint(address recipient, uint256 amount) external;
44+
}
45+
```
46+
47+
**Usage:**
48+
49+
```solidity
50+
// Only callable by admin address
51+
IMint(0x0000000000000000000000000000000000000100).mint(
52+
0xRecipient,
53+
1 ether
54+
);
55+
```
56+
57+
See [Mint Precompile Reference](/ev-reth/features/mint-precompile) for details.
58+
59+
## Creating Custom Precompiles
60+
61+
Custom precompiles require modifying ev-reth source code.
62+
63+
### Step 1: Define the Precompile
64+
65+
Create a new precompile in `crates/precompiles/src/`:
66+
67+
```rust
68+
// my_precompile.rs
69+
use revm::precompile::{Precompile, PrecompileOutput, PrecompileResult};
70+
use revm::primitives::{Bytes, U256};
71+
72+
pub const MY_PRECOMPILE_ADDRESS: Address = address!("0000000000000000000000000000000000000200");
73+
74+
pub fn my_precompile(input: &Bytes, gas_limit: u64) -> PrecompileResult {
75+
// Check gas
76+
let gas_used = 1000; // Base gas cost
77+
if gas_used > gas_limit {
78+
return Err(PrecompileError::OutOfGas);
79+
}
80+
81+
// Parse input
82+
// input[0..4] = function selector
83+
// input[4..] = encoded arguments
84+
85+
// Execute logic
86+
let result = process_input(input)?;
87+
88+
Ok(PrecompileOutput {
89+
gas_used,
90+
bytes: result,
91+
})
92+
}
93+
94+
fn process_input(input: &Bytes) -> Result<Bytes, PrecompileError> {
95+
// Your custom logic here
96+
Ok(Bytes::new())
97+
}
98+
```
99+
100+
### Step 2: Register the Precompile
101+
102+
Add the precompile to the precompile set:
103+
104+
```rust
105+
// In precompiles/src/lib.rs
106+
pub fn evolve_precompiles(chain_spec: &ChainSpec) -> PrecompileSet {
107+
let mut precompiles = standard_precompiles();
108+
109+
// Add mint precompile if configured
110+
if let Some(mint_config) = &chain_spec.evolve.mint_precompile {
111+
precompiles.insert(mint_config.address, mint_precompile);
112+
}
113+
114+
// Add your custom precompile
115+
if chain_spec.evolve.my_feature_enabled {
116+
precompiles.insert(MY_PRECOMPILE_ADDRESS, my_precompile);
117+
}
118+
119+
precompiles
120+
}
121+
```
122+
123+
### Step 3: Add Chainspec Configuration
124+
125+
Define configuration structure:
126+
127+
```rust
128+
// In chainspec types
129+
#[derive(Debug, Clone, Serialize, Deserialize)]
130+
pub struct MyPrecompileConfig {
131+
pub address: Address,
132+
pub admin: Option<Address>,
133+
pub some_parameter: u64,
134+
}
135+
```
136+
137+
Update chainspec parsing to include new config.
138+
139+
### Step 4: Build and Test
140+
141+
```bash
142+
# Build ev-reth
143+
cargo build --release
144+
145+
# Run tests
146+
cargo test --package ev-reth-precompiles
147+
```
148+
149+
## Precompile Best Practices
150+
151+
### Gas Metering
152+
153+
Charge gas proportional to computation:
154+
155+
```rust
156+
fn my_precompile(input: &Bytes, gas_limit: u64) -> PrecompileResult {
157+
// Base cost
158+
let mut gas_used = 100;
159+
160+
// Per-byte cost for input processing
161+
gas_used += input.len() as u64 * 3;
162+
163+
// Additional cost for expensive operations
164+
if requires_crypto_operation(input) {
165+
gas_used += 10000;
166+
}
167+
168+
if gas_used > gas_limit {
169+
return Err(PrecompileError::OutOfGas);
170+
}
171+
172+
// Process...
173+
}
174+
```
175+
176+
### Access Control
177+
178+
For privileged operations, check caller:
179+
180+
```rust
181+
fn admin_only_precompile(
182+
input: &Bytes,
183+
context: &PrecompileContext,
184+
config: &MyConfig,
185+
) -> PrecompileResult {
186+
// Verify caller is admin
187+
if context.caller != config.admin {
188+
return Err(PrecompileError::Custom("unauthorized".into()));
189+
}
190+
191+
// Process...
192+
}
193+
```
194+
195+
### Input Validation
196+
197+
Always validate input thoroughly:
198+
199+
```rust
200+
fn my_precompile(input: &Bytes) -> PrecompileResult {
201+
// Check minimum length
202+
if input.len() < 36 { // 4 byte selector + 32 byte arg
203+
return Err(PrecompileError::InvalidInput);
204+
}
205+
206+
// Validate selector
207+
let selector = &input[0..4];
208+
if selector != MY_FUNCTION_SELECTOR {
209+
return Err(PrecompileError::InvalidInput);
210+
}
211+
212+
// Parse and validate arguments
213+
let amount = U256::from_be_slice(&input[4..36]);
214+
if amount.is_zero() {
215+
return Err(PrecompileError::InvalidInput);
216+
}
217+
218+
// Process...
219+
}
220+
```
221+
222+
### Determinism
223+
224+
Precompiles must be deterministic:
225+
226+
- No random number generation
227+
- No external network calls
228+
- No time-dependent logic
229+
- Same input always produces same output
230+
231+
## Testing Precompiles
232+
233+
### Unit Tests
234+
235+
```rust
236+
#[cfg(test)]
237+
mod tests {
238+
use super::*;
239+
240+
#[test]
241+
fn test_my_precompile_success() {
242+
let input = encode_input(/* args */);
243+
let result = my_precompile(&input, 100000).unwrap();
244+
assert_eq!(result.bytes, expected_output());
245+
}
246+
247+
#[test]
248+
fn test_my_precompile_out_of_gas() {
249+
let input = encode_input(/* args */);
250+
let result = my_precompile(&input, 10); // Too little gas
251+
assert!(matches!(result, Err(PrecompileError::OutOfGas)));
252+
}
253+
}
254+
```
255+
256+
### Integration Tests
257+
258+
Test precompile calls from Solidity:
259+
260+
```solidity
261+
// test/MyPrecompile.t.sol
262+
contract MyPrecompileTest is Test {
263+
address constant PRECOMPILE = 0x0000000000000000000000000000000000000200;
264+
265+
function testPrecompileCall() public {
266+
(bool success, bytes memory result) = PRECOMPILE.call(
267+
abi.encodeWithSignature("myFunction(uint256)", 100)
268+
);
269+
assertTrue(success);
270+
// Assert result...
271+
}
272+
}
273+
```
274+
275+
## See Also
276+
277+
- [Mint Precompile](/ev-reth/features/mint-precompile) - Built-in minting
278+
- [ev-reth Configuration](/ev-reth/configuration) - Chainspec setup
279+
- [ev-reth Overview](/ev-reth/overview) - Architecture

0 commit comments

Comments
 (0)