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
5 changes: 5 additions & 0 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {Signature} from "@aztec/shared/libraries/SignatureLib.sol";
import {ChainTipsLib, CompressedChainTips} from "./libraries/compressed-data/Tips.sol";
import {ProposeLib, ValidateHeaderArgs} from "./libraries/rollup/ProposeLib.sol";
import {RewardLib, RewardConfig} from "./libraries/rollup/RewardLib.sol";
import {DepositArgs} from "./libraries/StakingQueue.sol";
import {
RollupCore,
GenesisState,
Expand Down Expand Up @@ -531,6 +532,10 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
return StakingLib.getStorage().isBootstrapped;
}

function getEntryQueueAt(uint256 _index) external view override(IStaking) returns (DepositArgs memory) {
return StakingLib.getEntryQueueAt(_index);
}

function getBurnAddress() external pure override(IRollup) returns (address) {
return RewardLib.BURN_ADDRESS;
}
Expand Down
2 changes: 2 additions & 0 deletions l1-contracts/src/core/interfaces/IStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity >=0.8.27;

import {StakingQueueConfig} from "@aztec/core/libraries/compressed-data/StakingQueueConfig.sol";
import {Exit, Status, AttesterView} from "@aztec/core/libraries/rollup/StakingLib.sol";
import {DepositArgs} from "@aztec/core/libraries/StakingQueue.sol";
import {AttesterConfig, GSE} from "@aztec/governance/GSE.sol";
import {G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol";
import {Timestamp, Epoch} from "@aztec/shared/libraries/TimeMath.sol";
Expand Down Expand Up @@ -72,6 +73,7 @@ interface IStaking is IStakingCore {
function getStatus(address _attester) external view returns (Status);
function getNextFlushableEpoch() external view returns (Epoch);
function getEntryQueueLength() external view returns (uint256);
function getEntryQueueAt(uint256 _index) external view returns (DepositArgs memory);
function getAvailableValidatorFlushes() external view returns (uint256);
function getIsBootstrapped() external view returns (bool);
}
8 changes: 2 additions & 6 deletions l1-contracts/src/core/libraries/StakingQueue.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,7 @@ library StakingQueueLib {
len = self.last - self.first;
}

function getFirst(StakingQueue storage self) internal view returns (uint256) {
return self.first;
}

function getLast(StakingQueue storage self) internal view returns (uint256) {
return self.last;
function at(StakingQueue storage self, uint256 index) internal view returns (DepositArgs memory validator) {
validator = self.validators[self.first + index];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ library FeeConfigLib {
}

function getCongestionUpdateFraction(CompressedFeeConfig _compressedFeeConfig) internal pure returns (uint256) {
return (CompressedFeeConfig.unwrap(_compressedFeeConfig) >> 64) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
return (CompressedFeeConfig.unwrap(_compressedFeeConfig) >> 64) & MASK_128_BITS;
}

function getProvingCostPerMana(CompressedFeeConfig _compressedFeeConfig) internal pure returns (EthValue) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,30 +73,30 @@ library FeeStructsLib {
library FeeHeaderLib {
using SafeCast for uint256;

uint256 internal constant MASK_32_BITS = 0xFFFFFFFF;
uint256 internal constant MASK_48_BITS = 0xFFFFFFFFFFFF;
uint256 internal constant MASK_63_BITS = 0x7FFFFFFFFFFFFFFF;
uint256 internal constant MASK_64_BITS = 0xFFFFFFFFFFFFFFFF;

function getManaUsed(CompressedFeeHeader _compressedFeeHeader) internal pure returns (uint256) {
// Reads the bits 224-256
return CompressedFeeHeader.unwrap(_compressedFeeHeader) & 0xFFFFFFFF;
return CompressedFeeHeader.unwrap(_compressedFeeHeader) & MASK_32_BITS;
}

function getExcessMana(CompressedFeeHeader _compressedFeeHeader) internal pure returns (uint256) {
// Reads the bits 176-223
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 32) & 0xFFFFFFFFFFFF;
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 32) & MASK_48_BITS;
}

function getFeeAssetPriceNumerator(CompressedFeeHeader _compressedFeeHeader) internal pure returns (uint256) {
// Reads the bits 128-175
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 80) & 0xFFFFFFFFFFFF;
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 80) & MASK_48_BITS;
}

function getCongestionCost(CompressedFeeHeader _compressedFeeHeader) internal pure returns (uint256) {
// Reads the bits 64-127
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 128) & 0xFFFFFFFFFFFFFFFF;
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 128) & MASK_64_BITS;
}

