Skip to content

Commit

Permalink
throw error cleanup, add more guards
Browse files Browse the repository at this point in the history
  • Loading branch information
adraffy committed Sep 2, 2024
1 parent 6171866 commit 87b3aa3
Show file tree
Hide file tree
Showing 17 changed files with 141 additions and 88 deletions.
2 changes: 1 addition & 1 deletion v2/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@unruggable/evmgateway",
"version": "0.0.4",
"version": "0.0.5",
"keywords": [
"ethereum",
"evm",
Expand Down
8 changes: 3 additions & 5 deletions v2/src/linea/LineaRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,21 +74,19 @@ export class LineaRollup extends AbstractRollup<LineaCommit> {
commit.stateRoot
)
);
if (!event) throw new Error('missing DataFinalized event');
if (!event) throw new Error('no DataFinalized event');
// find the block that finalized this root
const prevStateRoot = event.topics[2];
const [prevEvent] = await this.L1MessageService.queryFilter(
this.L1MessageService.filters.DataFinalized(null, null, prevStateRoot)
);
if (!prevEvent) throw new Error('missing prior DataFinalized event');
if (!prevEvent) throw new Error('no prior DataFinalized event');
return BigInt(prevEvent.topics[1]); // l2BlockNumber
}
protected override async _fetchCommit(index: bigint): Promise<LineaCommit> {
const stateRoot: HexString32 =
await this.L1MessageService.stateRootHashes(index);
if (stateRoot === ZeroHash) {
throw new Error('not finalized');
}
if (stateRoot === ZeroHash) throw new Error('not finalized');
const prover = new LineaProver(this.provider2, toString16(index));
return { index, stateRoot, prover };
}
Expand Down
14 changes: 9 additions & 5 deletions v2/src/nitro/NitroRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,23 @@ export class NitroRollup extends AbstractRollupV1<NitroCommit> {
return node.prevNum;
}
protected override async _fetchCommit(index: bigint): Promise<NitroCommit> {
const { createdAtBlock }: ABINodeTuple = await this.L2Rollup.getNode(index);
if (!createdAtBlock) throw new Error('unknown node');
const [event] = await this.L2Rollup.queryFilter(
this.L2Rollup.filters.NodeCreated(index)
this.L2Rollup.filters.NodeCreated(index),
createdAtBlock,
createdAtBlock
);
if (!(event instanceof EventLog)) {
throw new Error('missing NodeCreated event');
}
if (!(event instanceof EventLog)) throw new Error('no NodeCreated event');
// ethers bug: named abi parsing doesn't propagate through event tuples
// [4][1][0][0] == event.args.afterState.globalState.bytes32Vals[0];
const [blockHash, sendRoot] = event.args[4][1][0][0];
const block: RPCEthGetBlock = await this.provider2.send(
const block: RPCEthGetBlock | null = await this.provider2.send(
'eth_getBlockByHash',
[blockHash, false]
);
if (!block) throw new Error(`no block: ${blockHash}`);
// note: block.sendRoot == sendRoot
const rlpEncodedBlock = encodeRlpBlock(block);
const prover = new EthProver(this.provider2, block.number);
return { index, prover, sendRoot, rlpEncodedBlock };
Expand Down
1 change: 1 addition & 0 deletions v2/src/nitro/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export const ROLLUP_ABI = new Interface([

export type ABINodeTuple = {
readonly prevNum: bigint;
readonly createdAtBlock: bigint;
};
26 changes: 11 additions & 15 deletions v2/src/op/AbstractOPRollup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { HexAddress, HexString } from '../types.js';
import type { RPCEthGetBlock, RPCEthGetProof } from '../eth/types.js';
import type { RPCEthGetBlock } from '../eth/types.js';
import type { ProofSequence, ProofSequenceV1 } from '../vm.js';
import { AbstractRollupV1, type RollupCommit } from '../rollup.js';
import { EthProver } from '../eth/EthProver.js';
Expand Down Expand Up @@ -27,23 +27,19 @@ export abstract class AbstractOPRollup extends AbstractRollupV1<OPCommit> {
L2ToL1MessagePasser: HexAddress =
'0x4200000000000000000000000000000000000016';
async createCommit(index: bigint, block: HexString): Promise<OPCommit> {
const [{ storageHash: passerRoot }, { stateRoot, hash: blockHash }] =
await Promise.all([
this.provider2.send('eth_getProof', [
this.L2ToL1MessagePasser,
[],
block,
]) as Promise<RPCEthGetProof>,
this.provider2.send('eth_getBlockByNumber', [
block,
false,
]) as Promise<RPCEthGetBlock>,
]);
const prover = new EthProver(this.provider2, block);
const [{ storageHash: passerRoot }, blockInfo] = await Promise.all([
prover.fetchProofs(this.L2ToL1MessagePasser),
this.provider2.send('eth_getBlockByNumber', [
block,
false,
]) as Promise<RPCEthGetBlock | null>,
]);
if (!blockInfo) throw new Error('no block');
return {
index,
blockHash,
stateRoot,
blockHash: blockInfo.hash,
stateRoot: blockInfo.stateRoot,
passerRoot,
prover,
};
Expand Down
1 change: 1 addition & 0 deletions v2/src/op/OPRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class OPRollup extends AbstractOPRollup {
return commit.index - 1n;
}
protected override async _fetchCommit(index: bigint) {
// this fails with ARRAY_RANGE_ERROR when invalid
const output: ABIOutputProposal =
await this.L2OutputOracle.getL2Output(index);
return this.createCommit(index, toString16(output.l2BlockNumber));
Expand Down
7 changes: 4 additions & 3 deletions v2/src/polygon/PolygonPoSRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export class PolygonPoSRollup extends AbstractRollup<PolygonPoSCommit> {
});
if (logs.length) return logs[logs.length - 1];
}
throw new Error(`unable to find earlier root: ${l2BlockNumber}`);
throw new Error(`no earlier root: ${l2BlockNumber}`);
}
async findPosterHeaderBefore(l2BlockNumber: bigint) {
// find the most recent post that occurred before this block
Expand Down Expand Up @@ -179,7 +179,7 @@ export class PolygonPoSRollup extends AbstractRollup<PolygonPoSCommit> {
fromBlock: l2BlockNumberStart,
toBlock: l2BlockNumberEnd,
});
if (!events.length) throw new Error(`Commit(${index}) no post`);
if (!events.length) throw new Error(`no poster`);
const event = events[events.length - 1];
const prevBlockHash = extractPrevBlockHash(event);
// rlpEncodedProof:
Expand All @@ -195,8 +195,9 @@ export class PolygonPoSRollup extends AbstractRollup<PolygonPoSCommit> {
this.provider2.send('eth_getBlockByHash', [
prevBlockHash,
false,
]) as Promise<RPCEthGetBlock>,
]) as Promise<RPCEthGetBlock | null>,
]);
if (!prevBlock) throw new Error('no prevBlock');
const rlpEncodedBlock = getBytes(encodeRlpBlock(prevBlock));
// if (ethers.keccak256(rlpEncodedBlock) !== prevBlockHash) {
// throw new Error('block hash mismatch`);
Expand Down
14 changes: 9 additions & 5 deletions v2/src/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,23 @@ export abstract class AbstractRollup<C extends RollupCommit<AbstractProver>> {
// abstract wrappers
async fetchParentCommitIndex(commit: C) {
try {
if (!commit.index) throw new Error('genesis');
if (!commit.index) throw undefined;
const index = await this._fetchParentCommitIndex(commit);
if (index >= commit.index) throw new Error('bug');
if (index < 0) throw undefined;
return index;
} catch (cause) {
throw new Error(`no earlier commit: ${commit.index}`, { cause });
throw new Error(`no parent commit: ${commit.index}`, { cause });
}
}
async fetchCommit(index: bigint) {
const commit = await this._fetchCommit(index);
this.configure?.(commit);
return commit;
try {
const commit = await this._fetchCommit(index);
this.configure?.(commit);
return commit;
} catch (cause) {
throw new Error(`invalid commit: ${index}`, { cause });
}
}

// convenience
Expand Down
8 changes: 2 additions & 6 deletions v2/src/scroll/ScrollRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,13 @@ export class ScrollRollup extends AbstractRollupV1<ScrollCommit> {
const receipt = await this.provider1.getTransactionReceipt(
commit.finalTxHash
);
if (!receipt) {
throw new Error(`missing commit tx: ${commit.finalTxHash}`);
}
if (!receipt) throw new Error(`no commit tx: ${commit.finalTxHash}`);
return this.findFinalizedBatchIndexBefore(BigInt(receipt.blockNumber));
}
protected override async _fetchCommit(index: bigint): Promise<ScrollCommit> {
const { status, l2BlockNumber, finalTxHash } =
await this.fetchAPIBatchIndexInfo(index);
if (status !== 'finalized') {
throw new Error(`not finalized: ${status}`);
}
if (status !== 'finalized') throw new Error(`not finalized: ${status}`);
const prover = new EthProver(this.provider2, toString16(l2BlockNumber));
return { index, prover, finalTxHash };
}
Expand Down
10 changes: 5 additions & 5 deletions v2/src/taiko/TaikoRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ export class TaikoRollup extends AbstractRollup<TaikoCommit> {
return commit.index - this.commitStep;
}
protected override async _fetchCommit(index: bigint): Promise<TaikoCommit> {
const block = toString16(index);
const { parentHash }: RPCEthGetBlock = await this.provider2.send(
const blockInfo: RPCEthGetBlock | null = await this.provider2.send(
'eth_getBlockByNumber',
[block, false]
[toString16(index), false]
);
const prover = new EthProver(this.provider2, block);
return { index, prover, parentHash };
if (!blockInfo) throw new Error('no block');
const prover = new EthProver(this.provider2, blockInfo.number);
return { index, prover, parentHash: blockInfo.parentHash };
}
override encodeWitness(
commit: TaikoCommit,
Expand Down
33 changes: 15 additions & 18 deletions v2/src/zksync/ZKSyncRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
type ABIZKSyncCommitBatchInfo,
type RPCZKSyncL1BatchDetails,
} from './types.js';
import { Contract, EventLog } from 'ethers';
import { Contract, EventLog, ZeroHash } from 'ethers';
import { CHAINS } from '../chains.js';
import {
type RollupDeployment,
Expand Down Expand Up @@ -71,36 +71,33 @@ export class ZKSyncRollup extends AbstractRollup<ZKSyncCommit> {
}
protected override async _fetchCommit(index: bigint): Promise<ZKSyncCommit> {
const batchIndex = Number(index);
const details: RPCZKSyncL1BatchDetails = await this.provider2.send(
const details: RPCZKSyncL1BatchDetails | null = await this.provider2.send(
'zks_getL1BatchDetails',
[batchIndex] // rpc requires number
[batchIndex] // rpc requires Number
);
if (!details) throw new Error(`no batch details`);
if (!details.rootHash) throw new Error('no rootHash');
if (!details.commitTxHash) throw new Error('no commitTxHash');
// 20240810: this check randomly fails even though the block is finalized
// if (details.status !== 'verified') {
// throw new Error(`not verified: ${details.status}`);
// }
const { rootHash, commitTxHash } = details;
if (!rootHash || !commitTxHash) {
throw new Error(`not finalized`);
}
const [tx, [log], l2LogsTreeRoot] = await Promise.all([
this.provider1.getTransaction(commitTxHash),
this.provider1.getTransaction(details.commitTxHash),
this.DiamondProxy.queryFilter(
this.DiamondProxy.filters.BlockCommit(index, rootHash)
this.DiamondProxy.filters.BlockCommit(index, details.rootHash)
),
this.DiamondProxy.l2LogsRootHash(index) as Promise<HexString32>,
]);
if (!tx || !(log instanceof EventLog)) {
throw new Error(`missing commit tx: ${commitTxHash}`);
}
if (!tx) throw new Error(`missing commit tx: ${details.commitTxHash}`);
if (!(log instanceof EventLog)) throw new Error(`no BlockCommit event`);
if (l2LogsTreeRoot === ZeroHash) throw new Error('not finalized');
const commits: ABIZKSyncCommitBatchInfo[] = DIAMOND_ABI.decodeFunctionData(
'commitBatchesSharedBridge',
tx.data
).newBatchesData;
const batchInfo = commits.find((x) => x.batchNumber == index);
if (!batchInfo) {
throw new Error(`commit not in batch`);
}
if (!batchInfo) throw new Error(`commit not in batch`);
const abiEncodedBatch = ABI_CODER.encode(
[
'uint64', // batchNumber
Expand All @@ -113,8 +110,8 @@ export class ZKSyncRollup extends AbstractRollup<ZKSyncCommit> {
'bytes32', // commitment
],
[
batchInfo.batchNumber,
batchInfo.newStateRoot,
batchInfo.batchNumber, // == index
batchInfo.newStateRoot, // == details.rootHash
batchInfo.indexRepeatedStorageChanges,
batchInfo.numberOfLayer1Txs,
batchInfo.priorityOperationsHash,
Expand All @@ -127,7 +124,7 @@ export class ZKSyncRollup extends AbstractRollup<ZKSyncCommit> {
return {
index,
prover,
stateRoot: rootHash,
stateRoot: details.rootHash,
abiEncodedBatch,
};
}
Expand Down
36 changes: 35 additions & 1 deletion v2/test/debug/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,45 @@ import { EVMRequest } from '../../src/vm.js';
import { EthProver } from '../../src/eth/EthProver.js';
//import {Foundry} from '@adraffy/blocksmith';
//import {ethers} from 'ethers';
import { createProvider } from '../providers.js';
import { createProvider, createProviderPair } from '../providers.js';
import { CHAINS } from '../../src/chains.js';
import { NitroRollup, OPRollup, TaikoRollup, ZKSyncRollup } from '../../src/index.js';

// this is just a worksheet

if (0) {
const config = OPRollup.baseMainnetConfig;
const rollup = new OPRollup(createProviderPair(config), config);
//const commit = await rollup.fetchLatestCommit();
const commit = await rollup.fetchCommit(0n);
console.log(commit);
throw 1;
}

if (0) {
const config = NitroRollup.arb1MainnetConfig;
const rollup = new NitroRollup(createProviderPair(config), config);
const commit = await rollup.fetchLatestCommit();
console.log(commit);
throw 1;
}

if (0) {
const config = TaikoRollup.mainnetConfig;
const rollup = await TaikoRollup.create(createProviderPair(config), config);
const commit = await rollup.fetchCommit(123124124n);
console.log(await commit.prover.prove([[config.TaikoL1, true]]));
throw 1;
}

if (1) {
const config = ZKSyncRollup.mainnetConfig;
const rollup = new ZKSyncRollup(createProviderPair(config), config);
const commit = await rollup.fetchLatestCommit();
console.log(await commit.prover.prove([[config.DiamondProxy, true]]));
throw 1;
}

//let foundry = await Foundry.launch({infoLog: false});

const prover = await EthProver.latest(createProvider(CHAINS.MAINNET));
Expand Down
28 changes: 28 additions & 0 deletions v2/test/debug/speed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { OPRollup } from "../../src/op/OPRollup.js";
import { createProviderPair } from "../providers.js";

const config = OPRollup.baseMainnetConfig;
const rollup = new OPRollup(createProviderPair(config), config);

const commit = await logTime('fetchLatestCommit', rollup.fetchLatestCommit());
await logTime('fetchParentCommit', rollup.fetchParentCommit(commit));

await logTime('prove(cold)', commit.prover.prove([[config.L2OutputOracle, true]]));

commit.prover.proofLRU.clear();

await logTime('getStorage(cold)', commit.prover.getStorage(config.L2OutputOracle, 0n));
await logTime('getProofs(warm)', commit.prover.getProofs(config.L2OutputOracle, [1n]));
await logTime('getStorage(hot)', commit.prover.getStorage(config.L2OutputOracle, 0n));

await logTime('prove(hot)', commit.prover.prove([
[config.L2OutputOracle, true],
[config.L2OutputOracle, 1n]
]));

async function logTime<T>(label: string, promise: Promise<T>): Promise<T> {
const t = performance.now();
const ret = await promise;
console.log((performance.now() - t).toFixed().padStart(5), label);
return ret;
}
2 changes: 1 addition & 1 deletion v2/test/gateway/scroll.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ describe('scroll', async () => {
file: 'SlotDataReader',
args: [verifier, '0x09D2233D3d109683ea95Da4546e7E9Fc17a6dfAF'],
});
runSlotDataTests(reader, true);
runSlotDataTests(reader);
});
2 changes: 1 addition & 1 deletion v2/test/gateway/taiko.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ describe('taiko', async () => {
file: 'SlotDataReader',
args: [verifier, '0xAF7f1Fa8D5DF0D9316394433E841321160408565'],
});
runSlotDataTests(reader, true);
runSlotDataTests(reader);
});
Loading

0 comments on commit 87b3aa3

Please sign in to comment.