1
1
package miner
2
2
3
3
import (
4
+ "crypto/ecdsa"
4
5
"errors"
6
+ "fmt"
5
7
"math/big"
6
8
"sync/atomic"
7
9
@@ -20,6 +22,8 @@ const (
20
22
popTx = 2
21
23
)
22
24
25
+ var emptyCodeHash = common .HexToHash ("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" )
26
+
23
27
var errInterrupt = errors .New ("miner worker interrupted" )
24
28
25
29
type environmentDiff struct {
@@ -263,3 +267,111 @@ func (envDiff *environmentDiff) commitBundle(bundle *types.SimulatedBundle, chDa
263
267
* envDiff = * tmpEnvDiff
264
268
return nil
265
269
}
270
+
271
+ func estimatePayoutTxGas (env * environment , sender , receiver common.Address , prv * ecdsa.PrivateKey , chData chainData ) (uint64 , bool , error ) {
272
+ if codeHash := env .state .GetCodeHash (receiver ); codeHash == (common.Hash {}) || codeHash == emptyCodeHash {
273
+ return params .TxGas , true , nil
274
+ }
275
+ gasLimit := env .gasPool .Gas ()
276
+
277
+ balance := new (big.Int ).SetBytes ([]byte {0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF })
278
+ value := new (big.Int ).SetBytes ([]byte {0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF })
279
+
280
+ diff := newEnvironmentDiff (env )
281
+ diff .state .SetBalance (sender , balance )
282
+ receipt , err := diff .commitPayoutTx (value , sender , receiver , gasLimit , prv , chData )
283
+ if err != nil {
284
+ return 0 , false , err
285
+ }
286
+ return receipt .GasUsed , false , nil
287
+ }
288
+
289
+ func insertPayoutTx (env * environment , sender , receiver common.Address , gas uint64 , isEOA bool , availableFunds * big.Int , prv * ecdsa.PrivateKey , chData chainData ) (* types.Receipt , error ) {
290
+ diff := newEnvironmentDiff (env )
291
+ applyTx := func (gas uint64 ) (* types.Receipt , error ) {
292
+ fee := new (big.Int ).Mul (env .header .BaseFee , new (big.Int ).SetUint64 (gas ))
293
+ amount := new (big.Int ).Sub (availableFunds , fee )
294
+ if amount .Sign () < 0 {
295
+ return nil , errors .New ("not enough funds available" )
296
+ }
297
+ rec , err := diff .commitPayoutTx (amount , sender , receiver , gas , prv , chData )
298
+ if err != nil {
299
+ return nil , fmt .Errorf ("failed to commit payment tx: %w" , err )
300
+ }
301
+ if rec .Status != types .ReceiptStatusSuccessful {
302
+ return nil , fmt .Errorf ("payment tx failed" )
303
+ }
304
+ return rec , nil
305
+ }
306
+
307
+ if isEOA {
308
+ rec , err := applyTx (gas )
309
+ if err != nil {
310
+ return nil , err
311
+ }
312
+ diff .applyToBaseEnv ()
313
+ return rec , nil
314
+ }
315
+
316
+ var (
317
+ rec * types.Receipt
318
+ err error
319
+ )
320
+ for i := 0 ; i < 6 ; i ++ {
321
+ rec , err = applyTx (gas )
322
+ if err != nil {
323
+ gas += 1000
324
+ } else {
325
+ break
326
+ }
327
+ }
328
+
329
+ if err != nil {
330
+ return nil , err
331
+ }
332
+ diff .applyToBaseEnv ()
333
+ return rec , nil
334
+ }
335
+
336
+ func (envDiff * environmentDiff ) commitPayoutTx (amount * big.Int , sender , receiver common.Address , gas uint64 , prv * ecdsa.PrivateKey , chData chainData ) (* types.Receipt , error ) {
337
+ senderBalance := envDiff .state .GetBalance (sender )
338
+
339
+ if gas < params .TxGas {
340
+ return nil , errors .New ("not enough gas for intrinsic gas cost" )
341
+ }
342
+
343
+ requiredBalance := new (big.Int ).Mul (envDiff .header .BaseFee , new (big.Int ).SetUint64 (gas ))
344
+ requiredBalance = requiredBalance .Add (requiredBalance , amount )
345
+ if requiredBalance .Cmp (senderBalance ) > 0 {
346
+ return nil , errors .New ("not enough balance" )
347
+ }
348
+
349
+ signer := envDiff .baseEnvironment .signer
350
+ tx , err := types .SignNewTx (prv , signer , & types.DynamicFeeTx {
351
+ ChainID : chData .chainConfig .ChainID ,
352
+ Nonce : envDiff .state .GetNonce (sender ),
353
+ GasTipCap : new (big.Int ),
354
+ GasFeeCap : envDiff .header .BaseFee ,
355
+ Gas : gas ,
356
+ To : & receiver ,
357
+ Value : amount ,
358
+ })
359
+ if err != nil {
360
+ return nil , err
361
+ }
362
+
363
+ txSender , err := signer .Sender (tx )
364
+ if err != nil {
365
+ return nil , err
366
+ }
367
+ if txSender != sender {
368
+ return nil , errors .New ("incorrect sender private key" )
369
+ }
370
+
371
+ receipt , _ , err := envDiff .commitTx (tx , chData )
372
+ if err != nil {
373
+ return nil , err
374
+ }
375
+
376
+ return receipt , nil
377
+ }
0 commit comments