gasprice_test.go 6.4 KB

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