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

feat: serve one chain only #140

Merged
merged 2 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,4 @@ scripts/
packages/*/lib
skandha
db
packages/cli/.git-data.json
97 changes: 44 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ Or follow the steps below:
4. edit `config.json`
5. (optional) run local geth-node from `test/geth-dev`
6. run `./skandha`
7. Skandha will run for all chains available in `config.json`
8. Networks will be available at `http://localhost:14337/{chainId}/` (e.g. for dev `http://localhost:14337/1337/`)
7. The bundler will be available on `http://localhost:14337/rpc/`

## 🐳 How to run (a Docker image)

Expand All @@ -68,64 +67,56 @@ Or follow the steps below:
#### Simplest config.json
```yaml
{
"networks": {
"mumbai": {
"entryPoints": [
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
],
"relayer": "0x{RELAYER-PRIVATE-KEY}",
"beneficiary": "0x{BENEFICIARY-ADDRESS}",
"rpcEndpoint": "https://polygon-mumbai.blockpi.network/v1/rpc/public"
}
}
"entryPoints": [
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
],
"relayer": "0x{RELAYER-PRIVATE-KEY}",
"beneficiary": "0x{BENEFICIARY-ADDRESS}",
"rpcEndpoint": "https://polygon-mumbai.blockpi.network/v1/rpc/public"
}
```

#### config.json with a default value of each config parameter

```yaml
{
"networks": {
"dev": { # network Id (check packages/params/src/networks/<network>.ts)
"entryPoints": [ # supported entry points
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
],
"relayers": [
"0x0101010101010101010101010101010101010101010101010101010101010101",
"test test test test test test test test test test test junk"
], # relayers private keys, can access from here or via environment variables (SKANDHA_MUMBAI_RELAYERS | SKANDHA_DEV_RELAYERS | etc.)
"beneficiary": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", # optional, fee collector, avaiable via env var (SKANDHA_MUMBAI_BENEFICIARY | etc) - if not set, relayer will be used
"rpcEndpoint": "http://localhost:8545", # rpc provider, also available via env variable (SKANDHA_MUMBAI_RPC | etc)
"minInclusionDenominator": 10, # optional, see EIP-4337
"throttlingSlack": 10, # optional, see EIP-4337
"banSlack": 50 # optional, see EIP-4337
"minStake": 10000000000, # optional, min stake of an entity (in wei)
"minUnstakeDelay": 0, # optional, min unstake delay of an entity
"minSignerBalance": 1, # optional, default is 0.1 ETH. If the relayer's balance drops lower than this, it will be selected as a fee collector
"multicall": "0xcA11bde05977b3631167028862bE2a173976CA11", # optional, multicall3 contract (see https://github.com/mds1/multicall#multicall3-contract-addresses)
"estimationStaticBuffer": 21000, # optional,adds certain amount of gas to callGasLimit on estimation
"validationGasLimit": 10e6, # optional,gas limit during simulateHandleOps and simulateValidation calls
"receiptLookupRange": 1024, # optional,limits the block range of getUserOperationByHash and getUserOperationReceipt
"etherscanApiKey": "", # optional,etherscan api is used to fetch gas prices
"conditionalTransactions": false, # optional,enable conditional transactions
"rpcEndpointSubmit": "", # optional,rpc endpoint that is used only during submission of a bundle
"gasPriceMarkup": 0, # optional,adds % markup on reported gas price via skandha_getGasPrice, 10000 = 100.00%, 500 = 5%
"enforceGasPrice": false, # optional,do not bundle userops with low gas prices
"enforceGasPriceThreshold": 1000, # optional,gas price threshold in bps. If set to 500, userops' gas price is allowed to be 5% lower than the network's gas price
"eip2930": false, # optional, enables eip-2930
"useropsTTL": 300, # optional, Userops time to live (in seconds)
"whitelistedEntities": { # optional, Entities that bypass stake and opcode validation (array of addresses)
"factory": [],
"paymaster": [],
"account": []
},
"bundleGasLimitMarkup": 25000, # optional, adds some amount of additional gas to a bundle tx
"relayingMode": "classic"; # optional, allows to switch to Flashbots Builder api if set to "flashbots", see packages/executor/src/interfaces.ts for more
"bundleInterval": 10000, # bundle creation interval
"bundleSize": 4, # optional, max size of a bundle, 4 userops by default
"pvgMarkup": 0 # optional, adds some gas on top of estimated PVG
}
}
"entryPoints": [ # supported entry points
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
],
"relayers": [
"0x0101010101010101010101010101010101010101010101010101010101010101",
"test test test test test test test test test test test junk"
], # relayers private keys, can access from here or via environment variables (SKANDHA_MUMBAI_RELAYERS | SKANDHA_DEV_RELAYERS | etc.)
"beneficiary": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", # optional, fee collector, avaiable via env var (SKANDHA_MUMBAI_BENEFICIARY | etc) - if not set, relayer will be used
"rpcEndpoint": "http://localhost:8545", # rpc provider, also available via env variable (SKANDHA_MUMBAI_RPC | etc)
"minInclusionDenominator": 10, # optional, see EIP-4337
"throttlingSlack": 10, # optional, see EIP-4337
"banSlack": 50 # optional, see EIP-4337
"minStake": 10000000000, # optional, min stake of an entity (in wei)
"minUnstakeDelay": 0, # optional, min unstake delay of an entity
"minSignerBalance": 1, # optional, default is 0.1 ETH. If the relayer's balance drops lower than this, it will be selected as a fee collector
"multicall": "0xcA11bde05977b3631167028862bE2a173976CA11", # optional, multicall3 contract (see https://github.com/mds1/multicall#multicall3-contract-addresses)
"estimationStaticBuffer": 21000, # optional,adds certain amount of gas to callGasLimit on estimation
"validationGasLimit": 10e6, # optional,gas limit during simulateHandleOps and simulateValidation calls
"receiptLookupRange": 1024, # optional,limits the block range of getUserOperationByHash and getUserOperationReceipt
"etherscanApiKey": "", # optional,etherscan api is used to fetch gas prices
"conditionalTransactions": false, # optional,enable conditional transactions
"rpcEndpointSubmit": "", # optional,rpc endpoint that is used only during submission of a bundle
"gasPriceMarkup": 0, # optional,adds % markup on reported gas price via skandha_getGasPrice, 10000 = 100.00%, 500 = 5%
"enforceGasPrice": false, # optional,do not bundle userops with low gas prices
"enforceGasPriceThreshold": 1000, # optional,gas price threshold in bps. If set to 500, userops' gas price is allowed to be 5% lower than the network's gas price
"eip2930": false, # optional, enables eip-2930
"useropsTTL": 300, # optional, Userops time to live (in seconds)
"whitelistedEntities": { # optional, Entities that bypass stake and opcode validation (array of addresses)
"factory": [],
"paymaster": [],
"account": []
},
"bundleGasLimitMarkup": 25000, # optional, adds some amount of additional gas to a bundle tx
"relayingMode": "classic"; # optional, allows to switch to Flashbots Builder api if set to "flashbots", see packages/executor/src/interfaces.ts for more
"bundleInterval": 10000, # bundle creation interval
"bundleSize": 4, # optional, max size of a bundle, 4 userops by default
"pvgMarkup": 0 # optional, adds some gas on top of estimated PVG
}
```
## 💬 Contact
Expand Down
20 changes: 8 additions & 12 deletions config.json.default
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
{
"networks": {
"dev": {
"entryPoints": [
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
],
"relayers": [
"test test test test test test test test test test test junk",
"0x0101010101010101010101010101010101010101010101010101010101010101"
],
"rpcEndpoint": "http://localhost:8545"
}
}
"entryPoints": [
"0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789"
],
"relayers": [
"test test test test test test test test test test test junk",
"0x0101010101010101010101010101010101010101010101010101010101010101"
],
"rpcEndpoint": "http://localhost:8545"
}
40 changes: 7 additions & 33 deletions packages/api/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { NetworkName } from "types/lib";
import { IDbController } from "types/lib";
import { Executor } from "executor/lib/executor";
import { Executors } from "executor/lib/interfaces";
import { Config } from "executor/lib/config";
import RpcError from "types/lib/api/errors/rpc-error";
import * as RpcErrorCodes from "types/lib/api/errors/rpc-error-codes";
import { FastifyInstance, RouteHandler } from "fastify";
import logger from "./logger";
import {
BundlerRPCMethods,
CustomRPCMethods,
Expand All @@ -18,16 +14,13 @@ import { deepHexlify } from "./utils";
import { SkandhaAPI } from "./modules/skandha";

export interface RpcHandlerOptions {
network: NetworkName;
db: IDbController;
config: Config;
}

export interface EtherspotBundlerOptions {
server: FastifyInstance;
config: Config;
db: IDbController;
executors: Executors;
executor: Executor;
testingMode: boolean;
redirectRpc: boolean;
}
Expand All @@ -43,45 +36,26 @@ export interface RelayerAPI {
export class ApiApp {
private server: FastifyInstance;
private config: Config;
private db: IDbController;
private executors: Executors;
private executor: Executor;

private testingMode = false;
private redirectRpc = false;

constructor(options: EtherspotBundlerOptions) {
this.server = options.server;
this.config = options.config;
this.db = options.db;
this.testingMode = options.testingMode;
this.redirectRpc = options.redirectRpc;
this.executors = options.executors;
this.setupRoutes();
this.executor = options.executor;
this.server.post("/rpc/", this.setupRoutes());
}

private setupRoutes(): void {
if (this.testingMode) {
this.server.post("/rpc/", this.setupRouteFor(1337));
logger.info("Setup route for dev: /rpc/");
return;
}

const networkNames = this.config.supportedNetworks;
for (const [network, chainId] of Object.entries(networkNames)) {
this.server.post(`/${chainId}`, this.setupRouteFor(chainId));
logger.info(`Setup route for ${network}: /${chainId}/`);
}
}

private setupRouteFor(chainId: number): RouteHandler {
const executor = this.executors.get(chainId);
if (!executor) {
throw new Error("Couldn't find executor");
}
private setupRoutes(): RouteHandler {
const { executor } = this;
const ethApi = new EthAPI(executor.eth);
const debugApi = new DebugAPI(executor.debug);
const web3Api = new Web3API(executor.web3);
const redirectApi = new RedirectAPI(executor.networkName, this.config);
const redirectApi = new RedirectAPI(this.config);
const skandhaApi = new SkandhaAPI(executor.eth, executor.skandha);

const handleRpc = async (ip: string, request: any): Promise<any> => {
Expand Down
7 changes: 2 additions & 5 deletions packages/api/src/modules/redirect.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import { providers } from "ethers";
import { Config } from "executor/lib/config";
import { NetworkName } from "types/lib";

export class RedirectAPI {
private provider: providers.JsonRpcProvider;

constructor(private network: NetworkName, private config: Config) {
this.provider = this.config.getNetworkProvider(
this.network
) as providers.JsonRpcProvider;
constructor(private config: Config) {
this.provider = this.config.getNetworkProvider();
}

async redirect(method: string, params: any[]): Promise<any> {
Expand Down
3 changes: 2 additions & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
},
"scripts": {
"clean": "rm -rf lib && rm -f *.tsbuildinfo",
"build": "tsc -p tsconfig.build.json",
"build": "tsc -p tsconfig.build.json && yarn write-git-data",
"write-git-data": "node lib/util/writeGitData.js",
"lint": "eslint --color --ext .ts src/ test/",
"lint:fix": "yarn run lint --fix",
"pretest": "yarn run check-types",
Expand Down
12 changes: 7 additions & 5 deletions packages/cli/src/cmds/node/handler.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/* eslint-disable no-console */
import { Config } from "executor/lib/config";
import { Namespace, getNamespaceByValue, RocksDbController } from "db/lib";
import { ConfigOptions } from "executor/lib/interfaces";
import { NetworkConfig } from "executor/lib/interfaces";
import { BundlerNode, IBundlerNodeOptions, defaultOptions } from "node/lib";
import { initNetworkOptions } from "node/lib";
import logger from "api/lib/logger";
import { ExecutorOptions, ApiOptions, P2POptions } from "types/lib/options";
import { MetricsOptions } from "types/lib/options/metrics";
import { IGlobalArgs } from "../../options";
import { mkdir, readFile } from "../../util";
import { getVersionData } from "../../util/version";
import { initPeerIdAndEnr } from "./initPeerIdAndEnr";

