From 2e3cbfa62b33c3340327be44697f17bcc503dde9 Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Thu, 17 Aug 2023 16:46:35 +0000 Subject: [PATCH 1/5] increment time by 1 for next rollup if warped --- .../src/sequencer/public_processor.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.ts index 8ff1a223ca0..bbf261da852 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.ts @@ -73,6 +73,17 @@ export class PublicProcessorFactory { globalVariables: GlobalVariables, ): Promise { const blockData = await getHistoricBlockData(this.merkleTree, prevGlobalVariables); + + // TODO(rahul) - fix #1614. By using the cheatcode warp to modify L2 time, + // txs in the new rollup would have same time as the txs in the previous rollup. + // We overcome this now by identifying if the last rollup time was warped (if two rollups have same time) + // and tell public-processor to use a different time (increment last rollup block) + // more details at https://github.com/AztecProtocol/aztec-packages/issues/1614 + const isWarped = prevGlobalVariables.timestamp == globalVariables.timestamp; + if (isWarped) { + globalVariables.timestamp = new Fr(globalVariables.timestamp.value + 1n); + } + return new PublicProcessor( this.merkleTree, getPublicExecutor(this.merkleTree, this.contractDataSource, this.l1Tol2MessagesDataSource, blockData), From e737c0ffb8e0e560995c713fe2ae7a3231b2b2d0 Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Thu, 17 Aug 2023 17:09:16 +0000 Subject: [PATCH 2/5] move timestamp change to sequencer --- .../src/sequencer/public_processor.ts | 11 ----------- .../sequencer-client/src/sequencer/sequencer.ts | 12 ++++++++++++ 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/yarn-project/sequencer-client/src/sequencer/public_processor.ts b/yarn-project/sequencer-client/src/sequencer/public_processor.ts index bbf261da852..8ff1a223ca0 100644 --- a/yarn-project/sequencer-client/src/sequencer/public_processor.ts +++ b/yarn-project/sequencer-client/src/sequencer/public_processor.ts @@ -73,17 +73,6 @@ export class PublicProcessorFactory { globalVariables: GlobalVariables, ): Promise { const blockData = await getHistoricBlockData(this.merkleTree, prevGlobalVariables); - - // TODO(rahul) - fix #1614. By using the cheatcode warp to modify L2 time, - // txs in the new rollup would have same time as the txs in the previous rollup. - // We overcome this now by identifying if the last rollup time was warped (if two rollups have same time) - // and tell public-processor to use a different time (increment last rollup block) - // more details at https://github.com/AztecProtocol/aztec-packages/issues/1614 - const isWarped = prevGlobalVariables.timestamp == globalVariables.timestamp; - if (isWarped) { - globalVariables.timestamp = new Fr(globalVariables.timestamp.value + 1n); - } - return new PublicProcessor( this.merkleTree, getPublicExecutor(this.merkleTree, this.contractDataSource, this.l1Tol2MessagesDataSource, blockData), diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index b3a6e3b7540..df516ccfe10 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -144,6 +144,18 @@ export class Sequencer { const newGlobalVariables = await this.globalsBuilder.buildGlobalVariables(new Fr(blockNumber)); const prevGlobalVariables = (await this.l2BlockSource.getL2Block(-1))?.globalVariables ?? GlobalVariables.empty(); + // TODO(rahul) - fix #1614. By using the cheatcode warp to modify L2 time, + // txs in the new rollup would have same time as the txs in the previous rollup. + // We overcome this now by identifying if the last rollup time was warped (if two rollups have same time) + // and tell public-processor to use a different time (increment last rollup block) + // more details at https://github.com/AztecProtocol/aztec-packages/issues/1614 + const isWarped = + !prevGlobalVariables.timestamp.equals(Fr.ZERO) && + prevGlobalVariables.timestamp.equals(newGlobalVariables.timestamp); + if (isWarped) { + newGlobalVariables.timestamp = new Fr(newGlobalVariables.timestamp.value + 1n); + } + // Process txs and drop the ones that fail processing // We create a fresh processor each time to reset any cached state (eg storage writes) const processor = await this.publicProcessorFactory.create(prevGlobalVariables, newGlobalVariables); From 13b0ad3cfe95b41da5c5520fc1db7956265fe27f Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Thu, 24 Aug 2023 13:54:50 +0000 Subject: [PATCH 3/5] move to simple global builder --- l1-contracts/src/core/Rollup.sol | 3 ++ .../aztec.js/src/utils/cheat_codes.ts | 2 ++ .../end-to-end/src/e2e_cheat_codes.test.ts | 15 ++++++---- .../global_variable_builder/global_builder.ts | 28 ++++++++++++++++++- .../global_variable_builder/viem-reader.ts | 8 ++++++ .../src/sequencer/sequencer.ts | 12 -------- 6 files changed, 49 insertions(+), 19 deletions(-) diff --git a/l1-contracts/src/core/Rollup.sol b/l1-contracts/src/core/Rollup.sol index d1c0210f2cd..391af51b1df 100644 --- a/l1-contracts/src/core/Rollup.sol +++ b/l1-contracts/src/core/Rollup.sol @@ -28,6 +28,9 @@ contract Rollup is IRollup { bytes32 public rollupStateHash; uint256 public lastBlockTs; + // Tracks the last time time was warped on L2 ("warp" is the testing cheatocde). + // See https://github.com/AztecProtocol/aztec-packages/issues/1614 + uint256 public lastWarpedBlockTs; constructor(IRegistry _registry) { VERIFIER = new MockVerifier(); diff --git a/yarn-project/aztec.js/src/utils/cheat_codes.ts b/yarn-project/aztec.js/src/utils/cheat_codes.ts index e8fd8780dfc..d94b73b28e3 100644 --- a/yarn-project/aztec.js/src/utils/cheat_codes.ts +++ b/yarn-project/aztec.js/src/utils/cheat_codes.ts @@ -266,6 +266,8 @@ export class AztecCheatCodes { // also store this time on the rollup contract (slot 1 tracks `lastBlockTs`). // This is because when the sequencer executes public functions, it uses the timestamp stored in the rollup contract. await this.eth.store(rollupContract, 1n, BigInt(to)); + // also store this on slot 2 of the rollup contract (`lastWarpedBlockTs`) which tracks the last time warp was used. + await this.eth.store(rollupContract, 2n, BigInt(to)); } /** diff --git a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts index acae936aa18..d7ec7962ee4 100644 --- a/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts +++ b/yarn-project/end-to-end/src/e2e_cheat_codes.test.ts @@ -156,16 +156,19 @@ describe('e2e_cheat_codes', () => { // ensure rollup contract is correctly updated const rollup = getContract({ address: getAddress(rollupAddress.toString()), abi: RollupAbi, publicClient }); expect(Number(await rollup.read.lastBlockTs())).toEqual(newTimestamp); + expect(Number(await rollup.read.lastWarpedBlockTs())).toEqual(newTimestamp); const txIsTimeEqual = contract.methods.isTimeEqual(newTimestamp).send({ origin: recipient }); - await txIsTimeEqual.isMined({ interval: 0.1 }); - const isTimeEqualReceipt = await txIsTimeEqual.getReceipt(); + const isTimeEqualReceipt = await txIsTimeEqual.wait({ interval: 0.1 }); expect(isTimeEqualReceipt.status).toBe(TxStatus.MINED); - const txTimeNotEqual = contract.methods.isTimeEqual(0).send({ origin: recipient }); - await txTimeNotEqual.isMined({ interval: 0.1 }); - const isTimeNotEqualReceipt = await txTimeNotEqual.getReceipt(); - expect(isTimeNotEqualReceipt.status).toBe(TxStatus.DROPPED); + // Since last rollup block was warped, txs for this rollup will have time incremented by 1 + // See https://github.com/AztecProtocol/aztec-packages/issues/1614 for details + const txTimeNotEqual = contract.methods.isTimeEqual(newTimestamp + 1).send({ origin: recipient }); + const isTimeNotEqualReceipt = await txTimeNotEqual.wait({ interval: 0.1 }); + expect(isTimeNotEqualReceipt.status).toBe(TxStatus.MINED); + // block is published at t >= newTimestamp + 1. + expect(Number(await rollup.read.lastBlockTs())).toBeGreaterThanOrEqual(newTimestamp + 1); }, 50_000); it('should throw if setting L2 block time to a past timestamp', async () => { diff --git a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts index 4b878107284..57d959dde22 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts @@ -20,6 +20,18 @@ export interface L1GlobalReader { * @returns The chain id. */ getChainId(): Promise; + + /** + * Gets the current L1 time. + * @returns The current L1 time. + */ + getL1CurrentTime(): Promise; + + /** + * Gets the last time L2 was warped as tracked by the rollup contract. + * @returns The warped time. + */ + getLastWarpedBlockTs(): Promise; } /** @@ -47,10 +59,24 @@ export class SimpleGlobalVariableBuilder implements GlobalVariableBuilder { * @returns The global variables for the given block number. */ public async buildGlobalVariables(blockNumber: Fr): Promise { - const lastTimestamp = new Fr(await this.reader.getLastTimestamp()); + let lastTimestamp = new Fr(await this.reader.getLastTimestamp()); const version = new Fr(await this.reader.getVersion()); const chainId = new Fr(await this.reader.getChainId()); + // TODO(rahul) - fix #1614. By using the cheatcode warp to modify L2 time, + // txs in the next rollup would have same time as the txs in the current rollup (i.e. the rollup that was warped). + // So, for now you check if L2 time was warped and if so, serve warpedTime + 1 to txs in the new rollup. + // Check if L2 time was warped in the last rollup by checking if current L1 time is same as the warpedTime (stored on the rollup contract). + // more details at https://github.com/AztecProtocol/aztec-packages/issues/1614 + + const currTimestamp = await this.reader.getL1CurrentTime(); + const rollupWarpTime = await this.reader.getLastWarpedBlockTs(); + const isLastBlockWarped = rollupWarpTime === currTimestamp; + this.log('isLastBlockWarped, ', isLastBlockWarped, rollupWarpTime, currTimestamp, lastTimestamp); + if (isLastBlockWarped) { + lastTimestamp = new Fr(lastTimestamp.value + 1n); + } + this.log( `Built global variables for block ${blockNumber}: (${chainId}, ${version}, ${blockNumber}, ${lastTimestamp})`, ); diff --git a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts index 54328f78c3a..e351db0c09d 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/viem-reader.ts @@ -50,4 +50,12 @@ export class ViemReader implements L1GlobalReader { public async getChainId(): Promise { return await Promise.resolve(BigInt(this.publicClient.chain.id)); } + + public async getL1CurrentTime(): Promise { + return await Promise.resolve((await this.publicClient.getBlock()).timestamp); + } + + public async getLastWarpedBlockTs(): Promise { + return BigInt(await this.rollupContract.read.lastWarpedBlockTs()); + } } diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index df516ccfe10..b3a6e3b7540 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -144,18 +144,6 @@ export class Sequencer { const newGlobalVariables = await this.globalsBuilder.buildGlobalVariables(new Fr(blockNumber)); const prevGlobalVariables = (await this.l2BlockSource.getL2Block(-1))?.globalVariables ?? GlobalVariables.empty(); - // TODO(rahul) - fix #1614. By using the cheatcode warp to modify L2 time, - // txs in the new rollup would have same time as the txs in the previous rollup. - // We overcome this now by identifying if the last rollup time was warped (if two rollups have same time) - // and tell public-processor to use a different time (increment last rollup block) - // more details at https://github.com/AztecProtocol/aztec-packages/issues/1614 - const isWarped = - !prevGlobalVariables.timestamp.equals(Fr.ZERO) && - prevGlobalVariables.timestamp.equals(newGlobalVariables.timestamp); - if (isWarped) { - newGlobalVariables.timestamp = new Fr(newGlobalVariables.timestamp.value + 1n); - } - // Process txs and drop the ones that fail processing // We create a fresh processor each time to reset any cached state (eg storage writes) const processor = await this.publicProcessorFactory.create(prevGlobalVariables, newGlobalVariables); From c8090baa64269e7edadf2efb9e2f11a618da3b86 Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Thu, 24 Aug 2023 14:27:13 +0000 Subject: [PATCH 4/5] rename simply block builder --- .../src/global_variable_builder/global_builder.ts | 7 ++++--- .../sequencer-client/src/global_variable_builder/index.ts | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts index 57d959dde22..076dd08ddca 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts @@ -47,10 +47,11 @@ export interface GlobalVariableBuilder { } /** - * Simple implementation of a builder that uses the minimum time possible for the global variables. + * Simple test implementation of a builder that uses the minimum time possible for the global variables. + * Also uses a "hack" to make use of the warp cheatcode that manipulates time on Aztec. */ -export class SimpleGlobalVariableBuilder implements GlobalVariableBuilder { - private log = createDebugLogger('aztec:sequencer:simple_global_variable_builder'); +export class SimpleTestGlobalVariableBuilder implements GlobalVariableBuilder { + private log = createDebugLogger('aztec:sequencer:simple_test_global_variable_builder'); constructor(private readonly reader: L1GlobalReader) {} /** diff --git a/yarn-project/sequencer-client/src/global_variable_builder/index.ts b/yarn-project/sequencer-client/src/global_variable_builder/index.ts index b3b666b7513..8de0248afcc 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/index.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/index.ts @@ -1,8 +1,8 @@ import { GlobalReaderConfig } from './config.js'; -import { GlobalVariableBuilder, SimpleGlobalVariableBuilder } from './global_builder.js'; +import { GlobalVariableBuilder, SimpleTestGlobalVariableBuilder } from './global_builder.js'; import { ViemReader } from './viem-reader.js'; -export { SimpleGlobalVariableBuilder } from './global_builder.js'; +export { SimpleTestGlobalVariableBuilder as SimpleGlobalVariableBuilder } from './global_builder.js'; export { GlobalReaderConfig } from './config.js'; /** @@ -11,5 +11,5 @@ export { GlobalReaderConfig } from './config.js'; * @returns A new instance of the global variable builder. */ export function getGlobalVariableBuilder(config: GlobalReaderConfig): GlobalVariableBuilder { - return new SimpleGlobalVariableBuilder(new ViemReader(config)); + return new SimpleTestGlobalVariableBuilder(new ViemReader(config)); } From ab045502317ca11cfad33158fc8a6b5efdf32dac Mon Sep 17 00:00:00 2001 From: Rahul Kothari Date: Fri, 25 Aug 2023 00:18:34 +0000 Subject: [PATCH 5/5] remove log --- .../src/global_variable_builder/global_builder.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts index 076dd08ddca..1347c1eb69b 100644 --- a/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts +++ b/yarn-project/sequencer-client/src/global_variable_builder/global_builder.ts @@ -73,7 +73,6 @@ export class SimpleTestGlobalVariableBuilder implements GlobalVariableBuilder { const currTimestamp = await this.reader.getL1CurrentTime(); const rollupWarpTime = await this.reader.getLastWarpedBlockTs(); const isLastBlockWarped = rollupWarpTime === currTimestamp; - this.log('isLastBlockWarped, ', isLastBlockWarped, rollupWarpTime, currTimestamp, lastTimestamp); if (isLastBlockWarped) { lastTimestamp = new Fr(lastTimestamp.value + 1n); }