|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +Gaiko is a Golang port of Raiko, a state transition prover for Taiko blockchain that runs in Trusted Execution Environments (TEEs). It performs state transitions for Ethereum-compatible blocks and generates cryptographic proofs using SGX (Software Guard Extensions) technology. |
| 8 | + |
| 9 | +## Quick Start |
| 10 | + |
| 11 | +### Development Setup |
| 12 | + |
| 13 | +```bash |
| 14 | +# Build for development (no TEE required) |
| 15 | +go build -tags dev -o gaiko ./cmd/gaiko |
| 16 | + |
| 17 | +# Run tests with required environment variable |
| 18 | +GAIKO=1 go test ./... |
| 19 | + |
| 20 | +# Run specific test suite |
| 21 | +cd tests && GAIKO=1 go test -v -run TestSingle |
| 22 | +``` |
| 23 | + |
| 24 | +### Common Workflows |
| 25 | + |
| 26 | +**Running a single block proof:** |
| 27 | + |
| 28 | +```bash |
| 29 | +GAIKO=1 ./gaiko one-shot --sgx-type dev --witness input.json --proof output.json |
| 30 | +``` |
| 31 | + |
| 32 | +**Running batch block proofs:** |
| 33 | + |
| 34 | +```bash |
| 35 | +GAIKO=1 ./gaiko one-batch-shot --sgx-type dev --witness batch-input.json --proof batch-output.json |
| 36 | +``` |
| 37 | + |
| 38 | +**Starting the API server:** |
| 39 | + |
| 40 | +```bash |
| 41 | +GAIKO=1 ./gaiko server --sgx-type dev --port 8080 |
| 42 | +``` |
| 43 | + |
| 44 | +## Build Commands |
| 45 | + |
| 46 | +### Standard Build |
| 47 | + |
| 48 | +```bash |
| 49 | +go build -o gaiko ./cmd/gaiko |
| 50 | +``` |
| 51 | + |
| 52 | +### SGX/TEE Builds |
| 53 | + |
| 54 | +For production SGX builds using EGO: |
| 55 | + |
| 56 | +```bash |
| 57 | +ego-go build -o gaiko-ego ./cmd/gaiko |
| 58 | +ego sign && ego bundle gaiko-ego gaiko |
| 59 | +ego uniqueid gaiko-ego |
| 60 | +ego signerid gaiko-ego |
| 61 | +``` |
| 62 | + |
| 63 | +For development mode (without TEE): |
| 64 | + |
| 65 | +```bash |
| 66 | +go build -tags dev -o gaiko ./cmd/gaiko |
| 67 | +``` |
| 68 | + |
| 69 | +### Docker Build |
| 70 | + |
| 71 | +```bash |
| 72 | +./scripts/build-docker.sh |
| 73 | +# Interactive: choose local(0) for gaiko-local image |
| 74 | +``` |
| 75 | + |
| 76 | +## Testing |
| 77 | + |
| 78 | +**IMPORTANT**: All tests require the `GAIKO=1` environment variable to be set. |
| 79 | + |
| 80 | +### Run All Tests |
| 81 | + |
| 82 | +```bash |
| 83 | +GAIKO=1 go test ./... |
| 84 | +``` |
| 85 | + |
| 86 | +### Run Specific Test Suites |
| 87 | + |
| 88 | +```bash |
| 89 | +cd tests |
| 90 | +GAIKO=1 go test -v -run TestSingle # Test single block transitions |
| 91 | +GAIKO=1 go test -v -run TestBatch # Test batch block transitions |
| 92 | +GAIKO=1 go test -v -run TestAggregate # Test aggregate proofs |
| 93 | +``` |
| 94 | + |
| 95 | +### Run Tests in Specific Packages |
| 96 | + |
| 97 | +```bash |
| 98 | +GAIKO=1 go test -v ./internal/prover/... |
| 99 | +GAIKO=1 go test -v ./internal/transition/... |
| 100 | +GAIKO=1 go test -v ./pkg/mpt/... |
| 101 | +``` |
| 102 | + |
| 103 | +### Run Tests with Race Detection |
| 104 | + |
| 105 | +```bash |
| 106 | +GAIKO=1 go test -race ./... |
| 107 | +``` |
| 108 | + |
| 109 | +### Run Tests with Coverage |
| 110 | + |
| 111 | +```bash |
| 112 | +GAIKO=1 go test -coverprofile=coverage.out ./... |
| 113 | +go tool cover -html=coverage.out |
| 114 | +``` |
| 115 | + |
| 116 | +## Environment Variables |
| 117 | + |
| 118 | +- `GAIKO=1` - **Required** for all tests and runtime execution. Must be set when running gaiko commands. |
| 119 | +- `PORT` - Override default server port (8080) |
| 120 | +- `LOG_LEVEL` - Control logging verbosity (debug, info, warn, error) |
| 121 | + |
| 122 | +## CLI Commands |
| 123 | + |
| 124 | +Gaiko provides several subcommands: |
| 125 | + |
| 126 | +- `one-shot` - Run state transition for a single block |
| 127 | +- `one-batch-shot` - Run state transitions for multiple blocks in a batch |
| 128 | +- `aggregate` - Run aggregate proof generation |
| 129 | +- `bootstrap` - Initialize TEE instance with cryptographic keys |
| 130 | +- `check` - Verify TEE instance configuration |
| 131 | +- `server` - Start HTTP API server (port 8080 by default) |
| 132 | + |
| 133 | +### Common Flags |
| 134 | + |
| 135 | +All commands support: |
| 136 | + |
| 137 | +- `--sgx-type` - TEE type: "debug", "ego", "gramine", or "dev" |
| 138 | +- `--witness` - Input witness file path |
| 139 | +- `--proof` - Output proof file path |
| 140 | +- `--config-dir` - Configuration directory (default: ~/.config/raiko/config) |
| 141 | +- `--secret-dir` - Secrets directory (default: ~/.config/raiko/secrets) |
| 142 | + |
| 143 | +### CLI Examples |
| 144 | + |
| 145 | +**Initialize TEE instance:** |
| 146 | + |
| 147 | +```bash |
| 148 | +GAIKO=1 ./gaiko bootstrap --sgx-type ego --config-dir ./config --secret-dir ./secrets |
| 149 | +``` |
| 150 | + |
| 151 | +**Check TEE configuration:** |
| 152 | + |
| 153 | +```bash |
| 154 | +GAIKO=1 ./gaiko check --sgx-type ego |
| 155 | +``` |
| 156 | + |
| 157 | +**Generate aggregate proof:** |
| 158 | + |
| 159 | +```bash |
| 160 | +GAIKO=1 ./gaiko aggregate --sgx-type dev --witness aggregate-input.json --proof aggregate-output.json |
| 161 | +``` |
| 162 | + |
| 163 | +## Architecture |
| 164 | + |
| 165 | +### High-Level Data Flow |
| 166 | + |
| 167 | +1. **Input**: Witness data (GuestInput or BatchGuestInput) containing block headers, transactions, state tries, and Taiko-specific metadata |
| 168 | +2. **Verification**: Validate chain specs, blob proofs, and input consistency |
| 169 | +3. **Transition**: Execute block transactions using stateless witness approach |
| 170 | +4. **Proof Generation**: Generate SGX attestation quotes and cryptographic proofs |
| 171 | +5. **Output**: ProofResponse with state root, block hash, and TEE attestation |
| 172 | + |
| 173 | +### Core Components |
| 174 | + |
| 175 | +**`internal/prover`** - Prover abstraction layer |
| 176 | + |
| 177 | +- `Prover` interface defines methods: Oneshot, BatchOneshot, Aggregate, Bootstrap, Check |
| 178 | +- `SGXProver` implements TEE-backed proving using Provider interface |
| 179 | +- Proof generation (genOneshotProof, genAggregateProof) handles signing and attestation |
| 180 | + |
| 181 | +**`internal/witness`** - Witness data structures |
| 182 | + |
| 183 | +- `GuestInput`: Single block witness with parent state, transactions, Taiko metadata |
| 184 | +- `BatchGuestInput`: Multiple block witness for batch processing |
| 185 | +- `WitnessInput` interface with methods: GuestInputs(), Verify(), BlockMetadataFork(), etc. |
| 186 | +- Implements unmarshaling logic for different Taiko hard forks (Hekla, Ontake, Shasta) |
| 187 | +- Converts MPT tries to stateless witnesses for go-ethereum's ExecuteStateless |
| 188 | + |
| 189 | +**`internal/transition`** - State transition execution |
| 190 | + |
| 191 | +- `ExecuteAndVerify()`: Main entry point that executes blocks using stateless witness |
| 192 | +- Uses `core.ExecuteStateless()` from go-ethereum for verification |
| 193 | +- Validates state root and receipt root match expected values |
| 194 | +- Runs transitions concurrently using errgroup for batch inputs |
| 195 | + |
| 196 | +**`internal/tee`** - TEE provider abstraction |
| 197 | + |
| 198 | +- `Provider` interface for SGX operations (LoadQuote, LoadPrivateKey, SavePrivateKey) |
| 199 | +- Implementations: EGO (`sgx_ego.go`), Gramine (`sgx_gramine.go`), TDX (`tdx.go`), Dev mode (`dev.go`) |
| 200 | +- Bootstrap data saves public key, instance address, and attestation quote |
| 201 | + |
| 202 | +**`internal/types`** - Type conversions between Raiko and Gaiko |
| 203 | + |
| 204 | +- Ethereum types (Header, Transaction, Block, AccessList) |
| 205 | +- Taiko event types (BlockProposed, BlockMetadata, BatchProposed) |
| 206 | +- Uses `fjl/gencodec` for JSON marshaling code generation |
| 207 | + |
| 208 | +**`pkg/mpt`** - Merkle Patricia Trie implementation |
| 209 | + |
| 210 | +- Ported from Raiko's Rust implementation |
| 211 | +- Provides stateful MPT operations (Get, Insert, Delete, Hash) |
| 212 | +- Converts to stateless witness format for go-ethereum |
| 213 | + |
| 214 | +**`pkg/keccak`** - Pooled Keccak hasher |
| 215 | + |
| 216 | +- Thread-safe hasher pool for performance |
| 217 | +- Single function `Keccak(data []byte) common.Hash` |
| 218 | + |
| 219 | +### Hard Fork Support |
| 220 | + |
| 221 | +Gaiko supports multiple Taiko protocol versions: |
| 222 | + |
| 223 | +- **Hekla**: Uses BlockMetadata with single block parameters |
| 224 | +- **Ontake**: Uses BlockMetadataV2 with enhanced fields (liveness bond, base fee config) |
| 225 | +- **Pacaya**: Batch mode with multi-block support |
| 226 | +- **Shasta**: Latest fork with manifest-based transaction derivation |
| 227 | + |
| 228 | +Hard fork detection is automatic based on BlockProposed event structure. |
| 229 | + |
| 230 | +### Witness to Stateless Conversion |
| 231 | + |
| 232 | +The key innovation is `GuestInput.NewWitness()` in `internal/witness/stateless.go`: |
| 233 | + |
| 234 | +1. Collects all MPT nodes from parent state trie and storage tries |
| 235 | +2. Validates parent state root matches expected value |
| 236 | +3. Packages nodes into `stateless.Witness` structure |
| 237 | +4. Allows go-ethereum's `core.ExecuteStateless()` to verify transitions without full state DB |
| 238 | + |
| 239 | +### Build Tags |
| 240 | + |
| 241 | +- `dev` tag: Use development TEE provider (no actual SGX, for testing) |
| 242 | +- Default (no tags): Use production TEE providers (EGO/Gramine/TDX) |
| 243 | + |
| 244 | +### Testing Fixtures |
| 245 | + |
| 246 | +Test fixtures in `tests/fixtures/` contain: |
| 247 | + |
| 248 | +- JSON input files with witness data |
| 249 | +- JSON output files with expected proofs |
| 250 | +- Embedded using `//go:embed` for convenient testing |
| 251 | + |
| 252 | +## Code Generation |
| 253 | + |
| 254 | +Several types use code generation: |
| 255 | + |
| 256 | +- `internal/types/gen_*.go` - JSON marshalers via `fjl/gencodec` |
| 257 | +- `internal/witness/gen_*.go` - Chain spec and constant marshalers |
| 258 | + |
| 259 | +Regenerate with: |
| 260 | + |
| 261 | +```bash |
| 262 | +go generate ./... |
| 263 | +``` |
| 264 | + |
| 265 | +## Dependencies |
| 266 | + |
| 267 | +Key dependencies: |
| 268 | + |
| 269 | +- `github.com/ethereum/go-ethereum` - Core Ethereum types and execution (custom fork: taikoxyz/taiko-geth) |
| 270 | +- `github.com/ethereum-optimism/optimism` - Blob utilities (custom fork: taikoxyz/optimism) |
| 271 | +- `github.com/taikoxyz/taiko-mono` - Taiko protocol bindings and utilities |
| 272 | +- `github.com/edgelesssys/ego` - EGO SGX framework |
| 273 | +- `github.com/google/go-tdx-guest` - TDX attestation |
| 274 | +- `github.com/urfave/cli/v2` - CLI framework |
| 275 | + |
| 276 | +## Debugging |
| 277 | + |
| 278 | +### Enable Debug Logging |
| 279 | + |
| 280 | +```bash |
| 281 | +GAIKO=1 LOG_LEVEL=debug ./gaiko one-shot --sgx-type dev --witness input.json |
| 282 | +``` |
| 283 | + |
| 284 | +### Run with Delve Debugger |
| 285 | + |
| 286 | +```bash |
| 287 | +GAIKO=1 dlv debug ./cmd/gaiko -- one-shot --sgx-type dev --witness input.json |
| 288 | +``` |
| 289 | + |
| 290 | +### Useful Debug Commands |
| 291 | + |
| 292 | +```bash |
| 293 | +# Check Go environment |
| 294 | +go env |
| 295 | + |
| 296 | +# Verify module dependencies |
| 297 | +go mod verify |
| 298 | +go mod tidy |
| 299 | + |
| 300 | +# View test output with verbose logging |
| 301 | +GAIKO=1 go test -v -count=1 ./tests |
| 302 | +``` |
| 303 | + |
| 304 | +## Troubleshooting |
| 305 | + |
| 306 | +### Common Issues |
| 307 | + |
| 308 | +**Commands fail or behave unexpectedly:** |
| 309 | +- Solution: Always set `GAIKO=1` environment variable for ALL gaiko operations (tests and runtime) |
| 310 | +- Example for tests: `GAIKO=1 go test ./...` |
| 311 | +- Example for runtime: `GAIKO=1 ./gaiko one-shot --sgx-type dev --witness input.json` |
| 312 | + |
| 313 | +**Build fails with SGX errors:** |
| 314 | +- Ensure you're using the correct build command for your target |
| 315 | +- For development without TEE: `go build -tags dev -o gaiko ./cmd/gaiko` |
| 316 | +- For production SGX: Use `ego-go build` commands |
| 317 | + |
| 318 | +**Witness validation errors:** |
| 319 | +- Verify the witness file matches the expected hard fork (Hekla, Ontake, Pacaya, Shasta) |
| 320 | +- Check that parent state root is correct |
| 321 | +- Ensure block continuity for batch inputs |
| 322 | + |
| 323 | +**State root mismatch:** |
| 324 | +- Verify all MPT nodes are included in the witness |
| 325 | +- Check transaction execution order matches expected sequence |
| 326 | +- Validate chain spec parameters match the network |
| 327 | + |
| 328 | +## Development Tips |
| 329 | + |
| 330 | +### Working with Different Hard Forks |
| 331 | + |
| 332 | +The codebase automatically detects hard forks based on witness structure. When adding support for new forks: |
| 333 | + |
| 334 | +1. Update `internal/witness/input.go` with new metadata structures |
| 335 | +2. Add unmarshaling logic in `UnmarshalJSON` methods |
| 336 | +3. Update `BlockMetadataFork()` to detect the new fork |
| 337 | +4. Add test fixtures in `tests/fixtures/` |
| 338 | + |
| 339 | +### Adding New Test Cases |
| 340 | + |
| 341 | +1. Generate witness data from Raiko or create manually |
| 342 | +2. Place in `tests/fixtures/proposals/` directory |
| 343 | +3. Add expected output in `tests/fixtures/proofs/` |
| 344 | +4. Update test files to include new case |
| 345 | +5. Run with: `cd tests && GAIKO=1 go test -v -run TestSingle` |
| 346 | + |
| 347 | +### Code Style Guidelines |
| 348 | + |
| 349 | +- Follow standard Go conventions (gofmt, golint) |
| 350 | +- Use meaningful variable names that reflect domain concepts |
| 351 | +- Add comments for complex cryptographic or TEE operations |
| 352 | +- Keep functions focused and modular |
| 353 | +- Write tests for all new functionality |
| 354 | + |
| 355 | +## Important Notes |
| 356 | + |
| 357 | +- **`GAIKO=1` environment variable is required for ALL operations** - both tests and runtime execution. Always prefix commands with `GAIKO=1` |
| 358 | +- Always use `go-ethereum`'s stateless witness approach (`core.ExecuteStateless`) for block verification |
| 359 | +- TEE providers must implement secure key storage - private keys are sealed to MRENCLAVE |
| 360 | +- Blob proofs support two modes: KZG versioned hash or proof of equivalence |
| 361 | +- Batch inputs require strict block continuity validation (sequential parent-child relationships) |
| 362 | +- For Shasta fork, transaction manifests are decoded from blob data at specific offsets |
| 363 | +- This requirement is critical for CI/CD pipelines and production deployments |
0 commit comments