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
35 changes: 17 additions & 18 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,23 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
return ValidatorSelectionLib.getCommitteeAt(StakingLib.getStorage(), getCurrentEpoch());
}

/**
* @notice Get the validator set for a given epoch
*
* @dev Consider removing this to replace with a `size` and individual getter.
*
* @param _epoch The epoch number to get the validator set for
*
* @return The validator set for the given epoch
*/
function getEpochCommittee(Epoch _epoch)
external
override(IValidatorSelection)
returns (address[] memory)
{
return ValidatorSelectionLib.getCommitteeAt(StakingLib.getStorage(), _epoch);
}

/**
* @notice Get the committee for a given timestamp
*
Expand Down Expand Up @@ -394,24 +411,6 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
OperatorInfo({proposer: StakingLib.getStorage().info[attester].proposer, attester: attester});
}

/**
* @notice Get the validator set for a given epoch
*
* @dev Consider removing this to replace with a `size` and individual getter.
*
* @param _epoch The epoch number to get the validator set for
*
* @return The validator set for the given epoch
*/
function getEpochCommittee(Epoch _epoch)
external
view
override(IValidatorSelection)
returns (address[] memory)
{
return ValidatorSelectionLib.getStorage().epochs[_epoch].committee;
}

/**
* @notice Get the sample seed for a given timestamp
*
Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/src/core/interfaces/IValidatorSelection.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ interface IValidatorSelection is IValidatorSelectionCore {
// Non view as uses transient storage
function getCurrentEpochCommittee() external returns (address[] memory);
function getCommitteeAt(Timestamp _ts) external returns (address[] memory);
function getEpochCommittee(Epoch _epoch) external returns (address[] memory);

// Stable
function getCurrentEpoch() external view returns (Epoch);
Expand All @@ -46,7 +47,6 @@ interface IValidatorSelection is IValidatorSelectionCore {

// Likely removal of these to replace with a size and indiviual getter
// Get the current epoch committee
function getEpochCommittee(Epoch _epoch) external view returns (address[] memory);
function getAttesters() external view returns (address[] memory);

function getSampleSeedAt(Timestamp _ts) external view returns (uint256);
Expand Down
8 changes: 7 additions & 1 deletion l1-contracts/src/periphery/SlashPayload.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,20 @@ contract SlashPayload is IPayload {
IValidatorSelection public immutable VALIDATOR_SELECTION;
uint256 public immutable AMOUNT;

address[] public attesters;

constructor(Epoch _epoch, IValidatorSelection _validatorSelection, uint256 _amount) {
EPOCH = _epoch;
VALIDATOR_SELECTION = _validatorSelection;
AMOUNT = _amount;

address[] memory attesters_ = IValidatorSelection(VALIDATOR_SELECTION).getEpochCommittee(EPOCH);
for (uint256 i = 0; i < attesters_.length; i++) {
attesters.push(attesters_[i]);
}
}

function getActions() external view override(IPayload) returns (IPayload.Action[] memory) {
address[] memory attesters = IValidatorSelection(VALIDATOR_SELECTION).getEpochCommittee(EPOCH);
IPayload.Action[] memory actions = new IPayload.Action[](attesters.length);

for (uint256 i = 0; i < attesters.length; i++) {
Expand Down
18 changes: 18 additions & 0 deletions l1-contracts/test/validator-selection/ValidatorSelection.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,24 @@ contract ValidatorSelectionTest is DecoderBase {
assertEq(expectedProposer, actualProposer, "Invalid proposer");
}

function testCommitteeForNonSetupEpoch(uint8 _epochsToJump) public setup(4) {
Epoch pre = rollup.getCurrentEpoch();
vm.warp(
block.timestamp
+ uint256(_epochsToJump) * rollup.getEpochDuration() * rollup.getSlotDuration()
);

Epoch post = rollup.getCurrentEpoch();

uint256 validatorSetSize = rollup.getAttesters().length;
uint256 targetCommitteeSize = rollup.getTargetCommitteeSize();
uint256 expectedSize =
validatorSetSize > targetCommitteeSize ? targetCommitteeSize : validatorSetSize;

assertEq(rollup.getEpochCommittee(pre).length, expectedSize, "Invalid committee size");
assertEq(rollup.getEpochCommittee(post).length, expectedSize, "Invalid committee size");
}

function testValidatorSetLargerThanCommittee(bool _insufficientSigs) public setup(100) {
assertGt(rollup.getAttesters().length, rollup.getTargetCommitteeSize(), "Not enough validators");
uint256 committeeSize = rollup.getTargetCommitteeSize() * 2 / 3 + (_insufficientSigs ? 0 : 1);
Expand Down
15 changes: 11 additions & 4 deletions yarn-project/ethereum/src/contracts/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,17 @@ export class RollupContract {
return result;
}

async getEpochCommittee(epoch: bigint) {
const { result } = await this.client.simulateContract({
address: this.address,
abi: RollupAbi,
functionName: 'getEpochCommittee',
args: [epoch],
});

return result;
}

getBlock(blockNumber: bigint) {
return this.rollup.read.getBlock([blockNumber]);
}
Expand Down Expand Up @@ -391,10 +402,6 @@ export class RollupContract {
return this.rollup.read.getAttesters();
}

getEpochCommittee(epoch: bigint) {
return this.rollup.read.getEpochCommittee([epoch]);
}

getInfo(address: Hex | EthAddress) {
if (address instanceof EthAddress) {
address = address.toString();
Expand Down
Loading