This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
ev-node is a sovereign rollup framework built in Go that allows developers to build rollups on any DA layer. It provides a modular architecture where components like the data availability layer, executor, and sequencer can be plugged in.
Uses just as the command runner. Run just help to list all recipes.
just build- Builds the Testapp CLI to./build/testappjust install- Installs Testapp CLI to your Go bin directoryjust build-all- Builds all ev-node binariesjust docker-build- Builds Docker image tagged asevstack:local-dev
just test- Runs unit tests for all go.mod filesjust test-integration- Runs integration tests (15m timeout)just test-e2e- Runs end-to-end tests (requires building binaries first)just test-cover- Generates code coverage reportjust test-all- Runs all tests including Docker E2E tests
just lint- Runs all linters (golangci-lint, markdownlint, hadolint, yamllint, goreleaser check, actionlint)just lint-fix- Auto-fixes linting issues where possiblejust vet- Runs go vet
just deps- Downloads dependencies and runs go mod tidy for all modulesjust proto-gen- Generates protobuf files (requires Docker)just mock-gen- Generates mocks using mockeryjust run-n 3- Run multiple nodes locally (default: 1)
The project uses a zero-dependency core package pattern:
- core/ - Contains only interfaces and types, no external dependencies
- block/ - Block management, creation, validation, and synchronization
- pkg/p2p/ - Networking layer built on libp2p
- pkg/sequencers/ - Modular sequencer implementations
- apps/testapp/ - Reference implementation for testing
- Executor (
core/executor.go) - Handles state transitions - Sequencer (
core/sequencer.go) - Orders transactions - DA (
pkg/da/types) - Data availability layer abstraction
- Each component has an interface in the core package
- Implementations are in separate packages
- Components are wired together via dependency injection
- Multiple go.mod files enable modular builds
- Built on libp2p with GossipSub and Kademlia DHT
- Nodes advertise capabilities (full/light, DA layers)
- Automatic peer discovery with rendezvous points
- Unit tests:
*_test.gofiles alongside code - Integration tests:
test/integration/ - E2E tests:
test/e2e/
# Run a single test
go test -run TestSpecificFunction ./package/...
# Run with verbose output
go test -v ./package/...
# Run with race detection
go test -race ./package/...- Mocks are defined in
.mockery.yaml - Generate with
just mock-gen - Mocks are placed in
mocks/directories
- Follow standard Go formatting (enforced by golangci-lint)
- Use meaningful variable names
- Keep functions small and focused
- Document exported types and functions
- Use context.Context for cancellation
- Wrap errors with context using
fmt.Errorf - Return errors early
- Use custom error types for domain-specific errors
- Use structured logging (look for existing patterns)
- Include relevant context in log messages
- Use appropriate log levels
- Implement the
DAinterface frompkg/da/types - Add configuration in the appropriate config package
- Wire it up in the initialization code
- Add tests following existing patterns
- Edit
.protofiles intypes/pb/ - Run
just proto-gento regenerate Go code - Update any affected code
- Run tests to ensure compatibility
- Place unit tests next to the code being tested
- Use table-driven tests where appropriate
- Mock external dependencies using mockery
- Ensure tests are deterministic
- Never expose private keys in logs or errors
- Validate all inputs from external sources
- Use secure random number generation
- Follow the principle of least privilege
- Be careful with concurrent access to shared state
- The project uses concurrent processing extensively
- Be mindful of goroutine leaks
- Use buffered channels appropriately
- Profile before optimizing
- Consider memory allocation in hot paths
- Use
just run-n 2to test multi-node scenarios locally - Check logs for error messages and stack traces
- Use Go's built-in profiling tools for performance issues
- The testapp provides a simple way to test changes
- All code must pass linting (
just lint) - All tests must pass (
just test-all) - Follow the existing code patterns
- Update tests when changing functionality
- Keep commits focused and atomic