> [!Note]
> Current version: https://github.com/developeruche/prysm/tree/ca228fca440f72da329f0d5d0488d105a633118c
> [!Tip]
> Legend
> - ✅: Complete!
> - 🚧: Under construction.
> - 🔘: Nothing done.
## ✅ Flags
- **`--activate-zkvm`**: If specified, set `cfg.EnableZkvm` to `true`. We can use `features.Get().EnableZkvm` to access this value in the codebase.
- **`--zkvm-generation-proof-types`**: If specified, set `cfg.ProofGenerationTypes` to the slice of `ExecutionProofId`. We can use `flags.Get().ProofGenerationTypes` to access this value in the codebase.
## ✅ Data types
```go
// ExecutionProofId identifies which zkVM/proof system a proof belongs to.
type ExecutionProofId uint8
```
- **`ExecutionProofId`**: Alias for `uint8`. Implemented in `consensus-types/primitives/execution_proof_id.go` ([Link](https://github.com/syjn99/prysm/blob/2d9e6ad2c8302b0045a4c6020f52e997c3f20bdf/consensus-types/primitives/execution_proof_id.go)).
```protobuf
message ExecutionProof {
// Which proof type (zkVM+EL combination) this proof belongs to
// Examples: 0=SP1+Reth, 1=Risc0+Geth, 2=SP1+Geth, etc.
uint64 proof_id = 1 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.ExecutionProofId"
];
// The slot of the beacon block this proof validates
uint64 slot = 2 [
(ethereum.eth.ext.cast_type) =
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives.Slot"
];
// The block hash of the execution payload this proof validates
bytes block_hash = 3 [ (ethereum.eth.ext.ssz_size) = "32" ];
// The beacon block root corresponding to the beacon block
// with the execution payload, that this proof attests to.
bytes block_root = 4 [ (ethereum.eth.ext.ssz_size) = "32" ];
// The actual proof data
bytes proof_data = 5 [ (ethereum.eth.ext.ssz_max) = "1048576" ];
}
```
- **`ExecutionProof`**: A core SSZ Container that is used in P2P, Proof Generation Service, etc. Defined as a proto message at `proto/prysm/v1alpha1/execution_proof.proto` ([Link](https://github.com/syjn99/prysm/blob/2d9e6ad2c8302b0045a4c6020f52e997c3f20bdf/proto/prysm/v1alpha1/execution_proof.proto)) and implemented corresponding SSZ-related methods (e.g., `MarshalSSZ`, `HashTreeRoot`) under the same directory.
## ✅ Cache
- [x] Currently implemented in `zkvm-execution-layer/proof_cache.go` ([Link](https://github.com/syjn99/prysm/blob/2d9e6ad2c8302b0045a4c6020f52e997c3f20bdf/zkvm-execution-layer/proof_cache.go))
- [x] **would be better** to re-implement and move this under `beacon-chain/cache` ([Link](https://github.com/OffchainLabs/prysm/tree/develop/beacon-chain/cache)). See other cache examples under the directory.
## ✅ P2P
> [!Note]
> We assume all functionalities are enabled **after** Fulu.
### ✅ ENR: `"zkvm"`
When a node activates zkVM mode by `--activate-zkvm`, it *explicitly* advertises by adding an entry for `zkvm`.
- [x] Add `ZkvmKey` (= `zkvm`) under `NetworkConfig` in `config/params/network_config.go`
- [x] Set zkVM entry in `updateSubnetRecordWithMetadataV3`.
### ✅ Gossip
A node [subscribes](https://github.com/OffchainLabs/prysm/blob/2773bdef89ab460aea4353d4d98833a4eeaa4918/beacon-chain/sync/fork_watcher.go#L19) to each pubsub topic *after* chain starts.
Note: Unlike the [specification](https://github.com/ethereum/consensus-specs/blob/master/specs/_features/eip8025/p2p-interface.md#topics-and-messages), current implementation has **one single global** topic `/eth2/{fork_digest}/execution_proof`.
- [x] Add `ExecutionProofTopicFormat`(`/eth2/{fork_digest}/execution_proof`) under `beacon-chain/p2p/topics.go`
- [x] Add `defaultExecutionProofTopicParams()` under `beacon-chain/p2p/gossip_scoring_params.go`
- [x] Add `seenExecutionProofCache` and lock for the Sync service
- [x] Add validation function (`validateExecutionProof()`)
- [x] Add subscriber (`executionProofSubscriber`)
- [x] Register the subscriber (`registerSubscribers`)
### ✅ RPC (Req/Resp)
Handlers for P2P RPC are [registered](https://github.com/OffchainLabs/prysm/blob/2773bdef89ab460aea4353d4d98833a4eeaa4918/beacon-chain/sync/service.go#L383) when the Sync service starts.
- [x] Add `RPCExecutionProofsByRootTopicV1` (`/eth2/beacon_chain/req/execution_proofs_by_root/1/`) under `beacon-chain/p2p/rpc_topic_mappings.go`
- [x] Add an entry for `RPCTopicMappings`
- [x] Add rate limiter for this (modification in `newRateLimiter`)
- [x] Add handler
- [x] Send request by block hash
## ✅ DA Check
```rust!
// Check if this node needs execution proofs to validate blocks.
// Nodes that have EL and generate proofs validate via EL execution.
// Nodes that have EL but DON'T generate proofs are lightweight verifiers and wait for proofs.
// TODO(zkproofs): This is a technicality mainly because we cannot remove the EL on kurtosis
// ie each CL is coupled with an EL
let needs_execution_proofs =
spec.zkvm_min_proofs_required().is_some() && !has_execution_layer_and_proof_gen;
if needs_execution_proofs {
let min_proofs = spec.zkvm_min_proofs_required().unwrap();
let num_proofs = self.execution_proof_subnet_count();
if num_proofs < min_proofs {
// Not enough execution proofs yet
return Ok(None);
}
}
```
We need to add whether we've seen enough proofs. `ReceiveBlock` in `beacon-chain/blockchain/receive_block.go` is the core function when a block is received from gossip/rpc.
```go!
func (s *Service) handleDA(ctx context.Context, avs das.AvailabilityStore, block blocks.ROBlock) (time.Duration, error) {
var err error
start := time.Now()
if avs != nil {
err = avs.IsDataAvailable(ctx, s.CurrentSlot(), block)
} else {
err = s.isDataAvailable(ctx, block)
}
elapsed := time.Since(start)
if err == nil {
dataAvailWaitedTime.Observe(float64(elapsed.Milliseconds()))
}
return elapsed, err
}
```
For now, we can ignore `das.AvailabilityStore` and add proof availability logic in `isDataAvaiable`.
## ✅ Proof Generation Service
- [x] Add skeleton under `beacon-chain/proof-generation` and register when zkVM mode is enabled.
- [x] Generate execution proofs in altruistic manner when a block is imported.
- [x] Check whether the proof generation is needed or not.
- [x] Broadcast the proof via gossipsub.
## 📚 References
- My current implementation: https://github.com/syjn99/prysm/pull/11
- Kev's implementation on Lighthouse: https://github.com/sigp/lighthouse/pull/8316
- Related write-up: https://hackmd.io/@kevaundray/BJeZCo5Tgx
- Developeruche's initial implementation on Prysm: https://github.com/OffchainLabs/prysm/pull/16003
- Related write-up: https://hackmd.io/@0xdeveloperuche/rJyb-aEyWx
- EIP-8025 Specification (Note: Spec is outdated): https://github.com/ethereum/consensus-specs/tree/master/specs/_features/eip8025