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

fix: bundler relies on eth_getLogs with indefinite range #855

Merged
merged 6 commits into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
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: 0 additions & 1 deletion packages/boba/account-abstraction/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
"@gnosis.pm/safe-contracts": "^1.3.0",
"@nomiclabs/hardhat-etherscan": "^3.1.0",
"@openzeppelin/contracts": "^4.2.0",
"@openzeppelin/contracts-upgradeable": "4.3.2",
"@thehubbleproject/bls": "^0.5.1",
"@typechain/hardhat": "^6.1.2",
"@types/mocha": "^9.0.0",
Expand Down
1 change: 0 additions & 1 deletion packages/boba/bundler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
},
"dependencies": {
"@openzeppelin/contracts": "^4.2.0",
"@openzeppelin/contracts-upgradeable": "4.3.2",
"@boba/accountabstraction": "^1.0.0",
"@boba/bundler_utils": "^0.2.3",
"@bobanetwork/bundler_sdk": "*",
Expand Down
6 changes: 6 additions & 0 deletions packages/boba/bundler/src/BundlerConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export interface BundlerConfig {
addressManager: string
l1NodeWeb3Url: string
enableDebugMethods: boolean
l2Offset?: number
logsChunkSize?: number
}

// TODO: implement merging config (args -> config.js -> default) and runtime shape validation
Expand All @@ -46,6 +48,8 @@ export const BundlerConfigShape = {
addressManager: ow.string,
l1NodeWeb3Url: ow.string,
enableDebugMethods: ow.boolean,
l2Offset: ow.optional.number,
logsChunkSize: ow.optional.number,
}

// TODO: consider if we want any default fields at all
Expand All @@ -60,4 +64,6 @@ export const bundlerConfigDefault: Partial<BundlerConfig> = {
autoBundleInterval: 1,
autoBundleMempoolSize: 1,
enableDebugMethods: false,
l2Offset: 0,
logsChunkSize: 5000,
}
4 changes: 2 additions & 2 deletions packages/boba/bundler/src/BundlerServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,10 @@ export class BundlerServer {
)
break
case 'eth_getUserOperationReceipt':
result = await this.methodHandler.getUserOperationReceipt(params[0])
result = await this.methodHandler.getUserOperationReceipt(params[0], params[1])
break
case 'eth_getUserOperationByHash':
result = await this.methodHandler.getUserOperationByHash(params[0])
result = await this.methodHandler.getUserOperationByHash(params[0], params[1])
InoMurko marked this conversation as resolved.
Show resolved Hide resolved
break
case 'web3_clientVersion':
result = this.methodHandler.clientVersion()
Expand Down
17 changes: 11 additions & 6 deletions packages/boba/bundler/src/UserOpMethodHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,11 +227,14 @@ export class UserOpMethodHandler {
}

async _getUserOperationEvent(
userOpHash: string
userOpHash: string,
opts?: any
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add a type for this?

): Promise<UserOperationEventEvent> {
// TODO: eth_getLogs is throttled. must be acceptable for finding a UserOperation by hash
const event = await this.entryPoint.queryFilter(
this.entryPoint.filters.UserOperationEvent(userOpHash)
this.entryPoint.filters.UserOperationEvent(userOpHash),
opts?.fromBlock,
opts?.toBlock
)
return event[0]
}
Expand Down Expand Up @@ -269,14 +272,15 @@ export class UserOpMethodHandler {
}

async getUserOperationByHash(
userOpHash: string
userOpHash: string,
opts?: any
): Promise<UserOperationByHashResponse | null> {
requireCond(
userOpHash?.toString()?.match(HEX_REGEX) != null,
'Missing/invalid userOpHash',
-32601
)
const event = await this._getUserOperationEvent(userOpHash)
const event = await this._getUserOperationEvent(userOpHash, opts)
if (event == null) {
return null
}
Expand Down Expand Up @@ -334,14 +338,15 @@ export class UserOpMethodHandler {
}

async getUserOperationReceipt(
userOpHash: string
userOpHash: string,
opts?: any
): Promise<UserOperationReceipt | null> {
requireCond(
userOpHash?.toString()?.match(HEX_REGEX) != null,
'Missing/invalid userOpHash',
-32601
)
const event = await this._getUserOperationEvent(userOpHash)
const event = await this._getUserOperationEvent(userOpHash, opts)
if (event == null) {
return null
}
Expand Down
32 changes: 29 additions & 3 deletions packages/boba/bundler/src/modules/EventsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ReputationManager } from './ReputationManager'
import { EntryPoint } from '@boba/accountabstraction'
import Debug from 'debug'
import { TypedEvent } from '@boba/accountabstraction/dist/types/common'
import { JsonRpcProvider } from '@ethersproject/providers'
import { MempoolManager } from './MempoolManager'

const debug = Debug('aa.events')
Expand All @@ -15,13 +16,21 @@ const debug = Debug('aa.events')
* listen to events. trigger ReputationManager's Included
*/
export class EventsManager {
provider: JsonRpcProvider
lastBlock = 0
chunkSize = 5000

constructor(
readonly entryPoint: EntryPoint,
readonly mempoolManager: MempoolManager,
readonly reputationManager: ReputationManager
) {}
readonly reputationManager: ReputationManager,
readonly l2Offset: number,
readonly logsChunkSize: number
) {
this.provider = entryPoint.provider as JsonRpcProvider
this.lastBlock = l2Offset
this.chunkSize = logsChunkSize > 0 ? logsChunkSize : 1
}

/**
* automatically listen to all UserOperationEvent events
Expand All @@ -40,9 +49,26 @@ export class EventsManager {
* process all new events since last run
*/
async handlePastEvents(): Promise<void> {
let startBlock = this.lastBlock
const currentBlock = await this.provider.getBlockNumber()
if (currentBlock > startBlock + this.chunkSize) {
while (startBlock + this.chunkSize < currentBlock) {
const events = await this.entryPoint.queryFilter(
{ address: this.entryPoint.address },
startBlock,
startBlock + (this.chunkSize - 1)
)
for (const ev of events) {
this.handleEvent(ev)
}
startBlock = startBlock + this.chunkSize
}
this.lastBlock = startBlock
}
const events = await this.entryPoint.queryFilter(
{ address: this.entryPoint.address },
this.lastBlock
this.lastBlock,
currentBlock
)
for (const ev of events) {
this.handleEvent(ev)
Expand Down
2 changes: 1 addition & 1 deletion packages/boba/bundler/src/modules/initServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function initServer (config: BundlerConfig, signer: Signer): [ExecutionMa
const reputationManager = new ReputationManager(BundlerReputationParams, parseEther(config.minStake), config.minUnstakeDelay)
const mempoolManager = new MempoolManager(reputationManager)
const validationManager = new ValidationManager(entryPoint, reputationManager, config.unsafe, entryPointWrapper)
const eventsManager = new EventsManager(entryPoint, mempoolManager, reputationManager)
const eventsManager = new EventsManager(entryPoint, mempoolManager, reputationManager, config.l2Offset, config.logsChunkSize)
const bundleManager = new BundleManager(entryPoint, eventsManager, mempoolManager, validationManager, reputationManager,
config.beneficiary, parseEther(config.minBalance), config.maxBundleGas, config.conditionalRpc, false, entryPointWrapper)
const executionManager = new ExecutionManager(reputationManager, mempoolManager, bundleManager, validationManager)
Expand Down
2 changes: 2 additions & 0 deletions packages/boba/bundler/src/runBundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ export async function runBundler(
.option('--l1NodeWeb3Url <string>', 'L1 network url for Address Manager', '')
.option('--maxBundleGas <number>', 'Max Bundle Gas available to use', '5000000')
.option('--enableDebugMethods', 'debug_* methods available', false)
.option('--l2Offset <number>', 'l2 Offset to start from')
.option('--logsChunkSize <number>', 'eth_getLogs range supported by network')

const programOpts = program.parse(argv).opts()
showStackTraces = programOpts.showStackTraces
Expand Down