github.com/theQRL/go-zond@v0.2.1/miner/ordering_test.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package miner 18 19 import ( 20 "math/big" 21 "math/rand" 22 "testing" 23 "time" 24 25 "github.com/theQRL/go-qrllib/dilithium" 26 "github.com/theQRL/go-zond/common" 27 "github.com/theQRL/go-zond/core/txpool" 28 "github.com/theQRL/go-zond/core/types" 29 "github.com/theQRL/go-zond/crypto" 30 ) 31 32 func TestTransactionPriceNonceSort1559(t *testing.T) { 33 t.Parallel() 34 testTransactionPriceNonceSort(t, big.NewInt(0)) 35 testTransactionPriceNonceSort(t, big.NewInt(5)) 36 testTransactionPriceNonceSort(t, big.NewInt(50)) 37 } 38 39 // Tests that transactions can be correctly sorted according to their price in 40 // decreasing order, but at the same time with increasing nonces when issued by 41 // the same account. 42 func testTransactionPriceNonceSort(t *testing.T, baseFee *big.Int) { 43 // Generate a batch of accounts to start with 44 keys := make([]*dilithium.Dilithium, 25) 45 for i := 0; i < len(keys); i++ { 46 keys[i], _ = crypto.GenerateDilithiumKey() 47 } 48 signer := types.LatestSignerForChainID(common.Big1) 49 50 // Generate a batch of transactions with overlapping values, but shifted nonces 51 groups := map[common.Address][]*txpool.LazyTransaction{} 52 expectedCount := 0 53 for start, key := range keys { 54 addr := key.GetAddress() 55 count := 25 56 for i := 0; i < 25; i++ { 57 var tx *types.Transaction 58 gasFeeCap := rand.Intn(50) 59 tx = types.NewTx(&types.DynamicFeeTx{ 60 Nonce: uint64(start + i), 61 To: &common.Address{}, 62 Value: big.NewInt(100), 63 Gas: 100, 64 GasFeeCap: big.NewInt(int64(gasFeeCap)), 65 GasTipCap: big.NewInt(int64(rand.Intn(gasFeeCap + 1))), 66 Data: nil, 67 }) 68 if count == 25 && int64(gasFeeCap) < baseFee.Int64() { 69 count = i 70 } 71 tx, err := types.SignTx(tx, signer, key) 72 if err != nil { 73 t.Fatalf("failed to sign tx: %s", err) 74 } 75 groups[addr] = append(groups[addr], &txpool.LazyTransaction{ 76 Hash: tx.Hash(), 77 Tx: tx, 78 Time: tx.Time(), 79 GasFeeCap: tx.GasFeeCap(), 80 GasTipCap: tx.GasTipCap(), 81 Gas: tx.Gas(), 82 }) 83 } 84 expectedCount += count 85 } 86 // Sort the transactions and cross check the nonce ordering 87 txset := newTransactionsByPriceAndNonce(signer, groups, baseFee) 88 89 txs := types.Transactions{} 90 for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { 91 txs = append(txs, tx.Tx) 92 txset.Shift() 93 } 94 if len(txs) != expectedCount { 95 t.Errorf("expected %d transactions, found %d", expectedCount, len(txs)) 96 } 97 for i, txi := range txs { 98 fromi, _ := types.Sender(signer, txi) 99 100 // Make sure the nonce order is valid 101 for j, txj := range txs[i+1:] { 102 fromj, _ := types.Sender(signer, txj) 103 if fromi == fromj && txi.Nonce() > txj.Nonce() { 104 t.Errorf("invalid nonce ordering: tx #%d (A=%x N=%v) < tx #%d (A=%x N=%v)", i, fromi[:4], txi.Nonce(), i+j, fromj[:4], txj.Nonce()) 105 } 106 } 107 // If the next tx has different from account, the price must be lower than the current one 108 if i+1 < len(txs) { 109 next := txs[i+1] 110 fromNext, _ := types.Sender(signer, next) 111 tip, err := txi.EffectiveGasTip(baseFee) 112 nextTip, nextErr := next.EffectiveGasTip(baseFee) 113 if err != nil || nextErr != nil { 114 t.Errorf("error calculating effective tip: %v, %v", err, nextErr) 115 } 116 if fromi != fromNext && tip.Cmp(nextTip) < 0 { 117 t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)", i, fromi[:4], txi.GasPrice(), i+1, fromNext[:4], next.GasPrice()) 118 } 119 } 120 } 121 } 122 123 // Tests that if multiple transactions have the same price, the ones seen earlier 124 // are prioritized to avoid network spam attacks aiming for a specific ordering. 125 func TestTransactionTimeSort(t *testing.T) { 126 t.Parallel() 127 // Generate a batch of accounts to start with 128 keys := make([]*dilithium.Dilithium, 5) 129 for i := 0; i < len(keys); i++ { 130 keys[i], _ = crypto.GenerateDilithiumKey() 131 } 132 signer := types.ShanghaiSigner{ChainId: big.NewInt(0)} 133 134 // Generate a batch of transactions with overlapping prices, but different creation times 135 groups := map[common.Address][]*txpool.LazyTransaction{} 136 for start, key := range keys { 137 addr := key.GetAddress() 138 139 tx, _ := types.SignTx(types.NewTx(&types.DynamicFeeTx{Nonce: 0, To: &common.Address{}, Value: big.NewInt(100), Gas: 100, Data: nil}), signer, key) 140 tx.SetTime(time.Unix(0, int64(len(keys)-start))) 141 142 groups[addr] = append(groups[addr], &txpool.LazyTransaction{ 143 Hash: tx.Hash(), 144 Tx: tx, 145 Time: tx.Time(), 146 GasFeeCap: tx.GasFeeCap(), 147 GasTipCap: tx.GasTipCap(), 148 Gas: tx.Gas(), 149 }) 150 } 151 // Sort the transactions and cross check the nonce ordering 152 txset := newTransactionsByPriceAndNonce(signer, groups, nil) 153 154 txs := types.Transactions{} 155 for tx, _ := txset.Peek(); tx != nil; tx, _ = txset.Peek() { 156 txs = append(txs, tx.Tx) 157 txset.Shift() 158 } 159 if len(txs) != len(keys) { 160 t.Errorf("expected %d transactions, found %d", len(keys), len(txs)) 161 } 162 for i, txi := range txs { 163 fromi, _ := types.Sender(signer, txi) 164 if i+1 < len(txs) { 165 next := txs[i+1] 166 fromNext, _ := types.Sender(signer, next) 167 168 if txi.GasPrice().Cmp(next.GasPrice()) < 0 { 169 t.Errorf("invalid gasprice ordering: tx #%d (A=%x P=%v) < tx #%d (A=%x P=%v)", i, fromi[:4], txi.GasPrice(), i+1, fromNext[:4], next.GasPrice()) 170 } 171 // Make sure time order is ascending if the txs have the same gas price 172 if txi.GasPrice().Cmp(next.GasPrice()) == 0 && txi.Time().After(next.Time()) { 173 t.Errorf("invalid received time ordering: tx #%d (A=%x T=%v) > tx #%d (A=%x T=%v)", i, fromi[:4], txi.Time(), i+1, fromNext[:4], next.Time()) 174 } 175 } 176 } 177 }