github.com/theQRL/go-zond@v0.2.1/zond/gasprice/gasprice_test.go (about) 1 // Copyright 2020 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 gasprice 18 19 import ( 20 "context" 21 "math" 22 "math/big" 23 "testing" 24 25 "github.com/theQRL/go-zond/common" 26 "github.com/theQRL/go-zond/consensus/beacon" 27 "github.com/theQRL/go-zond/core" 28 "github.com/theQRL/go-zond/core/state" 29 "github.com/theQRL/go-zond/core/types" 30 "github.com/theQRL/go-zond/core/vm" 31 "github.com/theQRL/go-zond/crypto/pqcrypto" 32 "github.com/theQRL/go-zond/event" 33 "github.com/theQRL/go-zond/params" 34 "github.com/theQRL/go-zond/rpc" 35 ) 36 37 const testHead = 32 38 39 type testBackend struct { 40 chain *core.BlockChain 41 pending bool // pending block available 42 } 43 44 func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) { 45 if number > testHead { 46 return nil, nil 47 } 48 if number == rpc.EarliestBlockNumber { 49 number = 0 50 } 51 if number == rpc.FinalizedBlockNumber { 52 return b.chain.CurrentFinalBlock(), nil 53 } 54 if number == rpc.SafeBlockNumber { 55 return b.chain.CurrentSafeBlock(), nil 56 } 57 if number == rpc.LatestBlockNumber { 58 number = testHead 59 } 60 if number == rpc.PendingBlockNumber { 61 if b.pending { 62 number = testHead + 1 63 } else { 64 return nil, nil 65 } 66 } 67 return b.chain.GetHeaderByNumber(uint64(number)), nil 68 } 69 70 func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 71 if number > testHead { 72 return nil, nil 73 } 74 if number == rpc.EarliestBlockNumber { 75 number = 0 76 } 77 if number == rpc.FinalizedBlockNumber { 78 number = rpc.BlockNumber(b.chain.CurrentFinalBlock().Number.Uint64()) 79 } 80 if number == rpc.SafeBlockNumber { 81 number = rpc.BlockNumber(b.chain.CurrentSafeBlock().Number.Uint64()) 82 } 83 if number == rpc.LatestBlockNumber { 84 number = testHead 85 } 86 if number == rpc.PendingBlockNumber { 87 if b.pending { 88 number = testHead + 1 89 } else { 90 return nil, nil 91 } 92 } 93 return b.chain.GetBlockByNumber(uint64(number)), nil 94 } 95 96 func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 97 return b.chain.GetReceiptsByHash(hash), nil 98 } 99 100 func (b *testBackend) Pending() (*types.Block, types.Receipts, *state.StateDB) { 101 if b.pending { 102 block := b.chain.GetBlockByNumber(testHead + 1) 103 state, _ := b.chain.StateAt(block.Root()) 104 return block, b.chain.GetReceiptsByHash(block.Hash()), state 105 } 106 return nil, nil, nil 107 } 108 109 func (b *testBackend) ChainConfig() *params.ChainConfig { 110 return b.chain.Config() 111 } 112 113 func (b *testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 114 return nil 115 } 116 117 func (b *testBackend) teardown() { 118 b.chain.Stop() 119 } 120 121 // newTestBackend creates a test backend. OBS: don't forget to invoke tearDown 122 // after use, otherwise the blockchain instance will mem-leak via goroutines. 123 func newTestBackend(t *testing.T, pending bool) *testBackend { 124 var ( 125 key, _ = pqcrypto.HexToDilithium("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 126 addr = key.GetAddress() 127 config = *params.TestChainConfig // needs copy because it is modified below 128 gspec = &core.Genesis{ 129 Config: &config, 130 Alloc: core.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}}, 131 } 132 signer = types.LatestSigner(gspec.Config) 133 ) 134 135 engine := beacon.NewFaker() 136 137 // Generate testing blocks 138 db, blocks, _ := core.GenerateChainWithGenesis(gspec, engine, testHead+1, func(i int, b *core.BlockGen) { 139 b.SetCoinbase(common.Address{1}) 140 141 txdata := &types.DynamicFeeTx{ 142 ChainID: gspec.Config.ChainID, 143 Nonce: b.TxNonce(addr), 144 To: &common.Address{}, 145 Gas: 30000, 146 GasFeeCap: big.NewInt(100 * params.GWei), 147 GasTipCap: big.NewInt(int64(i+1) * params.GWei), 148 Data: []byte{}, 149 } 150 b.AddTx(types.MustSignNewTx(key, signer, txdata)) 151 }) 152 // Construct testing chain 153 chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieCleanNoPrefetch: true}, gspec, engine, vm.Config{}, nil) 154 if err != nil { 155 t.Fatalf("Failed to create local chain, %v", err) 156 } 157 if i, err := chain.InsertChain(blocks); err != nil { 158 t.Fatalf("Failed to insert block %d: %v", i, err) 159 } 160 chain.SetFinalized(chain.GetBlockByNumber(25).Header()) 161 chain.SetSafe(chain.GetBlockByNumber(25).Header()) 162 return &testBackend{chain: chain, pending: pending} 163 } 164 165 func (b *testBackend) CurrentHeader() *types.Header { 166 return b.chain.CurrentHeader() 167 } 168 169 func (b *testBackend) GetBlockByNumber(number uint64) *types.Block { 170 return b.chain.GetBlockByNumber(number) 171 } 172 173 func TestSuggestTipCap(t *testing.T) { 174 config := Config{ 175 Blocks: 3, 176 Percentile: 60, 177 Default: big.NewInt(params.GWei), 178 } 179 var cases = []struct { 180 fork *big.Int // London fork number 181 expect *big.Int // Expected gasprice suggestion 182 }{ 183 {nil, big.NewInt(params.GWei * int64(30))}, 184 {big.NewInt(0), big.NewInt(params.GWei * int64(30))}, // Fork point in genesis 185 {big.NewInt(1), big.NewInt(params.GWei * int64(30))}, // Fork point in first block 186 {big.NewInt(32), big.NewInt(params.GWei * int64(30))}, // Fork point in last block 187 {big.NewInt(33), big.NewInt(params.GWei * int64(30))}, // Fork point in the future 188 } 189 for _, c := range cases { 190 backend := newTestBackend(t, false) 191 oracle := NewOracle(backend, config) 192 193 // The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G 194 got, err := oracle.SuggestTipCap(context.Background()) 195 backend.teardown() 196 if err != nil { 197 t.Fatalf("Failed to retrieve recommended gas price: %v", err) 198 } 199 if got.Cmp(c.expect) != 0 { 200 t.Fatalf("Gas price mismatch, want %d, got %d", c.expect, got) 201 } 202 } 203 }