11package miner
22
33import (
4+ "crypto/ecdsa"
45 "errors"
6+ "fmt"
57 "math/big"
68 "sync/atomic"
79
@@ -20,6 +22,8 @@ const (
2022 popTx = 2
2123)
2224
25+ var emptyCodeHash = common .HexToHash ("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" )
26+
2327var errInterrupt = errors .New ("miner worker interrupted" )
2428
2529type environmentDiff struct {
@@ -263,3 +267,111 @@ func (envDiff *environmentDiff) commitBundle(bundle *types.SimulatedBundle, chDa
263267 * envDiff = * tmpEnvDiff
264268 return nil
265269}
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