github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/cmd/dummytx/dummytx.go (about) 1 package main 2 3 import ( 4 "context" 5 "crypto/ecdsa" 6 "crypto/rand" 7 common2 "github.com/bigzoro/my_simplechain/cmd/dummytx/common" 8 "github.com/bigzoro/my_simplechain/cmd/dummytx/config" 9 "log" 10 "math/big" 11 "strconv" 12 "time" 13 14 "github.com/bigzoro/my_simplechain/common" 15 "github.com/bigzoro/my_simplechain/core/types" 16 "github.com/bigzoro/my_simplechain/crypto" 17 "github.com/bigzoro/my_simplechain/ethclient" 18 ) 19 20 const ( 21 warnPrefix = "\x1b[93mwarn:\x1b[0m" 22 errPrefix = "\x1b[91merror:\x1b[0m" 23 ) 24 25 func init() { 26 log.SetFlags(log.Lshortfile | log.LstdFlags) 27 } 28 29 type Sender struct { 30 url string 31 keyFile string 32 certFile string 33 rootCAFile []string 34 ctx context.Context 35 client *ethclient.Client 36 senders []common.Address 37 pks []*ecdsa.PrivateKey 38 receiver common.Address 39 gasPrice *big.Int 40 gasLimit *big.Int 41 dummyInternal int64 42 chainID string 43 txsCount int64 44 signal chan bool 45 firstNonce uint64 46 } 47 48 func newSender(ctx context.Context, config *config.Config, txsCount int64) *Sender { 49 var s = &Sender{ 50 url: config.SipeAddr, 51 keyFile: config.PrivateKey, 52 certFile: config.Cert, 53 rootCAFile: config.CACerts, 54 ctx: ctx, 55 receiver: common.HexToAddress(config.Receiver), 56 gasPrice: big.NewInt(config.GasPrice), 57 gasLimit: big.NewInt(config.GasPriceLimit), 58 dummyInternal: config.DummyInternal, 59 txsCount: txsCount, 60 chainID: config.ChainId, 61 signal: make(chan bool, 1), 62 } 63 64 for i, pk := range config.SenderPrivateKey { 65 key, err := common2.GetKey(pk, config.SenderPrivateKeyPassword[i]) 66 if err != nil { 67 log.Fatalf(errPrefix+" get private key file: %v", err) 68 } 69 privateKey := key.PrivateKey 70 s.pks = append(s.pks, privateKey) 71 publicKey := privateKey.Public() 72 publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) 73 if !ok { 74 log.Fatalf(errPrefix + " cannot assert type: publicKey is not of type *ecdsa.PublicKey") 75 } 76 fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) 77 log.Printf("sender:%d %s\n", i, fromAddress.String()) 78 79 s.senders = append(s.senders, fromAddress) 80 } 81 return s 82 } 83 84 func (s *Sender) connect() { 85 client, err := ethclient.Dial(s.url, s.certFile, s.keyFile, s.rootCAFile) 86 if err != nil { 87 log.Fatalf(errPrefix+" connect %s: %v", s.url, err) 88 } 89 90 s.client = client 91 } 92 93 func (s *Sender) dummyTx() { 94 gasPrice, err := s.client.SuggestGasPrice(s.ctx) 95 if err != nil { 96 log.Fatalf(errPrefix+" get gas price: %v", err) 97 } 98 s.gasPrice = gasPrice 99 100 for i, sender := range s.senders { 101 go s.loopSendTxsByNum(i, sender) 102 } 103 } 104 105 func (s *Sender) claimFunds() { 106 value := new(big.Int).Mul(big.NewInt(10000), big.NewInt(1)) // in wei (10000 eth) 107 for i, sender := range s.senders { 108 nonce, err := s.client.PendingNonceAt(s.ctx, sender) 109 if err != nil { 110 log.Fatalf(errPrefix+" get new nonce: %v", err) 111 } 112 tx := types.NewTransaction(nonce, sender, value, s.gasLimit.Uint64(), s.gasPrice, nil) 113 //Remove signature for POA test 114 chainID, err := strconv.ParseInt(s.chainID, 10, 64) 115 if err != nil { 116 log.Fatalf(errPrefix+"chainid transfer failed %v", err) 117 } 118 signedTx, err := types.SignTx(tx, types.NewEIP155Signer(new(big.Int).SetInt64(chainID)), s.pks[i]) 119 if err != nil { 120 log.Fatalf(errPrefix+" sign tx in claimFunds: %v", err) 121 } 122 err = s.client.SendTransaction(s.ctx, signedTx) 123 if err != nil { 124 log.Fatalf(errPrefix+" sign tx in claimFunds: %v", err) 125 } 126 nonce++ 127 } 128 log.Printf("waiting %v seconds for claim funds txs finalize to block...\n", s.dummyInternal) 129 time.Sleep(time.Duration(s.dummyInternal) * time.Second) 130 } 131 132 func (s *Sender) loopSendTxsByNum(index int, fromAddress common.Address) { 133 nonce, err := s.client.PendingNonceAt(s.ctx, fromAddress) 134 if err != nil { 135 log.Fatalf(errPrefix+" get new nonce: %v", err) 136 } 137 s.firstNonce = nonce 138 for i := 0; i < int(s.txsCount); i++ { 139 go s.sendTx(nonce+uint64(i), index, fromAddress) 140 } 141 } 142 143 func (s *Sender) sendTx(nonce uint64, index int, fromAddress common.Address) { 144 var ( 145 data [20 + 64]byte 146 ) 147 copy(data[:], fromAddress.Bytes()) 148 _, _ = rand.Read(data[20:]) //hash 149 s.sendDummyTx(nonce, data[:], fromAddress, index) 150 } 151 152 func (s *Sender) sendDummyTx(nonce uint64, data []byte, fromAddress common.Address, index int) { 153 tx := types.NewTransaction(nonce, fromAddress, big.NewInt(0), s.gasLimit.Uint64(), s.gasPrice, data) 154 //Remove signature for POA test 155 chainID, err := strconv.ParseInt(s.chainID, 10, 64) 156 if err != nil { 157 log.Fatalf(errPrefix+"chainid transfer failed %v", err) 158 } 159 signedTx, err := types.SignTx(tx, types.NewEIP155Signer(new(big.Int).SetInt64(chainID)), s.pks[index]) 160 if err != nil { 161 log.Fatalf(errPrefix+"sign tx: %v", err) 162 } 163 err = s.client.SendTransaction(s.ctx, signedTx) 164 if err != nil { 165 log.Printf(warnPrefix+" send tx: %v", err) 166 } 167 } 168 169 func (s *Sender) calcTotalCount(ctx context.Context) { 170 heads := make(chan *types.Header, 1) 171 sub, err := s.client.SubscribeNewHead(context.Background(), heads) 172 if err != nil { 173 log.Fatalf(errPrefix+"Failed to subscribe to head events %v", err) 174 } 175 defer sub.Unsubscribe() 176 177 var ( 178 txsCount uint 179 finalCount uint64 180 start = time.Now() 181 calcTotalCountExit = func(txsCount uint64, seconds float64) { 182 log.Printf("total finalize %v txs in %v seconds, %v txs/s", txsCount, seconds, float64(txsCount)/seconds) 183 } 184 ) 185 for { 186 select { 187 case <-ctx.Done(): 188 calcTotalCountExit(finalCount, time.Since(start).Seconds()) 189 s.signal <- true 190 return 191 case head := <-heads: 192 txsCount, err = s.client.TransactionCount(ctx, head.Hash()) 193 if err != nil { 194 log.Printf(warnPrefix+"get txCount of block %v: %v", head.Hash(), err) 195 } 196 197 log.Printf("Time %8.2fs\tblock Number %6d\ttxCount %6d", time.Since(start).Seconds(), head.Number.Uint64(), txsCount) 198 199 finalCount += uint64(txsCount) 200 nonce, err := s.client.NonceAt(s.ctx, s.senders[0], big.NewInt(int64(head.Number.Uint64()))) 201 if err != nil { 202 continue 203 } 204 if s.firstNonce+uint64(s.txsCount) == nonce { 205 calcTotalCountExit(finalCount, time.Since(start).Seconds()) 206 s.signal <- true 207 return 208 } 209 default: 210 //do nothing 211 } 212 } 213 }