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: Websocket & mempool archieve & userop status method #175

Merged
merged 12 commits into from
Apr 29, 2024
4 changes: 2 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ module.exports = {
},
{
files: ["**/test/**/*.test.ts"],
plugins: ["mocha", "chai-expect"],
extends: ["plugin:mocha/recommended", "plugin:chai-expect/recommended"],
plugins: ["mocha"],
extends: ["plugin:mocha/recommended"],
rules: {
// We observed that having multiple top level "describe" save valuable indentation
// https://github.com/lo1tuma/eslint-plugin-mocha/blob/master/docs/rules/max-top-level-suites.md
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,13 @@ For a video tutorial on the above, you can [view this here.](https://www.youtube
- [x] Unsafe mode - bypass opcode & stake validation
- [x] Redirect RPC - Redirect ETH rpc calls to the underlying execution client. This is needed if you use UserOp.js
- [x] P2P - Exchange of UserOps between all the nodes in the network. Heavily inspired by the Lodestar's implementation of p2p (https://github.com/ChainSafe/lodestar/)
- [x] Websockets event - to listen to pending and submitted userops

### ⚡️ CLI Options
- `--unsafeMode` - enables unsafeMode
- `--redirectRpc` - enables redirecting eth rpc calls
- `--executor.bundlingMode manual|auto` - sets bundling mode to `manual` or `auto` on start. Default value is `auto`
- `--websocket true|false` - enables / disables websocket server. Default is `true`

## 🔑 Relayer Configuration

Expand Down Expand Up @@ -124,6 +126,7 @@ For a video tutorial on the above, you can [view this here.](https://www.youtube
"skipBundleValidation": false, # # optional, skips bundle validation
"userOpGasLimit": 25000000, # optional, gas limit of a userop
"bundleGasLimit": 25000000, # optional, gas limit of a bundle
"archieveDuration": 5184000 # optional, keeps submitted, reverted and cancelled userops in the mempool for this many seconds
}
```
## 💬 Contact
Expand Down
110 changes: 110 additions & 0 deletions docs/eth_subscribe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
## eth_subscribe

Creates a new subscription for desired events. Sends data as soon as it occurs.

### Event Types

- pendingUserOps - user ops validated and put in the mempool
- submittedUserOps - user ops successfully submitted on chain

### Examples:

### Request

```json
{
"method": "eth_subscribe",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we rename this as skandha_susbcribe?

This is skandha specific endpoints, so let's prefix it with skandha_

"params": [
"pendingUserOps"
],
"id": 1,
"jsonrpc": "2.0"
}
```

#### Response

```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0xcf47424b5f492abfaa97ca5d4aed1f1d"
}
```


#### Event

```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0xadbb9a1155801acd7c5ed0f8c5ade57a",
"result": {
"userOp": {
"sender": "0xb582979C2136189475326c648732F76677B16B98",
"nonce": "0x3",
"initCode": "0x",
"callData": "0x47e1da2a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009fd4f6088f2025427ab1e89257a44747081ed590000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000009184e72a000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit": "0xb957",
"verificationGasLimit": "0x9b32",
"maxFeePerGas": "0x59682f1e",
"maxPriorityFeePerGas": "0x59682f00",
"paymasterAndData": "0x",
"preVerificationGas": "0xae70",
"signature": "0xa6caf148ca0cbe4202240f26a8b26981fc871cf0e1ce821fab57dc33e6769b192cb569dacab5c721e9d8da7f019fb3d50841d0d7a938a084c0b03554bee4594c1b"
},
"userOpHash": "0x79930ad0a2cd260b271df23cdbef6403fb428be9273b3c41eaa5836fc44d9b70",
"entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"prefund": "0xb3da24f0102e",
"submittedTime": "0x18f0cb7a7a1"
}
}
}
```

---

### Request

```json
{
"method": "eth_subscribe",
"params": [
"submittedUserOps"
],
"id": 1,
"jsonrpc": "2.0"
}
```

#### Event

```json
{
"jsonrpc": "2.0",
"method": "eth_subscription",
"params": {
"subscription": "0xcf47424b5f492abfaa97ca5d4aed1f1d",
"result": {
"userOp": {
"sender": "0xb582979C2136189475326c648732F76677B16B98",
"nonce": "0x3",
"initCode": "0x",
"callData": "0x47e1da2a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009fd4f6088f2025427ab1e89257a44747081ed590000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000009184e72a000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit": "0xb957",
"verificationGasLimit": "0x9b32",
"maxFeePerGas": "0x59682f1e",
"maxPriorityFeePerGas": "0x59682f00",
"paymasterAndData": "0x",
"preVerificationGas": "0xae70",
"signature": "0xa6caf148ca0cbe4202240f26a8b26981fc871cf0e1ce821fab57dc33e6769b192cb569dacab5c721e9d8da7f019fb3d50841d0d7a938a084c0b03554bee4594c1b"
},
"userOpHash": "0x79930ad0a2cd260b271df23cdbef6403fb428be9273b3c41eaa5836fc44d9b70",
"entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"transaction": "0xbe69980ecd9fede48c7c6e489fff68b36e2da4a9f3b9e8facdbc77ba5fa32463"
}
}
}
```
136 changes: 68 additions & 68 deletions P2P.md → docs/p2p.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,68 @@
# How to test p2p
### Run geth-dev
`cd test`
`docker-compose up -d geth-dev`
### Deploy EP and Factory from EF account-abstraction repo
1. clone the https://github.com/eth-infinitism/account-abstraction repo `git clone https://github.com/eth-infinitism/account-abstraction.git`
2. run `yarn deploy --network localhost`
We should have deployments in the following addresses.
- Entrypoint addr: 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
- SimpleAccountFactory addr: 0x9406Cc6185a346906296840746125a0E44976454
- SimpleAccount addr: 0xbba97eC4fFF328d485382DfD5A9bf9653c6018Af // sample address, deployed address could be different
### Top up account
go to docker console
```
> geth attach http://127.0.0.1:8545
```
Inside geth terminal
```
> eth.sendTransaction({ from: eth.accounts[0], to: "0xbba97eC4fFF328d485382DfD5A9bf9653c6018Af", value: 1000000000000000000 })
```
### Modify the
### Generate userop from erc4337 examples
`yarn simpleAccount transfer --to 0x9406Cc6185a346906296840746125a0E44976454 --amount 0`
Example:
```
{
"sender":"0xbba97eC4fFF328d485382DfD5A9bf9653c6018Af",
"nonce":"0x0",
"initCode":"0x9406cc6185a346906296840746125a0e449764545fbfb9cf00000000000000000000000005449b55b91e9ebdd099ed584cb6357234f2ab3b0000000000000000000000000000000000000000000000000000000000000000",
"callData":"0xb61d27f60000000000000000000000009406cc6185a346906296840746125a0e4497645400000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit":"0x5568",
"verificationGasLimit":"0x5ea0c",
"preVerificationGas":"0xb820",
"maxFeePerGas":"0x4ac312de",
"maxPriorityFeePerGas":"0xed2ba9a",
"paymasterAndData":"0x",
"signature":"0xecdc2665d72b04bf133e39a3849d3eedc4913550d17f839eda442db2ea175e906750b860ba0e3ac1d3de068c2e16183a1e430f77fae2ec94e44298083576033e1c"
}
```
### Run the bootnode
```
./skandha node --redirectRpc --executor.bundlingMode manual
```
### Run a regular node
```
./skandha node --redirectRpc --executor.bundlingMode manual --dataDir ./db --api.port 14338 --p2p.port 4338 --p2p.enrPort 4338 --p2p.bootEnrs [enr]
```
### Run the second regular node
```
./skandha node --redirectRpc --executor.bundlingMode manual --dataDir ./db2 --api.port 14339 --p2p.port 4339 --p2p.enrPort 4339 --p2p.bootEnrs [enr]
```
## How to test p2p

