style: typecasting, formatting and cleanup

This commit is contained in:
Derrick Hammer 2023-07-07 07:16:18 -04:00
parent 40d652fa22
commit 7ffc07f474
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
14 changed files with 116 additions and 112 deletions

View File

@ -1,4 +1,5 @@
import { import {
Bytes32,
ClientConfig, ClientConfig,
ExecutionInfo, ExecutionInfo,
LightClientUpdate, LightClientUpdate,
@ -15,6 +16,7 @@ import {
import { import {
computeSyncPeriodAtSlot, computeSyncPeriodAtSlot,
getCurrentSlot, getCurrentSlot,
isValidMerkleBranch,
} from "@lodestar/light-client/utils"; } from "@lodestar/light-client/utils";
import { import {
assertValidLightClientUpdate, assertValidLightClientUpdate,
@ -22,8 +24,9 @@ import {
} from "@lodestar/light-client/validation"; } from "@lodestar/light-client/validation";
import { SyncCommitteeFast } from "@lodestar/light-client"; import { SyncCommitteeFast } from "@lodestar/light-client";
import bls, { init } from "@chainsafe/bls/switchable"; import bls, { init } from "@chainsafe/bls/switchable";
import { PublicKey } from "@chainsafe/bls/types.js"; // @ts-ignore
import { fromHexString } from "@chainsafe/ssz"; import type { PublicKey } from "@chainsafe/bls/types.js";
import { fromHexString, toHexString } from "@chainsafe/ssz";
import * as phase0 from "@lodestar/types/phase0"; import * as phase0 from "@lodestar/types/phase0";
import * as capella from "@lodestar/types/capella"; import * as capella from "@lodestar/types/capella";
import NodeCache from "node-cache"; import NodeCache from "node-cache";
@ -41,7 +44,7 @@ export default class Client {
latestBlockHash?: string; latestBlockHash?: string;
private config: ClientConfig = getDefaultClientConfig(); private config: ClientConfig = getDefaultClientConfig();
private genesisCommittee: Uint8Array[] = this.config.genesis.committee.map( private genesisCommittee: Uint8Array[] = this.config.genesis.committee.map(
(pk) => fromHexString(pk) (pk) => fromHexString(pk),
); );
private genesisPeriod = computeSyncPeriodAtSlot(this.config.genesis.slot); private genesisPeriod = computeSyncPeriodAtSlot(this.config.genesis.slot);
private genesisTime = this.config.genesis.time; private genesisTime = this.config.genesis.time;
@ -56,7 +59,7 @@ export default class Client {
prover: IProver, prover: IProver,
store: IStore, store: IStore,
beaconUrl: string, beaconUrl: string,
rpcUrl: string rpcUrl: string,
) { ) {
this.prover = prover; this.prover = prover;
this.store = store; this.store = store;
@ -67,7 +70,7 @@ export default class Client {
private _provider?: VerifyingProvider; private _provider?: VerifyingProvider;
get provider(): VerifyingProvider { get provider(): VerifyingProvider {
return this._provider; return this._provider as VerifyingProvider;
} }
private _latestPeriod: number = -1; private _latestPeriod: number = -1;
@ -102,7 +105,7 @@ export default class Client {
const provider = new VerifyingProvider( const provider = new VerifyingProvider(
this.rpcUrl, this.rpcUrl,
blockNumber, blockNumber,
blockhash blockhash,
); );
this._provider = provider; this._provider = provider;
} }
@ -111,25 +114,25 @@ export default class Client {
if (ei && ei.blockhash !== this.latestBlockHash) { if (ei && ei.blockhash !== this.latestBlockHash) {
this.latestBlockHash = ei.blockhash; this.latestBlockHash = ei.blockhash;
} }
this._provider.update(ei.blockhash, ei.blockNumber); this._provider.update(ei?.blockhash as string, ei?.blockNumber as bigint);
} }
async syncProver( async syncProver(
startPeriod: number, startPeriod: number,
currentPeriod: number, currentPeriod: number,
startCommittee: Uint8Array[] startCommittee: Uint8Array[],
): Promise<{ syncCommittee: Uint8Array[]; period: number }> { ): Promise<{ syncCommittee: Uint8Array[]; period: number }> {
for (let period = startPeriod; period < currentPeriod; period += 1) { for (let period = startPeriod; period < currentPeriod; period += 1) {
try { try {
const update = await this.prover.getSyncUpdate( const update = await this.prover.getSyncUpdate(
period, period,
currentPeriod, currentPeriod,
DEFAULT_BATCH_SIZE DEFAULT_BATCH_SIZE,
); );
const validOrCommittee = await this.syncUpdateVerifyGetCommittee( const validOrCommittee = await this.syncUpdateVerifyGetCommittee(
startCommittee, startCommittee,
period, period,
update update,
); );
if (!(validOrCommittee as boolean)) { if (!(validOrCommittee as boolean)) {
@ -160,7 +163,7 @@ export default class Client {
public getCurrentPeriod(): number { public getCurrentPeriod(): number {
return computeSyncPeriodAtSlot( return computeSyncPeriodAtSlot(
getCurrentSlot(this.config.chainConfig, this.genesisTime) getCurrentSlot(this.config.chainConfig, this.genesisTime),
); );
} }
@ -170,12 +173,12 @@ export default class Client {
async optimisticUpdateVerify( async optimisticUpdateVerify(
committee: Uint8Array[], committee: Uint8Array[],
update: OptimisticUpdate update: OptimisticUpdate,
): Promise<VerifyWithReason> { ): Promise<VerifyWithReason> {
try { try {
const { attestedHeader: header, syncAggregate } = update; const { attestedHeader: header, syncAggregate } = update;
const headerBlockRoot = phase0.ssz.BeaconBlockHeader.hashTreeRoot( const headerBlockRoot = phase0.ssz.BeaconBlockHeader.hashTreeRoot(
header.beacon header.beacon,
); );
const committeeFast = this.deserializeSyncCommittee(committee); const committeeFast = this.deserializeSyncCommittee(committee);
try { try {
@ -184,7 +187,7 @@ export default class Client {
committeeFast, committeeFast,
syncAggregate, syncAggregate,
headerBlockRoot, headerBlockRoot,
header.beacon.slot header.beacon.slot,
); );
} catch (e) { } catch (e) {
return { correct: false, reason: "invalid signatures" }; return { correct: false, reason: "invalid signatures" };
@ -209,27 +212,27 @@ export default class Client {
private isValidLightClientHeader( private isValidLightClientHeader(
config: ChainForkConfig, config: ChainForkConfig,
header: allForks.LightClientHeader header: allForks.LightClientHeader,
): boolean { ): boolean {
return isValidMerkleBranch( return isValidMerkleBranch(
config config
.getExecutionForkTypes(header.beacon.slot) .getExecutionForkTypes(header.beacon.slot)
.ExecutionPayloadHeader.hashTreeRoot( .ExecutionPayloadHeader.hashTreeRoot(
(header as capella.LightClientHeader).execution (header as capella.LightClientHeader).execution,
), ),
(header as capella.LightClientHeader).executionBranch, (header as capella.LightClientHeader).executionBranch,
EXECUTION_PAYLOAD_DEPTH, EXECUTION_PAYLOAD_DEPTH,
EXECUTION_PAYLOAD_INDEX, EXECUTION_PAYLOAD_INDEX,
header.beacon.bodyRoot header.beacon.bodyRoot,
); );
} }
public async getNextValidExecutionInfo( public async getNextValidExecutionInfo(
retry: number = 10 retry: number = 10,
): Promise<ExecutionInfo> { ): Promise<ExecutionInfo> {
if (retry === 0) if (retry === 0)
throw new Error( throw new Error(
"no valid execution payload found in the given retry limit" "no valid execution payload found in the given retry limit",
); );
const ei = await this.getLatestExecution(); const ei = await this.getLatestExecution();
if (ei) return ei; if (ei) return ei;
@ -240,23 +243,23 @@ export default class Client {
public async getExecutionFromBlockRoot( public async getExecutionFromBlockRoot(
slot: bigint, slot: bigint,
expectedBlockRoot: Bytes32 expectedBlockRoot: Bytes32,
): Promise<ExecutionInfo> { ): Promise<ExecutionInfo> {
const res = await handleGETRequest( const res = await handleGETRequest(
`${this.beaconChainAPIURL}/eth/v2/beacon/blocks/${slot}` `${this.beaconChainAPIURL}/eth/v2/beacon/blocks/${slot}`,
); );
if (!res) { if (!res) {
throw Error(`fetching block failed`); throw Error(`fetching block failed`);
} }
const blockJSON = res.data.message.body; const blockJSON = res.data.message.body;
const block = bellatrix.ssz.BeaconBlockBody.fromJson(blockJSON); const block = capella.ssz.BeaconBlockBody.fromJson(blockJSON);
const blockRoot = toHexString( const blockRoot = toHexString(
bellatrix.ssz.BeaconBlockBody.hashTreeRoot(block) capella.ssz.BeaconBlockBody.hashTreeRoot(block),
); );
if (blockRoot !== expectedBlockRoot) { if (blockRoot !== expectedBlockRoot) {
throw Error( throw Error(
`block provided by the beacon chain api doesn't match the expected block root` `block provided by the beacon chain api doesn't match the expected block root`,
); );
} }
@ -292,13 +295,13 @@ export default class Client {
let startPeriod = this.genesisPeriod; let startPeriod = this.genesisPeriod;
let startCommittee = this.genesisCommittee; let startCommittee = this.genesisCommittee;
console.log( console.log(
`Sync started from period(${startPeriod}) to period(${currentPeriod})` `Sync started from period(${startPeriod}) to period(${currentPeriod})`,
); );
const { syncCommittee, period } = await this.syncProver( const { syncCommittee, period } = await this.syncProver(
startPeriod, startPeriod,
currentPeriod, currentPeriod,
startCommittee startCommittee,
); );
if (period === currentPeriod) { if (period === currentPeriod) {
return syncCommittee; return syncCommittee;
@ -316,7 +319,7 @@ export default class Client {
const { syncCommittee, period } = await this.syncProver( const { syncCommittee, period } = await this.syncProver(
startPeriod, startPeriod,
currentPeriod, currentPeriod,
startCommittee startCommittee as Uint8Array[],
); );
if (period === currentPeriod) { if (period === currentPeriod) {
return syncCommittee; return syncCommittee;
@ -327,14 +330,14 @@ export default class Client {
protected async syncUpdateVerifyGetCommittee( protected async syncUpdateVerifyGetCommittee(
prevCommittee: Uint8Array[], prevCommittee: Uint8Array[],
period: number, period: number,
update: LightClientUpdate update: LightClientUpdate,
): Promise<false | Uint8Array[]> { ): Promise<false | Uint8Array[]> {
const updatePeriod = computeSyncPeriodAtSlot( const updatePeriod = computeSyncPeriodAtSlot(
update.attestedHeader.beacon.slot update.attestedHeader.beacon.slot,
); );
if (period !== updatePeriod) { if (period !== updatePeriod) {
console.error( console.error(
`Expected update with period ${period}, but recieved ${updatePeriod}` `Expected update with period ${period}, but recieved ${updatePeriod}`,
); );
return false; return false;
} }
@ -345,7 +348,7 @@ export default class Client {
await assertValidLightClientUpdate( await assertValidLightClientUpdate(
this.config.chainConfig, this.config.chainConfig,
prevCommitteeFast, prevCommitteeFast,
update update,
); );
return update.nextSyncCommittee.pubkeys; return update.nextSyncCommittee.pubkeys;
} catch (e) { } catch (e) {
@ -356,15 +359,15 @@ export default class Client {
protected async getLatestExecution(): Promise<ExecutionInfo | null> { protected async getLatestExecution(): Promise<ExecutionInfo | null> {
const updateJSON = await handleGETRequest( const updateJSON = await handleGETRequest(
`${this.beaconChainAPIURL}/eth/v1/beacon/light_client/optimistic_update` `${this.beaconChainAPIURL}/eth/v1/beacon/light_client/optimistic_update`,
); );
if (!updateJSON) { if (!updateJSON) {
throw Error(`fetching optimistic update failed`); throw Error(`fetching optimistic update failed`);
} }
const update = this.optimisticUpdateFromJSON(updateJSON.data); const update = this.optimisticUpdateFromJSON(updateJSON.data);
const verify = await this.optimisticUpdateVerify( const verify = await this.optimisticUpdateVerify(
this.latestCommittee, this.latestCommittee as Uint8Array[],
update update,
); );
if (!verify.correct) { if (!verify.correct) {
@ -374,12 +377,12 @@ export default class Client {
} }
return this.getExecutionFromBlockRoot( return this.getExecutionFromBlockRoot(
updateJSON.data.attested_header.beacon.slot, updateJSON.data.attested_header.beacon.slot,
updateJSON.data.attested_header.beacon.body_root updateJSON.data.attested_header.beacon.body_root,
); );
} }
private deserializeSyncCommittee( private deserializeSyncCommittee(
syncCommittee: Uint8Array[] syncCommittee: Uint8Array[],
): SyncCommitteeFast { ): SyncCommitteeFast {
const pubkeys = this.deserializePubkeys(syncCommittee); const pubkeys = this.deserializePubkeys(syncCommittee);
return { return {

View File

@ -522,7 +522,7 @@ export const mainnetConfig = {
}; };
export const BEACON_SYNC_SUPER_MAJORITY = Math.ceil( export const BEACON_SYNC_SUPER_MAJORITY = Math.ceil(
(BEACON_SYNC_COMMITTEE_SIZE * 2) / 3 (BEACON_SYNC_COMMITTEE_SIZE * 2) / 3,
); );
// These are the rough numbers from benchmark experiments // These are the rough numbers from benchmark experiments

View File

@ -5,7 +5,7 @@ export interface IProver {
getSyncUpdate( getSyncUpdate(
period: number, period: number,
currentPeriod: number, currentPeriod: number,
cacheCount: number cacheCount: number,
): AsyncOrSync<LightClientUpdate>; ): AsyncOrSync<LightClientUpdate>;
} }
export interface IStore { export interface IStore {

View File

@ -18,7 +18,7 @@ export class MemoryStore implements IStore {
update: LightClientUpdateSSZ.serialize(update), update: LightClientUpdateSSZ.serialize(update),
nextCommittee: CommitteeSSZ.serialize(update.nextSyncCommittee.pubkeys), nextCommittee: CommitteeSSZ.serialize(update.nextSyncCommittee.pubkeys),
nextCommitteeHash: digest( nextCommitteeHash: digest(
concatUint8Array(update.nextSyncCommittee.pubkeys) concatUint8Array(update.nextSyncCommittee.pubkeys),
), ),
}; };
} }

View File

@ -13,11 +13,10 @@ export default class Prover implements IProver {
async _getSyncUpdates( async _getSyncUpdates(
startPeriod: number, startPeriod: number,
maxCount: number maxCount: number,
): Promise<LightClientUpdate[]> { ): Promise<LightClientUpdate[]> {
const res = await handleGETRequest( const res = await handleGETRequest(
`${this.serverUrl}/eth/v1/beacon/light_client/updates?start_period=${startPeriod}&count=${maxCount}`, `${this.serverUrl}/eth/v1/beacon/light_client/updates?start_period=${startPeriod}&count=${maxCount}`,
false
); );
return res.map((u: any) => altair.ssz.LightClientUpdate.fromJson(u.data)); return res.map((u: any) => altair.ssz.LightClientUpdate.fromJson(u.data));
} }
@ -25,7 +24,7 @@ export default class Prover implements IProver {
async getSyncUpdate( async getSyncUpdate(
period: number, period: number,
currentPeriod: number, currentPeriod: number,
cacheCount: number cacheCount: number,
): Promise<LightClientUpdate> { ): Promise<LightClientUpdate> {
const _cacheCount = Math.min(currentPeriod - period + 1, cacheCount); const _cacheCount = Math.min(currentPeriod - period + 1, cacheCount);
if (!this.cachedSyncUpdate.has(period)) { if (!this.cachedSyncUpdate.has(period)) {

View File

@ -1,10 +1,10 @@
export const ZERO_ADDR = '0x0000000000000000000000000000000000000000'; export const ZERO_ADDR = "0x0000000000000000000000000000000000000000";
// TODO: set the correct gas limit! // TODO: set the correct gas limit!
export const GAS_LIMIT = '0x1c9c380'; export const GAS_LIMIT = "0x1c9c380";
export const REQUEST_BATCH_SIZE = 10; export const REQUEST_BATCH_SIZE = 10;
export const MAX_SOCKET = 10; export const MAX_SOCKET = 10;
export const EMPTY_ACCOUNT_EXTCODEHASH = export const EMPTY_ACCOUNT_EXTCODEHASH =
'0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
export const MAX_BLOCK_HISTORY = BigInt(256); export const MAX_BLOCK_HISTORY = BigInt(256);
export const MAX_BLOCK_FUTURE = BigInt(3); export const MAX_BLOCK_FUTURE = BigInt(3);
export const DEFAULT_BLOCK_PARAMETER = 'latest'; export const DEFAULT_BLOCK_PARAMETER = "latest";

View File

@ -1,4 +1,4 @@
import { JSONRPCErrorCode, JSONRPCErrorException } from 'json-rpc-2.0'; import { JSONRPCErrorCode, JSONRPCErrorException } from "json-rpc-2.0";
export class InternalError extends JSONRPCErrorException { export class InternalError extends JSONRPCErrorException {
constructor(message: string) { constructor(message: string) {

View File

@ -35,7 +35,10 @@ import {
MAX_BLOCK_FUTURE, MAX_BLOCK_FUTURE,
DEFAULT_BLOCK_PARAMETER, DEFAULT_BLOCK_PARAMETER,
} from "./constants.js"; } from "./constants.js";
import { headerDataFromWeb3Response, blockDataFromWeb3Response } from "./utils"; import {
headerDataFromWeb3Response,
blockDataFromWeb3Response,
} from "./utils.js";
import { keccak256 } from "ethers"; import { keccak256 } from "ethers";
import { InternalError, InvalidParamsError } from "./errors.js"; import { InternalError, InvalidParamsError } from "./errors.js";
@ -65,14 +68,14 @@ export class VerifyingProvider {
eth_estimateGas: this.estimateGas, eth_estimateGas: this.estimateGas,
eth_sendRawTransaction: this.sendRawTransaction, eth_sendRawTransaction: this.sendRawTransaction,
eth_getTransactionReceipt: this.getTransactionReceipt, eth_getTransactionReceipt: this.getTransactionReceipt,
}) }),
); );
constructor( constructor(
providerURL: string, providerURL: string,
blockNumber: bigint | number, blockNumber: bigint | number,
blockHash: Bytes32, blockHash: Bytes32,
chain: bigint | Chain = Chain.Mainnet chain: bigint | Chain = Chain.Mainnet,
) { ) {
this._rpc = new RPC({ URL: providerURL }); this._rpc = new RPC({ URL: providerURL });
this.common = new Common({ this.common = new Common({
@ -96,7 +99,7 @@ export class VerifyingProvider {
this.blockHashes[blockNumberHex] !== blockHash this.blockHashes[blockNumberHex] !== blockHash
) { ) {
console.log( console.log(
"Overriding an existing verified blockhash. Possibly the chain had a reorg" "Overriding an existing verified blockhash. Possibly the chain had a reorg",
); );
} }
const latestBlockNumber = this.latestBlockNumber; const latestBlockNumber = this.latestBlockNumber;
@ -128,7 +131,7 @@ export class VerifyingProvider {
private async getBalance( private async getBalance(
addressHex: AddressHex, addressHex: AddressHex,
blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER,
) { ) {
const header = await this.getBlockHeader(blockOpt); const header = await this.getBlockHeader(blockOpt);
const address = Address.fromString(addressHex); const address = Address.fromString(addressHex);
@ -143,7 +146,7 @@ export class VerifyingProvider {
address, address,
[], [],
header.stateRoot, header.stateRoot,
proof proof,
); );
if (!isAccountCorrect) { if (!isAccountCorrect) {
throw new InternalError("Invalid account proof provided by the RPC"); throw new InternalError("Invalid account proof provided by the RPC");
@ -162,10 +165,10 @@ export class VerifyingProvider {
private async getCode( private async getCode(
addressHex: AddressHex, addressHex: AddressHex,
blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER,
): Promise<HexString> { ): Promise<HexString> {
const header = await this.getBlockHeader(blockOpt); const header = await this.getBlockHeader(blockOpt);
const res = await this._rpc.requestBatch([ const res: any[] = await this._rpc.requestBatch([
{ {
method: "eth_getProof", method: "eth_getProof",
params: [addressHex, [], bigIntToHex(header.number)], params: [addressHex, [], bigIntToHex(header.number)],
@ -186,7 +189,7 @@ export class VerifyingProvider {
address, address,
[], [],
header.stateRoot, header.stateRoot,
accountProof accountProof,
); );
if (!isAccountCorrect) { if (!isAccountCorrect) {
throw new InternalError(`invalid account proof provided by the RPC`); throw new InternalError(`invalid account proof provided by the RPC`);
@ -194,11 +197,11 @@ export class VerifyingProvider {
const isCodeCorrect = await this.verifyCodeHash( const isCodeCorrect = await this.verifyCodeHash(
code, code,
accountProof.codeHash accountProof.codeHash,
); );
if (!isCodeCorrect) { if (!isCodeCorrect) {
throw new InternalError( throw new InternalError(
`code provided by the RPC doesn't match the account's codeHash` `code provided by the RPC doesn't match the account's codeHash`,
); );
} }
@ -207,7 +210,7 @@ export class VerifyingProvider {
private async getTransactionCount( private async getTransactionCount(
addressHex: AddressHex, addressHex: AddressHex,
blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER,
): Promise<HexString> { ): Promise<HexString> {
const header = await this.getBlockHeader(blockOpt); const header = await this.getBlockHeader(blockOpt);
const address = Address.fromString(addressHex); const address = Address.fromString(addressHex);
@ -223,7 +226,7 @@ export class VerifyingProvider {
address, address,
[], [],
header.stateRoot, header.stateRoot,
proof proof,
); );
if (!isAccountCorrect) { if (!isAccountCorrect) {
throw new InternalError(`invalid account proof provided by the RPC`); throw new InternalError(`invalid account proof provided by the RPC`);
@ -234,7 +237,7 @@ export class VerifyingProvider {
private async call( private async call(
transaction: RPCTx, transaction: RPCTx,
blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER,
) { ) {
try { try {
this.validateTx(transaction); this.validateTx(transaction);
@ -274,7 +277,7 @@ export class VerifyingProvider {
private async estimateGas( private async estimateGas(
transaction: RPCTx, transaction: RPCTx,
blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER blockOpt: BlockOpt = DEFAULT_BLOCK_PARAMETER,
) { ) {
try { try {
this.validateTx(transaction); this.validateTx(transaction);
@ -293,7 +296,7 @@ export class VerifyingProvider {
? 2 ? 2
: transaction.accessList : transaction.accessList
? 1 ? 1
: 0 : 0,
); );
if (txType == BigInt(2)) { if (txType == BigInt(2)) {
transaction.maxFeePerGas = transaction.maxFeePerGas =
@ -359,7 +362,7 @@ export class VerifyingProvider {
} }
private async getTransactionReceipt( private async getTransactionReceipt(
txHash: Bytes32 txHash: Bytes32,
): Promise<JSONRPCReceipt | null> { ): Promise<JSONRPCReceipt | null> {
const { result: receipt, success } = await this._rpc.request({ const { result: receipt, success } = await this._rpc.request({
method: "eth_getTransactionReceipt", method: "eth_getTransactionReceipt",
@ -371,7 +374,7 @@ export class VerifyingProvider {
const header = await this.getBlockHeader(receipt.blockNumber); const header = await this.getBlockHeader(receipt.blockNumber);
const block = await this.getBlock(header); const block = await this.getBlock(header);
const index = block.transactions.findIndex( const index = block.transactions.findIndex(
(tx) => bufferToHex(tx.hash()) === txHash.toLowerCase() (tx) => bufferToHex(tx.hash()) === txHash.toLowerCase(),
); );
if (index === -1) { if (index === -1) {
throw new InternalError("the recipt provided by the RPC is invalid"); throw new InternalError("the recipt provided by the RPC is invalid");
@ -462,7 +465,7 @@ export class VerifyingProvider {
} }
const responses = _.chunk( const responses = _.chunk(
rawResponse.map((r: any) => r.result), rawResponse.map((r: any) => r.result),
2 2,
) as [AccountResponse, CodeResponse][]; ) as [AccountResponse, CodeResponse][];
for (let i = 0; i < accessList.length; i++) { for (let i = 0; i < accessList.length; i++) {
@ -480,7 +483,7 @@ export class VerifyingProvider {
address, address,
storageKeys, storageKeys,
header.stateRoot, header.stateRoot,
accountProof accountProof,
); );
if (!isAccountCorrect) { if (!isAccountCorrect) {
throw new InternalError(`invalid account proof provided by the RPC`); throw new InternalError(`invalid account proof provided by the RPC`);
@ -489,7 +492,7 @@ export class VerifyingProvider {
const isCodeCorrect = await this.verifyCodeHash(code, codeHash); const isCodeCorrect = await this.verifyCodeHash(code, codeHash);
if (!isCodeCorrect) { if (!isCodeCorrect) {
throw new InternalError( throw new InternalError(
`code provided by the RPC doesn't match the account's codeHash` `code provided by the RPC doesn't match the account's codeHash`,
); );
} }
@ -505,7 +508,7 @@ export class VerifyingProvider {
await vm.stateManager.putContractStorage( await vm.stateManager.putContractStorage(
address, address,
setLengthLeft(toBuffer(storageAccess.key), 32), setLengthLeft(toBuffer(storageAccess.key), 32),
setLengthLeft(toBuffer(storageAccess.value), 32) setLengthLeft(toBuffer(storageAccess.value), 32),
); );
} }
@ -536,7 +539,7 @@ export class VerifyingProvider {
throw new InvalidParamsError("specified block is too far in future"); throw new InvalidParamsError("specified block is too far in future");
} else if (blockNumber + MAX_BLOCK_HISTORY < this.latestBlockNumber) { } else if (blockNumber + MAX_BLOCK_HISTORY < this.latestBlockNumber) {
throw new InvalidParamsError( throw new InvalidParamsError(
`specified block cannot older that ${MAX_BLOCK_HISTORY}` `specified block cannot older that ${MAX_BLOCK_HISTORY}`,
); );
} }
return blockNumber; return blockNumber;
@ -575,7 +578,7 @@ export class VerifyingProvider {
if (!header.hash().equals(toBuffer(blockHash))) { if (!header.hash().equals(toBuffer(blockHash))) {
throw new InternalError( throw new InternalError(
`blockhash doesn't match the blockInfo provided by the RPC` `blockhash doesn't match the blockInfo provided by the RPC`,
); );
} }
this.blockHeaders[blockHash] = header; this.blockHeaders[blockHash] = header;
@ -587,14 +590,14 @@ export class VerifyingProvider {
address: Address, address: Address,
storageKeys: Bytes32[], storageKeys: Bytes32[],
stateRoot: Buffer, stateRoot: Buffer,
proof: GetProof proof: GetProof,
): Promise<boolean> { ): Promise<boolean> {
const trie = new Trie(); const trie = new Trie();
const key = keccak256(address.toString()); const key = keccak256(address.toString());
const expectedAccountRLP = await trie.verifyProof( const expectedAccountRLP = await trie.verifyProof(
stateRoot, stateRoot,
toBuffer(key), toBuffer(key),
proof.accountProof.map((a) => toBuffer(a)) proof.accountProof.map((a) => toBuffer(a)),
); );
const account = Account.fromAccountData({ const account = Account.fromAccountData({
nonce: BigInt(proof.nonce), nonce: BigInt(proof.nonce),
@ -610,12 +613,12 @@ export class VerifyingProvider {
for (let i = 0; i < storageKeys.length; i++) { for (let i = 0; i < storageKeys.length; i++) {
const sp = proof.storageProof[i]; const sp = proof.storageProof[i];
const key = keccak256( const key = keccak256(
bufferToHex(setLengthLeft(toBuffer(storageKeys[i]), 32)) bufferToHex(setLengthLeft(toBuffer(storageKeys[i]), 32)),
); );
const expectedStorageRLP = await trie.verifyProof( const expectedStorageRLP = await trie.verifyProof(
toBuffer(proof.storageHash), toBuffer(proof.storageHash),
toBuffer(key), toBuffer(key),
sp.proof.map((a) => toBuffer(a)) sp.proof.map((a) => toBuffer(a)),
); );
const isStorageValid = const isStorageValid =
(!expectedStorageRLP && sp.value === "0x0") || (!expectedStorageRLP && sp.value === "0x0") ||
@ -648,7 +651,7 @@ export class VerifyingProvider {
BigInt(tx.maxPriorityFeePerGas) > BigInt(tx.maxFeePerGas) BigInt(tx.maxPriorityFeePerGas) > BigInt(tx.maxFeePerGas)
) { ) {
throw new Error( throw new Error(
`maxPriorityFeePerGas (${tx.maxPriorityFeePerGas.toString()}) is bigger than maxFeePerGas (${tx.maxFeePerGas.toString()})` `maxPriorityFeePerGas (${tx.maxPriorityFeePerGas.toString()}) is bigger than maxFeePerGas (${tx.maxFeePerGas.toString()})`,
); );
} }
} }
@ -668,13 +671,13 @@ export class VerifyingProvider {
if (!block.header.hash().equals(header.hash())) { if (!block.header.hash().equals(header.hash())) {
throw new InternalError( throw new InternalError(
`BN(${header.number}): blockhash doest match the blockData provided by the RPC` `BN(${header.number}): blockhash doest match the blockData provided by the RPC`,
); );
} }
if (!(await block.validateTransactionsTrie())) { if (!(await block.validateTransactionsTrie())) {
throw new InternalError( throw new InternalError(
`transactionTree doesn't match the transactions provided by the RPC` `transactionTree doesn't match the transactions provided by the RPC`,
); );
} }
@ -697,7 +700,7 @@ export class VerifyingProvider {
this.blockHashes[parentBlockNumberHex] !== parentBlockHash this.blockHashes[parentBlockNumberHex] !== parentBlockHash
) { ) {
console.log( console.log(
"Overriding an existing verified blockhash. Possibly the chain had a reorg" "Overriding an existing verified blockhash. Possibly the chain had a reorg",
); );
} }
this.blockHashes[parentBlockNumberHex] = parentBlockHash; this.blockHashes[parentBlockNumberHex] = parentBlockHash;

View File

@ -56,7 +56,7 @@ export class RPC {
throw new Error("method not supported by the provider"); throw new Error("method not supported by the provider");
} }
const res = []; const res: RPCResponse[] = [];
for (const request of requests) { for (const request of requests) {
const r = await this._retryRequest(request); const r = await this._retryRequest(request);
res.push(r); res.push(r);
@ -78,7 +78,7 @@ export class RPC {
method: request.method, method: request.method,
params: request.params, params: request.params,
}; };
const hash = this._pluginApi.util.crypto const hash = (this._pluginApi as PluginAPI).util.crypto
.createHash(stringify(tempRequest)) .createHash(stringify(tempRequest))
.toString("hex"); .toString("hex");
// this._cache.set(hash, response); // this._cache.set(hash, response);
@ -97,7 +97,7 @@ export class RPC {
private async _retryRequest( private async _retryRequest(
_request: RPCRequest, _request: RPCRequest,
retry = 5 retry = 5,
): Promise<RPCResponse> { ): Promise<RPCResponse> {
const request = { const request = {
..._request, ..._request,
@ -114,8 +114,8 @@ export class RPC {
`RPC batch request failed after maximum retries: ${JSON.stringify( `RPC batch request failed after maximum retries: ${JSON.stringify(
request, request,
null, null,
2 2,
)} ${JSON.stringify(res, null, 2)}` )} ${JSON.stringify(res, null, 2)}`,
); );
} }
} }
@ -126,7 +126,7 @@ export class RPC {
return Math.floor(Math.random() * 2 ** 64).toFixed(); return Math.floor(Math.random() * 2 ** 64).toFixed();
} }
public getCachedRequest(request: RPCRequest): RPCResponse | null { /* public getCachedRequest(request: RPCRequest): RPCResponse | null {
const hash = this.hashRequest(request); const hash = this.hashRequest(request);
if (this.cache.has(hash)) { if (this.cache.has(hash)) {
@ -135,7 +135,7 @@ export class RPC {
} }
return null; return null;
} }*/
public deleteCachedRequest(request: RPCRequest): void { public deleteCachedRequest(request: RPCRequest): void {
const hash = this.hashRequest(request); const hash = this.hashRequest(request);
@ -149,7 +149,7 @@ export class RPC {
params: request.params, params: request.params,
}; };
return this._pluginApi.util.crypto return (this._pluginApi as PluginAPI).util.crypto
.createHash(stringify(tempRequest)) .createHash(stringify(tempRequest))
.toString("hex"); .toString("hex");
} }

View File

@ -40,7 +40,7 @@ export function headerDataFromWeb3Response(blockInfo: any): HeaderData {
} }
export function txDataFromWeb3Response( export function txDataFromWeb3Response(
txInfo: any txInfo: any,
): TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData { ): TxData | AccessListEIP2930TxData | FeeMarketEIP1559TxData {
return { return {
...txInfo, ...txInfo,

View File

@ -1,4 +1,4 @@
import { InvalidParamsError } from './errors'; import { InvalidParamsError } from "./errors.js";
// Most of the validations are taken from: // Most of the validations are taken from:
// https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/client/lib/rpc/validation.ts // https://github.com/ethereumjs/ethereumjs-monorepo/blob/master/packages/client/lib/rpc/validation.ts
@ -30,13 +30,13 @@ export const validators = {
* @param index index of parameter * @param index index of parameter
*/ */
hex(params: any[], index: number) { hex(params: any[], index: number) {
if (typeof params[index] !== 'string') { if (typeof params[index] !== "string") {
throw new InvalidParamsError( throw new InvalidParamsError(
`invalid argument ${index}: argument must be a hex string`, `invalid argument ${index}: argument must be a hex string`,
); );
} }
if (params[index].substr(0, 2) !== '0x') { if (params[index].substr(0, 2) !== "0x") {
throw new InvalidParamsError( throw new InvalidParamsError(
`invalid argument ${index}: hex string without 0x prefix`, `invalid argument ${index}: hex string without 0x prefix`,
); );
@ -67,14 +67,14 @@ export const validators = {
blockOption(params: any[], index: number) { blockOption(params: any[], index: number) {
const blockOption = params[index]; const blockOption = params[index];
if (typeof blockOption !== 'string') { if (typeof blockOption !== "string") {
throw new InvalidParamsError( throw new InvalidParamsError(
`invalid argument ${index}: argument must be a string`, `invalid argument ${index}: argument must be a string`,
); );
} }
try { try {
if (['latest', 'earliest', 'pending'].includes(blockOption)) { if (["latest", "earliest", "pending"].includes(blockOption)) {
return; return;
} }
return this.hex([blockOption], 0); return this.hex([blockOption], 0);
@ -91,7 +91,7 @@ export const validators = {
* @param index index of parameter * @param index index of parameter
*/ */
bool(params: any[], index: number) { bool(params: any[], index: number) {
if (typeof params[index] !== 'boolean') { if (typeof params[index] !== "boolean") {
throw new InvalidParamsError( throw new InvalidParamsError(
`invalid argument ${index}: argument is not boolean`, `invalid argument ${index}: argument is not boolean`,
); );
@ -118,7 +118,7 @@ export const validators = {
transaction(params: any[], index: number) { transaction(params: any[], index: number) {
const tx = params[index]; const tx = params[index];
if (typeof tx !== 'object') { if (typeof tx !== "object") {
throw new InvalidParamsError( throw new InvalidParamsError(
`invalid argument ${index}: argument must be an object`, `invalid argument ${index}: argument must be an object`,
); );

View File

@ -11,12 +11,12 @@ const MAX_BATCHSIZE = 10000;
export const LightClientUpdateSSZ = capella.ssz.LightClientUpdate; export const LightClientUpdateSSZ = capella.ssz.LightClientUpdate;
export const LightClientUpdatesSSZ = new ListCompositeType( export const LightClientUpdatesSSZ = new ListCompositeType(
LightClientUpdateSSZ as any, LightClientUpdateSSZ as any,
MAX_BATCHSIZE MAX_BATCHSIZE,
); );
export const CommitteeSSZ = new VectorCompositeType( export const CommitteeSSZ = new VectorCompositeType(
new ByteVectorType(48), new ByteVectorType(48),
BEACON_SYNC_COMMITTEE_SIZE BEACON_SYNC_COMMITTEE_SIZE,
); );
const HashSSZ = new ByteVectorType(32); const HashSSZ = new ByteVectorType(32);

View File

@ -1,5 +1,4 @@
import { fromHexString, toHexString } from "@chainsafe/ssz"; import { fromHexString } from "@chainsafe/ssz";
import bls from "@chainsafe/bls/switchable";
import { createBeaconConfig } from "@lodestar/config"; import { createBeaconConfig } from "@lodestar/config";
import { mainnetConfig } from "./constants.js"; import { mainnetConfig } from "./constants.js";
import { networksChainConfig } from "@lodestar/config/networks"; import { networksChainConfig } from "@lodestar/config/networks";
@ -19,7 +18,7 @@ export function concatUint8Array(data: Uint8Array[]) {
export function getDefaultClientConfig() { export function getDefaultClientConfig() {
const chainConfig = createBeaconConfig( const chainConfig = createBeaconConfig(
networksChainConfig.mainnet, networksChainConfig.mainnet,
fromHexString(mainnetConfig.genesis_validator_root) fromHexString(mainnetConfig.genesis_validator_root),
); );
return { return {
genesis: { genesis: {
@ -34,7 +33,7 @@ export function getDefaultClientConfig() {
export async function handleGETRequest( export async function handleGETRequest(
url: string, url: string,
retry: number = 3 retry: number = 3,
): Promise<any> { ): Promise<any> {
if (retry < 0) { if (retry < 0) {
throw Error(`GET request failed: ${url}`); throw Error(`GET request failed: ${url}`);

View File

@ -1,6 +1,4 @@
import type { Plugin, PluginAPI } from "@lumeweb/interface-relay"; import type { Plugin, PluginAPI } from "@lumeweb/interface-relay";
import fetch, { Request, RequestInit } from "node-fetch";
import NodeCache from "node-cache";
import { Client, Prover } from "./client/index.js"; import { Client, Prover } from "./client/index.js";
import { MemoryStore } from "./client/memory-store.js"; import { MemoryStore } from "./client/memory-store.js";
import { computeSyncPeriodAtSlot } from "@lodestar/light-client/utils"; import { computeSyncPeriodAtSlot } from "@lodestar/light-client/utils";
@ -55,7 +53,7 @@ const plugin: Plugin = {
api.registerMethod("consensus_committee_hashes", { api.registerMethod("consensus_committee_hashes", {
cacheable: false, cacheable: false,
async handler( async handler(
request: ConsensusCommitteeHashesRequest request: ConsensusCommitteeHashesRequest,
): Promise<Uint8Array> { ): Promise<Uint8Array> {
if (!(request?.start && typeof request.start == "number")) { if (!(request?.start && typeof request.start == "number")) {
throw new Error('start required and must be a number"'); throw new Error('start required and must be a number"');
@ -91,7 +89,7 @@ const plugin: Plugin = {
api.registerMethod("consensus_committee_period", { api.registerMethod("consensus_committee_period", {
cacheable: false, cacheable: false,
async handler( async handler(
request: ConsensusCommitteePeriodRequest request: ConsensusCommitteePeriodRequest,
): Promise<Uint8Array> { ): Promise<Uint8Array> {
if ( if (
!( !(
@ -110,7 +108,7 @@ const plugin: Plugin = {
try { try {
committee = store.getCommittee( committee = store.getCommittee(
request.period === "latest" ? client.latestPeriod : request.period request.period === "latest" ? client.latestPeriod : request.period,
); );
} catch { } catch {
await client.sync(); await client.sync();
@ -119,7 +117,9 @@ const plugin: Plugin = {
if (!committee) { if (!committee) {
try { try {
committee = store.getCommittee( committee = store.getCommittee(
request.period === "latest" ? client.latestPeriod : request.period request.period === "latest"
? client.latestPeriod
: request.period,
); );
} catch (e) { } catch (e) {
return e; return e;
@ -160,7 +160,7 @@ const plugin: Plugin = {
cacheable: false, cacheable: false,
async handler(): Promise<object> { async handler(): Promise<object> {
return await handleGETRequest( return await handleGETRequest(
`${CONSENSUS_RPC_URL}/eth/v1/beacon/light_client/optimistic_update` `${CONSENSUS_RPC_URL}/eth/v1/beacon/light_client/optimistic_update`,
); );
}, },
}); });
@ -192,11 +192,11 @@ const plugin: Plugin = {
state = await prover.getSyncUpdate( state = await prover.getSyncUpdate(
period, period,
period, period,
DEFAULT_BATCH_SIZE DEFAULT_BATCH_SIZE,
); );
await client.getExecutionFromBlockRoot( await client.getExecutionFromBlockRoot(
request.block as any, request.block as any,
toHexString(state.attestedHeader.beacon.bodyRoot) toHexString(state.attestedHeader.beacon.bodyRoot),
); );
} catch {} } catch {}
} }
@ -204,11 +204,11 @@ const plugin: Plugin = {
if (client.blockCache.has(request.block)) { if (client.blockCache.has(request.block)) {
client.blockCache.ttl(request.block); client.blockCache.ttl(request.block);
return client.blockCache.get(request.block); return client.blockCache.get(request.block) as object;
} }
const ret = await handleGETRequest( const ret = await handleGETRequest(
`${CONSENSUS_RPC_URL}/eth/v2/beacon/blocks/${request.block}` `${CONSENSUS_RPC_URL}/eth/v2/beacon/blocks/${request.block}`,
); );
client.blockCache.set(request.block, ret); client.blockCache.set(request.block, ret);