function getProverCost(CompressedFeeHeader _compressedFeeHeader) internal pure returns (uint256) {
// The prover cost is only 63 bits so use mask to remove first bit
// Reads the bits 1-63
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 192) & 0x7FFFFFFFFFFFFFFF;
return (CompressedFeeHeader.unwrap(_compressedFeeHeader) >> 192) & MASK_63_BITS;
}

function compress(FeeHeader memory _feeHeader) internal pure returns (CompressedFeeHeader) {
Expand All @@ -107,7 +107,7 @@ library FeeHeaderLib {
value |= uint256(_feeHeader.congestionCost.toUint64()) << 128;

uint256 proverCost = uint256(_feeHeader.proverCost.toUint64());
require(proverCost == proverCost & 0x7FFFFFFFFFFFFFFF);
require(proverCost == proverCost & MASK_63_BITS);
value |= proverCost << 192;

// Preheat
Expand All @@ -119,15 +119,15 @@ library FeeHeaderLib {
function decompress(CompressedFeeHeader _compressedFeeHeader) internal pure returns (FeeHeader memory) {
uint256 value = CompressedFeeHeader.unwrap(_compressedFeeHeader);

uint256 manaUsed = value & 0xFFFFFFFF;
uint256 manaUsed = value & MASK_32_BITS;
value >>= 32;
uint256 excessMana = value & 0xFFFFFFFFFFFF;
uint256 excessMana = value & MASK_48_BITS;
value >>= 48;
uint256 feeAssetPriceNumerator = value & 0xFFFFFFFFFFFF;
uint256 feeAssetPriceNumerator = value & MASK_48_BITS;
value >>= 48;
uint256 congestionCost = value & 0xFFFFFFFFFFFFFFFF;
uint256 congestionCost = value & MASK_64_BITS;
value >>= 64;
uint256 proverCost = value & 0x7FFFFFFFFFFFFFFF;
uint256 proverCost = value & MASK_63_BITS;

return FeeHeader({
manaUsed: uint256(manaUsed),
Expand All @@ -137,10 +137,4 @@ library FeeHeaderLib {
proverCost: uint256(proverCost)
});
}

function preheat(CompressedFeeHeader _compressedFeeHeader) internal pure returns (CompressedFeeHeader) {
uint256 value = CompressedFeeHeader.unwrap(_compressedFeeHeader);
value |= 1 << 255;
return CompressedFeeHeader.wrap(value);
}
}
6 changes: 3 additions & 3 deletions l1-contracts/src/core/libraries/rollup/EpochProofLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ import {SafeCast} from "@oz/utils/math/SafeCast.sol";
* status.
*
* Attestation Verification:
* Before accepting an epoch proof, this library verifies the attestations for the last block in the epoch.
* This ensures that the committee has properly validated the final state of the epoch. Note that this is
* equivalent to verifying the attestations for every block in the epoch, since the committee should not attest
* Before accepting an epoch proof, this library verifies the attestations for the end block of the proof.
* This ensures that the committee has properly validated the final state of the proof. Note that this is
* equivalent to verifying the attestations for every prior block, since the committee should not attest
* to a block unless its ancestors are also valid and have been attested to. This step checks that the committee
* have agreed on the same output state of the proven range. For honest nodes, this is done by re-executing the
* transactions in the proven range and matching the state root, effectively acting as training wheels for the
Expand Down
6 changes: 3 additions & 3 deletions l1-contracts/src/core/libraries/rollup/RewardLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ library RewardLib {
}
}

uint256 sequencerShare = BpsLib.mul(blockRewardsAvailable, rewardStorage.config.sequencerBps);
v.sequencerBlockReward = sequencerShare / added;
uint256 sequenceBlockRewards = BpsLib.mul(blockRewardsAvailable, rewardStorage.config.sequencerBps);
v.sequencerBlockReward = sequenceBlockRewards / added;

$er.rewards += (blockRewardsAvailable - sequencerShare).toUint128();
$er.rewards += (blockRewardsAvailable - sequenceBlockRewards).toUint128();
}

bool isTxsEnabled = FeeLib.isTxsEnabled();
Expand Down
4 changes: 4 additions & 0 deletions l1-contracts/src/core/libraries/rollup/StakingLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ library StakingLib {
return getStorage().gse.getAttesterFromIndexAtTime(address(this), _index, Timestamp.wrap(block.timestamp));
}

function getEntryQueueAt(uint256 _index) internal view returns (DepositArgs memory) {
return getStorage().entryQueue.at(_index);
}

function getAttesterFromIndexAtTime(uint256 _index, Timestamp _timestamp) internal view returns (address) {
return getStorage().gse.getAttesterFromIndexAtTime(address(this), _index, _timestamp);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {TransientSlot} from "@oz/utils/TransientSlot.sol";
*
* 1. Committee Selection:
* - At the start of each epoch, a committee is sampled from the active validator set
* - Committee size is configurable (targetCommitteeSize) but validators must meet this minimum
* - Committee size is configurable at deployment (targetCommitteeSize), and must be met
* - Selection uses cryptographic randomness (prevrandao + epoch)
* - Committee remains stable throughout the entire epoch for consistency
* - Committee commitment is stored onchain and validated against reconstructed committees
Expand Down
10 changes: 9 additions & 1 deletion l1-contracts/test/staking/flushEntryQueue.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {Epoch, Timestamp} from "@aztec/shared/libraries/TimeMath.sol";
import {Status, AttesterView, IStakingCore} from "@aztec/core/interfaces/IStaking.sol";
import {Math} from "@oz/utils/math/Math.sol";
import {GSE, IGSECore} from "@aztec/governance/GSE.sol";
import {StakingQueueLib} from "@aztec/core/libraries/StakingQueue.sol";
import {StakingQueueLib, DepositArgs} from "@aztec/core/libraries/StakingQueue.sol";
import {StakingQueueConfig, StakingQueueConfigLib} from "@aztec/core/libraries/compressed-data/StakingQueueConfig.sol";
import {Rollup} from "@aztec/core/Rollup.sol";
import {BN254Lib, G1Point, G2Point} from "@aztec/shared/libraries/BN254Lib.sol";
Expand Down Expand Up @@ -204,6 +204,14 @@ contract FlushEntryQueueTest is StakingBase {
});

assertEq(stakingAsset.balanceOf(address(staking)), balance + ACTIVATION_THRESHOLD, "invalid balance");

DepositArgs memory validator = staking.getEntryQueueAt(staking.getEntryQueueLength() - 1);
assertEq(validator.attester, _attester, "invalid attester");
assertEq(validator.withdrawer, _withdrawer, "invalid withdrawer");
assertTrue(BN254Lib.isZero(validator.publicKeyInG1), "invalid public key in G1");
assertTrue(BN254Lib.isZero(validator.publicKeyInG2), "invalid public key in G2");
assertTrue(BN254Lib.isZero(validator.proofOfPossession), "invalid proof of possession");
assertEq(validator.moveWithLatestRollup, _moveWithLatestRollup, "invalid move with latest rollup");
}

function _help_flushEntryQueue(uint256 _numValidators, uint256 _expectedFlushSize) internal {
Expand Down
Loading