mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/txpool/localpool: add basic test and benchmark
This commit is contained in:
parent
6bbe856697
commit
a4f2744da2
3 changed files with 162 additions and 3 deletions
39
core/txpool/localpool/blockchain_test.go
Normal file
39
core/txpool/localpool/blockchain_test.go
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
package localpool
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
type MockBC struct {
|
||||
currentBlock *types.Header
|
||||
dbs map[common.Hash]*state.StateDB
|
||||
}
|
||||
|
||||
func (m *MockBC) Config() *params.ChainConfig {
|
||||
return params.AllDevChainProtocolChanges
|
||||
}
|
||||
|
||||
func (m *MockBC) CurrentBlock() *types.Header {
|
||||
return m.currentBlock
|
||||
}
|
||||
|
||||
func (m *MockBC) GetBlock(hash common.Hash, number uint64) *types.Block {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockBC) StateAt(root common.Hash) (*state.StateDB, error) {
|
||||
state, ok := m.dbs[root]
|
||||
if !ok {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func (m *MockBC) SetState(root common.Hash, db *state.StateDB) {
|
||||
m.dbs[root] = db
|
||||
}
|
||||
|
|
@ -87,7 +87,7 @@ func (l *LocalPool) Init(gasTip *big.Int, head *types.Header, reserve txpool.Add
|
|||
l.reserver = reserve
|
||||
// TODO load transactions.rlp
|
||||
l.Reset(nil, head)
|
||||
return errors.New("not implemented")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LocalPool) Close() error {
|
||||
|
|
@ -149,7 +149,7 @@ func (l *LocalPool) Add(txs []*types.Transaction, local bool, sync bool) []error
|
|||
}
|
||||
// notify all listeners about successfully added txs
|
||||
l.txFeed.Send(core.NewTxsEvent{Txs: successfulTxs})
|
||||
return nil
|
||||
return errs
|
||||
}
|
||||
|
||||
func (l *LocalPool) add(tx *types.Transaction) error {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,17 @@
|
|||
package localpool
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func (l *LocalPool) verifyConsistency() error {
|
||||
for _, list := range l.allAccounts {
|
||||
|
|
@ -25,3 +36,112 @@ func (l *LocalPool) verifyConsistency() error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestReset(t *testing.T) {
|
||||
// Generate a faucet
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
// Setup a mock blockchain
|
||||
bc := &MockBC{
|
||||
currentBlock: &types.Header{Root: common.Hash{}},
|
||||
dbs: make(map[common.Hash]*state.StateDB),
|
||||
}
|
||||
initialDB, err := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initialDB.CreateAccount(addr)
|
||||
initialDB.SetBalance(addr, big.NewInt(1_000_000_000_000_000_000))
|
||||
bc.SetState(common.Hash{}, initialDB)
|
||||
// Setup the txpool
|
||||
pool, err := NewLocalPool(bc, types.LatestSigner(params.AllDevChainProtocolChanges))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := pool.Init(nil, &types.Header{Root: common.Hash{}, GasLimit: 200_000}, func(addr common.Address, reserve bool) error { return nil }); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Queue transactions
|
||||
// TODO there might be an off-by-one error here
|
||||
for i := 1; i < 100; i++ {
|
||||
tx := types.NewTransaction(uint64(i), common.Address{}, new(big.Int), 100000, big.NewInt(1234), nil)
|
||||
signer := types.LatestSigner(params.AllDevChainProtocolChanges)
|
||||
signed, err := types.SignTx(tx, signer, key)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if errs := pool.Add([]*types.Transaction{signed}, true, false); errs[0] != nil {
|
||||
t.Fatal(errs[0])
|
||||
}
|
||||
}
|
||||
// Verify integrity
|
||||
if err := pool.verifyConsistency(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pending, queued := pool.ContentFrom(addr)
|
||||
if len(pending) != 99 || len(queued) != 0 {
|
||||
t.Fatal(len(pending), len(queued))
|
||||
}
|
||||
// Reset the pool
|
||||
newDB := initialDB.Copy()
|
||||
newDB.SetNonce(addr, uint64(100+1))
|
||||
bc.SetState(common.Hash{1}, newDB)
|
||||
pool.Reset(nil, &types.Header{Root: common.Hash{1}})
|
||||
// Verify post state
|
||||
if err := pool.verifyConsistency(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pending, queued = pool.ContentFrom(addr)
|
||||
if len(pending) != 0 || len(queued) != 0 {
|
||||
t.Fatal(pending, queued)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReorg(b *testing.B) {
|
||||
// Generate a faucet
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
addr := crypto.PubkeyToAddress(key.PublicKey)
|
||||
// Setup a mock blockchain
|
||||
bc := &MockBC{
|
||||
currentBlock: &types.Header{Root: common.Hash{}},
|
||||
dbs: make(map[common.Hash]*state.StateDB),
|
||||
}
|
||||
initialDB, err := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
initialDB.CreateAccount(addr)
|
||||
initialDB.SetBalance(addr, big.NewInt(1_000_000_000_000_000_000))
|
||||
bc.SetState(common.Hash{}, initialDB)
|
||||
// Setup the txpool
|
||||
pool, err := NewLocalPool(bc, types.LatestSigner(params.AllDevChainProtocolChanges))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if err := pool.Init(nil, &types.Header{Root: common.Hash{}, GasLimit: 200_000}, func(addr common.Address, reserve bool) error { return nil }); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
// Queue transactions
|
||||
for i := 0; i < b.N; i++ {
|
||||
tx := types.NewTransaction(uint64(i), common.Address{}, new(big.Int), 100000, big.NewInt(1234), nil)
|
||||
signer := types.LatestSigner(params.AllDevChainProtocolChanges)
|
||||
signed, err := types.SignTx(tx, signer, key)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
if errs := pool.Add([]*types.Transaction{signed}, true, false); errs[0] != nil {
|
||||
b.Fatal(errs[0])
|
||||
}
|
||||
}
|
||||
newDB := initialDB.Copy()
|
||||
newDB.SetNonce(addr, uint64(b.N+1))
|
||||
bc.SetState(common.Hash{1}, newDB)
|
||||
b.ResetTimer()
|
||||
pool.Reset(nil, &types.Header{Root: common.Hash{1}})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue