Skip to content

Commit

Permalink
Merge branch 'main' into feat/horizontal-scaling
Browse files Browse the repository at this point in the history
  • Loading branch information
mouseless0x committed Feb 25, 2025
2 parents e6616ad + 141b555 commit 0291737
Show file tree
Hide file tree
Showing 37 changed files with 1,018 additions and 1,276 deletions.
56 changes: 17 additions & 39 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 5 additions & 10 deletions src/cli/setupServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,10 @@ import {
Mempool,
Monitor,
NullReputationManager,
ReputationManager
ReputationManager,
NonceQueuer
} from "@alto/mempool"
import {
NonceQueuer,
RpcHandler,
SafeValidator,
Server,
UnsafeValidator
} from "@alto/rpc"
import { RpcHandler, SafeValidator, Server, UnsafeValidator } from "@alto/rpc"
import type { InterfaceValidator } from "@alto/types"
import type { Metrics } from "@alto/utils"
import type { Registry } from "prom-client"
Expand Down Expand Up @@ -220,8 +215,8 @@ const getRpcHandler = ({
executorManager,
reputationManager,
metrics,
gasPriceManager,
eventManager
eventManager,
gasPriceManager
})
}

Expand Down
1 change: 1 addition & 0 deletions src/mempool/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./mempool"
export * from "./monitoring"
export * from "./reputationManager"
export * from "./nonceQueuer"
File renamed without changes.
13 changes: 8 additions & 5 deletions src/mempool/reputationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from "@alto/utils"
import { type Address, getAddress, getContract } from "viem"
import type { AltoConfig } from "../createConfig"
import { ReadonlyDeep } from "type-fest"

