This package is part of ChainSafe's Lodestar project
A set of tools allowing to verify EL client JSON-RPC calls.
You can use the @lodestar/prover
in two ways, as a Web3 Provider and as proxy. For prover use case see below example.
import Web3 from "web3";
import {createVerifiedExecutionProvider, LCTransport} from "@lodestar/prover";
const httpProvider = new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io");
const {provider, proofProvider} = createVerifiedExecutionProvider(httpProvider, {
transport: LCTransport.Rest,
urls: ["https://lodestar-sepolia.chainsafe.io"],
network: "sepolia",
wsCheckpoint: "trusted-checkpoint",
});
const web3 = new Web3(provider);
const address = "0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134";
const balance = await web3.eth.getBalance(address, "latest");
console.log({balance, address});
In this scenario the actual provider is mutated to handle the RPC requests and verify those. So here if you use provider
or httpProvider
both are the same objects. This behavior is useful when you already have an application and usage of any provider across the code space and don't want to change the code. So you mutate the provider during startup.
For some scenarios when you don't want to mutate the provider you can pass an option mutateProvider
as false
. In this scenario the object httpProvider
is not mutated and you get a new object provider
. This is useful when your provider object does not allow mutation, e.g. Metamask provider accessible through window.ethereum
. If not provided mutateProvider
is considered as true
by default. In coming releases we will switch its default behavior to false
.
import Web3 from "web3";
import {createVerifiedExecutionProvider, LCTransport} from "@lodestar/prover";
const httpProvider = new Web3.providers.HttpProvider("https://lodestar-sepoliarpc.chainsafe.io");
const {provider, proofProvider} = createVerifiedExecutionProvider(httpProvider, {
transport: LCTransport.Rest,
urls: ["https://lodestar-sepolia.chainsafe.io"],
network: "sepolia",
wsCheckpoint: "trusted-checkpoint",
mutateProvider: false,
});
const web3 = new Web3(provider);
const address = "0xf97e180c050e5Ab072211Ad2C213Eb5AEE4DF134";
const balance = await web3.eth.getBalance(address, "latest");
console.log({balance, address});
You can also invoke the package as binary.
npm i -g @lodestar/prover
lodestar-prover proxy \
--network sepolia \
--executionRpcUrl https://lodestar-sepoliarpc.chainsafe.io \
--beaconUrls https://lodestar-sepolia.chainsafe.io \
--port 8080
There can be different implementations of the web3 providers and each can handle the RPC request differently. We call those different provider types. We had provided builtin support for common providers e.g. web3.js, ethers or any eip1193 compatible providers. We inspect given provider instance at runtime to detect the correct provider type.
If your project is using some provider type which is not among above list, you have the option to register a custom provider type with the createVerifiedExecutionProvider
with the option providerTypes
which will be an array of your supported provider types. Your custom provider types will have higher priority than default provider types. Please see existing provide types implementations to know how to implement your own if needed.
✅ - Completed
⌛ - Todo
➡️ - Request will be forward to EL without any intermediary manipulations. You can limit these by providing unverifiedWhitelist
option for provider or --unverifiedWhitelist
from the cli. If not set then all methods will be forwarded.
❇️ - Always forwarded to EL.
Group | Method | Status | Version |
---|---|---|---|
Block | eth_getBlockByHash | ✅ | v0 |
eth_getBlockByNumber | ✅ | v0 | |
eth_getBlockTransactionCountByHash | ⌛ | v2 | |
eth_getBlockTransactionCountByNumber | ⌛ | v2 | |
eth_getUncleCountByBlockHash | ⌛ | v2 | |
eth_getUncleCountByBlockNumber | ⌛ | v2 | |
Chain/Network | eth_chainId | ➡️ | |
eth_syncing | ⌛ | v1 | |
eth_coinbase | ⌛ | v2 | |
eth_accounts | ➡️ | ||
eth_blockNumber | ➡️ | ||
Call and Estimate | eth_call | ✅ | v0 |
eth_estimateGas | ✅ | v0 | |
eth_createAccessList | ⌛ | v2 | |
eth_gasPrice | ⌛ | v1 | |
eth_maxPriorityFeePerGas | ⌛ | v1 | |
eth_feeHistory | ⌛ | v2 | |
Filters | eth_newFilter | ⌛ | v2 |
eth_newBlockFilter | ⌛ | v2 | |
eth_newPendingTransactionFilter | ⌛ | v2 | |
eth_uninstallFilter | ⌛ | v2 | |
eth_getFilterChanges | ⌛ | v2 | |
eth_getFilterLogs | ⌛ | v2 | |
eth_getLogs | ⌛ | v1 | |
Mining | eth_mining | ➡️ | |
eth_hashrate | ➡️ | ||
eth_getWork | ➡️ | ||
eth_submitWork | ➡️ | ||
eth_submitHashrate | ➡️ | ||
Signing | eth_sign | ➡️ | |
eth_signTransaction | ➡️ | ||
State | eth_getBalance | ✅ | v0 |
eth_getStorageAt | ⌛ | v1 | |
eth_getTransactionCount | ⌛ | v2 | |
eth_getCode | ✅ | v0 | |
eth_getProof | ❇️ | v0 | |
Transactions | eth_sendTransaction | ➡️ | |
eth_sendRawTransaction | ➡️ | ||
eth_getTransactionByHash | ⌛ | v2 | |
eth_getTransactionByBlockHashAndIndex | ⌛ | v2 | |
eth_getTransactionByBlockNumberAndIndex | ⌛ | v2 | |
eth_getTransactionReceipt | ⌛ | v2 | |
Events | eth_subscribe | ❇️ | v0 |
eth_unsubscribe | ❇️ | v0 |
- Currently does not support batch requests.
- To use this prover the ethereum provider must support the
eth_getProof
method. Unfortunately, Infura does not currently support this endpoint. As an alternative, we suggest using Alchemy.
You will need to go over the specification. You will also need to have a basic understanding of lightclient.
- Follow the installation guide to install Lodestar.
- Quickly try out the whole stack by starting a local testnet.
Read our contributors document, submit an issue or talk to us on our discord!
Apache-2.0 ChainSafe Systems