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
22 changes: 11 additions & 11 deletions l1-contracts/gas_benchmark.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@

## No Validators

| Function | Avg Gas | Max Gas | Calldata Size | Calldata Gas |
|----------------------|---------|-----------|---------------|--------------|
| propose | 199,366 | 225,550 | 996 | 15,936 |
| submitEpochRootProof | 994,761 | 1,033,254 | 14,148 | 226,368 |
| setupEpoch | 32,042 | 113,837 | - | - |
| Function | Avg Gas | Max Gas | Calldata Size | Calldata Gas |
|----------------------|-----------|-----------|---------------|--------------|
| propose | 200,097 | 226,280 | 996 | 15,936 |
| submitEpochRootProof | 1,035,434 | 1,074,129 | 14,148 | 226,368 |
| setupEpoch | 32,020 | 113,815 | - | - |

**Avg Gas Cost per Second**: 3,646.4 gas/second
**Avg Gas Cost per Second**: 3,691.8 gas/second
*Epoch duration*: 0h 38m 24s

## Validators

| Function | Avg Gas | Max Gas | Calldata Size | Calldata Gas |
|----------------------|-----------|-----------|---------------|--------------|
| propose | 327,774 | 355,591 | 4,516 | 72,256 |
| submitEpochRootProof | 1,575,811 | 1,673,651 | 16,644 | 266,304 |
| aggregate3 | 376,665 | 390,039 | - | - |
| setupEpoch | 46,504 | 547,670 | - | - |
| propose | 328,507 | 356,323 | 4,516 | 72,256 |
| submitEpochRootProof | 1,616,774 | 1,714,815 | 16,644 | 266,304 |
| aggregate3 | 377,506 | 390,880 | - | - |
| setupEpoch | 46,482 | 547,648 | - | - |

**Avg Gas Cost per Second**: 5,940.5 gas/second
**Avg Gas Cost per Second**: 5,986.2 gas/second
*Epoch duration*: 0h 38m 24s

56 changes: 28 additions & 28 deletions l1-contracts/gas_benchmark_results.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,62 +2,62 @@
"no_validators": {
"propose": {
"calls": 150,
"min": 185722,
"mean": 199366,
"median": 195111,
"max": 225550,
"min": 186452,
"mean": 200097,
"median": 195841,
"max": 226280,
"calldata_size": 996,
"calldata_gas": 15936
},
"setupEpoch": {
"calls": 150,
"min": 29309,
"mean": 32042,
"median": 29309,
"max": 113837
"min": 29287,
"mean": 32020,
"median": 29287,
"max": 113815
},
"submitEpochRootProof": {
"calls": 4,
"min": 976058,
"mean": 994761,
"median": 984867,
"max": 1033254,
"min": 1015256,
"mean": 1035434,
"median": 1026177,
"max": 1074129,
"calldata_size": 14148,
"calldata_gas": 226368
}
},
"validators": {
"propose": {
"calls": 150,
"min": 305434,
"mean": 327774,
"median": 327227,
"max": 355591,
"min": 306166,
"mean": 328507,
"median": 327959,
"max": 356323,
"calldata_size": 4516,
"calldata_gas": 72256
},
"setupEpoch": {
"calls": 150,
"min": 29309,
"mean": 46504,
"median": 29309,
"max": 547670
"min": 29287,
"mean": 46482,
"median": 29287,
"max": 547648
},
"submitEpochRootProof": {
"calls": 4,
"min": 1464053,
"mean": 1575811,
"median": 1582771,
"max": 1673651,
"min": 1505653,
"mean": 1616774,
"median": 1623315,
"max": 1714815,
"calldata_size": 16644,
"calldata_gas": 266304
},
"aggregate3": {
"calls": 55,
"min": 365547,
"mean": 376665,
"median": 376350,
"max": 390039
"min": 366388,
"mean": 377506,
"median": 377191,
"max": 390880
}
}
}
47 changes: 25 additions & 22 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributo
import {CompressedSlot, CompressedTimestamp, CompressedTimeMath} from "@aztec/shared/libraries/CompressedTimeMath.sol";
import {Signature} from "@aztec/shared/libraries/SignatureLib.sol";
import {ChainTipsLib, CompressedChainTips} from "./libraries/compressed-data/Tips.sol";
import {ValidateHeaderArgs} from "./libraries/rollup/ProposeLib.sol";
import {RewardExtLib, RewardConfig} from "./libraries/rollup/RewardExtLib.sol";
import {DepositArgs} from "./libraries/StakingQueue.sol";
import {
Expand Down Expand Up @@ -90,24 +89,15 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
*/
function validateHeaderWithAttestations(
ProposedHeader calldata _header,
CommitteeAttestations memory _attestations,
CommitteeAttestations calldata _attestations,
address[] calldata _signers,
Signature memory _attestationsAndSignersSignature,
Signature calldata _attestationsAndSignersSignature,
bytes32 _digest,
bytes32 _blobsHash,
CheckpointHeaderValidationFlags memory _flags
CheckpointHeaderValidationFlags calldata _flags
) external override(IRollup) {
RollupOperationsExtLib.validateHeaderWithAttestations(
ValidateHeaderArgs({
header: _header,
digest: _digest,
manaMinFee: getManaMinFeeAt(Timestamp.wrap(block.timestamp), true),
blobsHashesCommitment: _blobsHash,
flags: _flags
}),
_attestations,
_signers,
_attestationsAndSignersSignature
_header, _attestations, _signers, _attestationsAndSignersSignature, _digest, _blobsHash, _flags
);
}

Expand Down Expand Up @@ -335,6 +325,19 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
return STFLib.getStorage().tips.getPending();
}

