From bed19079fea963893e5e1cc15e7925635db7fc3b Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Mon, 17 Jul 2023 16:43:44 +0200 Subject: [PATCH 1/5] Update the lightclient to prover --- craco.config.js | 11 ++- package.json | 9 ++- src/AccountHelper.tsx | 1 - src/App.tsx | 150 +++++++++++++++-------------------------- src/Networks.tsx | 35 ---------- src/ProofReqResp.tsx | 4 +- src/SyncStatus.tsx | 18 +++-- src/TimeMonitor.tsx | 10 +-- src/types.ts | 3 + yarn.lock | 152 +++++++++++++++++++++++++++++++++++++----- 10 files changed, 223 insertions(+), 170 deletions(-) diff --git a/craco.config.js b/craco.config.js index c836e5f..746624d 100644 --- a/craco.config.js +++ b/craco.config.js @@ -2,13 +2,11 @@ const webpack = require("webpack"); module.exports = { babel: { - plugins: [ - "@babel/plugin-proposal-nullish-coalescing-operator", - "@babel/plugin-proposal-optional-chaining", - ], + plugins: ["@babel/plugin-proposal-nullish-coalescing-operator", "@babel/plugin-proposal-optional-chaining"], }, webpack: { configure: { + target: "web", module: { exprContextCritical: false, // turns off Critical dependency: the request of a dependency is an expression error }, @@ -17,7 +15,7 @@ module.exports = { }, resolve: { fallback: { - '@chainsafe/blst': false, // @chainsafe/blst is a peer dependency which is not needed in a browser environment + "@chainsafe/blst": false, // @chainsafe/blst is a peer dependency which is not needed in a browser environment http: require.resolve("stream-http"), https: require.resolve("https-browserify"), crypto: false, @@ -32,11 +30,12 @@ module.exports = { }, plugins: [ new webpack.DefinePlugin({ - process: { argv: [] }, + process: {argv: []}, }), new webpack.ProvidePlugin({ Buffer: ["buffer", "Buffer"], }), + new webpack.LoaderTargetPlugin('browser'), ], }, }; diff --git a/package.json b/package.json index 075b3a4..990ffc9 100644 --- a/package.json +++ b/package.json @@ -61,9 +61,9 @@ "last 1 safari version" ], "devDependencies": { - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.7", - "@babel/plugin-proposal-optional-chaining": "^7.16.7", - "@craco/craco": "^6.4.4", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.21.0", + "@craco/craco": "^7.1.0", "@types/lodash": "^4.14.177", "@typescript-eslint/parser": "^5.13.0", "eslint": "^7.14.0", @@ -74,5 +74,8 @@ "react-scripts": "5.0.1", "react-snap": "^1.23.0", "ts-node": "^10.4.0" + }, + "overrides": { + "webpack": "^5.88.1" } } diff --git a/src/AccountHelper.tsx b/src/AccountHelper.tsx index 5314171..59c7a5b 100644 --- a/src/AccountHelper.tsx +++ b/src/AccountHelper.tsx @@ -16,7 +16,6 @@ export type NewContractForm = { export type ParsedAccount = { type: string; balance: string; - nonce: string; verified: boolean; tokens: {name: string; balance: string; contractAddress: string}[]; }; diff --git a/src/App.tsx b/src/App.tsx index f529263..5cb7ab0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,39 +1,24 @@ import React, {useEffect, useState, useRef} from "react"; import {fromHexString, toHexString} from "@chainsafe/ssz"; -import {Api, ApiError, getClient} from "@lodestar/api"; +import {getClient} from "@lodestar/api"; import {Lightclient, LightclientEvent} from "@lodestar/light-client"; -import {LightClientRestTransport} from "@lodestar/light-client/transport"; -import {createChainForkConfig} from "@lodestar/config"; +import {createIChainForkConfig} from "@lodestar/config"; import {config as configDefault} from "@lodestar/config/default"; -import {SyncPeriod, bellatrix, allForks} from "@lodestar/types"; +import {phase0, SyncPeriod, ssz, bellatrix} from "@lodestar/types"; import {computeSyncPeriodAtSlot} from "@lodestar/light-client/utils"; -import {getLcLoggerConsole} from "@lodestar/light-client/utils"; import Web3 from "web3"; -import {toBuffer, keccak256} from "ethereumjs-util"; -import {DefaultStateManager} from "@ethereumjs/statemanager"; -import {numberToHex} from "web3-utils"; -import {defaultAbiCoder} from "@ethersproject/abi"; import Footer from "./components/Footer"; import {ErrorView} from "./components/ErrorView"; import {Loader} from "./components/Loader"; import {SyncStatus} from "./SyncStatus"; import {TimeMonitor} from "./TimeMonitor"; -import {ProofReqResp} from "./ProofReqResp"; -import {ReqStatus} from "./types"; -import { - NetworkName, - networkDefault, - getNetworkData, - defaultNetworkUrls, - defaultNetworkTokens, - ERC20Contract, -} from "./Networks"; +import {ProofProvider, ReqStatus} from "./types"; +import {NetworkName, networkDefault, defaultNetworkUrls, defaultNetworkTokens, ERC20Contract} from "./Networks"; import {ParsedAccount, DisplayAccount} from "./AccountHelper"; - -const stateManager = new DefaultStateManager(); +import {ProofReqResp} from "./ProofReqResp"; export default function App(): JSX.Element { const [network, setNetwork] = useState(networkDefault); @@ -41,8 +26,9 @@ export default function App(): JSX.Element { const [elRpcUrl, setElRpcUrl] = useState(defaultNetworkUrls[networkDefault].elRpcUrl); const [checkpointRootStr, setCheckpointRootStr] = useState(""); const [reqStatusInit, setReqStatusInit] = useState>({}); - const [head, setHead] = useState(); + const [head, setHead] = useState(); const [latestSyncedPeriod, setLatestSyncedPeriod] = useState(); + // Setting Avalanche Bridge as the default token address to showcase changing balances const [address, setAddress] = useState("0x8EB8a3b98659Cce290402893d0123abb75E3ab28"); const [accountReqStatus, setAccountReqStatus] = useState>({}); @@ -71,10 +57,10 @@ export default function App(): JSX.Element { return; } - const blockRes = await (client["transport"]["api"] as Api).beacon.getBlockV2(head.beacon.slot); - ApiError.assert(blockRes); + const blockHash = toHexString(ssz.phase0.BeaconBlockHeader.hashTreeRoot(head)); + const data = await client.api.beacon.getBlockV2(blockHash); - const block = blockRes.response.data as bellatrix.SignedBeaconBlock; + const {data: block} = data as unknown as {data: bellatrix.SignedBeaconBlock}; const executionPayload = block.message.body.executionPayload; // If the merge not complete, executionPayload would not exists @@ -86,7 +72,6 @@ export default function App(): JSX.Element { setAccountReqStatus({result: accountReqStatus.result, loading: `Fetching status from ${elRpcUrl}`}); const verifiedAccount = await fetchAndVerifyAddressBalances({ web3: web3.current, - executionPayload, address, erc20Contracts, }); @@ -94,20 +79,19 @@ export default function App(): JSX.Element { } fetchAndVerifyAccount().catch((e) => { - setAccountReqStatus({result: accountReqStatus.result, error: e}); + setAccountReqStatus({error: e, loading: undefined}); }); }, [head, address, elRpcUrl, erc20Contracts]); useEffect(() => { - const client = reqStatusInit.result; - if (!client) return; + const proofProvider = reqStatusInit.result; + if (!proofProvider) return; - client.start(); - const head = client.getHead(); + const head = proofProvider.getStatus().latest; setHead(head); - setLatestSyncedPeriod(computeSyncPeriodAtSlot(head.beacon.slot)); + setLatestSyncedPeriod(computeSyncPeriodAtSlot(head.slot)); - function onNewHead(newHeader: allForks.LightClientHeader) { + function onNewHead(newHeader: phase0.BeaconBlockHeader) { setHead(newHeader); } @@ -115,12 +99,12 @@ export default function App(): JSX.Element { setLatestSyncedPeriod(period); } - client.emitter.on(LightclientEvent.lightClientFinalityHeader, onNewHead); - // client.emitter.on(LightclientEvent.committee, onNewCommittee); + client.emitter.on(LightclientEvent.head, onNewHead); + client.emitter.on(LightclientEvent.committee, onNewCommittee); return function () { - client.emitter.off(LightclientEvent.lightClientFinalityHeader, onNewHead); - // client.emitter.off(LightclientEvent.committee, onNewCommittee); + client.emitter.off(LightclientEvent.head, onNewHead); + client.emitter.off(LightclientEvent.committee, onNewCommittee); }; }, [reqStatusInit.result]); @@ -138,17 +122,19 @@ export default function App(): JSX.Element { setReqStatusInit({loading: `Syncing from trusted checkpoint: ${checkpointRootHex}`}); const {genesisData, chainConfig} = await getNetworkData(network, beaconApiUrl); - const config = createChainForkConfig(chainConfig); + const config = createIChainForkConfig(chainConfig); const client = await Lightclient.initializeFromCheckpointRoot({ config, logger: getLcLoggerConsole({logDebug: true}), - transport: new LightClientRestTransport(getClient({urls: [beaconApiUrl]}, {config})), + beaconApiUrl, genesisData, checkpointRoot, }); - setReqStatusInit({result: client}); + web3.current = new Web3(provider); + + setReqStatusInit({result: proofProvider}); } catch (e) { (e as Error).message = `Error initializing from trusted checkpoint ${checkpointRootHex}: ${(e as Error).message}`; setReqStatusInit({error: e as Error}); @@ -250,19 +236,9 @@ export default function App(): JSX.Element { ) : (
- - {accountReqStatus.error || !accountReqStatus.result - ? "error" - : accountReqStatus.result.verified - ? "valid" - : "invalid"} - + {accountReqStatus.error || !accountReqStatus.result ? "invalid" : "valid"}

- {accountReqStatus.error || !accountReqStatus.result - ? "🛑" - : accountReqStatus.result.verified - ? "✅" - : "❌"} + {accountReqStatus.error || !accountReqStatus.result ? "❌" : "✅"}

)} @@ -328,9 +304,9 @@ export default function App(): JSX.Element { {reqStatusInit.result ? ( <> - - - {head !== undefined && } + + + {head !== undefined && } ) : reqStatusInit.error ? ( @@ -352,66 +328,46 @@ const externalAddressCodeHash = "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca822 async function fetchAndVerifyAddressBalances({ web3, - executionPayload, address, erc20Contracts, }: { web3: Web3 | undefined; - executionPayload: bellatrix.ExecutionPayload; address: string; erc20Contracts: Record; }): Promise { if (!web3) throw Error(`No valid connection to EL`); - const params: [string, string[], number] = [address, [], executionPayload.blockNumber]; - const stateRoot = toHexString(executionPayload.stateRoot); - const proof = await web3.eth.getProof(...params); - - const {balance, nonce} = proof; - - // Verify the proof, web3 converts nonce and balance into number strings, however - // ethereumjs verify proof requires them in the original hex format - proof.nonce = numberToHex(proof.nonce); - proof.balance = numberToHex(proof.balance); - - const proofStateRoot = toHexString(keccak256(toBuffer(proof.accountProof[0]))); - let verified = - stateRoot === proofStateRoot && - (proof.codeHash !== externalAddressCodeHash || proof.storageHash === externalAddressStorageHash) && - (await stateManager.verifyProof(proof)); + let balance: string = ""; + let verified: boolean; + + try { + balance = await web3.eth.getBalance(address); + verified = true; + } catch (err) { + verified = false; + } + let tokens = []; for (const contractName of Object.keys(erc20Contracts)) { const {contractAddress, balanceMappingIndex} = erc20Contracts[contractName]; - const balanceSlot = web3.utils.keccak256( - defaultAbiCoder.encode(["address", "uint"], [address, balanceMappingIndex]) - ); - const contractProof = await web3.eth.getProof(contractAddress, [balanceSlot], executionPayload.blockNumber); - if (contractProof.codeHash === externalAddressCodeHash) { - throw Error(`No contract deployed at ${contractAddress} for ${contractName}`); + try { + const contractBalance = await web3.eth.getBalance(contractAddress); + tokens.push({ + name: contractName, + balance: contractBalance, + contractAddress, + }); + } catch (err) { + console.error(`Error fetching contract balance`, err); } - const contractProofStateRoot = toHexString(keccak256(toBuffer(contractProof.accountProof[0]))); - // Verify the proof, web3 converts nonce and balance into number strings, however - // ethereumjs verify proof requires them in the original hex format - contractProof.nonce = numberToHex(contractProof.nonce); - contractProof.balance = numberToHex(contractProof.balance); - - verified = - verified && - stateRoot === contractProofStateRoot && - contractProof.storageProof[0]?.key === balanceSlot && - (await stateManager.verifyProof(contractProof)); - tokens.push({ - name: contractName, - contractAddress, - balance: web3.utils.fromWei(web3.utils.hexToNumberString(contractProof.storageProof[0]?.value ?? "0x0")), - }); } return { balance: web3.utils.fromWei(balance, "ether"), - nonce, verified, tokens, - type: proof.codeHash === externalAddressCodeHash ? "external" : "contract", + // TODO: Find a way to fix this + // type: proof.codeHash === externalAddressCodeHash ? "external" : "contract", + type: "external", }; } diff --git a/src/Networks.tsx b/src/Networks.tsx index ce0ef09..ebcc894 100644 --- a/src/Networks.tsx +++ b/src/Networks.tsx @@ -18,41 +18,6 @@ export type ERC20Contract = { balanceMappingIndex: number; }; -export async function getNetworkData(network: NetworkName, beaconApiUrl?: string) { - switch (network) { - case NetworkName.mainnet: - case NetworkName.goerli: - case NetworkName.sepolia: - return { - genesisData: networkGenesis[network], - chainConfig: networksChainConfig[network], - }; - - default: - if (!beaconApiUrl) { - throw Error(`Unknown network: ${network}, requires beaconApiUrl to load config`); - } - const api = getClient({baseUrl: beaconApiUrl}, {config: configDefault}); - - const genesisRes = await api.beacon.getGenesis(); - ApiError.assert(genesisRes); - const genesisData = genesisRes.response.data; - - const configRes = await api.config.getSpec(); - ApiError.assert(configRes); - const chainConfig = configRes.response.data; - - const networkData = { - genesisData: { - genesisTime: Number(genesisData.genesisTime), - genesisValidatorsRoot: toHexString(genesisData.genesisValidatorsRoot), - }, - chainConfig: chainConfigFromJson(chainConfig), - }; - return networkData; - } -} - export const defaultNetworkUrls: Record = { [NetworkName.mainnet]: { beaconApiUrl: process.env.REACT_APP_MAINNET_BEACON_API || "https://lodestar-mainnet.chainsafe.io", diff --git a/src/ProofReqResp.tsx b/src/ProofReqResp.tsx index 535ad23..0a4bdfc 100644 --- a/src/ProofReqResp.tsx +++ b/src/ProofReqResp.tsx @@ -2,9 +2,9 @@ import React, {useEffect, useMemo, useState} from "react"; import throttle from "lodash/throttle"; import {Lightclient} from "@lodestar/light-client"; import {TreeOffsetProof, computeDescriptor} from "@chainsafe/persistent-merkle-tree"; -import {ssz, allForks} from "@lodestar/types"; +import {phase0, ssz, allForks} from "@lodestar/types"; import {CompositeType, toHexString, CompositeView, JsonPath} from "@chainsafe/ssz"; -import {ReqStatus} from "./types"; +import {ProofProvider, ReqStatus} from "./types"; import {ErrorView} from "./components/ErrorView"; import {ApiError, Api} from "@lodestar/api"; diff --git a/src/SyncStatus.tsx b/src/SyncStatus.tsx index 425890c..cce3314 100644 --- a/src/SyncStatus.tsx +++ b/src/SyncStatus.tsx @@ -1,24 +1,32 @@ -import React from "react"; -import {Lightclient} from "@lodestar/light-client"; +import React, {useEffect, useState} from "react"; import {computeSyncPeriodAtSlot} from "@lodestar/light-client/utils"; import {SyncPeriod, allForks} from "@lodestar/types"; import {toHexString} from "@chainsafe/ssz"; +import {ProofProvider} from "./types"; export function SyncStatus({ - client, + proofProvider, latestSyncedPeriod, head, }: { - client: Lightclient; + proofProvider: ProofProvider; latestSyncedPeriod: SyncPeriod | undefined; head: allForks.LightClientHeader | undefined; }): JSX.Element { + const [stateRoot, setStateRoot] = useState(""); + + useEffect(() => { + proofProvider.getExecutionPayload(head ?? proofProvider.getStatus().latest).then((header) => { + setStateRoot(toHexString(header.stateRoot)); + }); + }); + return (

Sync Status

Latest sync period: {latestSyncedPeriod ?? "-"}
-
Clock sync period: {computeSyncPeriodAtSlot(client.currentSlot)}
+
Clock sync period: {computeSyncPeriodAtSlot(proofProvider.getStatus().latest)}

Latest Synced Snapshot Header

diff --git a/src/TimeMonitor.tsx b/src/TimeMonitor.tsx index 5db903e..413de2b 100644 --- a/src/TimeMonitor.tsx +++ b/src/TimeMonitor.tsx @@ -1,8 +1,8 @@ import React, {useState, useEffect} from "react"; import {EPOCHS_PER_SYNC_COMMITTEE_PERIOD, SLOTS_PER_EPOCH} from "@lodestar/params"; -import {Lightclient} from "@lodestar/light-client"; +import {ProofProvider} from "./types"; -export function TimeMonitor({client}: {client: Lightclient}): JSX.Element { +export function TimeMonitor({proofProvider}: {proofProvider: ProofProvider}): JSX.Element { const [, setCounter] = useState(); useEffect(() => { const interval = setInterval(() => { @@ -11,18 +11,18 @@ export function TimeMonitor({client}: {client: Lightclient}): JSX.Element { return () => clearInterval(interval); }, [setCounter]); - const {SECONDS_PER_SLOT} = client.config; + const {SECONDS_PER_SLOT} = proofProvider.config; const secondsPerEpoch = SECONDS_PER_SLOT * SLOTS_PER_EPOCH; const secondsPerPeriod = secondsPerEpoch * EPOCHS_PER_SYNC_COMMITTEE_PERIOD; - const diffInSeconds = Date.now() / 1000 - client.genesisTime; + const diffInSeconds = Date.now() / 1000 - proofProvider.config.MIN_GENESIS_TIME; const slot = Math.floor(diffInSeconds / SECONDS_PER_SLOT); const slotInEpoch = slot % SLOTS_PER_EPOCH; const slotRatio = (diffInSeconds % secondsPerEpoch) / secondsPerEpoch; const epoch = Math.floor(slot / SLOTS_PER_EPOCH); const epochInPeriod = epoch % EPOCHS_PER_SYNC_COMMITTEE_PERIOD; const epochRatio = (diffInSeconds % secondsPerPeriod) / secondsPerPeriod; - const period = Math.floor((epoch - client.config.ALTAIR_FORK_EPOCH) / EPOCHS_PER_SYNC_COMMITTEE_PERIOD); + const period = Math.floor((epoch - proofProvider.config.ALTAIR_FORK_EPOCH) / EPOCHS_PER_SYNC_COMMITTEE_PERIOD); return (
diff --git a/src/types.ts b/src/types.ts index 7d5032a..82b3919 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,8 @@ +import {createVerifiedExecutionProvider} from "@lodestar/prover"; + export interface ReqStatus { loading?: P; error?: Error; result?: T; } +export type ProofProvider = ReturnType["proofProvider"]; diff --git a/yarn.lock b/yarn.lock index 8d82270..196c2bf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -204,6 +204,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.6.tgz#9448974dd4fb1d80fefe72e8a0af37809cd30d6d" integrity sha512-gvZnm1YAAxh13eJdkb9EWHBnF3eAub3XTLCZEehHT2kWxiKVRL64+ae5Y6Ivne0mVHmMYKT+xWgZO+gQhuLUBg== +"@babel/helper-plugin-utils@^7.20.2": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" + integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== + "@babel/helper-remap-async-to-generator@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.6.tgz#fa1f81acd19daee9d73de297c0308783cd3cfc23" @@ -239,6 +244,13 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" + integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-split-export-declaration@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" @@ -246,11 +258,21 @@ dependencies: "@babel/types" "^7.18.6" +"@babel/helper-string-parser@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" + integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== + "@babel/helper-validator-identifier@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076" integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g== +"@babel/helper-validator-identifier@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" + integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ== + "@babel/helper-validator-option@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" @@ -375,7 +397,7 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== @@ -410,7 +432,7 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.16.0", "@babel/plugin-proposal-optional-chaining@^7.16.7", "@babel/plugin-proposal-optional-chaining@^7.18.6": +"@babel/plugin-proposal-optional-chaining@^7.16.0", "@babel/plugin-proposal-optional-chaining@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.6.tgz#46d4f2ffc20e87fad1d98bc4fa5d466366f6aa0b" integrity sha512-PatI6elL5eMzoypFAiYDpYQyMtXTn+iMhuxxQt5mAXD4fEmKorpSI3PHd+i3JXBJN3xyA6MvJv7at23HffFHwA== @@ -419,6 +441,15 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.18.6" "@babel/plugin-syntax-optional-chaining" "^7.8.3" +"@babel/plugin-proposal-optional-chaining@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea" + integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA== + dependencies: + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-private-methods@^7.16.0", "@babel/plugin-proposal-private-methods@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" @@ -1074,6 +1105,15 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" +"@babel/types@^7.22.5": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe" + integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1147,17 +1187,18 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@craco/craco@^6.4.4": - version "6.4.5" - resolved "https://registry.yarnpkg.com/@craco/craco/-/craco-6.4.5.tgz#471e67082a2ffd3edf73759b215bdc16250d27b3" - integrity sha512-8F2rIAao8sEh0FPP52ViEvDM9GjJ7acq0knu1c8UgI+EuZMD5/ZB270ol6jV4iNY7it9Umg/RoGBvNRUNr8U8w== +"@craco/craco@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@craco/craco/-/craco-7.1.0.tgz#12bd394c7f0334e214302e4d35a1768f68042fbb" + integrity sha512-oRAcPIKYrfPXp9rSzlsDNeOaVtDiKhoyqSXUoqiK24jCkHr4T8m/a2f74yXIzCbIheoUWDOIfWZyRgFgT+cpqA== dependencies: + autoprefixer "^10.4.12" cosmiconfig "^7.0.1" cosmiconfig-typescript-loader "^1.0.0" - cross-spawn "^7.0.0" - lodash "^4.17.15" - semver "^7.3.2" - webpack-merge "^4.2.2" + cross-spawn "^7.0.3" + lodash "^4.17.21" + semver "^7.3.7" + webpack-merge "^5.8.0" "@cspotcode/source-map-support@^0.8.0": version "0.8.1" @@ -3314,6 +3355,18 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== +autoprefixer@^10.4.12: + version "10.4.14" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d" + integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ== + dependencies: + browserslist "^4.21.5" + caniuse-lite "^1.0.30001464" + fraction.js "^4.2.0" + normalize-range "^0.1.2" + picocolors "^1.0.0" + postcss-value-parser "^4.2.0" + autoprefixer@^10.4.7: version "10.4.7" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.7.tgz#1db8d195f41a52ca5069b7593be167618edbbedf" @@ -3757,6 +3810,16 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4 node-releases "^2.0.5" update-browserslist-db "^1.0.4" +browserslist@^4.21.5: + version "4.21.9" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635" + integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg== + dependencies: + caniuse-lite "^1.0.30001503" + electron-to-chromium "^1.4.431" + node-releases "^2.0.12" + update-browserslist-db "^1.0.11" + bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" @@ -3936,6 +3999,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001359: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001363.tgz#26bec2d606924ba318235944e1193304ea7c4f15" integrity sha512-HpQhpzTGGPVMnCjIomjt+jvyUu8vNFo3TaDiZ/RcoTrlOq/5+tC8zHdsbgFB6MxmaY+jCpsH09aD80Bb4Ow3Sg== +caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503: + version "1.0.30001516" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001516.tgz#621b1be7d85a8843ee7d210fd9d87b52e3daab3a" + integrity sha512-Wmec9pCBY8CWbmI4HsjBeQLqDTqV91nFVR83DnZpYyRnPI1wePDsTg0bGLPC5VU/3OIZV1fmxEea1b+tFKe86g== + case-sensitive-paths-webpack-plugin@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4" @@ -4138,6 +4206,15 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -4491,7 +4568,7 @@ cross-fetch@^3.1.4: dependencies: node-fetch "2.6.7" -cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -5199,6 +5276,11 @@ electron-to-chromium@^1.4.172: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.185.tgz#3432d7944f1c5fe20664bb45d9cced2151405ce2" integrity sha512-9kV/isoOGpKkBt04yYNaSWIBn3187Q5VZRtoReq8oz5NY/A4XmU6cAoqgQlDp7kKJCZMRjWZ8nsQyxfpFHvfyw== +electron-to-chromium@^1.4.431: + version "1.4.461" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.461.tgz#6b14af66042732bf883ab63a4d82cac8f35eb252" + integrity sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ== + elliptic@6.5.4, elliptic@^6.4.0, elliptic@^6.5.3, elliptic@^6.5.4: version "6.5.4" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" @@ -7358,6 +7440,13 @@ is-plain-obj@^3.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== +is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" @@ -7457,6 +7546,11 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== +isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + isomorphic-fetch@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" @@ -8976,6 +9070,11 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw== +node-releases@^2.0.12: + version "2.0.13" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d" + integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== + node-releases@^2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" @@ -11240,6 +11339,13 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -12292,6 +12398,14 @@ upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== +update-browserslist-db@^1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940" + integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" + update-browserslist-db@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz#dbfc5a789caa26b1db8990796c2c8ebbce304824" @@ -12784,12 +12898,13 @@ webpack-manifest-plugin@^4.0.2: tapable "^2.0.0" webpack-sources "^2.2.0" -webpack-merge@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== +webpack-merge@^5.8.0: + version "5.9.0" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.9.0.tgz#dc160a1c4cf512ceca515cc231669e9ddb133826" + integrity sha512-6NbRQw4+Sy50vYNTw7EyOn41OZItPiXB8GNv3INSoe3PSFaHJEz3SHTrYVaRm2LilNGnFUzh0FAwqPEmU/CwDg== dependencies: - lodash "^4.17.15" + clone-deep "^4.0.1" + wildcard "^2.0.0" webpack-sources@^1.4.3: version "1.4.3" @@ -12960,6 +13075,11 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2 || 3 || 4" +wildcard@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" + integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== + winston-transport@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.5.0.tgz#6e7b0dd04d393171ed5e4e4905db265f7ab384fa" From b331b9a9745489fdd1b9b169d1790d5b5d55a1e7 Mon Sep 17 00:00:00 2001 From: Nazar Hussain Date: Fri, 21 Jul 2023 18:43:06 +0200 Subject: [PATCH 2/5] Use the prover for verification --- craco.config.js | 6 +- package.json | 16 +- src/App.tsx | 322 ++------- src/ProofReqResp.tsx | 172 ----- src/{ => components}/AccountHelper.tsx | 8 +- src/components/AccountVerification.tsx | 135 ++++ src/components/ProofProviderView.tsx | 58 ++ src/{ => components}/SyncStatus.tsx | 13 +- src/{ => components}/TimeMonitor.tsx | 2 +- src/components/TrustedCheckpoint.tsx | 48 ++ src/types.ts | 3 + src/utils/abi.ts | 129 ++++ src/utils/api.ts | 7 + src/{Networks.tsx => utils/networks.ts} | 30 +- yarn.lock | 882 +++++++++++++++++++++++- 15 files changed, 1353 insertions(+), 478 deletions(-) delete mode 100644 src/ProofReqResp.tsx rename src/{ => components}/AccountHelper.tsx (98%) create mode 100644 src/components/AccountVerification.tsx create mode 100644 src/components/ProofProviderView.tsx rename src/{ => components}/SyncStatus.tsx (79%) rename src/{ => components}/TimeMonitor.tsx (97%) create mode 100644 src/components/TrustedCheckpoint.tsx create mode 100644 src/utils/abi.ts create mode 100644 src/utils/api.ts rename src/{Networks.tsx => utils/networks.ts} (78%) diff --git a/craco.config.js b/craco.config.js index 746624d..2f7eeb3 100644 --- a/craco.config.js +++ b/craco.config.js @@ -6,7 +6,7 @@ module.exports = { }, webpack: { configure: { - target: "web", + target: ["web"], module: { exprContextCritical: false, // turns off Critical dependency: the request of a dependency is an expression error }, @@ -25,7 +25,7 @@ module.exports = { path: false, zlib: false, fs: false - }, + } }, }, plugins: [ @@ -35,7 +35,7 @@ module.exports = { new webpack.ProvidePlugin({ Buffer: ["buffer", "Buffer"], }), - new webpack.LoaderTargetPlugin('browser'), + new webpack.LoaderTargetPlugin('web'), ], }, }; diff --git a/package.json b/package.json index 990ffc9..8dd09d9 100644 --- a/package.json +++ b/package.json @@ -15,16 +15,17 @@ }, "dependencies": { "@chainsafe/bls": "7.1.1", - "@lodestar/api": "^1.9.2", - "@lodestar/config": "^1.9.2", - "@lodestar/light-client": "^1.9.2", - "@lodestar/params": "^1.9.2", - "@lodestar/types": "^1.9.2", - "@lodestar/utils": "^1.9.2", "@chainsafe/persistent-merkle-tree": "^0.6.1", "@chainsafe/ssz": "^0.10.2", "@ethereumjs/statemanager": "^1.0.0-beta.1", "@ethersproject/abi": "^5.6.0", + "@lodestar/api": "^1.9.1", + "@lodestar/config": "^1.9.1", + "@lodestar/light-client": "^1.9.1", + "@lodestar/params": "^1.9.1", + "@lodestar/prover": "^1.9.1", + "@lodestar/types": "^1.9.1", + "@lodestar/utils": "^1.9.1", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.1.0", "@testing-library/user-event": "^12.1.10", @@ -73,7 +74,8 @@ "prettier": "^2.5.1", "react-scripts": "5.0.1", "react-snap": "^1.23.0", - "ts-node": "^10.4.0" + "ts-node": "^10.4.0", + "webpack-cli": "^5.1.4" }, "overrides": { "webpack": "^5.88.1" diff --git a/src/App.tsx b/src/App.tsx index 5cb7ab0..2cc27bf 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,40 +1,40 @@ import React, {useEffect, useState, useRef} from "react"; -import {fromHexString, toHexString} from "@chainsafe/ssz"; -import {getClient} from "@lodestar/api"; -import {Lightclient, LightclientEvent} from "@lodestar/light-client"; -import {createIChainForkConfig} from "@lodestar/config"; -import {config as configDefault} from "@lodestar/config/default"; - -import {phase0, SyncPeriod, ssz, bellatrix} from "@lodestar/types"; -import {computeSyncPeriodAtSlot} from "@lodestar/light-client/utils"; +import {Api} from "@lodestar/api"; +import {createVerifiedExecutionProvider, LCTransport} from "@lodestar/prover"; +import {NetworkName as ConfigNetworkName} from "@lodestar/config/networks"; import Web3 from "web3"; import Footer from "./components/Footer"; -import {ErrorView} from "./components/ErrorView"; -import {Loader} from "./components/Loader"; -import {SyncStatus} from "./SyncStatus"; -import {TimeMonitor} from "./TimeMonitor"; import {ProofProvider, ReqStatus} from "./types"; -import {NetworkName, networkDefault, defaultNetworkUrls, defaultNetworkTokens, ERC20Contract} from "./Networks"; -import {ParsedAccount, DisplayAccount} from "./AccountHelper"; -import {ProofReqResp} from "./ProofReqResp"; +import {TrustedCheckpoint} from "./components/TrustedCheckpoint"; +import {createChainForkConfig} from "@lodestar/config"; +import {getApiClient} from "./utils/api"; +import {AccountVerification} from "./components/AccountVerification"; +import {ProofProviderView} from "./components/ProofProviderView"; +import { + ERC20Contract, + NetworkName, + defaultNetworkTokens, + defaultNetworkUrls, + getChainConfig, + networkDefault, +} from "./utils/networks"; export default function App(): JSX.Element { const [network, setNetwork] = useState(networkDefault); const [beaconApiUrl, setBeaconApiUrl] = useState(defaultNetworkUrls[networkDefault].beaconApiUrl); const [elRpcUrl, setElRpcUrl] = useState(defaultNetworkUrls[networkDefault].elRpcUrl); - const [checkpointRootStr, setCheckpointRootStr] = useState(""); - const [reqStatusInit, setReqStatusInit] = useState>({}); - const [head, setHead] = useState(); - const [latestSyncedPeriod, setLatestSyncedPeriod] = useState(); - - // Setting Avalanche Bridge as the default token address to showcase changing balances - const [address, setAddress] = useState("0x8EB8a3b98659Cce290402893d0123abb75E3ab28"); - const [accountReqStatus, setAccountReqStatus] = useState>({}); const [erc20Contracts, setErc20Contracts] = useState>( defaultNetworkTokens[networkDefault].full ); + + const [api, setApi] = useState(); + const [isProofProviderReady, setIsProofProviderReady] = useState(false); + + const [proofProviderReq, setProofProviderReq] = useState>({}); + const [trustedCheckpointReq, setTrustedCheckpointReq] = useState>({}); + const web3 = useRef(); useEffect(() => { @@ -44,130 +44,57 @@ export default function App(): JSX.Element { }, [network]); useEffect(() => { - async function fetchAndVerifyAccount() { - const client = reqStatusInit.result; - if (!client || !head || !address || !elRpcUrl) { - return; - } - - try { - if (!web3.current) web3.current = new Web3(elRpcUrl); - } catch (e) { - setAccountReqStatus({result: accountReqStatus.result, error: e as Error}); - return; - } - - const blockHash = toHexString(ssz.phase0.BeaconBlockHeader.hashTreeRoot(head)); - const data = await client.api.beacon.getBlockV2(blockHash); - - const {data: block} = data as unknown as {data: bellatrix.SignedBeaconBlock}; - const executionPayload = block.message.body.executionPayload; - - // If the merge not complete, executionPayload would not exists - if (!executionPayload) { - setAccountReqStatus({result: accountReqStatus.result, loading: `Waiting for an execution payload`}); - return; - } - - setAccountReqStatus({result: accountReqStatus.result, loading: `Fetching status from ${elRpcUrl}`}); - const verifiedAccount = await fetchAndVerifyAddressBalances({ - web3: web3.current, - address, - erc20Contracts, - }); - setAccountReqStatus({result: verifiedAccount}); + async function process() { + const config = createChainForkConfig(await getChainConfig(network, beaconApiUrl)); + const api = getApiClient(beaconApiUrl, config); + setApi(api); } - fetchAndVerifyAccount().catch((e) => { - setAccountReqStatus({error: e, loading: undefined}); - }); - }, [head, address, elRpcUrl, erc20Contracts]); + process().catch(console.error); + }, [beaconApiUrl]); useEffect(() => { - const proofProvider = reqStatusInit.result; - if (!proofProvider) return; + if (!proofProviderReq.result) return; - const head = proofProvider.getStatus().latest; - setHead(head); - setLatestSyncedPeriod(computeSyncPeriodAtSlot(head.slot)); - - function onNewHead(newHeader: phase0.BeaconBlockHeader) { - setHead(newHeader); - } - - function onNewCommittee(period: SyncPeriod) { - setLatestSyncedPeriod(period); + async function process() { + await proofProviderReq.result?.waitToBeReady(); + setIsProofProviderReady(true); } - client.emitter.on(LightclientEvent.head, onNewHead); - client.emitter.on(LightclientEvent.committee, onNewCommittee); + process().catch(console.error); + }, [proofProviderReq.result]); - return function () { - client.emitter.off(LightclientEvent.head, onNewHead); - client.emitter.off(LightclientEvent.committee, onNewCommittee); - }; - }, [reqStatusInit.result]); + async function initializeFromCheckpointStr(checkpointRootHex?: string) { + if (!checkpointRootHex) return; - async function initializeFromCheckpointStr(checkpointRootHex: string) { try { // Validate root if (!checkpointRootHex.startsWith("0x")) { throw Error("Root must start with 0x"); } - const checkpointRoot = fromHexString(checkpointRootHex); - if (checkpointRoot.length !== 32) { - throw Error(`Root must be 32 bytes long: ${checkpointRoot.length}`); + if (checkpointRootHex.length !== 64 + 2) { + throw Error(`Root must be 32 bytes long: ${checkpointRootHex.length}`); } - setReqStatusInit({loading: `Syncing from trusted checkpoint: ${checkpointRootHex}`}); - - const {genesisData, chainConfig} = await getNetworkData(network, beaconApiUrl); - const config = createIChainForkConfig(chainConfig); + setProofProviderReq({loading: `Syncing from trusted checkpoint: ${checkpointRootHex}`}); - const client = await Lightclient.initializeFromCheckpointRoot({ - config, - logger: getLcLoggerConsole({logDebug: true}), - beaconApiUrl, - genesisData, - checkpointRoot, + const {provider, proofProvider} = createVerifiedExecutionProvider(new Web3.providers.HttpProvider(elRpcUrl), { + transport: LCTransport.Rest, + urls: [beaconApiUrl], + wsCheckpoint: checkpointRootHex, + network: network as ConfigNetworkName, + logger: console as any, }); - web3.current = new Web3(provider); - - setReqStatusInit({result: proofProvider}); + setProofProviderReq({result: proofProvider}); } catch (e) { (e as Error).message = `Error initializing from trusted checkpoint ${checkpointRootHex}: ${(e as Error).message}`; - setReqStatusInit({error: e as Error}); - // eslint-disable-next-line no-console - console.error(e); - } - } - - async function fillCheckpointFromNode() { - try { - setReqStatusInit({loading: "Fetching checkpoint from trusted node"}); - - const client = getClient({baseUrl: beaconApiUrl}, {config: configDefault}); - const res = await client.beacon.getStateFinalityCheckpoints("head"); - ApiError.assert(res); - const finalizedCheckpoint = res.response.data.finalized; - setCheckpointRootStr(toHexString(finalizedCheckpoint.root)); - - // Hasn't load clint, just disable loader - setReqStatusInit({}); - } catch (e) { - (e as Error).message = `Error initializing from trusted node: ${(e as Error).message}`; - setReqStatusInit({error: e as Error}); + setProofProviderReq({error: e as Error}); // eslint-disable-next-line no-console console.error(e); } } - function deleteState() { - // deleteSnapshot(); - setReqStatusInit({}); - } - return ( <>
@@ -216,158 +143,41 @@ export default function App(): JSX.Element { -
-
-
- any ethereum address -
- setAddress(e.target.value)} /> -
-
- {(accountReqStatus.result || accountReqStatus.error) && ( -
-
- type - -
- -
- {accountReqStatus.loading ? ( - - ) : ( -
- {accountReqStatus.error || !accountReqStatus.result ? "invalid" : "valid"} -

- {accountReqStatus.error || !accountReqStatus.result ? "❌" : "✅"} -

-
- )} -
-
- )} -
-
- {accountReqStatus.result ? ( - - ) : accountReqStatus.loading ? ( - <> - -

{accountReqStatus.loading}

- ) : ( <> )} - {accountReqStatus.error && } +

- {!reqStatusInit.result ? ( - <> -
-
-
-

- Trusted checkpoint{" "} - - (Fill with latest finalized) - -

- setCheckpointRootStr(e.target.value)} - placeholder="0xaabb..." - /> -
-
+ {!isProofProviderReady && api && ( +
+ -
-
- -
+
+
+
- - ) : ( -
-
- -
)}
- {reqStatusInit.result ? ( - <> - - - {head !== undefined && } - - ) : reqStatusInit.error ? ( - - ) : reqStatusInit.loading ? ( - <> - -

Initializing light-client - {reqStatusInit.loading}

- - ) : null} + +