export interface InterfaceReputationManager {
checkReputation(
Expand Down Expand Up @@ -49,11 +50,13 @@ export interface InterfaceReputationManager {
): void
setReputation(
entryPoint: Address,
args: {
address: Address
opsSeen: bigint
opsIncluded: bigint
}[]
args: ReadonlyDeep<
{
address: Address
opsSeen: bigint
opsIncluded: bigint
}[]
>
): void
dumpReputations(entryPoint: Address): ReputationEntry[]
getStakeStatus(
Expand Down
1 change: 1 addition & 0 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"pino-http": "^8.4.0",
"pino-pretty": "^10.0.0",
"prom-client": "^14.2.0",
"type-fest": "^4.35.0",
"viem": "^2.19.0",
"yargs": "^17.7.1",
"zod": "^3.21.4",
Expand Down
62 changes: 62 additions & 0 deletions src/rpc/createMethodHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { z } from "zod"
import type { RpcHandler } from "./rpcHandler"
import type { ApiVersion } from "@alto/types"
import { ReadonlyDeep } from "type-fest"

export type MethodHandler<T extends z.ZodType = z.ZodType> = {
schema: T
method: z.infer<T>["method"]
handler: (args: {
rpcHandler: RpcHandler
params: ReadonlyDeep<z.infer<T>["params"]>
apiVersion: ApiVersion
}) => Promise<z.infer<T>["result"]> | z.infer<T>["result"]
}

const freezeDeep = <T>(obj: T): T => {
if (Array.isArray(obj)) {
return Object.freeze(obj.map(freezeDeep)) as T
}
if (obj !== null && typeof obj === "object") {
const frozenObj = Object.create(Object.getPrototypeOf(obj))
for (const prop of Object.getOwnPropertyNames(obj)) {
const value = obj[prop as keyof T]
frozenObj[prop] = freezeDeep(value)
}
return Object.freeze(frozenObj) as T
}
return obj as T
}

export const createMethodHandler = <T extends z.ZodType>(methodConfig: {
schema: T
method: z.infer<T>["method"]
handler: (args: {
rpcHandler: RpcHandler
params: ReadonlyDeep<z.infer<T>["params"]>
apiVersion: ApiVersion
}) => Promise<z.infer<T>["result"]> | z.infer<T>["result"]
}): {
schema: T
method: z.infer<T>["method"]
handler: (args: {
rpcHandler: RpcHandler
params: ReadonlyDeep<z.infer<T>["params"]>
apiVersion: ApiVersion
}) => Promise<z.infer<T>["result"]> | z.infer<T>["result"]
} => {
return {
schema: methodConfig.schema,
method: methodConfig.method,
handler: (args) => {
const frozenParams = freezeDeep(args.params)

// Call the handler with frozen params
return methodConfig.handler({
rpcHandler: args.rpcHandler,
params: frozenParams,
apiVersion: args.apiVersion
})
}
}
}
49 changes: 35 additions & 14 deletions src/rpc/estimation/gasEstimationHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,47 @@ import type { UserOperation } from "@alto/types"
import type { StateOverrides, UserOperationV07 } from "@alto/types"
import { deepHexlify, isVersion06 } from "@alto/utils"
import type { Hex } from "viem"
import { toHex, type Address, parseEther } from "viem"
import {
toHex,
type Address,
parseEther,
keccak256,
encodeAbiParameters
} from "viem"
import { GasEstimatorV06 } from "./gasEstimationsV06"
import { GasEstimatorV07 } from "./gasEstimationsV07"
import type { SimulateHandleOpResult } from "./types"
import type { AltoConfig } from "../../createConfig"

function getStateOverrides({
addSenderBalanceOverride,
addSenderDepositOverride,
userOperation,
entryPoint,
stateOverrides = {}
}: {
addSenderBalanceOverride: boolean
addSenderDepositOverride: boolean
stateOverrides: StateOverrides
entryPoint: Address
userOperation: UserOperation
}) {
const result: StateOverrides = { ...stateOverrides }
const balanceOverride = parseEther("1000000")

if (addSenderBalanceOverride) {
result[userOperation.sender] = {
...deepHexlify(stateOverrides?.[userOperation.sender] || {}),
balance: toHex(parseEther("1000000"))
if (addSenderDepositOverride) {
// Add deposit override.
const depositsMappingSlot = keccak256(
encodeAbiParameters(
[{ type: "address" }, { type: "uint256" }],
[userOperation.sender, 0n]
)
)

result[entryPoint] = {
...deepHexlify(stateOverrides?.[entryPoint] || {}),
stateDiff: {
...(stateOverrides?.[entryPoint]?.stateDiff || {}),
[depositsMappingSlot]: toHex(balanceOverride, { size: 32 })
}
}
}

Expand All @@ -42,17 +62,17 @@ export class GasEstimationHandler {
simulateHandleOp({
userOperation,
queuedUserOperations,
addSenderBalanceOverride,
balanceOverrideEnabled,
addSenderDepositOverride,
stateOverrideEnabled,
entryPoint,
targetAddress,
targetCallData,
stateOverrides = {}
}: {
userOperation: UserOperation
queuedUserOperations: UserOperation[]
addSenderBalanceOverride: boolean
balanceOverrideEnabled: boolean
addSenderDepositOverride: boolean
stateOverrideEnabled: boolean
entryPoint: Address
targetAddress: Address
targetCallData: Hex
Expand All @@ -61,11 +81,12 @@ export class GasEstimationHandler {
let finalStateOverride = undefined

// Add balance override only for v0.6 userOperations (so that prefund check during simulation passes).
if (balanceOverrideEnabled && isVersion06(userOperation)) {
if (stateOverrideEnabled && isVersion06(userOperation)) {
finalStateOverride = getStateOverrides({
userOperation,
addSenderBalanceOverride,
stateOverrides
addSenderDepositOverride,
stateOverrides,
entryPoint
})
}

Expand Down
1 change: 0 additions & 1 deletion src/rpc/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from "./rpcHandler"
export * from "./server"
export * from "./validation"
export * from "./nonceQueuer"
13 changes: 13 additions & 0 deletions src/rpc/methods/debug_bundler_clearReputation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createMethodHandler } from "../createMethodHandler"
import { debugClearReputationSchema } from "@alto/types"

export const debugClearReputationHandler = createMethodHandler({
schema: debugClearReputationSchema,
method: "debug_bundler_clearReputation",
handler: async ({ rpcHandler }) => {
rpcHandler.ensureDebugEndpointsAreEnabled("debug_bundler_clearReputation")
rpcHandler.reputationManager.clear()

return "ok" as const
}
})
Loading

0 comments on commit 0291737

Please sign in to comment.