Skip to content
Closed
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
5 changes: 2 additions & 3 deletions scripts/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
type RollupDeployment,
type RollupCommitType,
supportsV1,
isRollupDeployment,
} from '../src/rollup.js';
import {
createProviderPair,
Expand Down Expand Up @@ -592,7 +593,5 @@ function concealKeys(s: string) {

// hacky
function deployments<C>(rollupClass: object): RollupDeployment<C>[] {
return Object.values(rollupClass).filter(
(x) => x && typeof x === 'object' && 'chain1' in x && 'chain2' in x
);
return Object.values(rollupClass).filter(isRollupDeployment<C>);
}
1 change: 1 addition & 0 deletions src/GatewayProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export class GatewayProvider extends JsonRpcProvider {
// TODO: make this a provider-specific setting?
batchMaxCount = 10
) {
// 20251211: might be useful to modify batchStallTime
super(fr, chain, { staticNetwork: true, batchMaxCount });
}
override async _send(
Expand Down
3 changes: 2 additions & 1 deletion src/UncheckedRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { AbstractRollup, align, type RollupCommit } from './rollup.js';
import {
ABI_CODER,
fetchBlock,
fetchCode,
fetchStorage,
LATEST_BLOCK_TAG,
} from './utils.js';
Expand All @@ -20,7 +21,7 @@ export class UncheckedProver extends BlockProver {
override isContract(target: HexAddress): Promise<boolean> {
target = target.toLowerCase();
return this.cache.get(target, async (a) => {
const code = await this.provider.getCode(a, this.block);
const code = await fetchCode(this.provider, a, this.block);
return code.length > 2;
});
}
Expand Down
9 changes: 7 additions & 2 deletions src/eth/EthProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@ import {
} from './types.js';
import { BlockProver, makeStorageKey, type TargetNeed } from '../vm.js';
import { ZeroHash } from 'ethers/constants';
import { withResolvers, toPaddedHex, fetchStorage } from '../utils.js';
import {
withResolvers,
toPaddedHex,
fetchStorage,
fetchCode,
} from '../utils.js';

export class EthProver extends BlockProver {
static readonly EMPTY_STORAGE_HASH = EMPTY_STORAGE_HASH;
Expand All @@ -22,7 +27,7 @@ export class EthProver extends BlockProver {
return this.cache.get(target, async (a) => {
// note: this actually reverts when the block is bad
// eg. {"code": -32602, "message": "Unknown block number"}
const code = await this.provider.getCode(a, this.block);
const code = await fetchCode(this.provider, a, this.block);
return code.length > 2;
});
}
Expand Down
12 changes: 12 additions & 0 deletions src/gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ export class Gateway<R extends Rollup> extends EZCCIP {
`too old: ${index} vs ${latest.commit.index}[depth=${this.commitDepth}]`
);
}
async getRecentCommits(
depth = this.commitDepth
): Promise<RollupCommitType<R>[]> {
const commits: RollupCommitType<R>[] = [];
let cache = await this._updateLatest();
commits.push(cache.commit);
while (commits.length <= depth) {
cache = await this.cachedCommit(await cache.parent.get());
commits.push(cache.commit);
}
return commits;
}
private async cachedCommit(
index: bigint,
cacheMs?: number
Expand Down
3 changes: 2 additions & 1 deletion src/linea/LineaProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
toPaddedHex,
isRPCError,
fetchStorage,
fetchCode,
} from '../utils.js';
import {
type LineaProof,
Expand Down Expand Up @@ -45,7 +46,7 @@ export class LineaProver extends BlockProver {
override async isContract(target: HexString): Promise<boolean> {
if (this.fast) {
return this.cache.get(target, async () => {
const code = await this.provider.getCode(target, this.block);
const code = await fetchCode(this.provider, target, this.block);
return code.length > 2;
});
}
Expand Down
30 changes: 19 additions & 11 deletions src/op/AbstractOPRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,28 @@ export type AbstractOPCommit = RollupCommit<EthProver> & {
readonly passerRoot: HexString;
};

function encodeWitness<C extends AbstractOPCommit>(
commit: C,
proofSeq: ProofSequence
) {
return ABI_CODER.encode(
[`(uint256, ${OutputRootProofType}, bytes[], bytes)`],
[
[
commit.index,
outputRootProofTuple(commit),
proofSeq.proofs,
proofSeq.order,
],
]
);
}

export abstract class AbstractOPRollup<C extends AbstractOPCommit>
extends AbstractRollup<C>
implements RollupWitnessV1<C>
{
static readonly encodeWitness = encodeWitness;
L2ToL1MessagePasser = '0x4200000000000000000000000000000000000016';
async createCommit(
index: bigint,
Expand All @@ -62,17 +80,7 @@ export abstract class AbstractOPRollup<C extends AbstractOPCommit>
};
}
override encodeWitness(commit: C, proofSeq: ProofSequence) {
return ABI_CODER.encode(
[`(uint256, ${OutputRootProofType}, bytes[], bytes)`],
[
[
commit.index,
outputRootProofTuple(commit),
proofSeq.proofs,
proofSeq.order,
],
]
);
return encodeWitness(commit, proofSeq);
}
encodeWitnessV1(commit: C, proofSeq: ProofSequenceV1) {
return ABI_CODER.encode(
Expand Down
6 changes: 3 additions & 3 deletions src/polygon/ZKEVMProver.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ZeroHash } from 'ethers/constants';
import { HexAddress, HexString, ProofRef } from '../types.js';
import { BlockProver, makeStorageKey, type TargetNeed } from '../vm.js';
import { toPaddedHex } from '../utils.js';
import { fetchCode, fetchStorage, toPaddedHex } from '../utils.js';
import {
type ZKEVMAccountProof,
type ZKEVMStorageProof,
Expand All @@ -18,7 +18,7 @@ export class ZKEVMProver extends BlockProver {
target = target.toLowerCase();
if (this.fast) {
return this.cache.get(target, async () => {
const code = await this.provider.getCode(target, this.block);
const code = await fetchCode(this.provider, target, this.block);
return code.length > 2;
});
}
Expand Down Expand Up @@ -46,7 +46,7 @@ export class ZKEVMProver extends BlockProver {
}
if (fast) {
return this.cache.get(storageKey, () =>
this.provider.getStorage(target, slot, this.block)
fetchStorage(this.provider, target, slot, this.block)
);
}
const proofs = await this.getProofs(target, [slot]);
Expand Down
4 changes: 4 additions & 0 deletions src/rollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import type { AbstractProver } from './vm.js';

export type RollupDeployment<Config> = Readonly<ChainPair & Config>;

export function isRollupDeployment<C>(x: unknown): x is RollupDeployment<C> {
return !!x && typeof x === 'object' && 'chain1' in x && 'chain2' in x;
}

export type RollupCommit<P extends AbstractProver> = {
readonly index: bigint;
readonly prover: P;
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type EncodedProof = HexString;
export type ProofRef = { id: number; proof: EncodedProof };

export type Provider = JsonRpcApiProvider;
export type RawProvider = Pick<Provider, 'send'>;
export type ProviderPair = {
provider1: Provider;
provider2: Provider;
Expand Down
33 changes: 21 additions & 12 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { AbiCoder, Interface } from 'ethers/abi';
import { id as keccakStr } from 'ethers/hash';
import { isCallException, type EthersError } from 'ethers/utils';
import type {
Provider,
RawProvider,
BigNumberish,
HexString,
HexString32,
Expand Down Expand Up @@ -49,7 +49,7 @@ export function isBlockTag(x: BigNumberish): x is string {
}

export async function fetchBlock(
provider: Provider,
provider: RawProvider,
relBlockTag: BigNumberish = LATEST_BLOCK_TAG
): Promise<RPCEthGetBlock> {
if (!isBlockTag(relBlockTag)) {
Expand All @@ -66,7 +66,7 @@ export async function fetchBlock(
}

export async function fetchBlockFromHash(
provider: Provider,
provider: RawProvider,
blockHash: HexString32
): Promise<RPCEthGetBlock> {
const block: RPCEthGetBlock | null = await provider.send(
Expand All @@ -80,7 +80,7 @@ export async function fetchBlockFromHash(
// avoid an rpc if possible
// use negative (-100) for offset from "latest" (#-100)
export async function fetchBlockNumber(
provider: Provider,
provider: RawProvider,
relBlockTag: BigNumberish = LATEST_BLOCK_TAG
): Promise<bigint> {
if (relBlockTag === LATEST_BLOCK_TAG) {
Expand All @@ -98,7 +98,7 @@ export async function fetchBlockNumber(
// avoid an rpc if possible
// convert negative (-100) => absolute (#-100)
export async function fetchBlockTag(
provider: Provider,
provider: RawProvider,
relBlockTag: BigNumberish = LATEST_BLOCK_TAG
): Promise<string | bigint> {
return isBlockTag(relBlockTag)
Expand All @@ -107,7 +107,7 @@ export async function fetchBlockTag(
}

export async function fetchStorage(
provider: Provider,
provider: RawProvider,
target: HexAddress,
slot: BigNumberish,
relBlockTag: BigNumberish = LATEST_BLOCK_TAG
Expand All @@ -126,8 +126,16 @@ export async function fetchStorage(
return data.length === 66 ? data : toPaddedHex(data);
}

export async function fetchCode(
provider: RawProvider,
target: HexAddress,
relBlockTag: BigNumberish = LATEST_BLOCK_TAG
): Promise<HexString> {
return provider.send('eth_getCode', [target, relBlockTag]);
}

export async function staticCall<T>(
provider: Provider,
provider: RawProvider,
to: HexAddress,
abi: Interface,
fragment: string,
Expand All @@ -136,12 +144,13 @@ export async function staticCall<T>(
): Promise<T> {
const data = abi.encodeFunctionData(fragment, args);
try {
const answer = await provider.call({
to,
data,
enableCcipRead: true,
const answer: string = await provider.send('eth_call', [
{
to,
data: abi.encodeFunctionData(fragment, args),
},
blockTag,
});
]);
const result = abi.decodeFunctionResult(fragment, answer);
return (result.length == 1 ? result[0] : result) as T;
} catch (err) {
Expand Down
Loading
Loading