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

Chore: testing on local stack #211

Merged
merged 13 commits into from
Jul 29, 2024
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
50 changes: 22 additions & 28 deletions packages/linea-ccip-gateway/contracts/TestL1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {IEVMVerifier} from "linea-state-verifier/contracts/IEVMVerifier.sol";
contract TestL1 is EVMFetchTarget {
using EVMFetcher for EVMFetcher.EVMFetchRequest;

uint256 constant L2_BLOCK_RANGE_ACCEPTED = 86400;
uint256 constant ACCEPTED_L2_BLOCK_RANGE_LENGTH = 86400;

IEVMVerifier verifier; // Slot 0
address target;
Expand All @@ -18,10 +18,22 @@ contract TestL1 is EVMFetchTarget {
target = _target;
}

/**
* @dev inherits from EVMFetchTarget
*/
function getAcceptedL2BlockRangeLength()
public
pure
override
returns (uint256)
{
return ACCEPTED_L2_BLOCK_RANGE_LENGTH;
}

function getLatest() public view returns (uint256) {
EVMFetcher.newFetchRequest(verifier, target).getStatic(0).fetch(
this.getLatestCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
""
);
}

Expand All @@ -35,7 +47,7 @@ contract TestL1 is EVMFetchTarget {
function getName() public view returns (string memory) {
EVMFetcher.newFetchRequest(verifier, target).getDynamic(1).fetch(
this.getNameCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
""
);
}

Expand All @@ -51,10 +63,7 @@ contract TestL1 is EVMFetchTarget {
.newFetchRequest(verifier, target)
.getDynamic(3)
.element(idx)
.fetch(
this.getHighscorerCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
);
.fetch(this.getHighscorerCallback.selector, "");
}

function getHighscorerCallback(
Expand All @@ -70,10 +79,7 @@ contract TestL1 is EVMFetchTarget {
.getStatic(0)
.getStatic(2)
.ref(0)
.fetch(
this.getLatestHighscoreCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
);
.fetch(this.getLatestHighscoreCallback.selector, "");
}

function getLatestHighscoreCallback(
Expand All @@ -89,10 +95,7 @@ contract TestL1 is EVMFetchTarget {
.getStatic(0)
.getDynamic(3)
.ref(0)
.fetch(
this.getLatestHighscorerCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
);
.fetch(this.getLatestHighscorerCallback.selector, "");
}

function getLatestHighscorerCallback(
Expand All @@ -109,10 +112,7 @@ contract TestL1 is EVMFetchTarget {
.newFetchRequest(verifier, target)
.getDynamic(4)
.element(_name)
.fetch(
this.getNicknameCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
);
.fetch(this.getNicknameCallback.selector, "");
}

function getNicknameCallback(
Expand All @@ -128,10 +128,7 @@ contract TestL1 is EVMFetchTarget {
.getDynamic(1)
.getDynamic(4)
.ref(0)
.fetch(
this.getPrimaryNicknameCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
);
.fetch(this.getPrimaryNicknameCallback.selector, "");
}

function getPrimaryNicknameCallback(
Expand All @@ -144,7 +141,7 @@ contract TestL1 is EVMFetchTarget {
function getZero() public view returns (uint256) {
EVMFetcher.newFetchRequest(verifier, target).getStatic(5).fetch(
this.getZeroCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
""
);
}

Expand All @@ -161,10 +158,7 @@ contract TestL1 is EVMFetchTarget {
.getStatic(5)
.getStatic(2)
.ref(0)
.fetch(
this.getZeroIndexCallback.selector,
abi.encode(L2_BLOCK_RANGE_ACCEPTED)
);
.fetch(this.getZeroIndexCallback.selector, "");
}

function getZeroIndexCallback(
Expand Down
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);
thedarkjester marked this conversation as resolved.
Show resolved Hide resolved
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
Loading