### Run geth-dev

`cd test`
`docker-compose up -d geth-dev`

### Deploy EP and Factory from EF account-abstraction repo

1. clone the https://github.com/eth-infinitism/account-abstraction repo `git clone https://github.com/eth-infinitism/account-abstraction.git`
2. run `yarn deploy --network localhost`

We should have deployments in the following addresses.
- Entrypoint addr: 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789
- SimpleAccountFactory addr: 0x9406Cc6185a346906296840746125a0E44976454
- SimpleAccount addr: 0xbba97eC4fFF328d485382DfD5A9bf9653c6018Af // sample address, deployed address could be different

### Top up account

go to docker console
```
> geth attach http://127.0.0.1:8545
```
Inside geth terminal
```
> eth.sendTransaction({ from: eth.accounts[0], to: "0xbba97eC4fFF328d485382DfD5A9bf9653c6018Af", value: 1000000000000000000 })
```

### Modify the

### Generate userop from erc4337 examples

`yarn simpleAccount transfer --to 0x9406Cc6185a346906296840746125a0E44976454 --amount 0`

Example:
```
{
"sender":"0xbba97eC4fFF328d485382DfD5A9bf9653c6018Af",
"nonce":"0x0",
"initCode":"0x9406cc6185a346906296840746125a0e449764545fbfb9cf00000000000000000000000005449b55b91e9ebdd099ed584cb6357234f2ab3b0000000000000000000000000000000000000000000000000000000000000000",
"callData":"0xb61d27f60000000000000000000000009406cc6185a346906296840746125a0e4497645400000000000000000000000000000000000000000000000000000000000f424000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit":"0x5568",
"verificationGasLimit":"0x5ea0c",
"preVerificationGas":"0xb820",
"maxFeePerGas":"0x4ac312de",
"maxPriorityFeePerGas":"0xed2ba9a",
"paymasterAndData":"0x",
"signature":"0xecdc2665d72b04bf133e39a3849d3eedc4913550d17f839eda442db2ea175e906750b860ba0e3ac1d3de068c2e16183a1e430f77fae2ec94e44298083576033e1c"
}
```

