Skip to content

Commit 6b82e79

Browse files
committed
feat!: time library
1 parent 2779ea4 commit 6b82e79

File tree

69 files changed

+220
-175
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+220
-175
lines changed

docs/docs/guides/developer_guides/js_apps/test.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ The [`CheatCodes`](../../../reference/developer_references/sandbox_reference/che
134134
### Set next block timestamp
135135

136136
Since the rollup time is dependent on what "slot" the block is included in, time can be progressed by progressing slots.
137-
The duration of a slot is available by calling `SLOT_DURATION()` on the Rollup (code in Leonidas.sol).
137+
The duration of a slot is available by calling `getSlotDuration()` on the Rollup (code in Leonidas.sol).
138138

139139
You can then use the `warp` function on the EthCheatCodes to progress the underlying chain.
140140

l1-contracts/src/core/Leonidas.sol

+25-17
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
88
import {Errors} from "@aztec/core/libraries/Errors.sol";
99
import {LeonidasLib} from "@aztec/core/libraries/LeonidasLib/LeonidasLib.sol";
1010
import {
11-
Timestamp, Slot, Epoch, SlotLib, EpochLib, TimeFns
12-
} from "@aztec/core/libraries/TimeMath.sol";
11+
Timestamp, Slot, Epoch, SlotLib, EpochLib, TimeLib
12+
} from "@aztec/core/libraries/TimeLib.sol";
1313
import {Staking} from "@aztec/core/staking/Staking.sol";
1414
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
1515
import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol";
@@ -26,19 +26,19 @@ import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol";
2626
* It will be the duty of his successor (Pleistarchus) to optimize the costs with same functionality.
2727
*
2828
*/
29-
contract Leonidas is Staking, TimeFns, ILeonidas {
29+
contract Leonidas is Staking, ILeonidas {
3030
using EnumerableSet for EnumerableSet.AddressSet;
3131

3232
using SlotLib for Slot;
3333
using EpochLib for Epoch;
34+
using TimeLib for Timestamp;
35+
using TimeLib for Slot;
36+
using TimeLib for Epoch;
3437

3538
// The target number of validators in a committee
3639
// @todo #8021
3740
uint256 public immutable TARGET_COMMITTEE_SIZE;
3841

39-
// The time that the contract was deployed
40-
Timestamp public immutable GENESIS_TIME;
41-
4242
LeonidasStorage private leonidasStore;
4343

4444
constructor(
@@ -49,14 +49,22 @@ contract Leonidas is Staking, TimeFns, ILeonidas {
4949
uint256 _slotDuration,
5050
uint256 _epochDuration,
5151
uint256 _targetCommitteeSize
52-
)
53-
Staking(_stakingAsset, _minimumStake, _slashingQuorum, _roundSize)
54-
TimeFns(_slotDuration, _epochDuration)
55-
{
56-
GENESIS_TIME = Timestamp.wrap(block.timestamp);
57-
SLOT_DURATION = _slotDuration;
58-
EPOCH_DURATION = _epochDuration;
52+
) Staking(_stakingAsset, _minimumStake, _slashingQuorum, _roundSize) {
5953
TARGET_COMMITTEE_SIZE = _targetCommitteeSize;
54+
55+
TimeLib.initialize(block.timestamp, _slotDuration, _epochDuration);
56+
}
57+
58+
function getGenesisTime() external view override(ILeonidas) returns (Timestamp) {
59+
return Timestamp.wrap(TimeLib.getGenesisTime());
60+
}
61+
62+
function getSlotDuration() external view override(ILeonidas) returns (uint256) {
63+
return TimeLib.getSlotDuration();
64+
}
65+
66+
function getEpochDuration() external view override(ILeonidas) returns (uint256) {
67+
return TimeLib.getEpochDuration();
6068
}
6169

6270
/**
@@ -212,7 +220,7 @@ contract Leonidas is Staking, TimeFns, ILeonidas {
212220
override(ILeonidas)
213221
returns (Timestamp)
214222
{
215-
return GENESIS_TIME + toTimestamp(_slotNumber);
223+
return _slotNumber.toTimestamp();
216224
}
217225

218226
/**
@@ -263,7 +271,7 @@ contract Leonidas is Staking, TimeFns, ILeonidas {
263271
* @return The computed epoch
264272
*/
265273
function getEpochAt(Timestamp _ts) public view override(ILeonidas) returns (Epoch) {
266-
return _ts < GENESIS_TIME ? Epoch.wrap(0) : epochFromTimestamp(_ts - GENESIS_TIME);
274+
return _ts.epochFromTimestamp();
267275
}
268276

269277
/**
@@ -274,7 +282,7 @@ contract Leonidas is Staking, TimeFns, ILeonidas {
274282
* @return The computed slot
275283
*/
276284
function getSlotAt(Timestamp _ts) public view override(ILeonidas) returns (Slot) {
277-
return _ts < GENESIS_TIME ? Slot.wrap(0) : slotFromTimestamp(_ts - GENESIS_TIME);
285+
return _ts.slotFromTimestamp();
278286
}
279287

280288
/**
@@ -285,7 +293,7 @@ contract Leonidas is Staking, TimeFns, ILeonidas {
285293
* @return The computed epoch
286294
*/
287295
function getEpochAtSlot(Slot _slotNumber) public view override(ILeonidas) returns (Epoch) {
288-
return Epoch.wrap(_slotNumber.unwrap() / EPOCH_DURATION);
296+
return _slotNumber.epochFromSlot();
289297
}
290298

291299
// Can be used to add validators without setting up the epoch, useful for the initial set.

l1-contracts/src/core/ProofCommitmentEscrow.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pragma solidity >=0.8.27;
44

55
import {IProofCommitmentEscrow} from "@aztec/core/interfaces/IProofCommitmentEscrow.sol";
66
import {Errors} from "@aztec/core/libraries/Errors.sol";
7-
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";
7+
import {Timestamp} from "@aztec/core/libraries/TimeLib.sol";
88
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
99
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";
1010

l1-contracts/src/core/Rollup.sol

+7-8
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import {
3535
} from "@aztec/core/libraries/RollupLibs/ExtRollupLib.sol";
3636
import {IntRollupLib, EpochProofQuote} from "@aztec/core/libraries/RollupLibs/IntRollupLib.sol";
3737
import {ProposeArgs, ProposeLib} from "@aztec/core/libraries/RollupLibs/ProposeLib.sol";
38-
import {Timestamp, Slot, Epoch, SlotLib, EpochLib} from "@aztec/core/libraries/TimeMath.sol";
38+
import {Timestamp, Slot, Epoch, TimeLib} from "@aztec/core/libraries/TimeLib.sol";
3939
import {Inbox} from "@aztec/core/messagebridge/Inbox.sol";
4040
import {Outbox} from "@aztec/core/messagebridge/Outbox.sol";
4141
import {ProofCommitmentEscrow} from "@aztec/core/ProofCommitmentEscrow.sol";
@@ -63,8 +63,6 @@ struct Config {
6363
* @dev WARNING: This contract is VERY close to the size limit (500B at time of writing).
6464
*/
6565
contract Rollup is EIP712("Aztec Rollup", "1"), Ownable, Leonidas, IRollup, ITestRollup {
66-
using SlotLib for Slot;
67-
using EpochLib for Epoch;
6866
using ProposeLib for ProposeArgs;
6967
using IntRollupLib for uint256;
7068
using IntRollupLib for ManaBaseFeeComponents;
@@ -662,7 +660,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Ownable, Leonidas, IRollup, ITes
662660
rollupStore.blocks[blockOfInterest].feeHeader,
663661
getL1FeesAt(_timestamp),
664662
_inFeeAsset ? getFeeAssetPrice() : 1e9,
665-
EPOCH_DURATION
663+
TimeLib.getEpochDuration()
666664
);
667665
}
668666

@@ -683,7 +681,7 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Ownable, Leonidas, IRollup, ITes
683681
Slot currentSlot = getSlotAt(_ts);
684682
address currentProposer = getProposerAt(_ts);
685683
Epoch epochToProve = getEpochToProve();
686-
uint256 posInEpoch = positionInEpoch(currentSlot);
684+
uint256 posInEpoch = TimeLib.positionInEpoch(currentSlot);
687685
bytes32 digest = quoteToDigest(_quote.quote);
688686

689687
ExtRollupLib.validateEpochProofRightClaimAtTime(
@@ -786,16 +784,17 @@ contract Rollup is EIP712("Aztec Rollup", "1"), Ownable, Leonidas, IRollup, ITes
786784

787785
Slot currentSlot = getSlotAt(_ts);
788786
Epoch oldestPendingEpoch = getEpochForBlock(rollupStore.tips.provenBlockNumber + 1);
789-
Slot startSlotOfPendingEpoch = toSlots(oldestPendingEpoch);
787+
Slot startSlotOfPendingEpoch = TimeLib.toSlots(oldestPendingEpoch);
790788

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

798-
bool claimExists = currentSlot < startSlotOfPendingEpoch + toSlots(Epoch.wrap(2))
797+
bool claimExists = currentSlot < startSlotOfPendingEpoch + TimeLib.toSlots(Epoch.wrap(2))
799798
&& rollupStore.proofClaim.epochToProve == oldestPendingEpoch
800799
&& rollupStore.proofClaim.proposerClaimant != address(0);
801800

l1-contracts/src/core/interfaces/ILeonidas.sol

+5-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright 2024 Aztec Labs.
33
pragma solidity >=0.8.27;
44

5-
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeMath.sol";
5+
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol";
66

77
/**
88
* @notice The data structure for an epoch
@@ -49,4 +49,8 @@ interface ILeonidas {
4949
function getEpochAt(Timestamp _ts) external view returns (Epoch);
5050
function getSlotAt(Timestamp _ts) external view returns (Slot);
5151
function getEpochAtSlot(Slot _slotNumber) external view returns (Epoch);
52+
53+
function getGenesisTime() external view returns (Timestamp);
54+
function getSlotDuration() external view returns (uint256);
55+
function getEpochDuration() external view returns (uint256);
5256
}

l1-contracts/src/core/interfaces/IProofCommitmentEscrow.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright 2024 Aztec Labs.
33
pragma solidity >=0.8.27;
44

5-
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";
5+
import {Timestamp} from "@aztec/core/libraries/TimeLib.sol";
66
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
77

88
interface IProofCommitmentEscrow {

l1-contracts/src/core/interfaces/IRollup.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
FeeHeader, L1FeeData, ManaBaseFeeComponents
1616
} from "@aztec/core/libraries/RollupLibs/FeeMath.sol";
1717
import {ProposeArgs} from "@aztec/core/libraries/RollupLibs/ProposeLib.sol";
18-
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeMath.sol";
18+
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol";
1919

2020
struct SubmitEpochRootProofArgs {
2121
uint256 epochSize;

l1-contracts/src/core/interfaces/IStaking.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright 2024 Aztec Labs.
33
pragma solidity >=0.8.27;
44

5-
import {Timestamp} from "@aztec/core/libraries/TimeMath.sol";
5+
import {Timestamp} from "@aztec/core/libraries/TimeLib.sol";
66
import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol";
77

88
// None -> Does not exist in our setup

l1-contracts/src/core/libraries/DataStructures.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright 2024 Aztec Labs.
33
pragma solidity >=0.8.27;
44

5-
import {Epoch} from "@aztec/core/libraries/TimeMath.sol";
5+
import {Epoch} from "@aztec/core/libraries/TimeLib.sol";
66

77
/**
88
* @title Data Structures Library

l1-contracts/src/core/libraries/Errors.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Copyright 2024 Aztec Labs.
33
pragma solidity >=0.8.27;
44

5-
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeMath.sol";
5+
import {Timestamp, Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol";
66

77
/**
88
* @title Errors Library

l1-contracts/src/core/libraries/LeonidasLib/LeonidasLib.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {SampleLib} from "@aztec/core/libraries/crypto/SampleLib.sol";
88
import {SignatureLib, Signature} from "@aztec/core/libraries/crypto/SignatureLib.sol";
99
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
1010
import {Errors} from "@aztec/core/libraries/Errors.sol";
11-
import {Slot, Epoch} from "@aztec/core/libraries/TimeMath.sol";
11+
import {Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol";
1212
import {MessageHashUtils} from "@oz/utils/cryptography/MessageHashUtils.sol";
1313
import {EnumerableSet} from "@oz/utils/structs/EnumerableSet.sol";
1414

l1-contracts/src/core/libraries/RollupLibs/EpochProofLib.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
} from "@aztec/core/interfaces/IRollup.sol";
1010
import {Constants} from "@aztec/core/libraries/ConstantsGen.sol";
1111
import {Errors} from "@aztec/core/libraries/Errors.sol";
12-
import {Epoch} from "@aztec/core/libraries/TimeMath.sol";
12+
import {Epoch} from "@aztec/core/libraries/TimeLib.sol";
1313
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
1414
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
1515
import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol";

l1-contracts/src/core/libraries/RollupLibs/EpochProofQuoteLib.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
pragma solidity >=0.8.27;
44

55
import {Signature} from "@aztec/core/libraries/crypto/SignatureLib.sol";
6-
import {Slot, Epoch} from "@aztec/core/libraries/TimeMath.sol";
6+
import {Slot, Epoch} from "@aztec/core/libraries/TimeLib.sol";
77

88
/**
99
* @notice Struct encompassing an epoch proof quote

l1-contracts/src/core/libraries/RollupLibs/ExtRollupLib.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {BlockLog, RollupStore, SubmitEpochRootProofArgs} from "@aztec/core/inter
99
import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributor.sol";
1010
import {IERC20} from "@oz/token/ERC20/IERC20.sol";
1111
import {DataStructures} from "./../DataStructures.sol";
12-
import {Slot, Epoch} from "./../TimeMath.sol";
12+
import {Slot, Epoch} from "./../TimeLib.sol";
1313
import {BlobLib} from "./BlobLib.sol";
1414
import {
1515
EpochProofLib,

l1-contracts/src/core/libraries/RollupLibs/ValidationLib.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {BlockLog} from "@aztec/core/interfaces/IRollup.sol";
88
import {SignatureLib} from "@aztec/core/libraries/crypto/SignatureLib.sol";
99
import {DataStructures} from "./../DataStructures.sol";
1010
import {Errors} from "./../Errors.sol";
11-
import {Timestamp, Slot, Epoch} from "./../TimeMath.sol";
11+
import {Timestamp, Slot, Epoch} from "./../TimeLib.sol";
1212
import {SignedEpochProofQuote} from "./EpochProofQuoteLib.sol";
1313
import {Header} from "./HeaderLib.sol";
1414

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright 2024 Aztec Labs.
3+
pragma solidity >=0.8.27;
4+
5+
// solhint-disable-next-line no-unused-import
6+
import {Timestamp, Slot, Epoch, SlotLib, EpochLib} from "@aztec/core/libraries/TimeMath.sol";
7+
8+
struct TimeStorage {
9+
uint256 genesisTime;
10+
uint256 slotDuration; // Number of seconds in a slot
11+
uint256 epochDuration; // Number of slots in an epoch
12+
}
13+
14+
library TimeLib {
15+
bytes32 private constant TIME_STORAGE_POSITION = keccak256("aztec.time.storage");
16+
17+
function initialize(uint256 _genesisTime, uint256 _slotDuration, uint256 _epochDuration) internal {
18+
TimeStorage storage store = getStorage();
19+
store.genesisTime = _genesisTime;
20+
store.slotDuration = _slotDuration;
21+
store.epochDuration = _epochDuration;
22+
}
23+
24+
function getEpochDuration() internal view returns (uint256) {
25+
return getStorage().epochDuration;
26+
}
27+
28+
function getSlotDuration() internal view returns (uint256) {
29+
return getStorage().slotDuration;
30+
}
31+
32+
function getGenesisTime() internal view returns (uint256) {
33+
return getStorage().genesisTime;
34+
}
35+
36+
function toTimestamp(Slot _a) internal view returns (Timestamp) {
37+
TimeStorage storage store = getStorage();
38+
return Timestamp.wrap(store.genesisTime) + Timestamp.wrap(Slot.unwrap(_a) * store.slotDuration);
39+
}
40+
41+
function slotFromTimestamp(Timestamp _a) internal view returns (Slot) {
42+
TimeStorage storage store = getStorage();
43+
return Slot.wrap((Timestamp.unwrap(_a) - store.genesisTime) / store.slotDuration);
44+
}
45+
46+
function positionInEpoch(Slot _a) internal view returns (uint256) {
47+
return Slot.unwrap(_a) % getEpochDuration();
48+
}
49+
50+
function toSlots(Epoch _a) internal view returns (Slot) {
51+
return Slot.wrap(Epoch.unwrap(_a) * getEpochDuration());
52+
}
53+
54+
function toTimestamp(Epoch _a) internal view returns (Timestamp) {
55+
return toTimestamp(toSlots(_a));
56+
}
57+
58+
function epochFromTimestamp(Timestamp _a) internal view returns (Epoch) {
59+
TimeStorage storage store = getStorage();
60+
return Epoch.wrap(
61+
(Timestamp.unwrap(_a) - store.genesisTime) / (store.epochDuration * store.slotDuration)
62+
);
63+
}
64+
65+
function epochFromSlot(Slot _a) internal view returns (Epoch) {
66+
return Epoch.wrap(Slot.unwrap(_a) / getEpochDuration());
67+
}
68+
69+
function getStorage() internal pure returns (TimeStorage storage storageStruct) {
70+
bytes32 position = TIME_STORAGE_POSITION;
71+
assembly {
72+
storageStruct.slot := position
73+
}
74+
}
75+
}

0 commit comments

Comments
 (0)