Skip to content

Commit

Permalink
Merge pull request #211 from Consensys/chore/testing-on-local-stack
Browse files Browse the repository at this point in the history
Chore: testing on local stack
  • Loading branch information
Julink-eth authored Jul 29, 2024
2 parents b0bf0c5 + 40f6231 commit 2e0f0a8
Show file tree
Hide file tree
Showing 19 changed files with 1,778 additions and 35 deletions.
18 changes: 15 additions & 3 deletions packages/linea-ccip-gateway/src/L2ProofService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
ethers,
} from "ethers";
import { EVMProofHelper, IProofService, StateProof } from "./evm-gateway";
import { logError } from "./utils";
import { logDebug, logError } from "./utils";

export type L2ProvableBlock = number;

Expand All @@ -25,9 +25,10 @@ export class L2ProofService implements IProofService<L2ProvableBlock> {
constructor(
providerL1: JsonRpcProvider,
providerL2: JsonRpcProvider,
rollupAddress: string
rollupAddress: string,
shomeiNode?: JsonRpcProvider
) {
this.helper = new EVMProofHelper(providerL2);
this.helper = new EVMProofHelper(providerL2, shomeiNode);
const currentL2BlockNumberIface = new ethers.Interface([
currentL2BlockNumberSig,
]);
Expand All @@ -43,10 +44,15 @@ export class L2ProofService implements IProofService<L2ProvableBlock> {
*/
async getProvableBlock(): Promise<number> {
try {
logDebug(
"Calling currentL2BlockNumber() on Rollup Contract",
await this.rollup.getAddress()
);
const lastBlockFinalized = await this.rollup.currentL2BlockNumber({
blockTag: "finalized",
});
if (!lastBlockFinalized) throw new Error("No block found");
logDebug("Provable block found", lastBlockFinalized);
return lastBlockFinalized;
} catch (e) {
logError(e);
Expand Down Expand Up @@ -89,6 +95,12 @@ export class L2ProofService implements IProofService<L2ProvableBlock> {
): Promise<string> {
try {
let proof = await this.helper.getProofs(blockNo, address, slots);
if (!proof.accountProof) {
throw `No account proof on contract ${address} for block number ${blockNo}`;
}
if (proof.storageProofs.length === 0) {
throw `No storage proofs on contract ${address} for block number ${blockNo}`;
}
proof = this.checkStorageInitialized(proof);
return AbiCoder.defaultAbiCoder().encode(
[
Expand Down
15 changes: 13 additions & 2 deletions packages/linea-ccip-gateway/src/evm-gateway/EVMGateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
zeroPadValue,
} from "ethers";
import { IProofService, ProvableBlock } from "./IProofService";
import { logError } from "../utils";
import { logDebug, logError, logInfo } from "../utils";

const OP_CONSTANT = 0x00;
const OP_BACKREF = 0x20;
Expand Down Expand Up @@ -98,12 +98,23 @@ export class EVMGateway<T extends ProvableBlock> {
type: "getStorageSlots",
func: async (args) => {
const [addr, commands, constants] = args;
logInfo(`CCIP request started for L2 target contract`, {
address: addr,
});
logDebug("CCIP request started with args", addr, commands, constants);
try {
const proofs = await this.createProofs(addr, commands, constants);
logInfo(
`CCIP request successfully executed for L2 target contract`,
{
address: addr,
}
);
logDebug("CCIP request finished with encoded proofs", proofs);
return [proofs];
} catch (e) {
logError(e, { addr, commands, constants });
throw e;
throw "ccip-gateway error calling getStorageSlots";
}
},
},
Expand Down
14 changes: 11 additions & 3 deletions packages/linea-ccip-gateway/src/evm-gateway/EVMProofHelper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { toBeHex, AddressLike, JsonRpcProvider, ethers } from "ethers";
import { logDebug, logInfo } from "../utils";

interface ProofStruct {
key: string;
Expand Down Expand Up @@ -26,9 +27,12 @@ export interface StateProof {
*/
export class EVMProofHelper {
private readonly providerL2: JsonRpcProvider;
private readonly shomeiNode: JsonRpcProvider;

constructor(providerL2: JsonRpcProvider) {
constructor(providerL2: JsonRpcProvider, shomeiNode?: JsonRpcProvider) {
this.providerL2 = providerL2;
// shomeiNode optional since an rpc infura nodes can support both eth_getStorageAt and linea_getProof
this.shomeiNode = shomeiNode ? shomeiNode : providerL2;
}

/**
Expand Down Expand Up @@ -65,19 +69,23 @@ export class EVMProofHelper {
"0x" + blockNo.toString(16),
];

logInfo("Calling linea_getProof with args", args);

// We have to reinitilize the provider L2 because of an issue when multiple
// requests are sent at the same time, the provider becomes not aware of
// the linea_getProof method
const providerUrl = await this.providerL2._getConnection().url;
const providerChainId = await this.providerL2._network.chainId;
const providerUrl = await this.shomeiNode._getConnection().url;
const providerChainId = await this.shomeiNode._network.chainId;
const providerL2 = new ethers.JsonRpcProvider(
providerUrl,
providerChainId,
{
staticNetwork: true,
}
);
logDebug("Calling linea_getProof with L2 provider", providerUrl);
const proofs: StateProof = await providerL2.send("linea_getProof", args);
logDebug("Proof result", proofs);
return proofs;
}
}
5 changes: 3 additions & 2 deletions packages/linea-ccip-gateway/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ export type L1Gateway = EVMGateway<L2ProvableBlock>;
export function makeL2Gateway(
providerL1: JsonRpcProvider,
providerL2: JsonRpcProvider,
rollupAddress: string
rollupAddress: string,
shomeiNode?: JsonRpcProvider
): L1Gateway {
return new EVMGateway(
new L2ProofService(providerL1, providerL2, rollupAddress)
new L2ProofService(providerL1, providerL2, rollupAddress, shomeiNode)
);
}

Expand Down
20 changes: 19 additions & 1 deletion packages/linea-ccip-gateway/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,23 @@ export function logError(error: any, ...objects: any[]) {
error: error.message || error,
details: objects,
};
console.log(logObject);
console.error(logObject);
}

export function logDebug(message: string, ...objects: any[]) {
if (process.env.NODE_ENV === "debug") {
const logObject = {
message,
details: objects,
};
console.dir(logObject, { depth: 6 });
}
}

export function logInfo(message: string, ...objects: any[]) {
const logObject = {
message,
details: objects,
};
console.dir(logObject, { depth: 3 });
}
9 changes: 5 additions & 4 deletions packages/linea-ens-resolver/.mocharc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{
"require": "ts-node/register",
"loader": "ts-node/esm",
"extensions": ["ts", "tsx"],
"spec": ["test/**/*.spec.*"],
"watch-files": ["src"]
}
"extensions": [
"ts",
"tsx"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: BSD
pragma solidity ^0.8.4;

/// @title Clone
/// @author zefram.eth
/// @notice Provides helper functions for reading immutable args from calldata
contract Clone {
/// @notice Reads an immutable arg with type address
/// @param argOffset The offset of the arg in the packed data
/// @return arg The arg value
function _getArgAddress(
uint256 argOffset
) internal pure returns (address arg) {
uint256 offset = _getImmutableArgsOffset();
// solhint-disable-next-line no-inline-assembly
assembly {
arg := shr(0x60, calldataload(add(offset, argOffset)))
}
}

/// @notice Reads an immutable arg with type uint256
/// @param argOffset The offset of the arg in the packed data
/// @return arg The arg value
function _getArgUint256(
uint256 argOffset
) internal pure returns (uint256 arg) {
uint256 offset = _getImmutableArgsOffset();
// solhint-disable-next-line no-inline-assembly
assembly {
arg := calldataload(add(offset, argOffset))
}
}

/// @notice Reads a uint256 array stored in the immutable args.
/// @param argOffset The offset of the arg in the packed data
/// @param arrLen Number of elements in the array
/// @return arr The array
function _getArgUint256Array(
uint256 argOffset,
uint64 arrLen
) internal pure returns (uint256[] memory arr) {
uint256 offset = _getImmutableArgsOffset();
uint256 el;
arr = new uint256[](arrLen);
for (uint64 i = 0; i < arrLen; i++) {
// solhint-disable-next-line no-inline-assembly
assembly {
el := calldataload(add(add(offset, argOffset), mul(i, 32)))
}
arr[i] = el;
}
return arr;
}

/// @notice Reads an immutable arg with type uint64
/// @param argOffset The offset of the arg in the packed data
/// @return arg The arg value
function _getArgUint64(
uint256 argOffset
) internal pure returns (uint64 arg) {
uint256 offset = _getImmutableArgsOffset();
// solhint-disable-next-line no-inline-assembly
assembly {
arg := shr(0xc0, calldataload(add(offset, argOffset)))
}
}

/// @notice Reads an immutable arg with type uint8
/// @param argOffset The offset of the arg in the packed data
/// @return arg The arg value
function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) {
uint256 offset = _getImmutableArgsOffset();
// solhint-disable-next-line no-inline-assembly
assembly {
arg := shr(0xf8, calldataload(add(offset, argOffset)))
}
}

/// @return offset The offset of the packed immutable args in calldata
function _getImmutableArgsOffset() internal pure returns (uint256 offset) {
// solhint-disable-next-line no-inline-assembly
assembly {
offset := sub(
calldatasize(),
add(shr(240, calldataload(sub(calldatasize(), 2))), 2)
)
}
}
}
Loading

0 comments on commit 2e0f0a8

Please sign in to comment.