github.com/cgcardona/r-subnet-evm@v0.1.5/cmd/simulator/load/worker.go (about) 1 // Copyright (C) 2023, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package load 5 6 import ( 7 "context" 8 "fmt" 9 "time" 10 11 "github.com/cgcardona/r-subnet-evm/core/types" 12 "github.com/cgcardona/r-subnet-evm/ethclient" 13 "github.com/cgcardona/r-subnet-evm/interfaces" 14 "github.com/ethereum/go-ethereum/common" 15 "github.com/ethereum/go-ethereum/log" 16 ) 17 18 type singleAddressTxWorker struct { 19 client ethclient.Client 20 21 acceptedNonce uint64 22 address common.Address 23 24 sub interfaces.Subscription 25 newHeads chan *types.Header 26 } 27 28 // NewSingleAddressTxWorker creates and returns a singleAddressTxWorker 29 func NewSingleAddressTxWorker(ctx context.Context, client ethclient.Client, address common.Address) *singleAddressTxWorker { 30 newHeads := make(chan *types.Header) 31 tw := &singleAddressTxWorker{ 32 client: client, 33 address: address, 34 newHeads: newHeads, 35 } 36 37 sub, err := client.SubscribeNewHead(ctx, newHeads) 38 if err != nil { 39 log.Debug("failed to subscribe new heads, falling back to polling", "err", err) 40 } else { 41 tw.sub = sub 42 } 43 44 return tw 45 } 46 47 func (tw *singleAddressTxWorker) IssueTx(ctx context.Context, tx *types.Transaction) error { 48 return tw.client.SendTransaction(ctx, tx) 49 } 50 51 func (tw *singleAddressTxWorker) ConfirmTx(ctx context.Context, tx *types.Transaction) error { 52 txNonce := tx.Nonce() 53 54 for { 55 // If the is less than what has already been accepted, the transaction is confirmed 56 if txNonce < tw.acceptedNonce { 57 return nil 58 } 59 60 select { 61 case <-tw.newHeads: 62 case <-time.After(time.Second): 63 case <-ctx.Done(): 64 return fmt.Errorf("failed to await tx %s nonce %d: %w", tx.Hash(), txNonce, ctx.Err()) 65 } 66 67 // Update the worker's accepted nonce, so we can check on the next iteration 68 // if the transaction has been accepted. 69 acceptedNonce, err := tw.client.NonceAt(ctx, tw.address, nil) 70 if err != nil { 71 return fmt.Errorf("failed to await tx %s nonce %d: %w", tx.Hash(), txNonce, err) 72 } 73 tw.acceptedNonce = acceptedNonce 74 } 75 } 76 77 func (tw *singleAddressTxWorker) Close(ctx context.Context) error { 78 if tw.sub != nil { 79 tw.sub.Unsubscribe() 80 } 81 close(tw.newHeads) 82 return nil 83 }