diff --git a/contracts/src/SP1Helios.sol b/contracts/src/SP1Helios.sol index 1650b4f..6d7beaa 100644 --- a/contracts/src/SP1Helios.sol +++ b/contracts/src/SP1Helios.sol @@ -46,7 +46,10 @@ contract SP1Helios { uint256 newHead; bytes32 prevHeader; uint256 prevHead; + // Hash of the sync committee at the new head. bytes32 syncCommitteeHash; + // Hash of the current sync committee that signed the previous update. + bytes32 startSyncCommitteeHash; } struct InitParams { @@ -72,6 +75,7 @@ contract SP1Helios { error SyncCommitteeAlreadySet(uint256 period); error HeaderRootAlreadySet(uint256 slot); error StateRootAlreadySet(uint256 slot); + error SyncCommitteeStartMismatch(bytes32 given, bytes32 expected); constructor(InitParams memory params) { GENESIS_VALIDATORS_ROOT = params.genesisValidatorsRoot; @@ -99,17 +103,31 @@ contract SP1Helios { revert SlotBehindHead(po.newHead); } + uint256 currentPeriod = getSyncCommitteePeriod(head); + + // Note: We should always have a sync committee for the current head. + // The "start" sync committee hash is the hash of the sync committee that should sign the next update. + bytes32 currentSyncCommitteeHash = syncCommittees[currentPeriod]; + if (currentSyncCommitteeHash != po.startSyncCommitteeHash) { + revert SyncCommitteeStartMismatch(po.startSyncCommitteeHash, currentSyncCommitteeHash); + } + // Verify the proof with the associated public values. This will revert if proof invalid. ISP1Verifier(verifier).verifyProof(heliosProgramVkey, publicValues, proof); + // Check that the new header hasnt been set already. head = po.newHead; if (headers[po.newHead] != bytes32(0)) { revert HeaderRootAlreadySet(po.newHead); } + + // Check that the new state root hasnt been set already. headers[po.newHead] = po.newHeader; if (executionStateRoots[po.newHead] != bytes32(0)) { revert StateRootAlreadySet(po.newHead); } + + // Finally set the new state root. executionStateRoots[po.newHead] = po.executionStateRoot; emit HeadUpdate(po.newHead, po.newHeader); diff --git a/elf/sp1-helios-elf b/elf/sp1-helios-elf index 99ec0c9..cfbda71 100755 Binary files a/elf/sp1-helios-elf and b/elf/sp1-helios-elf differ diff --git a/primitives/src/types.rs b/primitives/src/types.rs index 4e28a0a..c3463d4 100644 --- a/primitives/src/types.rs +++ b/primitives/src/types.rs @@ -33,5 +33,6 @@ sol! { bytes32 prevHeader; uint256 prevHead; bytes32 syncCommitteeHash; + bytes32 startSyncCommitteeHash; } } diff --git a/program/src/main.rs b/program/src/main.rs index ccf48ca..a3a2026 100644 --- a/program/src/main.rs +++ b/program/src/main.rs @@ -27,6 +27,7 @@ pub fn main() { forks, } = serde_cbor::from_slice(&encoded_inputs).unwrap(); + let start_sync_committee_hash = store.current_sync_committee.tree_hash_root(); let prev_header: B256 = store.finalized_header.beacon().tree_hash_root(); let prev_head = store.finalized_header.beacon().slot; @@ -84,6 +85,7 @@ pub fn main() { prevHeader: prev_header, prevHead: U256::from(prev_head), syncCommitteeHash: sync_committee_hash, + startSyncCommitteeHash: start_sync_committee_hash, }; sp1_zkvm::io::commit_slice(&proof_outputs.abi_encode()); }