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
15 changes: 2 additions & 13 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import {
Slot,
Epoch,
Timestamp,
Errors,
CommitteeAttestations,
RollupOperationsExtLib,
ValidatorOperationsExtLib,
Expand Down Expand Up @@ -321,19 +320,9 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
}

function getBlock(uint256 _blockNumber) external view override(IRollup) returns (BlockLog memory) {
RollupStore storage rollupStore = STFLib.getStorage();
uint256 pendingBlockNumber = rollupStore.tips.getPendingBlockNumber();
require(_blockNumber <= pendingBlockNumber, Errors.Rollup__InvalidBlockNumber(pendingBlockNumber, _blockNumber));

// If the block is outside of the temp stored, will return default values (0)
// for all that would have been in temp.
TempBlockLog memory tempBlockLog;
if (!STFLib.isTempStale(_blockNumber)) {
tempBlockLog = STFLib.getTempBlockLog(_blockNumber);
}

TempBlockLog memory tempBlockLog = STFLib.getTempBlockLog(_blockNumber);
return BlockLog({
archive: rollupStore.archives[_blockNumber],
archive: STFLib.getStorage().archives[_blockNumber],
headerHash: tempBlockLog.headerHash,
blobCommitmentsHash: tempBlockLog.blobCommitmentsHash,
attestationsHash: tempBlockLog.attestationsHash,
Expand Down
6 changes: 4 additions & 2 deletions l1-contracts/src/core/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ library Errors {
error Outbox__AlreadyNullified(uint256 l2BlockNumber, uint256 leafIndex); // 0xfd71c2d4
error Outbox__NothingToConsumeAtBlock(uint256 l2BlockNumber); // 0xa4508f22
error Outbox__BlockNotProven(uint256 l2BlockNumber); // 0x0e194a6d
error Outbox__BlockAlreadyProven(uint256 l2BlockNumber);
error Outbox__PathTooLong();
error Outbox__LeafIndexOutOfBounds(uint256 leafIndex, uint256 pathLength);

// Rollup
error Rollup__InsufficientBondAmount(uint256 minimum, uint256 provided); // 0xa165f276
Expand All @@ -62,6 +64,7 @@ library Errors {
error Rollup__InvalidTimestamp(Timestamp expected, Timestamp actual); // 0x3132e895
error Rollup__InvalidAttestations();
error Rollup__AttestationsAreValid();
error Rollup__InvalidAttestationIndex();
error Rollup__BlockAlreadyProven();
error Rollup__BlockNotInPendingChain();
error Rollup__InvalidBlobHash(bytes32 expected, bytes32 actual); // 0x13031e6a
Expand All @@ -81,7 +84,6 @@ library Errors {
error Rollup__StartIsNotFirstBlockOfEpoch(); // 0x4ef11e0d
error Rollup__StartIsNotBuildingOnProven(); // 0x4a59f42e
error Rollup__TooManyBlocksInEpoch(uint256 expected, uint256 actual); // 0x7d5b1408
error Rollup__AlreadyClaimed(address prover, Epoch epoch);
error Rollup__NotPastDeadline(Epoch deadline, Epoch currentEpoch);
error Rollup__PastDeadline(Epoch deadline, Epoch currentEpoch);
error Rollup__ProverHaveAlreadySubmitted(address prover, Epoch epoch);
Expand All @@ -90,7 +92,7 @@ library Errors {
error Rollup__RewardsNotClaimable();
error Rollup__InvalidFirstEpochProof();
error Rollup__InvalidCoinbase();
error Rollup__StaleTempBlockLog(uint256 blockNumber, uint256 pendingBlockNumber, uint256 size);
error Rollup__UnavailableTempBlockLog(uint256 blockNumber, uint256 pendingBlockNumber, uint256 upperLimit);
error Rollup__NoBlobsInBlock();

// ProposedHeaderLib
Expand Down
4 changes: 2 additions & 2 deletions l1-contracts/src/core/libraries/compressed-data/Tips.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ library ChainTipsLib {
returns (CompressedChainTips)
{
uint256 value = CompressedChainTips.unwrap(_compressedChainTips) & ~PENDING_BLOCK_NUMBER_MASK;
return CompressedChainTips.wrap(value | (_pendingBlockNumber << 128));
return CompressedChainTips.wrap(value | (uint256(_pendingBlockNumber.toUint128()) << 128));
}

function updateProvenBlockNumber(CompressedChainTips _compressedChainTips, uint256 _provenBlockNumber)
Expand All @@ -41,7 +41,7 @@ library ChainTipsLib {
returns (CompressedChainTips)
{
uint256 value = CompressedChainTips.unwrap(_compressedChainTips) & ~PROVEN_BLOCK_NUMBER_MASK;
return CompressedChainTips.wrap(value | _provenBlockNumber);
return CompressedChainTips.wrap(value | _provenBlockNumber.toUint128());
}

function compress(ChainTips memory _chainTips) internal pure returns (CompressedChainTips) {
Expand Down
4 changes: 2 additions & 2 deletions l1-contracts/src/core/libraries/crypto/SampleLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ library SampleLib {
* @return shuffledIndex - The shuffled index
*/
function computeSampleIndex(uint256 _index, uint256 _indexCount, uint256 _seed) internal pure returns (uint256) {
// Cannot modulo by 0
if (_indexCount == 0) {
// Cannot modulo by 0 and if 1, then only acceptable value is 0
if (_indexCount <= 1) {
return 0;
}

Expand Down
4 changes: 3 additions & 1 deletion l1-contracts/src/core/libraries/rollup/InvalidateLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ library InvalidateLib {
* @custom:reverts Errors.Rollup__BlockAlreadyProven If block number is already proven
* @custom:reverts Errors.Rollup__InvalidAttestations If provided attestations don't match stored hash
* @custom:reverts Errors.ValidatorSelection__InvalidCommitteeCommitment If committee doesn't match stored commitment
* @custom:reverts Rollup__InvalidAttestationIndex if the _invalidIndex is beyond the committee
* @custom:reverts Errors.Rollup__AttestationsAreValid If the attestation at invalidIndex is actually valid
*/
function invalidateBadAttestation(
Expand All @@ -89,7 +90,8 @@ library InvalidateLib {
address[] memory _committee,
uint256 _invalidIndex
) internal {
(bytes32 digest,) = _validateInvalidationInputs(_blockNumber, _attestations, _committee);
(bytes32 digest, uint256 committeeSize) = _validateInvalidationInputs(_blockNumber, _attestations, _committee);
require(_invalidIndex < committeeSize, Errors.Rollup__InvalidAttestationIndex());

address recovered;

Expand Down
11 changes: 6 additions & 5 deletions l1-contracts/src/core/libraries/rollup/RewardLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,9 @@ library RewardLib {
Errors.Rollup__NotPastDeadline(_epochs[i].toDeadlineEpoch(), currentEpoch)
);

require(
!rewardStorage.proverClaimed[_prover].get(Epoch.unwrap(_epochs[i])),
Errors.Rollup__AlreadyClaimed(_prover, _epochs[i])
);
if (rewardStorage.proverClaimed[_prover].get(Epoch.unwrap(_epochs[i]))) {
continue;
}
rewardStorage.proverClaimed[_prover].set(Epoch.unwrap(_epochs[i]));

EpochRewards storage e = rewardStorage.epochRewards[_epochs[i]];
Expand All @@ -123,7 +122,9 @@ library RewardLib {
}
}

rollupStore.config.feeAsset.safeTransfer(_prover, accumulatedRewards);
if (accumulatedRewards > 0) {
rollupStore.config.feeAsset.safeTransfer(_prover, accumulatedRewards);
}

return accumulatedRewards;
}
Expand Down
40 changes: 18 additions & 22 deletions l1-contracts/src/core/libraries/rollup/STFLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -179,46 +179,42 @@ library STFLib {
}

/**
* @notice Determines if a temporary block log is stale (no longer accessible in circular storage)
* @notice Returns a storage reference to a compressed temporary block log
* @dev Provides direct access to the compressed block log in storage without decompression.
* Reverts if the block number is stale (no longer accessible in circular storage) or if
* the block have not happened yet.
*
* @dev A temporary block log is stale if it can no longer be accessed in the circular storage buffer.
* The staleness is determined by the relationship between the block number, current pending
* block, and the buffer size.
*
* Example with roundabout size 5 and pending block 7:
* Circular buffer state: [block5, block6, block7, block3, block4]
*
* Block 2 and below are stale because:
* - blockNumber + size <= pending
* - 2 + 5 <= 7 (stale)
* - 3 + 5 <= 7 (not stale)
* A block is available if:
* - blockNumber <= pending (it is not in the future)
* - pending < blockNumber + size (the override is in the future)
* Together as a span:
* - blockNumber <= pending < blockNumber + size
*
* For example, block 2 is unavailable since the override has happened:
* - 2 <= 7 (true) && 7 < 2 + 5 (false)
* But block 3 is available as it in the past, but not overridden yet
* - 3 <= 7 (true) && 7 < 3 + 5 (true)
*
* This ensures that only blocks within the current "window" of the circular buffer
* are considered valid and accessible.
*
* @param _blockNumber The block number to check for staleness
* @return isStale True if the block is stale and no longer accessible
*/
function isTempStale(uint256 _blockNumber) internal view returns (bool) {
uint256 pending = getStorage().tips.getPendingBlockNumber();
uint256 size = roundaboutSize();

return _blockNumber + size <= pending;
}

/**
* @notice Returns a storage reference to a compressed temporary block log
* @dev Provides direct access to the compressed block log in storage without decompression.
* Reverts if the block number is stale.
* @param _blockNumber The block number to get the storage reference for
* @return A storage reference to the compressed temporary block log
*/
function getStorageTempBlockLog(uint256 _blockNumber) internal view returns (CompressedTempBlockLog storage) {
uint256 pending = getStorage().tips.getPendingBlockNumber();
uint256 size = roundaboutSize();

bool isStale = _blockNumber + size <= pending;

require(!isStale, Errors.Rollup__StaleTempBlockLog(_blockNumber, pending, size));
uint256 upperLimit = _blockNumber + size;
bool available = _blockNumber <= pending && pending < upperLimit;
require(available, Errors.Rollup__UnavailableTempBlockLog(_blockNumber, pending, upperLimit));

return getStorage().tempBlockLogs[_blockNumber % size];
}
Expand Down
2 changes: 2 additions & 0 deletions l1-contracts/src/core/messagebridge/Outbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ contract Outbox is IOutbox {
*/
function insert(uint256 _l2BlockNumber, bytes32 _root) external override(IOutbox) {
require(msg.sender == address(ROLLUP), Errors.Outbox__Unauthorized());
require(_l2BlockNumber > ROLLUP.getProvenBlockNumber(), Errors.Outbox__BlockAlreadyProven(_l2BlockNumber));

roots[_l2BlockNumber].root = _root;

Expand All @@ -72,6 +73,7 @@ contract Outbox is IOutbox {
bytes32[] calldata _path
) external override(IOutbox) {
require(_path.length < 256, Errors.Outbox__PathTooLong());
require(_leafIndex < (1 << _path.length), Errors.Outbox__LeafIndexOutOfBounds(_leafIndex, _path.length));
require(_l2BlockNumber <= ROLLUP.getProvenBlockNumber(), Errors.Outbox__BlockNotProven(_l2BlockNumber));
require(_message.sender.version == VERSION, Errors.Outbox__VersionMismatch(_message.sender.version, VERSION));

Expand Down
2 changes: 1 addition & 1 deletion l1-contracts/src/governance/GSE.sol
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ contract GSECore is IGSECore, Ownable {
// Global attester information
mapping(address attester => AttesterConfig config) internal configOf;
// Mapping from the hashed public key in G1 of BN254 to the keys are registered.
mapping(bytes32 hashedPK1 => bool isRegistered) internal ownedPKs;
mapping(bytes32 hashedPK1 => bool isRegistered) public ownedPKs;

/**
* Contains state for:
Expand Down
5 changes: 4 additions & 1 deletion l1-contracts/test/MultiProof.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,12 @@ contract MultiProofTest is RollupBase {

assertEq(bobRewardsClaimed, bobRewards, "Bob rewards not claimed");
assertEq(rollup.getSpecificProverRewardsForEpoch(Epoch.wrap(0), bob), 0, "Bob rewards not zeroed");
vm.record();

vm.expectRevert(abi.encodeWithSelector(Errors.Rollup__AlreadyClaimed.selector, bob, Epoch.wrap(0)));
rollup.claimProverRewards(bob, epochs);
(, bytes32[] memory writes) = vm.accesses(address(rollup));
// Ensure that there was no writes! We are just doing no-ops if they were already claimed.
assertEq(writes.length, 0);
}
}

Expand Down
Loading
Loading