Skip to content

Commit d50427b

Browse files
feat: turn program IDs into a mapping
1 parent 7048c1b commit d50427b

12 files changed

+128
-60
lines changed

aggregation_mode/README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ We are using docker to produce deterministic builds so that the program ids are
7676

7777
### Updating the program id in `AlignedProofAggregationService` contract
7878

79-
If the program ids have changed, you will also need to update them in the `AlignedProofAggregationService` contract.
79+
If the program ids have changed, you will also need to add the updated one to the `AlignedProofAggregationService` contract. You can do this by calling the `addProgramId` method with the new image ID and the verifier type number as parameters (you can check the last parameter in the VerifierType definition at `contracts/src/core/AlignedProofAggregationService.sol`).
8080

81-
- Risc0: call `setRisc0AggregatorProgramImageId` method with the value of `risc0_root_aggregator_image_id` from `aggregation_mode/program_ids.json`.
82-
- SP1: call: `setSP1AggregatorProgramVKHash` method with the value of `sp1_root_aggregator_vk_hash` from `aggregation_mode/program_ids.json`.
81+
You can fetch the program ID values from the following:
82+
83+
- Risc0: Use the value of `risc0_root_aggregator_image_id` from `aggregation_mode/program_ids.json`.
84+
- SP1: Use the value of `sp1_root_aggregator_vk_hash` from `aggregation_mode/program_ids.json`.

aggregation_mode/abi/AlignedProofAggregationService.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

aggregation_mode/src/backend/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub struct Config {
2323
pub ecdsa: ECDSAConfig,
2424
pub proofs_per_chunk: u16,
2525
pub total_proofs_limit: u16,
26+
pub sp1_chunk_aggregator_vk_hash: String,
27+
pub risc0_chunk_aggregator_image_id: String,
2628
}
2729