export async function nodeHandler(args: IGlobalArgs): Promise<void> {
Expand All @@ -28,9 +28,9 @@ export async function nodeHandler(args: IGlobalArgs): Promise<void> {

let config: Config;
try {
const configOptions = readFile(params.configFile) as ConfigOptions;
const networkConfig = readFile(params.configFile) as NetworkConfig;
config = await Config.init({
networks: configOptions.networks,
config: networkConfig,
testingMode: params.testingMode,
unsafeMode: params.unsafeMode,
redirectRpc: params.redirectRpc,
Expand All @@ -42,7 +42,7 @@ export async function nodeHandler(args: IGlobalArgs): Promise<void> {
}
logger.info("Config file not found. Proceeding with env vars...");
config = await Config.init({
networks: {},
config: null,
testingMode: params.testingMode,
unsafeMode: params.unsafeMode,
redirectRpc: params.redirectRpc,
Expand All @@ -68,6 +68,7 @@ export async function nodeHandler(args: IGlobalArgs): Promise<void> {
network: initNetworkOptions(enr, params.p2p, params.dataDir),
};

const version = getVersionData();
const node = await BundlerNode.init({
nodeOptions: options,
relayersConfig: config,
Expand All @@ -77,6 +78,7 @@ export async function nodeHandler(args: IGlobalArgs): Promise<void> {
bundlingMode: params.executor.bundlingMode,
peerId,
metricsOptions: params.metrics,
version,
});

await node.start();
Expand Down
Loading