github.com/DxChainNetwork/dxc@v0.8.1-0.20220824085222-1162e304b6e7/eth/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/DxChainNetwork/dxc/common" 26 "github.com/DxChainNetwork/dxc/consensus/ethash" 27 "github.com/DxChainNetwork/dxc/core" 28 "github.com/DxChainNetwork/dxc/core/rawdb" 29 "github.com/DxChainNetwork/dxc/core/types" 30 "github.com/DxChainNetwork/dxc/core/vm" 31 "github.com/DxChainNetwork/dxc/crypto" 32 "github.com/DxChainNetwork/dxc/event" 33 "github.com/DxChainNetwork/dxc/params" 34 "github.com/DxChainNetwork/dxc/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.LatestBlockNumber { 49 number = testHead 50 } 51 if number == rpc.PendingBlockNumber { 52 if b.pending { 53 number = testHead + 1 54 } else { 55 return nil, nil 56 } 57 } 58 return b.chain.GetHeaderByNumber(uint64(number)), nil 59 } 60 61 func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) { 62 if number > testHead { 63 return nil, nil 64 } 65 if number == rpc.LatestBlockNumber { 66 number = testHead 67 } 68 if number == rpc.PendingBlockNumber { 69 if b.pending { 70 number = testHead + 1 71 } else { 72 return nil, nil 73 } 74 } 75 return b.chain.GetBlockByNumber(uint64(number)), nil 76 } 77 78 func (b *testBackend) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) { 79 return b.chain.GetReceiptsByHash(hash), nil 80 } 81 82 func (b *testBackend) PendingBlockAndReceipts() (*types.Block, types.Receipts) { 83 if b.pending { 84 block := b.chain.GetBlockByNumber(testHead + 1) 85 return block, b.chain.GetReceiptsByHash(block.Hash()) 86 } 87 return nil, nil 88 } 89 90 func (b *testBackend) ChainConfig() *params.ChainConfig { 91 return b.chain.Config() 92 } 93 94 func (b *testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { 95 return nil 96 } 97 98 func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend { 99 var ( 100 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 101 addr = crypto.PubkeyToAddress(key.PublicKey) 102 gspec = &core.Genesis{ 103 Config: params.TestChainConfig, 104 Alloc: core.GenesisAlloc{addr: {Balance: big.NewInt(math.MaxInt64)}}, 105 } 106 signer = types.LatestSigner(gspec.Config) 107 ) 108 if londonBlock != nil { 109 gspec.Config.LondonBlock = londonBlock 110 signer = types.LatestSigner(gspec.Config) 111 } else { 112 gspec.Config.LondonBlock = nil 113 } 114 engine := ethash.NewFaker() 115 db := rawdb.NewMemoryDatabase() 116 genesis, _ := gspec.Commit(db) 117 118 // Generate testing blocks 119 blocks, _ := core.GenerateChain(gspec.Config, genesis, engine, db, testHead+1, func(i int, b *core.BlockGen) { 120 b.SetCoinbase(common.Address{1}) 121 122 var tx *types.Transaction 123 if londonBlock != nil && b.Number().Cmp(londonBlock) >= 0 { 124 txdata := &types.DynamicFeeTx{ 125 ChainID: gspec.Config.ChainID, 126 Nonce: b.TxNonce(addr), 127 To: &common.Address{}, 128 Gas: 30000, 129 GasFeeCap: big.NewInt(100 * params.GWei), 130 GasTipCap: big.NewInt(int64(i+1) * params.GWei), 131 Data: []byte{}, 132 } 133 tx = types.NewTx(txdata) 134 } else { 135 txdata := &types.LegacyTx{ 136 Nonce: b.TxNonce(addr), 137 To: &common.Address{}, 138 Gas: 21000, 139 GasPrice: big.NewInt(int64(i+1) * params.GWei), 140 Value: big.NewInt(100), 141 Data: []byte{}, 142 } 143 tx = types.NewTx(txdata) 144 } 145 tx, err := types.SignTx(tx, signer, key) 146 if err != nil { 147 t.Fatalf("failed to create tx: %v", err) 148 } 149 b.AddTx(tx) 150 }) 151 // Construct testing chain 152 diskdb := rawdb.NewMemoryDatabase() 153 gspec.Commit(diskdb) 154 chain, err := core.NewBlockChain(diskdb, nil, gspec.Config, engine, vm.Config{}, nil, nil) 155 if err != nil { 156 t.Fatalf("Failed to create local chain, %v", err) 157 } 158 chain.InsertChain(blocks) 159 return &testBackend{chain: chain, pending: pending} 160 } 161 162 func (b *testBackend) CurrentHeader() *types.Header { 163 return b.chain.CurrentHeader() 164 } 165 166 func (b *testBackend) GetBlockByNumber(number uint64) *types.Block { 167 return b.chain.GetBlockByNumber(number) 168 } 169 170 func TestSuggestTipCap(t *testing.T) { 171 config := Config{ 172 Blocks: 3, 173 Percentile: 60, 174 Default: big.NewInt(params.GWei), 175 } 176 var cases = []struct { 177 fork *big.Int // London fork number 178 expect *big.Int // Expected gasprice suggestion 179 }{ 180 {nil, big.NewInt(params.GWei * int64(30))}, 181 {big.NewInt(0), big.NewInt(params.GWei * int64(30))}, // Fork point in genesis 182 {big.NewInt(1), big.NewInt(params.GWei * int64(30))}, // Fork point in first block 183 {big.NewInt(32), big.NewInt(params.GWei * int64(30))}, // Fork point in last block 184 {big.NewInt(33), big.NewInt(params.GWei * int64(30))}, // Fork point in the future 185 } 186 for _, c := range cases { 187 backend := newTestBackend(t, c.fork, false) 188 oracle := NewOracle(backend, config) 189 190 // The gas price sampled is: 32G, 31G, 30G, 29G, 28G, 27G 191 got, err := oracle.SuggestTipCap(context.Background()) 192 if err != nil { 193 t.Fatalf("Failed to retrieve recommended gas price: %v", err) 194 } 195 if got.Cmp(c.expect) != 0 { 196 t.Fatalf("Gas price mismatch, want %d, got %d", c.expect, got) 197 } 198 } 199 }