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  }