### Run the bootnode

```
./skandha node --redirectRpc --executor.bundlingMode manual
```

### Run a regular node

```
./skandha node --redirectRpc --executor.bundlingMode manual --dataDir ./db --api.port 14338 --p2p.port 4338 --p2p.enrPort 4338 --p2p.bootEnrs [enr]
```

### Run the second regular node

```
./skandha node --redirectRpc --executor.bundlingMode manual --dataDir ./db2 --api.port 14339 --p2p.port 4339 --p2p.enrPort 4339 --p2p.bootEnrs [enr]
```
99 changes: 99 additions & 0 deletions docs/skandha_userOperationStatus.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
## skandha_userOperationStatus

Returns the status of a userop by its hash

### Example

#### Request

```json
{
"id": 3,
"method": "skandha_userOperationStatus",
"params": [
"0x63e222d108878e7f7440036bce49aeb83007708f067ec8d01153961e97fe1c53"
],
"jsonrpc": "2.0"
}
```


#### Response

```json
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"userOp": {
"sender": "0xb582979C2136189475326c648732F76677B16B98",
"nonce": "0x4",
"initCode": "0x",
"callData": "0x47e1da2a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009fd4f6088f2025427ab1e89257a44747081ed590000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000009184e72a000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit": "0xb957",
"verificationGasLimit": "0x9b32",
"maxFeePerGas": "0x1cbbd765c",
"maxPriorityFeePerGas": "0x59682f00",
"paymasterAndData": "0x",
"preVerificationGas": "0xae70",
"signature": "0xb4ff57fa73e803b4e20b9016af228d30fd1563e71ce8313724230c5883560c873cc5785264e172d11ded202b4f4fc7eaaf88dee57965546f1747ebb5054178d51b"
},
"entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"status": "New"
}
}
```

#### Response (after some time)

```json
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"userOp": {
"sender": "0xb582979C2136189475326c648732F76677B16B98",
"nonce": "0x4",
"initCode": "0x",
"callData": "0x47e1da2a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009fd4f6088f2025427ab1e89257a44747081ed590000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000009184e72a000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit": "0xb957",
"verificationGasLimit": "0x9b32",
"maxFeePerGas": "0x1cbbd765c",
"maxPriorityFeePerGas": "0x59682f00",
"paymasterAndData": "0x",
"preVerificationGas": "0xae70",
"signature": "0xb4ff57fa73e803b4e20b9016af228d30fd1563e71ce8313724230c5883560c873cc5785264e172d11ded202b4f4fc7eaaf88dee57965546f1747ebb5054178d51b"
},
"entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"status": "Submitted",
"transaction": "0x0d6ea9c97aa783894dad00d31fc80f7615f49b3a5a8a3dca556d7ca595dcc4e1"
}
}
```

#### Response (after appearing on chain)

```json
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"userOp": {
"sender": "0xb582979C2136189475326c648732F76677B16B98",
"nonce": "0x4",
"initCode": "0x",
"callData": "0x47e1da2a000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009fd4f6088f2025427ab1e89257a44747081ed590000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000009184e72a000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000",
"callGasLimit": "0xb957",
"verificationGasLimit": "0x9b32",
"maxFeePerGas": "0x1cbbd765c",
"maxPriorityFeePerGas": "0x59682f00",
"paymasterAndData": "0x",
"preVerificationGas": "0xae70",
"signature": "0xb4ff57fa73e803b4e20b9016af228d30fd1563e71ce8313724230c5883560c873cc5785264e172d11ded202b4f4fc7eaaf88dee57965546f1747ebb5054178d51b"
},
"entryPoint": "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789",
"status": "OnChain",
"transaction": "0x0d6ea9c97aa783894dad00d31fc80f7615f49b3a5a8a3dca556d7ca595dcc4e1"
}
}
```
Loading
Loading