Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: increment time by 1 for previous rollup was warped #1594

Merged
merged 5 commits into from
Aug 25, 2023
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
3 changes: 3 additions & 0 deletions l1-contracts/src/core/Rollup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/aztec.js/src/utils/cheat_codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}

/**
Expand Down
15 changes: 9 additions & 6 deletions yarn-project/end-to-end/src/e2e_cheat_codes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ export interface L1GlobalReader {
* @returns The chain id.
*/
getChainId(): Promise<bigint>;

/**
* Gets the current L1 time.
* @returns The current L1 time.
*/
getL1CurrentTime(): Promise<bigint>;

/**
* Gets the last time L2 was warped as tracked by the rollup contract.
* @returns The warped time.
*/
getLastWarpedBlockTs(): Promise<bigint>;
}

/**
Expand All @@ -35,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) {}

/**
Expand All @@ -47,10 +60,23 @@ export class SimpleGlobalVariableBuilder implements GlobalVariableBuilder {
* @returns The global variables for the given block number.
*/
public async buildGlobalVariables(blockNumber: Fr): Promise<GlobalVariables> {
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;
if (isLastBlockWarped) {
lastTimestamp = new Fr(lastTimestamp.value + 1n);
}

this.log(
`Built global variables for block ${blockNumber}: (${chainId}, ${version}, ${blockNumber}, ${lastTimestamp})`,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -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';

/**
Expand All @@ -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));
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,12 @@ export class ViemReader implements L1GlobalReader {
public async getChainId(): Promise<bigint> {
return await Promise.resolve(BigInt(this.publicClient.chain.id));
}

public async getL1CurrentTime(): Promise<bigint> {
return await Promise.resolve((await this.publicClient.getBlock()).timestamp);
}

public async getLastWarpedBlockTs(): Promise<bigint> {
return BigInt(await this.rollupContract.read.lastWarpedBlockTs());
}
}