Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions l1-contracts/src/core/RollupCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,10 @@ contract RollupCore is
ExtRollupLib.setupEpoch();
}

function setupSeedSnapshotForNextEpoch() public override(IValidatorSelectionCore) {
ExtRollupLib.setupSeedSnapshotForNextEpoch();
}

/**
* @notice Updates the l1 gas fee oracle
* @dev This function is called by the `propose` function
Expand Down
1 change: 1 addition & 0 deletions l1-contracts/src/core/interfaces/IValidatorSelection.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ struct ValidatorSelectionStorage {

interface IValidatorSelectionCore {
function setupEpoch() external;
function setupSeedSnapshotForNextEpoch() external;
}

interface IValidatorSelection is IValidatorSelectionCore {
Expand Down
5 changes: 5 additions & 0 deletions l1-contracts/src/core/libraries/rollup/ExtRollupLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ library ExtRollupLib {
ValidatorSelectionLib.setupEpoch(StakingLib.getStorage(), currentEpoch);
}

function setupSeedSnapshotForNextEpoch() external {
Epoch currentEpoch = Timestamp.wrap(block.timestamp).epochFromTimestamp();
ValidatorSelectionLib.setSampleSeedForNextEpoch(currentEpoch);
}

function getEpochProofPublicInputs(
uint256 _start,
uint256 _end,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ library ValidatorSelectionLib {

// Set the sample seed for the next epoch if required
// function handles the case where it is already set
setSampleSeedForEpoch(_epochNumber + Epoch.wrap(1));
setSampleSeedForNextEpoch(_epochNumber);

//################ Committee ################
// If the committee is not set for this epoch, we need to sample it
Expand Down Expand Up @@ -226,6 +226,15 @@ library ValidatorSelectionLib {
return epoch.committee;
}

/**
* @notice Sets the sample seed for the next epoch
*
* @param _epoch - The epoch to set the sample seed for
*/
function setSampleSeedForNextEpoch(Epoch _epoch) internal {
setSampleSeedForEpoch(_epoch + Epoch.wrap(1));
}

/**
* @notice Sets the sample seed for an epoch
*
Expand Down
4 changes: 2 additions & 2 deletions l1-contracts/test/scream-and-shout.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ contract ScreamAndShoutTest is Test {

assertEq(
codeHash,
0x1d16acb8153d57a5977ea83c2adfd173c4299d2501a67084e54391b49f9e17a5,
0xf5661dc2c5fc8908f0046f7f5a4bad9f2bdd569e730ecc36db30d3bb4e6fb57b,
"You have changed the rollup!"
);
}
Expand All @@ -42,7 +42,7 @@ contract ScreamAndShoutTest is Test {

assertEq(
codeHash,
0xc4ca2e1a154150d0d4d8686009de461a136716e70e1fffd561442b8bc29c7af5,
0x6d6f5c217adc349976fc5992f0e001f83b8674c9f2206384422f8328306bb550,
"You have changed the registry!"
);
}
Expand Down
32 changes: 32 additions & 0 deletions l1-contracts/test/validator-selection/setupSampleSeed.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2025 Aztec Labs.
pragma solidity >=0.8.27;

import {ValidatorSelectionTestBase, CheatDepositArgs} from "./ValidatorSelectionBase.sol";
import {Epoch, Timestamp} from "@aztec/core/libraries/TimeLib.sol";
import {Checkpoints} from "@oz/utils/structs/Checkpoints.sol";
import {IValidatorSelection} from "@aztec/core/interfaces/IValidatorSelection.sol";
import {TestConstants} from "../harnesses/TestConstants.sol";

contract SetupSampleSeedTest is ValidatorSelectionTestBase {
function test_setupSampleSeed(uint16 _epochToTest) public setup(4) {
// Check that the epoch is not set
_epochToTest = uint16(bound(_epochToTest, 2, type(uint16).max));

uint256 timejump =
_epochToTest * TestConstants.AZTEC_EPOCH_DURATION * TestConstants.AZTEC_SLOT_DURATION;
uint256 originalSampleSeed =
rollup.getSampleSeedAt(Timestamp.wrap(block.timestamp + timejump + 1));

// Jump to just before the epoch we are testing
vm.warp(
block.timestamp
+ (_epochToTest - 1) * TestConstants.AZTEC_EPOCH_DURATION * TestConstants.AZTEC_SLOT_DURATION
);
rollup.setupSeedSnapshotForNextEpoch();

// The sample seed should have been updated
uint256 newSampleSeed = rollup.getSampleSeedAt(Timestamp.wrap(block.timestamp + timejump));
assertTrue(newSampleSeed != originalSampleSeed);
}
}
24 changes: 24 additions & 0 deletions yarn-project/cli/src/cmds/l1/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,30 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: Logger
});
});

program
.command('trigger-seed-snapshot')
.description('Triggers a seed snapshot for the next epoch.')
.option('-pk, --private-key <string>', 'The private key to use for deployment', PRIVATE_KEY)
.option(
'-m, --mnemonic <string>',
'The mnemonic to use in deployment',
'test test test test test test test test test test test junk',
)
.option('--rollup <address>', 'ethereum address of the rollup contract', parseEthereumAddress)
.addOption(l1RpcUrlsOption)
.addOption(l1ChainIdOption)
.action(async options => {
const { triggerSeedSnapshot } = await import('./trigger_seed_snapshot.js');
await triggerSeedSnapshot({
rollupAddress: options.rollup,
rpcUrls: options.l1RpcUrls,
chainId: options.l1ChainId,
privateKey: options.privateKey,
mnemonic: options.mnemonic,
log,
});
});

program
.command('debug-rollup')
.description('Debugs the rollup contract.')
Expand Down
31 changes: 31 additions & 0 deletions yarn-project/cli/src/cmds/l1/trigger_seed_snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { createEthereumChain, createExtendedL1Client } from '@aztec/ethereum';
import type { LogFn } from '@aztec/foundation/log';
import { RollupAbi } from '@aztec/l1-artifacts/RollupAbi';

import { getContract } from 'viem';

import type { RollupCommandArgs } from './update_l1_validators.js';

export async function triggerSeedSnapshot({
rpcUrls,
chainId,
privateKey,
mnemonic,
rollupAddress,
log,
}: RollupCommandArgs & { log: LogFn }) {
const chain = createEthereumChain(rpcUrls, chainId);
const client = createExtendedL1Client(rpcUrls, privateKey ?? mnemonic!, chain.chainInfo);

const rollup = getContract({
address: rollupAddress.toString(),
abi: RollupAbi,
client,
});

log('Triggering seed snapshot for next epoch');
const txHash = await rollup.write.setupSeedSnapshotForNextEpoch();
log(`Sent! | Seed snapshot setup for next epoch | tx hash: ${txHash}`);
const receipt = await client.waitForTransactionReceipt({ hash: txHash });
log(`Done! | Seed snapshot setup for next epoch | tx hash: ${txHash} | status: ${receipt.status}`);
}