@@ -26,6 +26,7 @@ type Bundler struct {
26
26
stop chan bool
27
27
watch chan bool
28
28
onStop func ()
29
+ maxBatch int
29
30
}
30
31
31
32
// New initializes a new EIP-4337 bundler which can be extended with modules for validating batches and
@@ -41,9 +42,15 @@ func New(mempool *mempool.Mempool, chainID *big.Int, supportedEntryPoints []comm
41
42
stop : make (chan bool ),
42
43
watch : make (chan bool ),
43
44
onStop : func () {},
45
+ maxBatch : 0 ,
44
46
}
45
47
}
46
48
49
+ // SetMaxBatch defines the max number of UserOperations per bundle. The default value is 0 (i.e. unlimited).
50
+ func (i * Bundler ) SetMaxBatch (max int ) {
51
+ i .maxBatch = max
52
+ }
53
+
47
54
// UseLogger defines the logger object used by the Bundler instance based on the go-logr/logr interface.
48
55
func (i * Bundler ) UseLogger (logger logr.Logger ) {
49
56
i .logger = logger .WithName ("bundler" )
@@ -54,65 +61,75 @@ func (i *Bundler) UseModules(handlers ...modules.BatchHandlerFunc) {
54
61
i .batchHandler = modules .ComposeBatchHandlerFunc (handlers ... )
55
62
}
56
63
64
+ // Process will create a batch from the mempool and send it through to the EntryPoint.
65
+ func (i * Bundler ) Process (ep common.Address ) (* modules.BatchHandlerCtx , error ) {
66
+ start := time .Now ()
67
+ l := i .logger .
68
+ WithName ("run" ).
69
+ WithValues ("entrypoint" , ep .String ()).
70
+ WithValues ("chain_id" , i .chainID .String ())
71
+
72
+ batch , err := i .mempool .BundleOps (ep )
73
+ if err != nil {
74
+ l .Error (err , "bundler run error" )
75
+ return nil , err
76
+ }
77
+ if len (batch ) == 0 {
78
+ return nil , nil
79
+ }
80
+ batch = adjustBatchSize (i .maxBatch , batch )
81
+
82
+ ctx := modules .NewBatchHandlerContext (batch , ep , i .chainID )
83
+ if err := i .batchHandler (ctx ); err != nil {
84
+ l .Error (err , "bundler run error" )
85
+ return nil , err
86
+ }
87
+
88
+ rmOps := append ([]* userop.UserOperation {}, ctx .Batch ... )
89
+ rmOps = append (rmOps , ctx .PendingRemoval ... )
90
+ if err := i .mempool .RemoveOps (ep , rmOps ... ); err != nil {
91
+ l .Error (err , "bundler run error" )
92
+ return nil , err
93
+ }
94
+
95
+ bat := []string {}
96
+ for _ , op := range ctx .Batch {
97
+ bat = append (bat , op .GetUserOpHash (ep , i .chainID ).String ())
98
+ }
99
+ l = l .WithValues ("batch_userop_hashes" , bat )
100
+
101
+ drp := []string {}
102
+ for _ , op := range ctx .PendingRemoval {
103
+ drp = append (drp , op .GetUserOpHash (ep , i .chainID ).String ())
104
+ }
105
+ l = l .WithValues ("dropped_userop_hashes" , drp )
106
+
107
+ for k , v := range ctx .Data {
108
+ l = l .WithValues (k , v )
109
+ }
110
+ l = l .WithValues ("duration" , time .Since (start ))
111
+ l .Info ("bundler run ok" )
112
+ return ctx , nil
113
+ }
114
+
57
115
// Run starts a goroutine that will continuously process batches from the mempool.
58
116
func (i * Bundler ) Run () error {
59
117
if i .isRunning {
60
118
return nil
61
119
}
62
120
63
121
go func (i * Bundler ) {
64
- logger := i .logger .WithName ("run" )
65
-
66
122
for {
67
123
select {
68
124
case <- i .stop :
69
125
return
70
126
case <- i .watch :
71
127
for _ , ep := range i .supportedEntryPoints {
72
- start := time .Now ()
73
- l := logger .
74
- WithValues ("entrypoint" , ep .String ()).
75
- WithValues ("chain_id" , i .chainID .String ())
76
-
77
- batch , err := i .mempool .BundleOps (ep )
128
+ _ , err := i .Process (ep )
78
129
if err != nil {
79
- l .Error (err , "bundler run error" )
80
- continue
81
- }
82
- if len (batch ) == 0 {
83
- continue
84
- }
85
-
86
- ctx := modules .NewBatchHandlerContext (batch , ep , i .chainID )
87
- if err := i .batchHandler (ctx ); err != nil {
88
- l .Error (err , "bundler run error" )
89
- continue
90
- }
91
-
92
- rmOps := append ([]* userop.UserOperation {}, ctx .Batch ... )
93
- rmOps = append (rmOps , ctx .PendingRemoval ... )
94
- if err := i .mempool .RemoveOps (ep , rmOps ... ); err != nil {
95
- l .Error (err , "bundler run error" )
130
+ // Already logged.
96
131
continue
97
132
}
98
-
99
- bat := []string {}
100
- for _ , op := range ctx .Batch {
101
- bat = append (bat , op .GetUserOpHash (ep , i .chainID ).String ())
102
- }
103
- l = l .WithValues ("batch_userop_hashes" , bat )
104
-
105
- drp := []string {}
106
- for _ , op := range ctx .PendingRemoval {
107
- drp = append (drp , op .GetUserOpHash (ep , i .chainID ).String ())
108
- }
109
- l = l .WithValues ("dropped_userop_hashes" , drp )
110
-
111
- for k , v := range ctx .Data {
112
- l = l .WithValues (k , v )
113
- }
114
- l = l .WithValues ("duration" , time .Since (start ))
115
- l .Info ("bundler run ok" )
116
133
}
117
134
}
118
135
}
0 commit comments