/**
* @notice Get the prover that first proved a given checkpoint
*
* @dev Reverts if the checkpoint is not proven yet
*
* @param _checkpointNumber - The checkpoint number to look up
*
* @return address - The prover that first proved the checkpoint
*/
function getFirstProvenBy(uint256 _checkpointNumber) external view override(IRollup) returns (address) {
return RewardExtLib.getFirstProvenBy(_checkpointNumber);
}

function getCheckpoint(uint256 _checkpointNumber) external view override(IRollup) returns (CheckpointLog memory) {
TempCheckpointLog memory tempCheckpointLog = STFLib.getTempCheckpointLog(_checkpointNumber);
return CheckpointLog({
Expand Down Expand Up @@ -604,14 +607,6 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
return ValidatorOperationsExtLib.getEntryQueueAt(_index);
}

function getSlasherExecutionDelay() external pure override(IStaking) returns (uint256) {
return StakingLib.SLASHER_EXECUTION_DELAY;
}

function getLegacySlasherDrainWindow() external pure override(IStaking) returns (uint256) {
return StakingLib.LEGACY_SLASHER_DRAIN_WINDOW;
}

function getProtocolFeeRecipient() external view override(IRollup) returns (address) {
return RewardExtLib.getProtocolFeeRecipient();
}
Expand All @@ -620,6 +615,14 @@ contract Rollup is IStaking, IValidatorSelection, IRollup, RollupCore {
return RewardExtLib.getProtocolFeeMargin();
}

function getSlasherExecutionDelay() external pure override(IStaking) returns (uint256) {
return StakingLib.SLASHER_EXECUTION_DELAY;
}

function getLegacySlasherDrainWindow() external pure override(IStaking) returns (uint256) {
return StakingLib.LEGACY_SLASHER_DRAIN_WINDOW;
}

/**
* @notice Get the validator set for a given epoch
*
Expand Down
4 changes: 4 additions & 0 deletions l1-contracts/src/core/interfaces/IRollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ struct RollupStore {
// The following represents a circular buffer. Key is `checkpointNumber % size`.
mapping(uint256 circularIndex => CompressedTempCheckpointLog temp) tempCheckpointLogs;
RollupConfig config;
// Only written at the checkpoint a proof ended at, so entries are sparse: a proof of checkpoints 1-10 followed by
// one of 11-20 records entries at 10 and 20 only. Use getFirstProvenBy to resolve an arbitrary checkpoint number.
mapping(uint256 checkpointNumber => uint256 encodedProverId) firstProvenBy;
}

interface IRollupCore {
Expand Down Expand Up @@ -214,6 +217,7 @@ interface IRollup is IRollupCore, IHaveVersion {
function getEthPerFeeAsset() external view returns (EthPerFeeAssetE12);

function getEpochForCheckpoint(uint256 _checkpointNumber) external view returns (Epoch);
function getFirstProvenBy(uint256 _checkpointNumber) external view returns (address);
function canPruneAtTime(Timestamp _ts) external view returns (bool);

function archive() external view returns (bytes32);
Expand Down
1 change: 1 addition & 0 deletions l1-contracts/src/core/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ library Errors {
error Rollup__CannotInvalidateEscapeHatch();
error Rollup__InvalidEscapeHatchProposer(address expected, address actual);
error Rollup__FieldElementOutOfRange(bytes32 value);
error Rollup__CheckpointNotProven(uint256 proven, uint256 requested);

// EscapeHatch
error EscapeHatch__AlreadyInCandidateSet(address candidate);
Expand Down
4 changes: 4 additions & 0 deletions l1-contracts/src/core/libraries/rollup/EpochProofLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ library EpochProofLib {
if (_args.end > tips.getProven()) {
rollupStore.tips = tips.updateProven(_args.end);

// Record who proved this range. Only the end checkpoint gets an entry, so lookups for the checkpoints in
// between walk forward to it; a later proof of an already proven range cannot reach here and overwrite it.
STFLib.recordFirstProvenBy(_args.end, _args.args.proverId);

// Handle L2->L1 message processing.
// The circuit outputs an empty out hash tree root if the epoch contains no messages.
// Since the out hash tree is append-only, with the first checkpoint at index 0, the second at index 1, and so on,
Expand Down
4 changes: 4 additions & 0 deletions l1-contracts/src/core/libraries/rollup/RewardExtLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ library RewardExtLib {
return STFLib.getEpochForCheckpoint(_checkpointNumber);
}

function getFirstProvenBy(uint256 _checkpointNumber) external view returns (address) {
return STFLib.getFirstProvenBy(_checkpointNumber);
}

function getL1FeesAt(Timestamp _timestamp) external view returns (L1FeeData memory) {
return FeeLib.getL1FeesAt(_timestamp);
}
Expand Down
3 changes: 2 additions & 1 deletion l1-contracts/src/core/libraries/rollup/RewardLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {STFLib} from "@aztec/core/libraries/rollup/STFLib.sol";
import {ValidatorSelectionLib} from "@aztec/core/libraries/rollup/ValidatorSelectionLib.sol";
import {Epoch, Timestamp, TimeLib} from "@aztec/core/libraries/TimeLib.sol";
import {IBoosterCore} from "@aztec/core/reward-boost/RewardBooster.sol";
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
import {GSE} from "@aztec/governance/GSE.sol";
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
import {Math} from "@oz/utils/math/Math.sol";
Expand Down Expand Up @@ -102,6 +102,7 @@ library RewardLib {
bytes32 private constant REWARD_STORAGE_POSITION = keccak256("aztec.reward.storage");

uint256 private constant REGISTRY_PROBE_GAS_LIMIT = 50_000;

/// @notice One-shot writer used during rollup construction. Writes every field of
/// {RewardConfig}, including the immutable `rewardDistributor` and `booster`.
/// @dev Must only be reachable from the constructor path. Post-deployment updates go through
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,20 @@
pragma solidity >=0.8.27;

import {Errors} from "@aztec/core/libraries/Errors.sol";
import {CheckpointHeaderValidationFlags} from "@aztec/core/interfaces/IRollup.sol";
import {STFLib} from "@aztec/core/libraries/rollup/STFLib.sol";
import {Timestamp, TimeLib, Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol";
import {BlobLib} from "@aztec-blob-lib/BlobLib.sol";
import {AttestationLib} from "@aztec/core/libraries/rollup/AttestationLib.sol";
import {FeeLib} from "@aztec/core/libraries/rollup/FeeLib.sol";
import {
ProposeLib,
ProposeArgs,
CommitteeAttestations,
ValidateHeaderArgs,
ValidatorSelectionLib
} from "./ProposeLib.sol";
import {ProposedHeader} from "./ProposedHeaderLib.sol";
import {Signature} from "@aztec/shared/libraries/SignatureLib.sol";

/**
Expand All @@ -37,21 +40,32 @@ library RollupOperationsExtLib {
using AttestationLib for CommitteeAttestations;

function validateHeaderWithAttestations(
ValidateHeaderArgs calldata _args,
ProposedHeader calldata _header,
CommitteeAttestations calldata _attestations,
address[] calldata _signers,
Signature calldata _attestationsAndSignersSignature
Signature calldata _attestationsAndSignersSignature,
bytes32 _digest,
bytes32 _blobsHash,
CheckpointHeaderValidationFlags calldata _flags
) external {
ProposeLib.validateHeader(_args);
ProposeLib.validateHeader(
ValidateHeaderArgs({
header: _header,
digest: _digest,
manaMinFee: FeeLib.summedMinFee(ProposeLib.getManaMinFeeComponentsAt(Timestamp.wrap(block.timestamp), true)),
blobsHashesCommitment: _blobsHash,
flags: _flags
})
);
if (_attestations.isEmpty()) {
return; // No attestations to validate
}

Slot slot = _args.header.slotNumber;
Slot slot = _header.slotNumber;
Epoch epoch = slot.epochFromSlot();
ValidatorSelectionLib.verifyAttestations(epoch, _attestations, _args.digest);
ValidatorSelectionLib.verifyAttestations(epoch, _attestations, _digest);
ValidatorSelectionLib.verifyProposer(
slot, epoch, _attestations, _signers, _args.digest, _attestationsAndSignersSignature, false
slot, epoch, _attestations, _signers, _digest, _attestationsAndSignersSignature, false
);
}

Expand Down
Loading
Loading