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
|
l.reserver = reserve
|
||||||
// TODO load transactions.rlp
|
// TODO load transactions.rlp
|
||||||
l.Reset(nil, head)
|
l.Reset(nil, head)
|
||||||
return errors.New("not implemented")
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LocalPool) Close() error {
|
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
|
// notify all listeners about successfully added txs
|
||||||
l.txFeed.Send(core.NewTxsEvent{Txs: successfulTxs})
|
l.txFeed.Send(core.NewTxsEvent{Txs: successfulTxs})
|
||||||
return nil
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LocalPool) add(tx *types.Transaction) error {
|
func (l *LocalPool) add(tx *types.Transaction) error {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
package localpool
|
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 {
|
func (l *LocalPool) verifyConsistency() error {
|
||||||
for _, list := range l.allAccounts {
|
for _, list := range l.allAccounts {
|
||||||
|
|
@ -25,3 +36,112 @@ func (l *LocalPool) verifyConsistency() error {
|
||||||
}
|
}
|
||||||
return nil
|
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