@@ -12,12 +12,15 @@ import (
12
12
"io/fs"
13
13
"io/ioutil"
14
14
15
+ etherum "github.com/ethereum/go-ethereum"
15
16
"github.com/ethereum/go-ethereum/accounts"
16
17
"github.com/ethereum/go-ethereum/accounts/abi"
17
18
"github.com/ethereum/go-ethereum/accounts/abi/bind"
18
19
"github.com/ethereum/go-ethereum/accounts/keystore"
19
20
"github.com/ethereum/go-ethereum/common"
20
21
ethcommon "github.com/ethereum/go-ethereum/common"
22
+ etherumtypes "github.com/ethereum/go-ethereum/core/types"
23
+ ethtypes "github.com/ethereum/go-ethereum/core/types"
21
24
"github.com/ethereum/go-ethereum/ethclient"
22
25
"github.com/palomachain/sparrow/config"
23
26
"github.com/palomachain/sparrow/errors"
@@ -87,25 +90,34 @@ func StoredContracts() map[string]StoredContract {
87
90
88
91
type PalomaClienter interface {
89
92
DeleteJob (ctx context.Context , queueTypeName string , id uint64 ) error
93
+ QueryGetEVMValsetByID (ctx context.Context , id uint64 , chainID string ) (* types.Valset , error )
90
94
}
91
95
92
96
type Client struct {
93
97
config config.EVM
94
98
95
- smartContractAbi abi.ABI
99
+ smartContractAbi abi.ABI
100
+ turnstoneEVMContract common.Address
96
101
97
102
addr ethcommon.Address
98
103
keystore * keystore.KeyStore
99
104
100
105
conn * ethclient.Client
101
106
102
107
paloma PalomaClienter
108
+
109
+ internalChainID string
103
110
}
104
111
105
- func NewClient (cfg config.EVM , palomaClient PalomaClienter ) Client {
112
+ func NewClient (
113
+ cfg config.EVM ,
114
+ palomaClient PalomaClienter ,
115
+ internalChainID string ,
116
+ ) Client {
106
117
client := & Client {
107
- config : cfg ,
108
- paloma : palomaClient ,
118
+ config : cfg ,
119
+ paloma : palomaClient ,
120
+ internalChainID : internalChainID ,
109
121
}
110
122
111
123
whoops .Assert (client .init ())
@@ -160,26 +172,26 @@ type executeSmartContractIn struct {
160
172
arguments []any
161
173
}
162
174
163
- func executeSmartContract (
175
+ func callSmartContract (
164
176
ctx context.Context ,
165
177
args executeSmartContractIn ,
166
- abiBytes []byte ,
167
- packedBytes []byte ,
168
- ) error {
178
+ ) (* etherumtypes.Transaction , error ) {
169
179
logger := log .WithFields (log.Fields {
170
- "chain-id" : args .chainID ,
171
- "arguments" : args .arguments ,
172
- "contract-addr" : args .contract ,
180
+ "chain-id" : args .chainID ,
181
+ "contract-addr" : args .contract ,
182
+
183
+ "method" : args .method ,
184
+ "arguments" : args .arguments ,
185
+
173
186
"gas-adjustments" : args .gasAdjustment ,
174
- "method" : args . method ,
175
- "signing-addr" : args .signingAddr ,
187
+
188
+ "signing-addr" : args .signingAddr ,
176
189
})
177
- return whoops .Try (func () {
178
- // TODO
179
- // packedBytes := whoops.Must(args.abi.Pack(
180
- // args.method,
181
- // args.arguments...,
182
- // ))
190
+ return whoops .TryVal (func () * etherumtypes.Transaction {
191
+ packedBytes := whoops .Must (args .abi .Pack (
192
+ args .method ,
193
+ args .arguments ... ,
194
+ ))
183
195
184
196
nonce := whoops .Must (
185
197
args .ethClient .PendingNonceAt (ctx , args .signingAddr ),
@@ -199,13 +211,9 @@ func executeSmartContract(
199
211
}).Info ("adusted gas price" )
200
212
}
201
213
202
- aabi := whoops .Must (abi .JSON (bytes .NewBuffer (abiBytes )))
203
-
204
214
boundContract := bind .NewBoundContract (
205
215
args .contract ,
206
- // TODO:
207
- // args.abi,
208
- aabi ,
216
+ args .abi ,
209
217
args .ethClient ,
210
218
args .ethClient ,
211
219
args .ethClient ,
@@ -226,54 +234,106 @@ func executeSmartContract(
226
234
logger = logger .WithFields (log.Fields {
227
235
"tx-opts" : txOpts ,
228
236
})
237
+
229
238
logger .Info ("executing tx" )
230
239
231
240
tx := whoops .Must (boundContract .RawTransact (txOpts , packedBytes ))
241
+
232
242
logger .WithFields (log.Fields {
233
243
"tx-hash" : tx .Hash (),
234
244
"tx-gas-limit" : tx .Gas (),
235
245
"tx-gas-price" : tx .GasPrice (),
236
246
"tx-cost" : tx .Cost (),
237
247
}).Info ("tx executed" )
238
-
239
- _ = tx
240
-
241
- // TODO: return tx hash and rest of the stuff
242
-
243
- return
248
+ return tx
244
249
})
245
250
}
246
251
247
252
func (c Client ) sign (ctx context.Context , bytes []byte ) ([]byte , error ) {
248
253
return c .keystore .SignHash (accounts.Account {Address : c .addr }, bytes )
249
254
}
250
255
251
- // TODO: this is just a placeholder
252
- func (c Client ) executeArbitraryMessage (
253
- ctx context.Context ,
254
- // TODO
255
- msg * types.ArbitrarySmartContractCall ,
256
- ) error {
257
- chainID := & big.Int {}
258
- chainID .SetString (c .config .ChainID , 10 )
256
+ // processAllLogs will gather all logs given a FilterQuery. If it encounters an
257
+ // error saying that there are too many results in the provided block window,
258
+ // then it's going to try to do this using a binary search approach while
259
+ // splitting the possible set in two, recursively.
260
+ func (c Client ) processAllLogs (ctx context.Context , fq etherum.FilterQuery , currBlockHeight * big.Int , fn func (logs []ethtypes.Log ) bool ) (bool , error ) {
261
+ if currBlockHeight == nil {
262
+ header , err := c .conn .HeaderByNumber (ctx , nil )
263
+ if err != nil {
264
+ panic (err )
265
+ }
266
+ currBlockHeight = header .Number
267
+ }
259
268
260
- return executeSmartContract (
269
+ if fq .BlockHash == nil {
270
+ if fq .ToBlock == nil {
271
+ fq .ToBlock = currBlockHeight
272
+ }
273
+ if fq .FromBlock == nil {
274
+ fq .FromBlock = big .NewInt (0 )
275
+ }
276
+ }
277
+
278
+ logs , err := c .conn .FilterLogs (ctx , fq )
279
+
280
+ switch {
281
+ case err == nil :
282
+ // awesome!
283
+ if len (logs ) == 0 {
284
+ return true , nil
285
+ }
286
+ return fn (logs ), nil
287
+ case err .Error () == "query returned more than 10000 results" :
288
+ // this appears to be ropsten specifict, but keepeing the logic here just in case
289
+ mid := big .NewInt (0 ).Sub (
290
+ fq .ToBlock ,
291
+ fq .FromBlock ,
292
+ )
293
+ mid .Div (mid , big .NewInt (2 ))
294
+ mid .Add (fq .FromBlock , mid )
295
+
296
+ fqLeft := fq
297
+ fqLeft .ToBlock = mid
298
+ shouldContinue , err := c .processAllLogs (ctx , fqLeft , currBlockHeight , fn )
299
+ if err != nil {
300
+ return false , err
301
+ }
302
+ if ! shouldContinue {
303
+ return false , nil
304
+ }
305
+ fqRight := fq
306
+ fqRight .FromBlock = big .NewInt (0 ).Add (mid , big .NewInt (1 ))
307
+
308
+ shouldContinue , err = c .processAllLogs (ctx , fqRight , currBlockHeight , fn )
309
+ if err != nil {
310
+ return false , err
311
+ }
312
+ if ! shouldContinue {
313
+ return false , nil
314
+ }
315
+ }
316
+ return false , err
317
+ }
318
+
319
+ func (c Client ) callSmartContract (
320
+ ctx context.Context ,
321
+ method string ,
322
+ arguments []any ,
323
+ ) (* etherumtypes.Transaction , error ) {
324
+ return callSmartContract (
261
325
ctx ,
262
326
executeSmartContractIn {
263
327
ethClient : c .conn ,
264
- chainID : chainID ,
328
+ chainID : c . config . GetChainID () ,
265
329
gasAdjustment : c .config .GasAdjustment ,
266
330
abi : c .smartContractAbi ,
267
- // contract: ethcommon.HexToAddress(c.config.EVMSpecificClientConfig.SmartContractAddress),
268
- contract : ethcommon .HexToAddress (msg .GetHexAddress ()),
269
- signingAddr : c .addr ,
270
- keystore : c .keystore ,
271
- method : "store" ,
272
- arguments : []any {
273
- big .NewInt (111 ),
274
- },
331
+ contract : c .turnstoneEVMContract ,
332
+ signingAddr : c .addr ,
333
+ keystore : c .keystore ,
334
+
335
+ method : method ,
336
+ arguments : arguments ,
275
337
},
276
- msg .GetAbi (),
277
- msg .GetPayload (),
278
338
)
279
339
}
0 commit comments