github.com/beyonderyue/gochain@v2.2.26+incompatible/eth/gasprice/gasprice_test.go (about) 1 package gasprice 2 3 import ( 4 "context" 5 "crypto/ecdsa" 6 "math/big" 7 "testing" 8 9 "math/rand" 10 11 "github.com/gochain-io/gochain/common" 12 "github.com/gochain-io/gochain/core/types" 13 "github.com/gochain-io/gochain/crypto" 14 "github.com/gochain-io/gochain/params" 15 "github.com/gochain-io/gochain/rpc" 16 ) 17 18 func TestOracle_SuggestPrice(t *testing.T) { 19 for _, test := range []suggestPriceTest{ 20 { 21 name: "default", 22 exp: Default.Uint64(), 23 params: Config{ 24 Blocks: 1, 25 Percentile: 60, 26 }, 27 backend: newTestBackend( 28 block{ 29 txs: []tx{{price: 1}}, 30 }, 31 ), 32 }, 33 { 34 name: "single", 35 exp: Default.Uint64(), 36 params: Config{ 37 Blocks: 1, 38 Percentile: 60, 39 }, 40 backend: newTestBackend( 41 block{ 42 txs: []tx{ 43 {price: 1000}, 44 }, 45 }, 46 ), 47 }, 48 { 49 name: "single full", 50 exp: 2000, 51 params: Config{ 52 Blocks: 1, 53 Percentile: 60, 54 }, 55 backend: newTestBackend( 56 block{ 57 full: true, 58 txs: []tx{ 59 {price: 2000}, 60 }, 61 }, 62 ), 63 }, 64 { 65 name: "incomplete", 66 exp: Default.Uint64(), 67 params: Config{ 68 Blocks: 10, 69 Percentile: 60, 70 }, 71 backend: newTestBackend( 72 block{ 73 full: true, 74 txs: []tx{ 75 {price: Default.Uint64() * 10}, 76 }, 77 }, 78 ), 79 }, 80 { 81 name: "some full", 82 exp: Default.Uint64(), 83 params: Config{ 84 Blocks: 5, 85 Percentile: 60, 86 }, 87 backend: newTestBackend( 88 block{ 89 full: true, 90 txs: []tx{{price: 10}}, 91 }, 92 block{ 93 txs: []tx{{price: 1}}, 94 }, 95 block{ 96 txs: []tx{{price: 5}}, 97 }, 98 block{ 99 full: true, 100 txs: []tx{{price: 7}}, 101 }, 102 block{ 103 txs: []tx{{price: 20}}, 104 }, 105 ), 106 }, 107 { 108 name: "some full-100", 109 exp: 20, 110 params: Config{ 111 Blocks: 5, 112 Percentile: 100, 113 Default: bigInt(1), 114 }, 115 backend: newTestBackend( 116 block{ 117 full: true, 118 txs: []tx{{price: 10}}, 119 }, 120 block{ 121 txs: []tx{{price: 1}}, 122 }, 123 block{ 124 txs: []tx{{price: 5}}, 125 }, 126 block{ 127 full: true, 128 txs: []tx{{price: 7}}, 129 }, 130 block{ 131 full: true, 132 txs: []tx{{price: 20}}, 133 }, 134 ), 135 }, 136 { 137 name: "all full", 138 exp: 7, 139 params: Config{ 140 Blocks: 5, 141 Percentile: 50, 142 }, 143 backend: newTestBackend( 144 block{ 145 full: true, 146 txs: []tx{{price: 10}}, 147 }, 148 block{ 149 full: true, 150 txs: []tx{{price: 1}}, 151 }, 152 block{ 153 full: true, 154 txs: []tx{{price: 5}}, 155 }, 156 block{ 157 full: true, 158 txs: []tx{{price: 7}}, 159 }, 160 block{ 161 full: true, 162 txs: []tx{{price: 20}}, 163 }, 164 ), 165 }, 166 { 167 name: "some empty", 168 exp: 5, 169 params: Config{ 170 Blocks: 5, 171 Percentile: 60, 172 Default: bigInt(1), 173 }, 174 backend: newTestBackend( 175 block{ 176 full: true, 177 txs: []tx{{price: 10}}, 178 }, 179 block{}, 180 block{ 181 full: true, 182 txs: []tx{{price: 5}}, 183 }, 184 block{ 185 full: true, 186 txs: []tx{{price: 7}}, 187 }, 188 block{}, 189 ), 190 }, 191 { 192 name: "all empty", 193 exp: Default.Uint64(), 194 params: Config{ 195 Blocks: 5, 196 Percentile: 50, 197 }, 198 backend: newTestBackend( 199 block{}, 200 block{}, 201 block{}, 202 block{}, 203 block{}, 204 ), 205 }, 206 { 207 name: "all full local", 208 exp: 1, 209 params: Config{ 210 Blocks: 5, 211 Percentile: 50, 212 Default: bigInt(1), 213 }, 214 backend: newTestBackend( 215 block{ 216 full: true, 217 txs: []tx{{price: 10, local: true}}, 218 }, 219 block{ 220 full: true, 221 txs: []tx{{price: 50, local: true}}, 222 }, 223 block{ 224 full: true, 225 txs: []tx{{price: 5, local: true}}, 226 }, 227 block{ 228 full: true, 229 txs: []tx{{price: 7, local: true}}, 230 }, 231 block{ 232 full: true, 233 txs: []tx{{price: 20, local: true}}, 234 }, 235 ), 236 }, 237 } { 238 t.Run(test.name, test.run) 239 } 240 241 } 242 243 type suggestPriceTest struct { 244 name string 245 exp uint64 246 params Config 247 backend Backend 248 } 249 250 func (test *suggestPriceTest) run(t *testing.T) { 251 o := NewOracle(test.backend, test.params) 252 got, err := o.SuggestPrice(context.Background()) 253 if err != nil { 254 t.Fatal(err) 255 } 256 if got.Uint64() != test.exp { 257 t.Errorf("expected %d but got %s", test.exp, got) 258 } 259 } 260 261 type testBackend struct { 262 config *params.ChainConfig 263 lastHeader *types.Header 264 blocks []*types.Block 265 } 266 267 type block struct { 268 full bool 269 txs []tx 270 } 271 272 type tx struct { 273 price uint64 274 local bool 275 } 276 277 func newTestBackend(blockSpec ...block) Backend { 278 number := rand.Intn(1000) 279 localKey, _ := crypto.GenerateKey() 280 localAddr := crypto.PubkeyToAddress(localKey.PublicKey) 281 otherKey, _ := crypto.GenerateKey() 282 var blocks []*types.Block 283 for i, b := range blockSpec { 284 gasUsed := uint64(len(b.txs)) * params.TxGas 285 gasLimit := gasUsed 286 if !b.full { 287 gasLimit += params.TxGas * 5 288 } 289 header := &types.Header{ 290 Number: new(big.Int).SetUint64(uint64(number + i)), 291 GasUsed: gasUsed, 292 GasLimit: gasLimit, 293 Coinbase: localAddr, 294 } 295 var txs []*types.Transaction 296 for _, tx := range b.txs { 297 key := otherKey 298 if tx.local { 299 key = localKey 300 } 301 txs = append(txs, transaction(0, tx.price, key)) 302 } 303 blocks = append(blocks, types.NewBlock(header, txs, nil, nil)) 304 } 305 return &testBackend{ 306 config: params.MainnetChainConfig, 307 lastHeader: blocks[len(blocks)-1].Header(), 308 blocks: blocks, 309 } 310 } 311 312 func (b *testBackend) ChainConfig() *params.ChainConfig { 313 return b.config 314 } 315 316 func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Header, error) { 317 if blockNr == rpc.LatestBlockNumber { 318 return b.lastHeader, nil 319 } 320 return nil, nil 321 } 322 323 func (b *testBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) { 324 for _, block := range b.blocks { 325 if block.Number().Int64() == int64(blockNr) { 326 return block, nil 327 } 328 } 329 return nil, nil 330 } 331 332 func bigInt(i uint64) *big.Int { 333 return new(big.Int).SetUint64(i) 334 } 335 336 func transaction(nonce uint64, gasPrice uint64, key *ecdsa.PrivateKey) *types.Transaction { 337 tx, _ := types.SignTx(types.NewTransaction(nonce, common.Address{}, big.NewInt(100), 100, bigInt(gasPrice), nil), types.HomesteadSigner{}, key) 338 return tx 339 }