2830
impl Config {

aggregation_mode/src/backend/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub struct ProofAggregator {
4444
proof_aggregation_service: AlignedProofAggregationServiceContract,
4545
fetcher: ProofsFetcher,
4646
config: Config,
47+
sp1_chunk_aggregator_vk_hash_bytes: [u8; 32],
48+
risc0_chunk_aggregator_image_id_bytes: [u8; 32],
4749
}
4850

4951
impl ProofAggregator {
@@ -66,11 +68,27 @@ impl ProofAggregator {
6668
ZKVMEngine::from_env().expect("AGGREGATOR env variable to be set to one of sp1|risc0");
6769
let fetcher = ProofsFetcher::new(&config);
6870

71+
let sp1_chunk_aggregator_vk_hash_bytes: [u8; 32] =
72+
hex::decode(&config.sp1_chunk_aggregator_vk_hash)
73+
.expect("Failed to decode SP1 chunk aggregator VK hash")
74+
.as_slice()
75+
.try_into()
76+
.expect("SP1 chunk aggregator VK hash must be 32 bytes");
77+
78+
let risc0_chunk_aggregator_image_id_bytes: [u8; 32] =
79+
hex::decode(&config.risc0_chunk_aggregator_image_id)
80+
.expect("Failed to decode Risc0 chunk aggregator image id")
81+
.as_slice()
82+
.try_into()
83+
.expect("Risc0 chunk aggregator image id must be 32 bytes");
84+
6985
Self {
7086
engine,
7187
proof_aggregation_service,
7288
fetcher,
7389
config,
90+
sp1_chunk_aggregator_vk_hash_bytes,
91+
risc0_chunk_aggregator_image_id_bytes,
7492
}
7593
}
7694

@@ -161,6 +179,7 @@ impl ProofAggregator {
161179
blob_versioned_hash.into(),
162180
proof.proof_with_pub_values.public_values.to_vec().into(),
163181
proof.proof_with_pub_values.bytes().into(),
182+
self.sp1_chunk_aggregator_vk_hash_bytes.into(),
164183
)
165184
.sidecar(blob)
166185
.into_transaction_request(),
@@ -173,6 +192,7 @@ impl ProofAggregator {
173192
blob_versioned_hash.into(),
174193
encoded_seal.into(),
175194
proof.receipt.journal.bytes.into(),
195+
self.risc0_chunk_aggregator_image_id_bytes.into(),
176196
)
177197
.sidecar(blob)
178198
.into_transaction_request()

config-files/config-proof-aggregator-ethereum-package.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ proofs_per_chunk: 512 # Amount of proofs to process per chunk
1313
# We can aggregate as much proofs as 126.976 / 32 = 3968 per blob
1414
total_proofs_limit: 3968
1515

16+
# These program ids are the ones from the chunk aggregator programs
17+
# Can be found in the Proof Aggregation Service deployment config
18+
sp1_chunk_aggregator_vk_hash: "0x00a18429d092a8e1f58aea6ff650ad715ad4e6d7056600bb201d38460244507b"
19+
risc0_chunk_aggregator_image_id: "0x4cc11a4ac146ce4fc71493d694a9707194316cbb609603a195ffbe0c4c099c97"
20+
1621
ecdsa:
1722
private_key_store_path: "config-files/anvil.proof-aggregator.ecdsa.key.json"
1823
private_key_store_password: ""

config-files/config-proof-aggregator-mock-ethereum-package.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ proofs_per_chunk: 512 # Amount of proofs to process per chunk
1313
# We can aggregate as much proofs as 126.976 / 32 = 3968 per blob
1414
total_proofs_limit: 3968
1515

16+
# These program ids are the ones from the chunk aggregator programs
17+
# Can be found in the Proof Aggregation Service deployment config
18+
sp1_chunk_aggregator_vk_hash: "0x00a18429d092a8e1f58aea6ff650ad715ad4e6d7056600bb201d38460244507b"
19+
risc0_chunk_aggregator_image_id: "0x4cc11a4ac146ce4fc71493d694a9707194316cbb609603a195ffbe0c4c099c97"
1620

1721
ecdsa:
1822
private_key_store_path: "config-files/anvil.proof-aggregator.ecdsa.key.json"

config-files/config-proof-aggregator-mock.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ proofs_per_chunk: 512 # Amount of proofs to process per chunk
1313
# We can aggregate as much proofs as 126.976 / 32 = 3968 per blob
1414
total_proofs_limit: 3968
1515

16+
# These program ids are the ones from the chunk aggregator programs
17+
# Can be found in the Proof Aggregation Service deployment config
18+
sp1_chunk_aggregator_vk_hash: "0x00a18429d092a8e1f58aea6ff650ad715ad4e6d7056600bb201d38460244507b"
19+
risc0_chunk_aggregator_image_id: "0x4cc11a4ac146ce4fc71493d694a9707194316cbb609603a195ffbe0c4c099c97"
1620

1721
ecdsa:
1822
private_key_store_path: "config-files/anvil.proof-aggregator.ecdsa.key.json"

config-files/config-proof-aggregator.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ proofs_per_chunk: 512 # Amount of proofs to process per chunk
1313
# We can aggregate as much proofs as 126.976 / 32 = 3968 per blob
1414
total_proofs_limit: 3968
1515

16+
# These program ids are the ones from the chunk aggregator programs
17+
# Can be found in the Proof Aggregation Service deployment config
18+
sp1_chunk_aggregator_vk_hash: "0x00a18429d092a8e1f58aea6ff650ad715ad4e6d7056600bb201d38460244507b"
19+
risc0_chunk_aggregator_image_id: "0x4cc11a4ac146ce4fc71493d694a9707194316cbb609603a195ffbe0c4c099c97"
1620

1721
ecdsa:
1822
private_key_store_path: "config-files/anvil.proof-aggregator.ecdsa.key.json"

contracts/script/deploy/AlignedProofAggregationServiceDeployer.s.sol

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
pragma solidity ^0.8.12;
22

33
import {AlignedProofAggregationService} from "../../src/core/AlignedProofAggregationService.sol";
4+
import {IAlignedProofAggregationService} from "../../src/core/IAlignedProofAggregationService.sol";
45
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
56

67
import "forge-std/Script.sol";
@@ -24,16 +25,24 @@ contract AlignedProofAggregationServiceDeployer is Script {
2425

2526
AlignedProofAggregationService alignedProofAggregationService = new AlignedProofAggregationService();
2627

28+
bytes32[] memory programIds = new bytes32[](2);
29+
programIds[0] = risc0AggregationProgramImageId;
30+
programIds[1] = sp1AggregationProgramVKHash;
31+
32+
uint8[] memory verifierTypes = new uint8[](2);
33+
verifierTypes[0] = uint8(IAlignedProofAggregationService.VerifierType.RISC0);
34+
verifierTypes[1] = uint8(IAlignedProofAggregationService.VerifierType.SP1);
35+
2736
ERC1967Proxy proxy = new ERC1967Proxy(
2837
address(alignedProofAggregationService),
2938
abi.encodeWithSignature(
30-
"initialize(address,address,address,address,bytes32,bytes32)",
39+
"initialize(address,address,address,address,bytes32[],uint8[])",
3140
ownerAddress,
3241
alignedAggregatorAddress,
3342
sp1VerifierAddress,
3443
risc0VerifierAddress,
35-
risc0AggregationProgramImageId,
36-
sp1AggregationProgramVKHash
44+
programIds,
45+
verifierTypes
3746
)
3847
);
3948

contracts/src/core/AlignedProofAggregationService.sol

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,10 @@ contract AlignedProofAggregationService is
3737
/// if the sp1 verifier address is set to this address, then we skip verification
3838
address public constant VERIFIER_MOCK_ADDRESS = address(0xFF);
3939

40-
/// The unique identifier (image ID) of the RISC Zero aggregator program.
41-
/// This ensures that only proofs generated by a trusted Risc0 program can be verified.
42-
bytes32 public risc0AggregatorProgramImageId;
43-
44-
/// The verification key hash for the SP1 aggregator program.
45-
/// This ensures that only proofs generated by a trusted SP1 program can be verified.
46-
bytes32 public sp1AggregatorProgramVKHash;
40+
/// @notice A mapping to track valid program IDs (image IDs for RISC Zero or vk hashes for SP1)
41+
/// to their corresponding verifier types. These program IDs are used to ensure that proofs are
42+
/// verified against known and registered programs.
43+
mapping(bytes32 => uint8) public programIds;
4744

4845
constructor() {
4946
_disableInitializers();
@@ -54,45 +51,54 @@ contract AlignedProofAggregationService is
5451
address _alignedAggregatorAddress,
5552
address _sp1VerifierAddress,
5653
address _risc0VerifierAddress,
57-
bytes32 _risc0AggregatorProgramImageId,
58-
bytes32 _sp1AggregatorProgramVKHash
54+
bytes32[] memory _programIds,
55+
uint8[] memory _verifierTypes
5956
) public initializer {
6057
__Ownable_init();
6158
__UUPSUpgradeable_init();
6259
_transferOwnership(newOwner);
6360
alignedAggregatorAddress = _alignedAggregatorAddress;
6461
sp1VerifierAddress = _sp1VerifierAddress;
6562
risc0VerifierAddress = _risc0VerifierAddress;
66-
risc0AggregatorProgramImageId = _risc0AggregatorProgramImageId;
67-
sp1AggregatorProgramVKHash = _sp1AggregatorProgramVKHash;
63+
for (uint256 i = 0; i < _programIds.length; i++) {
64+
programIds[_programIds[i]] = _verifierTypes[i];
65+
}
6866
}
6967

70-
function verifySP1(bytes32 blobVersionedHash, bytes calldata sp1PublicValues, bytes calldata sp1ProofBytes)
68+
function verifySP1(bytes32 blobVersionedHash, bytes calldata sp1PublicValues, bytes calldata sp1ProofBytes, bytes32 programId)
7169
public
7270
onlyAlignedAggregator
7371
{
7472
(bytes32 merkleRoot) = abi.decode(sp1PublicValues, (bytes32));
7573

74+
if (programIds[programId] != uint8(IAlignedProofAggregationService.VerifierType.SP1)) {
75+
revert InvalidProgramId(programId, IAlignedProofAggregationService.VerifierType.SP1, programIds[programId]);
76+
}
77+
7678
// In dev mode, poofs are mocked, so we skip the verification part
7779
if (_isSP1VerificationEnabled()) {
78-
ISP1Verifier(sp1VerifierAddress).verifyProof(sp1AggregatorProgramVKHash, sp1PublicValues, sp1ProofBytes);
80+
ISP1Verifier(sp1VerifierAddress).verifyProof(programId, sp1PublicValues, sp1ProofBytes);
7981
}
8082

8183
aggregatedProofs[merkleRoot] = true;
8284
emit AggregatedProofVerified(merkleRoot, blobVersionedHash);
8385
}
8486

85-
function verifyRisc0(bytes32 blobVersionedHash, bytes calldata risc0ReceiptSeal, bytes calldata risc0JournalBytes)
87+
function verifyRisc0(bytes32 blobVersionedHash, bytes calldata risc0ReceiptSeal, bytes calldata risc0JournalBytes, bytes32 programId)
8688
public
8789
onlyAlignedAggregator
8890
{
8991
(bytes32 merkleRoot) = abi.decode(risc0JournalBytes, (bytes32));
9092

93+
if (programIds[programId] != uint8(IAlignedProofAggregationService.VerifierType.RISC0)) {
94+
revert InvalidProgramId(programId, IAlignedProofAggregationService.VerifierType.RISC0, programIds[programId]);
95+
}
96+
9197
// In dev mode, poofs are mocked, so we skip the verification part
9298
if (_isRisc0VerificationEnabled()) {
9399
bytes32 risc0JournalDigest = sha256(risc0JournalBytes);
94100
IRiscZeroVerifier(risc0VerifierAddress).verify(
95-
risc0ReceiptSeal, risc0AggregatorProgramImageId, risc0JournalDigest
101+
risc0ReceiptSeal, programId, risc0JournalDigest
96102
);
97103
}
98104

@@ -153,24 +159,26 @@ contract AlignedProofAggregationService is
153159
emit Risc0VerifierAddressUpdated(_risc0VerifierAddress);
154160
}
155161

156-
/// @notice Sets the image id of the Risc0 program
157-
/// @param _risc0AggregatorProgramImageId The new imageid for the Risc0 aggregator program
158-
function setRisc0AggregatorProgramImageId(bytes32 _risc0AggregatorProgramImageId) external onlyOwner {
159-
risc0AggregatorProgramImageId = _risc0AggregatorProgramImageId;
160-
emit Risc0AggregatorProgramImageIdUpdated(_risc0AggregatorProgramImageId);
161-
}
162-
163162
/// @notice Sets the address of the SP1 verifier contract
164163
/// @param _sp1VerifierAddress The new address for the SP1 verifier contract
165164
function setSP1VerifierAddress(address _sp1VerifierAddress) external onlyOwner {
166165
sp1VerifierAddress = _sp1VerifierAddress;
167166
emit SP1VerifierAddressUpdated(_sp1VerifierAddress);
168167
}
169168

170-
/// @notice Sets the vk hash of the sp1 program
171-
/// @param _sp1AggregatorProgramVKHash The new vk hash for the sp1 aggregator program
172-
function setSP1AggregatorProgramVKHash(bytes32 _sp1AggregatorProgramVKHash) external onlyOwner {
173-
sp1AggregatorProgramVKHash = _sp1AggregatorProgramVKHash;
174-
emit SP1AggregatorProgramVKHashUpdated(_sp1AggregatorProgramVKHash);
169+
/// @notice Adds a new program ID to the list of valid program IDs.
170+
/// @param programId The program ID to add (image ID for RISC0 or vk hash for SP1).
171+
/// @param verifierType The type of verifier associated with the program ID.
172+
function addProgramId(bytes32 programId, IAlignedProofAggregationService.VerifierType verifierType) external onlyOwner {
173+
programIds[programId] = uint8(verifierType);
174+
emit ProgramIdAdded(programId, verifierType);
175+
}
176+
177+
/// @notice Deletes a program ID from the list of valid program IDs.
178+
/// @param programId The program ID to delete (image ID for RISC0 or vk hash for SP1).
179+
function deleteProgramId(bytes32 programId) external onlyOwner {
180+
// Check if we should verify its existence before deleting
181+
delete programIds[programId];
182+
emit ProgramIdDeleted(programId);
175183
}
176184
}

0 commit comments

Comments
 (0)