Skip to content

Commit

Permalink
feat: serve one chain only (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xSulpiride authored Jan 16, 2024
1 parent a16360c commit e9df4ca
Show file tree
Hide file tree
Showing 45 changed files with 438 additions and 597 deletions.
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

0 comments on commit e9df4ca

Please sign in to comment.