Skip to content

Commit

Permalink
Merge 7187cb5 into 23c122d
Browse files Browse the repository at this point in the history
  • Loading branch information
spalladino authored Nov 9, 2024
2 parents 23c122d + 7187cb5 commit d49f8d9
Show file tree
Hide file tree
Showing 71 changed files with 710 additions and 475 deletions.
43 changes: 18 additions & 25 deletions l1-contracts/src/core/Leonidas.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
pragma solidity >=0.8.27;

import {ILeonidas} from "@aztec/core/interfaces/ILeonidas.sol";
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
import {SampleLib} from "@aztec/core/libraries/crypto/SampleLib.sol";
import {SignatureLib} from "@aztec/core/libraries/crypto/SignatureLib.sol";
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {Timestamp, Slot, Epoch, SlotLib, EpochLib} from "@aztec/core/libraries/TimeMath.sol";
import {
Timestamp, Slot, Epoch, SlotLib, EpochLib, TimeFns
} from "@aztec/core/libraries/TimeMath.sol";
import {Ownable} from "@oz/access/Ownable.sol";
import {MessageHashUtils} from "@oz/utils/cryptography/MessageHashUtils.sol";
import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol";
Expand All @@ -27,7 +28,7 @@ import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol";
* It will be the duty of his successor (Pleistarchus) to optimize the costs with same functionality.
*
*/
contract Leonidas is Ownable, ILeonidas {
contract Leonidas is Ownable, TimeFns, ILeonidas {
using EnumerableSet for EnumerableSet.AddressSet;
using SignatureLib for SignatureLib.Signature;
using MessageHashUtils for bytes32;
Expand All @@ -47,25 +48,9 @@ contract Leonidas is Ownable, ILeonidas {
uint256 nextSeed;
}

// @note @LHerskind The multiple cause pain and suffering in the E2E tests as we introduce
// a timeliness requirement into the publication that did not exists before,
// and at the same time have a setup that will impact the time at every tx
// because of auto-mine. By using just 1, we can make our test work
// but anything using an actual working chain would eat dung as simulating
// transactions is slower than an actual ethereum slot.
//
// The value should be a higher multiple for any actual chain
// @todo #8019
uint256 public constant SLOT_DURATION = Constants.AZTEC_SLOT_DURATION;

// The duration of an epoch in slots
// @todo @LHerskind - This value should be updated when we are not blind.
// @todo #8020
uint256 public constant EPOCH_DURATION = Constants.AZTEC_EPOCH_DURATION;

// The target number of validators in a committee
// @todo #8021
uint256 public constant TARGET_COMMITTEE_SIZE = Constants.AZTEC_TARGET_COMMITTEE_SIZE;
uint256 public immutable TARGET_COMMITTEE_SIZE;

// The time that the contract was deployed
Timestamp public immutable GENESIS_TIME;
Expand All @@ -79,8 +64,16 @@ contract Leonidas is Ownable, ILeonidas {
// The last stored randao value, same value as `seed` in the last inserted epoch
uint256 private lastSeed;

constructor(address _ares) Ownable(_ares) {
constructor(
address _ares,
uint256 _slotDuration,
uint256 _epochDuration,
uint256 _targetCommitteeSize
) Ownable(_ares) TimeFns(_slotDuration, _epochDuration) {
GENESIS_TIME = Timestamp.wrap(block.timestamp);
SLOT_DURATION = _slotDuration;
EPOCH_DURATION = _epochDuration;
TARGET_COMMITTEE_SIZE = _targetCommitteeSize;
}

/**
Expand Down Expand Up @@ -232,7 +225,7 @@ contract Leonidas is Ownable, ILeonidas {
override(ILeonidas)
returns (Timestamp)
{
return GENESIS_TIME + _slotNumber.toTimestamp();
return GENESIS_TIME + toTimestamp(_slotNumber);
}

/**
Expand Down Expand Up @@ -303,7 +296,7 @@ contract Leonidas is Ownable, ILeonidas {
* @return The computed epoch
*/
function getEpochAt(Timestamp _ts) public view override(ILeonidas) returns (Epoch) {
return _ts < GENESIS_TIME ? Epoch.wrap(0) : EpochLib.fromTimestamp(_ts - GENESIS_TIME);
return _ts < GENESIS_TIME ? Epoch.wrap(0) : epochFromTimestamp(_ts - GENESIS_TIME);
}

/**
Expand All @@ -314,7 +307,7 @@ contract Leonidas is Ownable, ILeonidas {
* @return The computed slot
*/
function getSlotAt(Timestamp _ts) public view override(ILeonidas) returns (Slot) {
return _ts < GENESIS_TIME ? Slot.wrap(0) : SlotLib.fromTimestamp(_ts - GENESIS_TIME);
return _ts < GENESIS_TIME ? Slot.wrap(0) : slotFromTimestamp(_ts - GENESIS_TIME);
}

/**
Expand All @@ -324,7 +317,7 @@ contract Leonidas is Ownable, ILeonidas {
*
* @return The computed epoch
*/
function getEpochAtSlot(Slot _slotNumber) public pure override(ILeonidas) returns (Epoch) {
function getEpochAtSlot(Slot _slotNumber) public view override(ILeonidas) returns (Epoch) {
return Epoch.wrap(_slotNumber.unwrap() / EPOCH_DURATION);
}

Expand Down
12 changes: 8 additions & 4 deletions l1-contracts/src/core/ProofCommitmentEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
pragma solidity >=0.8.27;

import {IProofCommitmentEscrow} from "@aztec/core/interfaces/IProofCommitmentEscrow.sol";
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
Expand All @@ -17,8 +16,7 @@ contract ProofCommitmentEscrow is IProofCommitmentEscrow {
Timestamp executableAt;
}

uint256 public constant WITHDRAW_DELAY =
Constants.ETHEREUM_SLOT_DURATION * Constants.AZTEC_EPOCH_DURATION * 3;
uint256 public immutable WITHDRAW_DELAY;

address public immutable ROLLUP;
IERC20 public immutable TOKEN;
Expand All @@ -31,9 +29,15 @@ contract ProofCommitmentEscrow is IProofCommitmentEscrow {
_;
}

constructor(IERC20 _token, address _rollup) {
constructor(
IERC20 _token,
address _rollup,
uint256 _aztecSlotDuration,
uint256 _aztecEpochDuration
) {
ROLLUP = _rollup;
TOKEN = _token;
WITHDRAW_DELAY = _aztecSlotDuration * _aztecEpochDuration;
}

/**
Expand Down
40 changes: 29 additions & 11 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,18 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {
Slot slotNumber;
}

struct Config {
uint256 aztecSlotDuration;
uint256 aztecEpochDuration;
uint256 targetCommitteeSize;
uint256 aztecEpochProofClaimWindowInL2Slots;
}

// See https://github.com/AztecProtocol/engineering-designs/blob/main/in-progress/8401-proof-timeliness/proof-timeliness.ipynb
// for justification of CLAIM_DURATION_IN_L2_SLOTS.
uint256 public constant CLAIM_DURATION_IN_L2_SLOTS =
Constants.AZTEC_EPOCH_PROOF_CLAIM_WINDOW_IN_L2_SLOTS;
uint256 public constant PROOF_COMMITMENT_MIN_BOND_AMOUNT_IN_TST = 1000;

uint256 public immutable CLAIM_DURATION_IN_L2_SLOTS;
uint256 public immutable L1_BLOCK_AT_GENESIS;
IInbox public immutable INBOX;
IOutbox public immutable OUTBOX;
Expand All @@ -66,6 +72,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {
IFeeJuicePortal public immutable FEE_JUICE_PORTAL;
IRewardDistributor public immutable REWARD_DISTRIBUTOR;
IERC20 public immutable ASSET;

IVerifier public epochProofVerifier;

ChainTips public tips;
Expand All @@ -91,19 +98,30 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {
bytes32 _vkTreeRoot,
bytes32 _protocolContractTreeRoot,
address _ares,
address[] memory _validators
) Leonidas(_ares) {
address[] memory _validators,
Config memory _config
)
Leonidas(
_ares,
_config.aztecSlotDuration,
_config.aztecEpochDuration,
_config.targetCommitteeSize
)
{
epochProofVerifier = new MockVerifier();
FEE_JUICE_PORTAL = _fpcJuicePortal;
REWARD_DISTRIBUTOR = _rewardDistributor;
ASSET = _fpcJuicePortal.UNDERLYING();
PROOF_COMMITMENT_ESCROW = new ProofCommitmentEscrow(ASSET, address(this));
PROOF_COMMITMENT_ESCROW = new ProofCommitmentEscrow(
ASSET, address(this), _config.aztecSlotDuration, _config.aztecEpochDuration
);
INBOX = IInbox(address(new Inbox(address(this), Constants.L1_TO_L2_MSG_SUBTREE_HEIGHT)));
OUTBOX = IOutbox(address(new Outbox(address(this))));
vkTreeRoot = _vkTreeRoot;
protocolContractTreeRoot = _protocolContractTreeRoot;
VERSION = 1;
L1_BLOCK_AT_GENESIS = block.number;
CLAIM_DURATION_IN_L2_SLOTS = _config.aztecEpochProofClaimWindowInL2Slots;

// Genesis block
blocks[0] = BlockLog({
Expand Down Expand Up @@ -641,7 +659,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {
// out_hash: root of this epoch's l2 to l1 message tree
publicInputs[8] = _args[5];

uint256 feesLength = Constants.AZTEC_EPOCH_DURATION * 2;
uint256 feesLength = Constants.AZTEC_MAX_EPOCH_DURATION * 2;
// fees[9 to (9+feesLength-1)]: array of recipient-value pairs
for (uint256 i = 0; i < feesLength; i++) {
publicInputs[9 + i] = _fees[i];
Expand Down Expand Up @@ -703,8 +721,8 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {
);

require(
currentSlot.positionInEpoch() < CLAIM_DURATION_IN_L2_SLOTS,
Errors.Rollup__NotInClaimPhase(currentSlot.positionInEpoch(), CLAIM_DURATION_IN_L2_SLOTS)
positionInEpoch(currentSlot) < CLAIM_DURATION_IN_L2_SLOTS,
Errors.Rollup__NotInClaimPhase(positionInEpoch(currentSlot), CLAIM_DURATION_IN_L2_SLOTS)
);

// if the epoch to prove is not the one that has been claimed,
Expand Down Expand Up @@ -795,16 +813,16 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Leonidas, IRollup, ITestRollup {

Slot currentSlot = getSlotAt(_ts);
Epoch oldestPendingEpoch = getEpochForBlock(tips.provenBlockNumber + 1);
Slot startSlotOfPendingEpoch = oldestPendingEpoch.toSlots();
Slot startSlotOfPendingEpoch = toSlots(oldestPendingEpoch);

// suppose epoch 1 is proven, epoch 2 is pending, epoch 3 is the current epoch.
// we prune the pending chain back to the end of epoch 1 if:
// - the proof claim phase of epoch 3 has ended without a claim to prove epoch 2 (or proof of epoch 2)
// - we reach epoch 4 without a proof of epoch 2 (regardless of whether a proof claim was submitted)
bool inClaimPhase = currentSlot
< startSlotOfPendingEpoch + Epoch.wrap(1).toSlots() + Slot.wrap(CLAIM_DURATION_IN_L2_SLOTS);
< startSlotOfPendingEpoch + toSlots(Epoch.wrap(1)) + Slot.wrap(CLAIM_DURATION_IN_L2_SLOTS);

bool claimExists = currentSlot < startSlotOfPendingEpoch + Epoch.wrap(2).toSlots()
bool claimExists = currentSlot < startSlotOfPendingEpoch + toSlots(Epoch.wrap(2))
&& proofClaim.epochToProve == oldestPendingEpoch && proofClaim.proposerClaimant != address(0);

if (inClaimPhase || claimExists) {
Expand Down
12 changes: 4 additions & 8 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// GENERATED FILE - DO NOT EDIT, RUN yarn remake-constants in circuits.js
// SPDX-License-Identifier: Apache-2.0
// Copyright 2024 Aztec Labs.
// Copyright 2023 Aztec Labs.
pragma solidity >=0.8.27;

/**
Expand Down Expand Up @@ -94,11 +94,7 @@ library Constants {
uint256 internal constant INITIAL_L2_BLOCK_NUM = 1;
uint256 internal constant PRIVATE_LOG_SIZE_IN_BYTES = 576;
uint256 internal constant BLOB_SIZE_IN_BYTES = 126976;
uint256 internal constant ETHEREUM_SLOT_DURATION = 12;
uint256 internal constant AZTEC_SLOT_DURATION = 24;
uint256 internal constant AZTEC_EPOCH_DURATION = 16;
uint256 internal constant AZTEC_TARGET_COMMITTEE_SIZE = 48;
uint256 internal constant AZTEC_EPOCH_PROOF_CLAIM_WINDOW_IN_L2_SLOTS = 13;
uint256 internal constant AZTEC_MAX_EPOCH_DURATION = 32;
uint256 internal constant GENESIS_ARCHIVE_ROOT =
19007378675971183768036762391356802220352606103602592933942074152320327194720;
uint256 internal constant FEE_JUICE_INITIAL_MINT = 20000000000;
Expand Down Expand Up @@ -235,8 +231,8 @@ library Constants {
uint256 internal constant KERNEL_CIRCUIT_PUBLIC_INPUTS_LENGTH = 601;
uint256 internal constant CONSTANT_ROLLUP_DATA_LENGTH = 13;
uint256 internal constant BASE_OR_MERGE_PUBLIC_INPUTS_LENGTH = 30;
uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 60;
uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 44;
uint256 internal constant BLOCK_ROOT_OR_BLOCK_MERGE_PUBLIC_INPUTS_LENGTH = 90;
uint256 internal constant ROOT_ROLLUP_PUBLIC_INPUTS_LENGTH = 76;
uint256 internal constant GET_NOTES_ORACLE_RETURN_LENGTH = 674;
uint256 internal constant NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP = 2048;
uint256 internal constant NULLIFIERS_NUM_BYTES_PER_BASE_ROLLUP = 2048;
Expand Down
61 changes: 40 additions & 21 deletions l1-contracts/src/core/libraries/TimeMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,66 @@
// Copyright 2024 Aztec Labs.
pragma solidity >=0.8.27;

import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";

type Timestamp is uint256;

type Slot is uint256;

type Epoch is uint256;

library SlotLib {
function toTimestamp(Slot _a) internal pure returns (Timestamp) {
return Timestamp.wrap(Slot.unwrap(_a) * Constants.AZTEC_SLOT_DURATION);
abstract contract TimeFns {
// @note @LHerskind The multiple cause pain and suffering in the E2E tests as we introduce
// a timeliness requirement into the publication that did not exists before,
// and at the same time have a setup that will impact the time at every tx
// because of auto-mine. By using just 1, we can make our test work
// but anything using an actual working chain would eat dung as simulating
// transactions is slower than an actual ethereum slot.
//
// The value should be a higher multiple for any actual chain
// @todo #8019
uint256 public immutable SLOT_DURATION;

// The duration of an epoch in slots
// @todo @LHerskind - This value should be updated when we are not blind.
// @todo #8020
uint256 public immutable EPOCH_DURATION;

constructor(uint256 _slotDuration, uint256 _epochDuration) {
SLOT_DURATION = _slotDuration;
EPOCH_DURATION = _epochDuration;
}

function fromTimestamp(Timestamp _a) internal pure returns (Slot) {
return Slot.wrap(Timestamp.unwrap(_a) / Constants.AZTEC_SLOT_DURATION);
function toTimestamp(Slot _a) internal view returns (Timestamp) {
return Timestamp.wrap(Slot.unwrap(_a) * SLOT_DURATION);
}

function positionInEpoch(Slot _a) internal pure returns (uint256) {
return Slot.unwrap(_a) % Constants.AZTEC_EPOCH_DURATION;
function slotFromTimestamp(Timestamp _a) internal view returns (Slot) {
return Slot.wrap(Timestamp.unwrap(_a) / SLOT_DURATION);
}

function unwrap(Slot _a) internal pure returns (uint256) {
return Slot.unwrap(_a);
function positionInEpoch(Slot _a) internal view returns (uint256) {
return Slot.unwrap(_a) % EPOCH_DURATION;
}
}

library EpochLib {
function toSlots(Epoch _a) internal pure returns (Slot) {
return Slot.wrap(Epoch.unwrap(_a) * Constants.AZTEC_EPOCH_DURATION);
function toSlots(Epoch _a) internal view returns (Slot) {
return Slot.wrap(Epoch.unwrap(_a) * EPOCH_DURATION);
}

function toTimestamp(Epoch _a) internal view returns (Timestamp) {
return toTimestamp(toSlots(_a));
}

function toTimestamp(Epoch _a) internal pure returns (Timestamp) {
return SlotLib.toTimestamp(toSlots(_a));
function epochFromTimestamp(Timestamp _a) internal view returns (Epoch) {
return Epoch.wrap(Timestamp.unwrap(_a) / (EPOCH_DURATION * SLOT_DURATION));
}
}

function fromTimestamp(Timestamp _a) internal pure returns (Epoch) {
return Epoch.wrap(
Timestamp.unwrap(_a) / (Constants.AZTEC_EPOCH_DURATION * Constants.AZTEC_SLOT_DURATION)
);
library SlotLib {
function unwrap(Slot _a) internal pure returns (uint256) {
return Slot.unwrap(_a);
}
}

library EpochLib {
function unwrap(Epoch _a) internal pure returns (uint256) {
return Epoch.unwrap(_a);
}
Expand Down
Loading

0 comments on commit d49f8d9

Please sign in to comment.