Skip to content

Commit

Permalink
base fault, fix .latest(), move TrustedRollup out of eth/
Browse files Browse the repository at this point in the history
  • Loading branch information
adraffy committed Oct 31, 2024
1 parent 0b9e39a commit 0d1101e
Show file tree
Hide file tree
Showing 19 changed files with 128 additions and 84 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@unruggable/gateways",
"version": "0.1.4",
"version": "0.1.5",
"description": "Trustless Ethereum Multichain CCIP-Read Gateway",
"publishConfig": {
"access": "public"
Expand Down
46 changes: 19 additions & 27 deletions scripts/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import { EthSelfRollup } from '../src/eth/EthSelfRollup.js';
import { Contract } from 'ethers/contract';
import { SigningKey } from 'ethers/crypto';
import { toUnpaddedHex } from '../src/utils.js';
import { TrustedRollup } from '../src/eth/TrustedRollup.js';
import { TrustedRollup } from '../src/TrustedRollup.js';
import { EthProver } from '../src/eth/EthProver.js';
//import { LineaProver } from '../src/linea/LineaProver.js';
import { ZKSyncProver } from '../src/zksync/ZKSyncProver.js';
import { AbstractProver, type LatestProverFactory } from '../src/vm.js';

// NOTE: you can use CCIPRewriter to test an existing setup against a local gateway!
// [raffy] https://adraffy.github.io/ens-normalize.js/test/resolver.html#raffy.linea.eth.nb2hi4dthixs62dpnvss4ylooruxg5dvobuwiltdn5ws62duoryc6.ccipr.eth
Expand Down Expand Up @@ -180,13 +179,22 @@ async function createGateway(name: string) {
const slug = match[1].toUpperCase().replaceAll('-', '_');
if (slug in CHAINS) {
const chain = CHAINS[slug as keyof typeof CHAINS];
return new Gateway(
new TrustedRollup(
createProvider(chain),
getProverFactory(chain),
new SigningKey(signingKey)
)
);
const provider = createProvider(chain);
const key = new SigningKey(signingKey);
switch (chain) {
case CHAINS.ZKSYNC:
case CHAINS.ZKSYNC_SEPOLIA:
return new Gateway(new TrustedRollup(provider, ZKSyncProver, key));
// NOTE: linea should use eth_getProof instead of linea_getProof
// NOTE: this probably needs "--latest" cli option too
// rollup => SMT w/Mimc root using linea_getProof
// chain => PMT w/Keccak root using eth_getProof
// case CHAINS.LINEA:
// case CHAINS.LINEA_SEPOLIA:
// return LineaProver;
default:
return new Gateway(new TrustedRollup(provider, EthProver, key));
}
}
}
switch (name) {
Expand Down Expand Up @@ -287,7 +295,8 @@ async function createGateway(name: string) {
return new Gateway(new ZKSyncRollup(createProviderPair(config), config));
}
case 'base':
return createOPGateway(OPRollup.baseMainnetConfig);
// return createOPGateway(OPRollup.baseMainnetConfig);
return createOPFaultGateway(OPFaultRollup.baseMainnetConfig);
case 'base-sepolia':
return createOPFaultGateway(OPFaultRollup.baseSepoliaConfig);
case 'unfinalized-base-sepolia':
Expand Down Expand Up @@ -337,23 +346,6 @@ async function createGateway(name: string) {
}
}

function getProverFactory(chain: Chain): LatestProverFactory<AbstractProver> {
switch (chain) {
case CHAINS.ZKSYNC:
case CHAINS.ZKSYNC_SEPOLIA:
return ZKSyncProver;
// NOTE: linea should use eth_getProof instead of linea_getProof
// NOTE: this probably needs "--latest" cli option too
// rollup => SMT w/Mimc root using linea_getProof
// chain => PMT w/Keccak root using eth_getProof
// case CHAINS.LINEA:
// case CHAINS.LINEA_SEPOLIA:
// return LineaProver;
default:
return EthProver;
}
}

function createSelfGateway(chain: Chain) {
return new Gateway(new EthSelfRollup(createProvider(chain)));
}
Expand Down
17 changes: 9 additions & 8 deletions src/eth/TrustedRollup.ts → src/TrustedRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import type {
HexString32,
ProofSequence,
Provider,
} from '../types.js';
import { AbstractProver, type LatestProverFactory } from '../vm.js';
import { AbstractRollup, type RollupCommit } from '../rollup.js';
import { ABI_CODER } from '../utils.js';
import { CachedValue } from '../cached.js';
import { VOID_PROVIDER } from '../VoidProvider.js';
} from './types.js';
import type { AbstractProver, LatestProverFactory } from './vm.js';
import { AbstractRollup, type RollupCommit } from './rollup.js';
import { ABI_CODER } from './utils.js';
import { CachedValue } from './cached.js';
import { VOID_PROVIDER } from './VoidProvider.js';
import { ZeroAddress } from 'ethers/constants';
import { SigningKey } from 'ethers/crypto';
import { computeAddress } from 'ethers/transaction';
Expand All @@ -30,7 +30,7 @@ export class TrustedRollup<P extends AbstractProver> extends AbstractRollup<
readonly signingKey: SigningKey
) {
super({ provider1: VOID_PROVIDER, provider2 });
this.latest = new CachedValue<TrustedCommit<P>>(async () => {
this.latest = new CachedValue(async () => {
const prover = await factory.latest(this.provider2, this.latestBlockTag);
const stateRoot = await prover.fetchStateRoot();
const signedAt = Math.ceil(Date.now() / 1000);
Expand All @@ -57,8 +57,9 @@ export class TrustedRollup<P extends AbstractProver> extends AbstractRollup<
return -1n;
}
protected override async _fetchCommit(
_index: bigint
index: bigint
): Promise<TrustedCommit<P>> {
if (index) throw new Error('unsupported commit');
return this.latest.get();
}
override encodeWitness(
Expand Down
3 changes: 2 additions & 1 deletion src/eth/EthProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import { withResolvers, toPaddedHex } from '../utils.js';
export class EthProver extends BlockProver {
static readonly encodeProof = encodeProof;
static readonly isContract = isContract;
override async isContract(target: HexAddress) {
static readonly latest = this._createLatest();
override async isContract(target: HexAddress): Promise<boolean> {
target = target.toLowerCase();
if (this.fast) {
return this.cache.get(target, async () => {
Expand Down
7 changes: 4 additions & 3 deletions src/eth/EthSelfRollup.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { HexString, ProofSequence, Provider } from '../types.js';
import { AbstractRollup, type RollupCommit } from '../rollup.js';
import { ABI_CODER, fetchBlock, MAINNET_BLOCK_SEC } from '../utils.js';
import { fetchBlockNumber, ABI_CODER, MAINNET_BLOCK_SEC } from '../utils.js';
import { EthProver } from './EthProver.js';
import { encodeRlpBlock } from '../rlp.js';

Expand All @@ -23,8 +23,9 @@ export class EthSelfRollup extends AbstractRollup<EthSelfCommit> {
return index - (index % this.commitStep);
}
override async fetchLatestCommitIndex(): Promise<bigint> {
const blockInfo = await fetchBlock(this.provider1, this.latestBlockTag);
return this.align(BigInt(blockInfo.number));
return this.align(
await fetchBlockNumber(this.provider1, this.latestBlockTag)
);
}
protected override async _fetchParentCommitIndex(
commit: EthSelfCommit
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export * from './utils.js';
export * from './rlp.js';
export * from './chains.js';
export * from './VoidProvider.js';
export * from './GatewayProvider.js';

//export * from './ops.js'; use GatewayRequest.Opcodes instead
export * from './reader.js';
Expand Down Expand Up @@ -34,7 +35,7 @@ export * from './taiko/TaikoRollup.js';
export * from './scroll/ScrollRollup.js';
export * from './zksync/ZKSyncRollup.js';
export * from './eth/EthSelfRollup.js';
export * from './eth/TrustedRollup.js';
export * from './TrustedRollup.js';

export * from './gateway.js';
export * from './linea/LineaGatewayV1.js';
21 changes: 11 additions & 10 deletions src/linea/LineaProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,22 @@ export class LineaProver extends BlockProver {
static readonly isInclusionProof = isInclusionProof;
static readonly isContract = isContract;
static readonly encodeProof = encodeProof;
static readonly latest = this._createLatest();
stateRoot?: HexString32;
override async fetchStateRoot() {
if (!this.stateRoot) throw new Error(`unknown stateRoot`);
return this.stateRoot;
}
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);
return code.length > 2;
});
}
const { accountProof } = await this.getProofs(target);
return isContract(accountProof);
}
override async getStorage(
target: HexString,
slot: bigint,
Expand Down Expand Up @@ -52,16 +63,6 @@ export class LineaProver extends BlockProver {
? proof.storageProofs[0].proof.value
: ZeroHash;
}
override async isContract(target: HexString) {
if (this.fast) {
return this.cache.get(target, async () => {
const code = await this.provider.getCode(target, this.block);
return code.length > 2;
});
}
const { accountProof } = await this.getProofs(target);
return isContract(accountProof);
}
protected override async _proveNeed(
need: TargetNeed,
accountRef: ProofRef,
Expand Down
8 changes: 7 additions & 1 deletion src/op/OPFaultRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,20 @@ export class OPFaultRollup extends AbstractOPRollup {
OptimismPortal: '0xbEb5Fc579115071764c7423A4f12eDde41f106Ed',
GameFinder: GAME_FINDER_MAINNET,
};

static readonly sepoliaConfig: RollupDeployment<OPFaultConfig> = {
chain1: CHAINS.SEPOLIA,
chain2: CHAINS.OP_SEPOLIA,
OptimismPortal: '0x16Fc5058F25648194471939df75CF27A2fdC48BC',
GameFinder: GAME_FINDER_SEPOLIA,
};

// https://docs.base.org/docs/base-contracts#l1-contract-addresses
static readonly baseMainnetConfig: RollupDeployment<OPFaultConfig> = {
chain1: CHAINS.MAINNET,
chain2: CHAINS.BASE,
OptimismPortal: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e',
GameFinder: GAME_FINDER_MAINNET,
};
// https://docs.base.org/docs/base-contracts/#ethereum-testnet-sepolia
static readonly baseSepoliaConfig: RollupDeployment<OPFaultConfig> = {
chain1: CHAINS.SEPOLIA,
Expand Down
12 changes: 6 additions & 6 deletions src/op/OPRollup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ export type OPConfig = {
};

export class OPRollup extends AbstractOPRollup {
// https://docs.base.org/docs/base-contracts#base-mainnet
static readonly baseMainnetConfig: RollupDeployment<OPConfig> = {
chain1: CHAINS.MAINNET,
chain2: CHAINS.BASE,
L2OutputOracle: '0x56315b90c40730925ec5485cf004d835058518A0',
};
// 20241030: base changed to fault proofs
// static readonly baseMainnetConfig: RollupDeployment<OPConfig> = {
// chain1: CHAINS.MAINNET,
// chain2: CHAINS.BASE,
// L2OutputOracle: '0x56315b90c40730925ec5485cf004d835058518A0',
// };

// https://docs.blast.io/building/contracts#mainnet
static readonly blastMainnnetConfig: RollupDeployment<OPConfig> = {
Expand Down
1 change: 1 addition & 0 deletions src/polygon/ZKEVMProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
export class ZKEVMProver extends BlockProver {
static readonly isContract = isContract;
static readonly encodeProof = encodeProof;
static readonly latest = this._createLatest();
override async isContract(target: HexAddress): Promise<boolean> {
target = target.toLowerCase();
if (this.fast) {
Expand Down
19 changes: 9 additions & 10 deletions src/vm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,6 @@ export function makeStorageKey(target: HexAddress, slot: bigint) {
return `${target}${slot.toString(16)}`;
}

export interface LatestProverFactory<P extends AbstractProver> {
latest(provider: Provider, relative: BigNumberish): Promise<P>;
}

// TODO: totalAssembledBytes
export abstract class AbstractProver {
// general proof cache
Expand Down Expand Up @@ -966,14 +962,17 @@ export abstract class AbstractProver {
}
}

export interface LatestProverFactory<P extends AbstractProver> {
latest(provider: Provider, relative?: BigNumberish): Promise<P>;
}

export abstract class BlockProver extends AbstractProver {
// absolutely disgusting typescript
static async latest<T extends InstanceType<typeof BlockProver>>(
this: new (...a: ConstructorParameters<typeof BlockProver>) => T,
provider: Provider,
relBlockTag: BigNumberish = 0
protected static _createLatest<P extends BlockProver>(
this: new (...a: ConstructorParameters<typeof BlockProver>) => P
) {
return new this(provider, await fetchBlockNumber(provider, relBlockTag));
return async (provider: Provider, relative: BigNumberish = 0) => {
return new this(provider, await fetchBlockNumber(provider, relative));
};
}
readonly block: HexString;
constructor(provider: Provider, block: BigNumberish) {
Expand Down
3 changes: 2 additions & 1 deletion src/zksync/ZKSyncProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ export class ZKSyncProver extends AbstractProver {
return batchIndex + Number(relative); //(typeof relative === 'string' ? 0 : Number(relative));
}
static async latest(provider: Provider, relative: BigNumberish = 0) {
return new this(provider, await this.latestBatchIndex(provider, relative));
const batchIndex = await this.latestBatchIndex(provider, relative);
return new this(provider, batchIndex);
}
constructor(
provider: Provider,
Expand Down
17 changes: 14 additions & 3 deletions test/debug/play.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
import { GatewayRequestV1, GatewayRequest, EthProver, CHAINS, NitroRollup, OPRollup, TaikoRollup, ZKSyncRollup, fetchBlockNumber } from '../../src/index.js';
import { randomBytes, SigningKey, ZeroHash } from 'ethers';
import { GatewayRequestV1, GatewayRequest, EthProver, CHAINS, NitroRollup, OPRollup, TaikoRollup, ZKSyncRollup, fetchBlockNumber, TrustedRollup, ZKEVMProver, ZKSyncProver, LineaProver, OPFaultRollup } from '../../src/index.js';
import { createProvider, createProviderPair } from '../providers.js';

// this is just a worksheet

//console.log(createProvider(1n)._getConnection())

if (1) {
const provider = createProvider(CHAINS.MAINNET);
const key = new SigningKey(randomBytes(32));
const rollup1 = new TrustedRollup(provider, EthProver, key);
const rollup2 = new TrustedRollup(provider, ZKSyncProver, key);
const rollup3 = new TrustedRollup(provider, LineaProver, key);
const rollup4 = new TrustedRollup(provider, ZKEVMProver, key);
throw 1;
}

if (1) {
const provider = createProvider(CHAINS.OP_SEPOLIA);
console.log(await fetchBlockNumber(provider, 'finalized'));
Expand All @@ -31,8 +42,8 @@ if (0) {


if (0) {
const config = OPRollup.baseMainnetConfig;
const rollup = new OPRollup(createProviderPair(config), config);
const config = OPFaultRollup.baseMainnetConfig;
const rollup = new OPFaultRollup(createProviderPair(config), config);
//const commit = await rollup.fetchLatestCommit();
const commit = await rollup.fetchCommit(0n);
console.log(commit);
Expand Down
9 changes: 6 additions & 3 deletions test/gateway/base.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { OPRollup } from '../../src/op/OPRollup.js';
import { testOP } from './common.js';
import { OPFaultRollup } from '../../src/op/OPFaultRollup.js';
import { testOPFault } from './common.js';

testOP(OPRollup.baseMainnetConfig, {
// 20241030: base changed to fault proofs
// https://base.mirror.xyz/eOsedW4tm8MU5OhdGK107A9wsn-aU7MAb8f3edgX5Tk
// https://twitter.com/base/status/1851672364439814529
testOPFault(OPFaultRollup.baseMainnetConfig, {
// https://basescan.org/address/0x0C49361E151BC79899A9DD31B8B0CCdE4F6fd2f6
slotDataContract: '0x0C49361E151BC79899A9DD31B8B0CCdE4F6fd2f6',
});
2 changes: 1 addition & 1 deletion test/gateway/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
ScrollRollup,
} from '../../src/scroll/ScrollRollup.js';
import { EthSelfRollup } from '../../src/eth/EthSelfRollup.js';
import { TrustedRollup } from '../../src/eth/TrustedRollup.js';
import { TrustedRollup } from '../../src/TrustedRollup.js';
import { EthProver } from '../../src/eth/EthProver.js';
import { randomBytes, SigningKey } from 'ethers/crypto';
import { afterAll } from 'bun:test';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { OPRollup } from '../../src/op/OPRollup.js';
import { testOP } from './common.js';

testOP(OPRollup.baseMainnetConfig, {
// https://basescan.org/address/0x0C49361E151BC79899A9DD31B8B0CCdE4F6fd2f6
slotDataContract: '0x0C49361E151BC79899A9DD31B8B0CCdE4F6fd2f6',
testOP(OPRollup.zoraMainnetConfig, {
// https://explorer.zora.energy/address/0x73404681064a8e16c22C1411A02D47e6395f6582
slotDataContract: '0x73404681064a8e16c22C1411A02D47e6395f6582',
// delay by 1 hour
// NOTE: to delay longer, Gateway.commitDepth needs to be bigger
minAgeSec: 3600,
Expand Down
Loading

0 comments on commit 0d1101e

Please sign in to comment.