diff --git a/consensus/bor/api/caller_mock.go b/consensus/bor/api/caller_mock.go index fb8fa3b3c6..312467e435 100644 --- a/consensus/bor/api/caller_mock.go +++ b/consensus/bor/api/caller_mock.go @@ -30,7 +30,6 @@ type MockCallerMockRecorder struct { func NewMockCaller(ctrl *gomock.Controller) *MockCaller { mock := &MockCaller{ctrl: ctrl} mock.recorder = &MockCallerMockRecorder{mock} - return mock } @@ -40,33 +39,31 @@ func (m *MockCaller) EXPECT() *MockCallerMockRecorder { } // Call mocks base method. -func (m *MockCaller) Call(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *ethapi.StateOverride) (hexutil.Bytes, error) { +func (m *MockCaller) Call(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *ethapi.StateOverride, arg4 *ethapi.BlockOverrides) (hexutil.Bytes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Call", arg0, arg1, arg2, arg3) + ret := m.ctrl.Call(m, "Call", arg0, arg1, arg2, arg3, arg4) ret0, _ := ret[0].(hexutil.Bytes) ret1, _ := ret[1].(error) - return ret0, ret1 } // Call indicates an expected call of Call. -func (mr *MockCallerMockRecorder) Call(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { +func (mr *MockCallerMockRecorder) Call(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCaller)(nil).Call), arg0, arg1, arg2, arg3) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCaller)(nil).Call), arg0, arg1, arg2, arg3, arg4) } // CallWithState mocks base method. -func (m *MockCaller) CallWithState(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *state.StateDB, arg4 *ethapi.StateOverride) (hexutil.Bytes, error) { +func (m *MockCaller) CallWithState(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *state.StateDB, arg4 *ethapi.StateOverride, arg5 *ethapi.BlockOverrides) (hexutil.Bytes, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CallWithState", arg0, arg1, arg2, arg3, arg4) + ret := m.ctrl.Call(m, "CallWithState", arg0, arg1, arg2, arg3, arg4, arg5) ret0, _ := ret[0].(hexutil.Bytes) ret1, _ := ret[1].(error) - return ret0, ret1 } // CallWithState indicates an expected call of CallWithState. -func (mr *MockCallerMockRecorder) CallWithState(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call { +func (mr *MockCallerMockRecorder) CallWithState(arg0, arg1, arg2, arg3, arg4, arg5 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CallWithState", reflect.TypeOf((*MockCaller)(nil).CallWithState), arg0, arg1, arg2, arg3, arg4) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CallWithState", reflect.TypeOf((*MockCaller)(nil).CallWithState), arg0, arg1, arg2, arg3, arg4, arg5) } diff --git a/core/txpool/blobpool/blobpool_test.go b/core/txpool/blobpool/blobpool_test.go index 74caf79ec7..b877639eee 100644 --- a/core/txpool/blobpool/blobpool_test.go +++ b/core/txpool/blobpool/blobpool_test.go @@ -189,6 +189,10 @@ func makeAddressReserver() txpool.AddressReserver { } } +func MakeAddressReserver() { + makeAddressReserver() +} + // makeTx is a utility method to construct a random blob transaction and sign it // with a valid key, only setting the interesting fields from the perspective of // the blob pool. diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 7ccbc0f13e..a068db5104 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -241,6 +241,8 @@ type LegacyPool struct { initDoneCh chan struct{} // is closed once the pool is initialized (for tests) changesSinceReorg int // A counter for how many drops we've performed in-between reorg. + + promoteTxCh chan struct{} // should be used only for tests } type txpoolResetRequest struct { @@ -249,7 +251,7 @@ type txpoolResetRequest struct { // New creates a new transaction pool to gather, sort and filter inbound // transactions from the network. -func New(config Config, chain BlockChain) *LegacyPool { +func New(config Config, chain BlockChain, options ...func(pool *LegacyPool)) *LegacyPool { // Sanitize the input to ensure no vulnerable gas prices are set config = (&config).sanitize() @@ -280,6 +282,11 @@ func New(config Config, chain BlockChain) *LegacyPool { if !config.NoLocals && config.Journal != "" { pool.journal = newTxJournal(config.Journal) } + + // apply options + for _, fn := range options { + fn(pool) + } return pool } diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index 81b492f5dd..bd155fdd67 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -172,12 +172,12 @@ func setupPool() (*LegacyPool, *ecdsa.PrivateKey) { return setupPoolWithConfig(params.TestChainConfig) } -func setupPoolWithConfig(config *params.ChainConfig) (*LegacyPool, *ecdsa.PrivateKey) { +func setupPoolWithConfig(config *params.ChainConfig, options ...func(pool *LegacyPool)) (*LegacyPool, *ecdsa.PrivateKey) { statedb, _ := state.New(types.EmptyRootHash, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) blockchain := newTestBlockChain(config, 10000000, statedb, new(event.Feed)) key, _ := crypto.GenerateKey() - pool := New(testTxPoolConfig, blockchain) + pool := New(testTxPoolConfig, blockchain, options...) if err := pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver()); err != nil { panic(err) } @@ -2982,105 +2982,109 @@ func BenchmarkPoolAccountMultiBatchInsert(b *testing.B) { } } -// TODO - Arpit -// func BenchmarkPoolAccountMultiBatchInsertRace(b *testing.B) { -// // Generate a batch of transactions to enqueue into the pool -// pool, _ := setupPool() -// defer pool.Close() +func BenchmarkPoolAccountMultiBatchInsertRace(b *testing.B) { + // Generate a batch of transactions to enqueue into the pool + pool, _ := setupPool() + defer pool.Close() -// batches := make(types.Transactions, b.N) + batches := make(types.Transactions, b.N) -// for i := 0; i < b.N; i++ { -// key, _ := crypto.GenerateKey() -// account := crypto.PubkeyToAddress(key.PublicKey) -// tx := transaction(uint64(0), 100000, key) + for i := 0; i < b.N; i++ { + key, _ := crypto.GenerateKey() + account := crypto.PubkeyToAddress(key.PublicKey) + tx := transaction(uint64(0), 100000, key) -// pool.currentState.AddBalance(account, big.NewInt(1000000)) + pool.currentState.AddBalance(account, big.NewInt(1000000)) -// batches[i] = tx -// } + batches[i] = tx + } -// done := make(chan struct{}) + done := make(chan struct{}) -// go func() { -// t := time.NewTicker(time.Microsecond) -// defer t.Stop() + go func() { + t := time.NewTicker(time.Microsecond) + defer t.Stop() -// var pending map[common.Address]types.Transactions + var pending map[common.Address][]*txpool.LazyTransaction -// loop: -// for { -// select { -// case <-t.C: -// pending = pool.Pending(true) -// case <-done: -// break loop -// } -// } + loop: + for { + select { + case <-t.C: + pending = pool.Pending(true) + case <-done: + break loop + } + } -// fmt.Fprint(io.Discard, pending) -// }() + fmt.Fprint(io.Discard, pending) + }() -// b.ReportAllocs() -// b.ResetTimer() + b.ReportAllocs() + b.ResetTimer() -// for _, tx := range batches { -// pool.addRemotesSync([]*types.Transaction{tx}) -// } + for _, tx := range batches { + pool.addRemotesSync([]*types.Transaction{tx}) + } -// close(done) -// } + close(done) +} -// TODO - Arpit -// func BenchmarkPoolAccountMultiBatchInsertNoLockRace(b *testing.B) { -// // Generate a batch of transactions to enqueue into the pool -// pendingAddedCh := make(chan struct{}, 1024) +func MakeWithPromoteTxCh(ch chan struct{}) func(*LegacyPool) { + return func(pool *LegacyPool) { + pool.promoteTxCh = ch + } +} -// pool, localKey := setupPoolWithConfig(params.TestChainConfig, testTxPoolConfig, txPoolGasLimit, MakeWithPromoteTxCh(pendingAddedCh)) -// defer pool.Close() +func BenchmarkPoolAccountMultiBatchInsertNoLockRace(b *testing.B) { + // Generate a batch of transactions to enqueue into the pool + pendingAddedCh := make(chan struct{}, 1024) -// _ = localKey + pool, localKey := setupPoolWithConfig(params.TestChainConfig, MakeWithPromoteTxCh(pendingAddedCh)) + defer pool.Close() -// batches := make(types.Transactions, b.N) + _ = localKey -// for i := 0; i < b.N; i++ { -// key, _ := crypto.GenerateKey() -// account := crypto.PubkeyToAddress(key.PublicKey) -// tx := transaction(uint64(0), 100000, key) + batches := make(types.Transactions, b.N) -// pool.currentState.AddBalance(account, big.NewInt(1000000)) + for i := 0; i < b.N; i++ { + key, _ := crypto.GenerateKey() + account := crypto.PubkeyToAddress(key.PublicKey) + tx := transaction(uint64(0), 100000, key) -// batches[i] = tx -// } + pool.currentState.AddBalance(account, big.NewInt(1000000)) -// done := make(chan struct{}) + batches[i] = tx + } -// go func() { -// t := time.NewTicker(time.Microsecond) -// defer t.Stop() + done := make(chan struct{}) -// var pending map[common.Address]types.Transactions + go func() { + t := time.NewTicker(time.Microsecond) + defer t.Stop() -// for range t.C { -// pending = pool.Pending(true) + var pending map[common.Address][]*txpool.LazyTransaction -// if len(pending) >= b.N/2 { -// close(done) + for range t.C { + pending = pool.Pending(true) -// return -// } -// } -// }() + if len(pending) >= b.N/2 { + close(done) -// b.ReportAllocs() -// b.ResetTimer() + return + } + } + }() -// for _, tx := range batches { -// pool.addRemotes([]*types.Transaction{tx}) -// } + b.ReportAllocs() + b.ResetTimer() -// <-done -// } + for _, tx := range batches { + pool.addRemotes([]*types.Transaction{tx}) + } + + <-done +} func BenchmarkPoolAccountsBatchInsert(b *testing.B) { // Generate a batch of transactions to enqueue into the pool @@ -3109,169 +3113,166 @@ func BenchmarkPoolAccountsBatchInsert(b *testing.B) { } } -// TODO - Arpit -// func BenchmarkPoolAccountsBatchInsertRace(b *testing.B) { -// // Generate a batch of transactions to enqueue into the pool -// pool, _ := setupPool() -// defer pool.Close() +func BenchmarkPoolAccountsBatchInsertRace(b *testing.B) { + // Generate a batch of transactions to enqueue into the pool + pool, _ := setupPool() + defer pool.Close() -// batches := make(types.Transactions, b.N) + batches := make(types.Transactions, b.N) -// for i := 0; i < b.N; i++ { -// key, _ := crypto.GenerateKey() -// account := crypto.PubkeyToAddress(key.PublicKey) -// tx := transaction(uint64(0), 100000, key) + for i := 0; i < b.N; i++ { + key, _ := crypto.GenerateKey() + account := crypto.PubkeyToAddress(key.PublicKey) + tx := transaction(uint64(0), 100000, key) -// pool.currentState.AddBalance(account, big.NewInt(1000000)) + pool.currentState.AddBalance(account, big.NewInt(1000000)) -// batches[i] = tx -// } + batches[i] = tx + } -// done := make(chan struct{}) + done := make(chan struct{}) -// go func() { -// t := time.NewTicker(time.Microsecond) -// defer t.Stop() + go func() { + t := time.NewTicker(time.Microsecond) + defer t.Stop() -// var pending map[common.Address]types.Transactions + var pending map[common.Address][]*txpool.LazyTransaction -// loop: -// for { -// select { -// case <-t.C: -// pending = pool.Pending(true) -// case <-done: -// break loop -// } -// } + loop: + for { + select { + case <-t.C: + pending = pool.Pending(true) + case <-done: + break loop + } + } -// fmt.Fprint(io.Discard, pending) -// }() + fmt.Fprint(io.Discard, pending) + }() -// b.ReportAllocs() -// b.ResetTimer() + b.ReportAllocs() + b.ResetTimer() -// for _, tx := range batches { -// _ = pool.addRemoteSync(tx) -// } + for _, tx := range batches { + _ = pool.addRemoteSync(tx) + } -// close(done) -// } + close(done) +} -// TODO - Arpit -// func BenchmarkPoolAccountsBatchInsertNoLockRace(b *testing.B) { -// // Generate a batch of transactions to enqueue into the pool -// pendingAddedCh := make(chan struct{}, 1024) +func BenchmarkPoolAccountsBatchInsertNoLockRace(b *testing.B) { + // Generate a batch of transactions to enqueue into the pool + pendingAddedCh := make(chan struct{}, 1024) -// pool, localKey := setupPoolWithConfig(params.TestChainConfig, testTxPoolConfig, txPoolGasLimit, MakeWithPromoteTxCh(pendingAddedCh)) -// defer pool.Close() + pool, localKey := setupPoolWithConfig(params.TestChainConfig, MakeWithPromoteTxCh(pendingAddedCh)) + defer pool.Close() -// _ = localKey + _ = localKey -// batches := make(types.Transactions, b.N) + batches := make(types.Transactions, b.N) -// for i := 0; i < b.N; i++ { -// key, _ := crypto.GenerateKey() -// account := crypto.PubkeyToAddress(key.PublicKey) -// tx := transaction(uint64(0), 100000, key) + for i := 0; i < b.N; i++ { + key, _ := crypto.GenerateKey() + account := crypto.PubkeyToAddress(key.PublicKey) + tx := transaction(uint64(0), 100000, key) -// pool.currentState.AddBalance(account, big.NewInt(1000000)) + pool.currentState.AddBalance(account, big.NewInt(1000000)) -// batches[i] = tx -// } + batches[i] = tx + } -// done := make(chan struct{}) + done := make(chan struct{}) -// go func() { -// t := time.NewTicker(time.Microsecond) -// defer t.Stop() + go func() { + t := time.NewTicker(time.Microsecond) + defer t.Stop() -// var pending map[common.Address]types.Transactions + var pending map[common.Address][]*txpool.LazyTransaction -// for range t.C { -// pending = pool.Pending(true) + for range t.C { + pending = pool.Pending(true) -// if len(pending) >= b.N/2 { -// close(done) + if len(pending) >= b.N/2 { + close(done) -// return -// } -// } -// }() + return + } + } + }() -// b.ReportAllocs() -// b.ResetTimer() + b.ReportAllocs() + b.ResetTimer() -// for _, tx := range batches { -// _ = pool.addRemote(tx) -// } + for _, tx := range batches { + _ = pool.addRemote(tx) + } -// <-done -// } + <-done +} -// TODO - Arpit -// func TestPoolMultiAccountBatchInsertRace(t *testing.T) { -// t.Parallel() +func TestPoolMultiAccountBatchInsertRace(t *testing.T) { + t.Parallel() -// // Generate a batch of transactions to enqueue into the pool -// pool, _ := setupPool() -// defer pool.Close() + // Generate a batch of transactions to enqueue into the pool + pool, _ := setupPool() + defer pool.Close() -// const n = 5000 + const n = 5000 -// batches := make(types.Transactions, n) -// batchesSecond := make(types.Transactions, n) + batches := make(types.Transactions, n) + batchesSecond := make(types.Transactions, n) -// for i := 0; i < n; i++ { -// batches[i] = newTxs(pool) -// batchesSecond[i] = newTxs(pool) -// } + for i := 0; i < n; i++ { + batches[i] = newTxs(pool) + batchesSecond[i] = newTxs(pool) + } -// done := make(chan struct{}) + done := make(chan struct{}) -// go func() { -// t := time.NewTicker(time.Microsecond) -// defer t.Stop() + go func() { + t := time.NewTicker(time.Microsecond) + defer t.Stop() -// var ( -// pending map[common.Address]types.Transactions -// total int -// ) + var ( + pending map[common.Address][]*txpool.LazyTransaction + total int + ) -// for range t.C { -// pending = pool.Pending(true) -// total = len(pending) + for range t.C { + pending = pool.Pending(true) + total = len(pending) -// _ = pool.Locals() + _ = pool.Locals() -// if total >= n { -// close(done) + if total >= n { + close(done) -// return -// } -// } -// }() + return + } + } + }() -// for _, tx := range batches { -// pool.addRemotesSync([]*types.Transaction{tx}) -// } + for _, tx := range batches { + pool.addRemotesSync([]*types.Transaction{tx}) + } -// for _, tx := range batchesSecond { -// pool.addRemotes([]*types.Transaction{tx}) -// } + for _, tx := range batchesSecond { + pool.addRemotes([]*types.Transaction{tx}) + } -// <-done -// } + <-done +} -// func newTxs(pool *LegacyPool) *types.Transaction { -// key, _ := crypto.GenerateKey() -// account := crypto.PubkeyToAddress(key.PublicKey) -// tx := transaction(uint64(0), 100000, key) +func newTxs(pool *LegacyPool) *types.Transaction { + key, _ := crypto.GenerateKey() + account := crypto.PubkeyToAddress(key.PublicKey) + tx := transaction(uint64(0), 100000, key) -// pool.currentState.AddBalance(account, big.NewInt(1_000_000_000)) + pool.currentState.AddBalance(account, big.NewInt(1_000_000_000)) -// return tx -// } + return tx +} type acc struct { nonce uint64 @@ -3399,7 +3400,7 @@ func defaultTxPoolRapidConfig() txPoolRapidConfig { } } -// TODO - Arpit +// TODO - Fix Later // TestSmallTxPool is not something to run in parallel as far it uses all CPUs // nolint:paralleltest // func TestSmallTxPool(t *testing.T) { @@ -3421,6 +3422,7 @@ func defaultTxPoolRapidConfig() txPoolRapidConfig { // testPoolBatchInsert(t, cfg) // } +// TODO - Fix Later // // This test is not something to run in parallel as far it uses all CPUs // // nolint:paralleltest // func TestBigTxPool(t *testing.T) { @@ -3893,6 +3895,7 @@ func BenchmarkBigs(b *testing.B) { // return total, pendingDuration, miningDuration // } +// TODO - Fix Later //nolint:paralleltest // func TestPoolMiningDataRaces(t *testing.T) { // if testing.Short() { diff --git a/eth/api_backend.go b/eth/api_backend.go index 3446b448a4..4474de6f6e 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -319,8 +319,11 @@ func (b *EthAPIBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscri return b.eth.BlockChain().SubscribeLogsEvent(ch) } -// TODO - Arpit func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { + if signedTx.GetOptions() != nil && !b.eth.Miner().GetWorker().IsRunning() { + return errors.New("bundled transactions are not broadcasted therefore they will not submitted to the transaction pool") + } + return b.eth.txPool.Add([]*txpool.Transaction{{Tx: signedTx}}, true, false)[0] } diff --git a/eth/protocols/eth/broadcast.go b/eth/protocols/eth/broadcast.go index f4b52f40e5..66400812b2 100644 --- a/eth/protocols/eth/broadcast.go +++ b/eth/protocols/eth/broadcast.go @@ -80,11 +80,14 @@ func (p *Peer) broadcastTransactions() { size common.StorageSize ) for i := 0; i < len(queue) && size < maxTxPacketSize; i++ { - // TODO - Arpit Pratik changes - if tx := p.txpool.Get(queue[i]); tx != nil { + tx := p.txpool.Get(queue[i]) + + // Skip EIP-4337 bundled transactions + if tx != nil && tx.Tx.GetOptions() == nil { txs = append(txs, tx.Tx) size += common.StorageSize(tx.Tx.Size()) } + hashesCount++ } queue = queue[:copy(queue, queue[hashesCount:])] @@ -150,9 +153,9 @@ func (p *Peer) announceTransactions() { size common.StorageSize ) for count = 0; count < len(queue) && size < maxTxPacketSize; count++ { - - // TODO - Arpit Pratik changes - if tx := p.txpool.Get(queue[count]); tx != nil { + tx := p.txpool.Get(queue[count]) + // Skip EIP-4337 bundled transactions + if tx != nil && tx.Tx.GetOptions() == nil { pending = append(pending, queue[count]) pendingTypes = append(pendingTypes, tx.Tx.Type()) pendingSizes = append(pendingSizes, uint32(tx.Tx.Size())) diff --git a/miner/fake_miner.go b/miner/fake_miner.go index 74296ec9be..2b2cff45e9 100644 --- a/miner/fake_miner.go +++ b/miner/fake_miner.go @@ -1,18 +1,29 @@ package miner import ( + "errors" + "math/big" + "testing" + "github.com/golang/mock/gomock" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/bor" "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/txpool/legacypool" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/tests/bor/mocks" "github.com/ethereum/go-ethereum/trie" ) @@ -27,100 +38,86 @@ type DefaultBorMiner struct { ContractMock bor.GenesisContract } -// TODO - Arpit -// func NewBorDefaultMiner(t *testing.T) *DefaultBorMiner { -// t.Helper() +func NewBorDefaultMiner(t *testing.T) *DefaultBorMiner { + t.Helper() -// ctrl := gomock.NewController(t) + ctrl := gomock.NewController(t) -// ethAPI := api.NewMockCaller(ctrl) -// ethAPI.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + ethAPI := api.NewMockCaller(ctrl) + ethAPI.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() -// spanner := bor.NewMockSpanner(ctrl) -// spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ -// { -// ID: 0, -// Address: common.Address{0x1}, -// VotingPower: 100, -// ProposerPriority: 0, -// }, -// }, nil).AnyTimes() + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: common.Address{0x1}, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() -// heimdallClient := mocks.NewMockIHeimdallClient(ctrl) -// heimdallClient.EXPECT().Close().Times(1) + heimdallClient := mocks.NewMockIHeimdallClient(ctrl) + heimdallClient.EXPECT().Close().Times(1) -// genesisContracts := bor.NewMockGenesisContract(ctrl) + genesisContracts := bor.NewMockGenesisContract(ctrl) -// miner, mux, cleanup := createBorMiner(t, ethAPI, spanner, heimdallClient, genesisContracts) + miner, mux, cleanup := createBorMiner(t, ethAPI, spanner, heimdallClient, genesisContracts) -// return &DefaultBorMiner{ -// Miner: miner, -// Mux: mux, -// Cleanup: cleanup, -// Ctrl: ctrl, -// EthAPIMock: ethAPI, -// HeimdallClientMock: heimdallClient, -// ContractMock: genesisContracts, -// } -// } + return &DefaultBorMiner{ + Miner: miner, + Mux: mux, + Cleanup: cleanup, + Ctrl: ctrl, + EthAPIMock: ethAPI, + HeimdallClientMock: heimdallClient, + ContractMock: genesisContracts, + } +} -// TODO - Arpit // //nolint:staticcheck -// func createBorMiner(t *testing.T, ethAPIMock api.Caller, spanner bor.Spanner, heimdallClientMock bor.IHeimdallClient, contractMock bor.GenesisContract) (*Miner, *event.TypeMux, func(skipMiner bool)) { -// t.Helper() - -// // Create Ethash config -// chainDB, genspec, chainConfig := NewDBForFakes(t) - -// engine := NewFakeBor(t, chainDB, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) +func createBorMiner(t *testing.T, ethAPIMock api.Caller, spanner bor.Spanner, heimdallClientMock bor.IHeimdallClient, contractMock bor.GenesisContract) (*Miner, *event.TypeMux, func(skipMiner bool)) { + t.Helper() -// // Create Ethereum backend -// bc, err := core.NewBlockChain(chainDB, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil) -// if err != nil { -// t.Fatalf("can't create new chain %v", err) -// } + // Create Ethash config + chainDB, genspec, chainConfig := NewDBForFakes(t) -// statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil) -// blockchain := &testBlockChain{statedb, 10000000, new(event.Feed)} + engine := NewFakeBor(t, chainDB, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) -// // blockchain := &blobpool.testBlockChain{ -// // config: blobpool.testChainConfig, -// // basefee: uint256.NewInt(params.InitialBaseFee), -// // blobfee: uint256.NewInt(params.BlobTxMinBlobGasprice), -// // statedb: statedb, -// // } + // Create Ethereum backend + bc, err := core.NewBlockChain(chainDB, nil, genspec, nil, engine, vm.Config{}, nil, nil, nil) + if err != nil { + t.Fatalf("can't create new chain %v", err) + } -// // pool := legacypool.New(testTxPoolConfig, blockchain) -// // pool.Init(new(big.Int).SetUint64(testTxPoolConfig.PriceLimit), blockchain.CurrentBlock(), makeAddressReserver()) + statedb, _ := state.New(common.Hash{}, state.NewDatabase(chainDB), nil) + blockchain := &testBlockChainBor{chainConfig, statedb, 10000000, new(event.Feed)} -// pool := legacypool.New(testTxPoolConfig, blockchain) -// txpool, _ := txpool.New(new(big.Int).SetUint64(blobpool.testTxPoolConfig.PriceLimit), blockchain, []txpool.SubPool{pool}) -// defer pool.Close() + pool := legacypool.New(testTxPoolConfigBor, blockchain) + txpool, _ := txpool.New(new(big.Int).SetUint64(testTxPoolConfigBor.PriceLimit), blockchain, []txpool.SubPool{pool}) -// // pool := txpool.NewTxPool(testTxPoolConfig, chainConfig, blockchain) -// backend := NewMockBackend(bc, txpool) + backend := NewMockBackendBor(bc, txpool) -// // Create event Mux -// mux := new(event.TypeMux) + // Create event Mux + mux := new(event.TypeMux) -// config := Config{ -// Etherbase: common.HexToAddress("123456789"), -// } + config := Config{ + Etherbase: common.HexToAddress("123456789"), + } -// // Create Miner -// miner := New(backend, &config, chainConfig, mux, engine, nil) + // Create Miner + miner := New(backend, &config, chainConfig, mux, engine, nil) -// cleanup := func(skipMiner bool) { -// bc.Stop() -// engine.Close() + cleanup := func(skipMiner bool) { + bc.Stop() + engine.Close() -// if !skipMiner { -// miner.Close() -// } -// } + if !skipMiner { + miner.Close() + } + } -// return miner, mux, cleanup -// } + return miner, mux, cleanup +} type TensingObject interface { Helper() @@ -159,95 +156,68 @@ func NewFakeBor(t TensingObject, chainDB ethdb.Database, chainConfig *params.Cha return bor.New(chainConfig, chainDB, ethAPIMock, spanner, heimdallClientMock, contractMock, false) } -// type mockBackend struct { -// bc *core.BlockChain -// txPool *txpool.TxPool -// } - -// // PeerCount implements Backend. -// func (*mockBackend) PeerCount() int { -// panic("unimplemented") -// } - -// func NewMockBackend(bc *core.BlockChain, txPool *txpool.TxPool) *mockBackend { -// return &mockBackend{ -// bc: bc, -// txPool: txPool, -// } -// } - -// func (m *mockBackend) BlockChain() *core.BlockChain { -// return m.bc -// } - -// func (m *mockBackend) TxPool() *txpool.TxPool { -// return m.txPool -// } - -// func (m *mockBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { -// return nil, errors.New("not supported") -// } - -// type testBlockChain struct { -// statedb *state.StateDB -// gasLimit uint64 -// chainHeadFeed *event.Feed -// } - -// func (bc *testBlockChain) CurrentBlock() *types.Header { -// return &types.Header{ -// GasLimit: bc.gasLimit, -// Number: new(big.Int), -// } -// } - -// func (bc *testBlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { -// return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) -// } - -// func (bc *testBlockChain) StateAt(common.Hash) (*state.StateDB, error) { -// return bc.statedb, nil -// } - -// func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { -// return bc.chainHeadFeed.Subscribe(ch) -// } - var ( -// Test chain configurations -// testTxPoolConfig txpool.Config + // Test chain configurations + testTxPoolConfigBor legacypool.Config +) + +// TODO - Arpit, Duplicate Functions +type mockBackendBor struct { + bc *core.BlockChain + txPool *txpool.TxPool +} + +func NewMockBackendBor(bc *core.BlockChain, txPool *txpool.TxPool) *mockBackendBor { + return &mockBackendBor{ + bc: bc, + txPool: txPool, + } +} -// ethashChainConfig *params.ChainConfig -// cliqueChainConfig *params.ChainConfig +func (m *mockBackendBor) BlockChain() *core.BlockChain { + return m.bc +} -// // Test accounts -// testBankKey, _ = crypto.GenerateKey() -// testBankFunds = big.NewInt(9000000000000000000) +// PeerCount implements Backend. +func (*mockBackendBor) PeerCount() int { + panic("unimplemented") +} -// testUserKey, _ = crypto.GenerateKey() -// testUserAddress = crypto.PubkeyToAddress(testUserKey.PublicKey) +func (m *mockBackendBor) TxPool() *txpool.TxPool { + return m.txPool +} -// // Test transactions -// pendingTxs []*types.Transaction -// newTxs []*types.Transaction +func (m *mockBackendBor) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { + return nil, errors.New("not supported") +} -// testConfig = &Config{ -// Recommit: time.Second, -// GasCeil: params.GenesisGasLimit, -// CommitInterruptFlag: true, -// } -) +// TODO - Arpit, Duplicate Functions +type testBlockChainBor struct { + config *params.ChainConfig + statedb *state.StateDB + gasLimit uint64 + chainHeadFeed *event.Feed +} + +func (bc *testBlockChainBor) Config() *params.ChainConfig { + return bc.config +} + +func (bc *testBlockChainBor) CurrentBlock() *types.Header { + return &types.Header{ + Number: new(big.Int), + GasLimit: bc.gasLimit, + } +} + +func (bc *testBlockChainBor) GetBlock(hash common.Hash, number uint64) *types.Block { + return types.NewBlock(bc.CurrentBlock(), nil, nil, nil, trie.NewStackTrie(nil)) +} + +func (bc *testBlockChainBor) StateAt(common.Hash) (*state.StateDB, error) { + return bc.statedb, nil +} -func init() { - // testTxPoolConfig = txpool.DefaultConfig - // testTxPoolConfig.Journal = "" - // ethashChainConfig = new(params.ChainConfig) - // *ethashChainConfig = *params.TestChainConfig - // cliqueChainConfig = new(params.ChainConfig) - // *cliqueChainConfig = *params.TestChainConfig - // - // cliqueChainConfig.Clique = ¶ms.CliqueConfig{ - // Period: 10, - // Epoch: 30000, - // } +func (bc *testBlockChainBor) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription { + return bc.chainHeadFeed.Subscribe(ch) } diff --git a/miner/miner_test.go b/miner/miner_test.go index a960071595..ef68bb31cf 100644 --- a/miner/miner_test.go +++ b/miner/miner_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" @@ -97,234 +98,227 @@ func (bc *testBlockChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) return bc.chainHeadFeed.Subscribe(ch) } -// // TODO - Arpit -// func TestMiner(t *testing.T) { -// t.Parallel() - -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(false) -// minerBor.Ctrl.Finish() -// }() - -// miner := minerBor.Miner -// mux := minerBor.Mux - -// miner.Start() -// waitForMiningState(t, miner, true) - -// // Start the downloader -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, false) - -// // Stop the downloader and wait for the update loop to run -// mux.Post(downloader.DoneEvent{}) -// waitForMiningState(t, miner, true) - -// // Subsequent downloader events after a successful DoneEvent should not cause the -// // miner to start or stop. This prevents a security vulnerability -// // that would allow entities to present fake high blocks that would -// // stop mining operations by causing a downloader sync -// // until it was discovered they were invalid, whereon mining would resume. -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, true) - -// mux.Post(downloader.FailedEvent{}) -// waitForMiningState(t, miner, true) -// } - -// // TODO - Arpit -// // TestMinerDownloaderFirstFails tests that mining is only -// // permitted to run indefinitely once the downloader sees a DoneEvent (success). -// // An initial FailedEvent should allow mining to stop on a subsequent -// // downloader StartEvent. -// func TestMinerDownloaderFirstFails(t *testing.T) { -// t.Parallel() - -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(false) -// minerBor.Ctrl.Finish() -// }() - -// miner := minerBor.Miner -// mux := minerBor.Mux - -// miner.Start() -// waitForMiningState(t, miner, true) - -// // Start the downloader -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, false) - -// // Stop the downloader and wait for the update loop to run -// mux.Post(downloader.FailedEvent{}) -// waitForMiningState(t, miner, true) - -// // Since the downloader hasn't yet emitted a successful DoneEvent, -// // we expect the miner to stop on next StartEvent. -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, false) - -// // Downloader finally succeeds. -// mux.Post(downloader.DoneEvent{}) -// waitForMiningState(t, miner, true) - -// // Downloader starts again. -// // Since it has achieved a DoneEvent once, we expect miner -// // state to be unchanged. -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, true) - -// mux.Post(downloader.FailedEvent{}) -// waitForMiningState(t, miner, true) -// } - -// // TODO - Arpit -// func TestMinerStartStopAfterDownloaderEvents(t *testing.T) { -// t.Parallel() - -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(false) -// minerBor.Ctrl.Finish() -// }() +func TestMiner(t *testing.T) { + t.Parallel() -// miner := minerBor.Miner -// mux := minerBor.Mux + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() -// miner.Start() -// waitForMiningState(t, miner, true) + miner := minerBor.Miner + mux := minerBor.Mux -// // Start the downloader -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, false) + miner.Start() + waitForMiningState(t, miner, true) -// // Downloader finally succeeds. -// mux.Post(downloader.DoneEvent{}) -// waitForMiningState(t, miner, true) + // Start the downloader + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, false) -// ch := make(chan struct{}) -// miner.Stop(ch) -// waitForMiningState(t, miner, false) + // Stop the downloader and wait for the update loop to run + mux.Post(downloader.DoneEvent{}) + waitForMiningState(t, miner, true) -// miner.Start() -// waitForMiningState(t, miner, true) + // Subsequent downloader events after a successful DoneEvent should not cause the + // miner to start or stop. This prevents a security vulnerability + // that would allow entities to present fake high blocks that would + // stop mining operations by causing a downloader sync + // until it was discovered they were invalid, whereon mining would resume. + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, true) -// ch = make(chan struct{}) -// miner.Stop(ch) -// waitForMiningState(t, miner, false) -// } + mux.Post(downloader.FailedEvent{}) + waitForMiningState(t, miner, true) +} + +// TestMinerDownloaderFirstFails tests that mining is only +// permitted to run indefinitely once the downloader sees a DoneEvent (success). +// An initial FailedEvent should allow mining to stop on a subsequent +// downloader StartEvent. +func TestMinerDownloaderFirstFails(t *testing.T) { + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + mux := minerBor.Mux + + miner.Start() + waitForMiningState(t, miner, true) + + // Start the downloader + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, false) + + // Stop the downloader and wait for the update loop to run + mux.Post(downloader.FailedEvent{}) + waitForMiningState(t, miner, true) + + // Since the downloader hasn't yet emitted a successful DoneEvent, + // we expect the miner to stop on next StartEvent. + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, false) + + // Downloader finally succeeds. + mux.Post(downloader.DoneEvent{}) + waitForMiningState(t, miner, true) + + // Downloader starts again. + // Since it has achieved a DoneEvent once, we expect miner + // state to be unchanged. + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, true) + + mux.Post(downloader.FailedEvent{}) + waitForMiningState(t, miner, true) +} -// // TODO - Arpit -// func TestStartWhileDownload(t *testing.T) { -// t.Parallel() +func TestMinerStartStopAfterDownloaderEvents(t *testing.T) { + t.Parallel() -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(false) -// minerBor.Ctrl.Finish() -// }() + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() -// miner := minerBor.Miner -// mux := minerBor.Mux + miner := minerBor.Miner + mux := minerBor.Mux -// waitForMiningState(t, miner, false) -// miner.Start() -// waitForMiningState(t, miner, true) + miner.Start() + waitForMiningState(t, miner, true) -// // Stop the downloader and wait for the update loop to run -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, false) + // Start the downloader + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, false) -// // Starting the miner after the downloader should not work -// miner.Start() -// waitForMiningState(t, miner, false) -// } + // Downloader finally succeeds. + mux.Post(downloader.DoneEvent{}) + waitForMiningState(t, miner, true) -// // TODO - Arpit -// func TestStartStopMiner(t *testing.T) { -// t.Parallel() + ch := make(chan struct{}) + miner.Stop(ch) + waitForMiningState(t, miner, false) -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(false) -// minerBor.Ctrl.Finish() -// }() + miner.Start() + waitForMiningState(t, miner, true) -// miner := minerBor.Miner + ch = make(chan struct{}) + miner.Stop(ch) + waitForMiningState(t, miner, false) +} -// waitForMiningState(t, miner, false) -// miner.Start() -// waitForMiningState(t, miner, true) +func TestStartWhileDownload(t *testing.T) { + t.Parallel() -// ch := make(chan struct{}) -// miner.Stop(ch) + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() -// waitForMiningState(t, miner, false) -// } + miner := minerBor.Miner + mux := minerBor.Mux -// // TODO - Arpit -// func TestCloseMiner(t *testing.T) { -// t.Parallel() + waitForMiningState(t, miner, false) + miner.Start() + waitForMiningState(t, miner, true) + + // Stop the downloader and wait for the update loop to run + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, false) + + // Starting the miner after the downloader should not work + miner.Start() + waitForMiningState(t, miner, false) +} -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(true) -// minerBor.Ctrl.Finish() -// }() +func TestStartStopMiner(t *testing.T) { + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + + waitForMiningState(t, miner, false) + miner.Start() + waitForMiningState(t, miner, true) + + ch := make(chan struct{}) + miner.Stop(ch) + + waitForMiningState(t, miner, false) +} -// miner := minerBor.Miner +func TestCloseMiner(t *testing.T) { + t.Parallel() -// waitForMiningState(t, miner, false) -// miner.Start() + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(true) + minerBor.Ctrl.Finish() + }() -// miner.Start() + miner := minerBor.Miner -// waitForMiningState(t, miner, true) + waitForMiningState(t, miner, false) + miner.Start() -// // Terminate the miner and wait for the update loop to run -// miner.Close() + miner.Start() -// waitForMiningState(t, miner, false) -// } + waitForMiningState(t, miner, true) + + // Terminate the miner and wait for the update loop to run + miner.Close() + + waitForMiningState(t, miner, false) +} // // TestMinerSetEtherbase checks that etherbase becomes set even if mining isn't // // possible at the moment -// // TODO - Arpit -// func TestMinerSetEtherbase(t *testing.T) { -// t.Parallel() - -// minerBor := NewBorDefaultMiner(t) -// defer func() { -// minerBor.Cleanup(false) -// minerBor.Ctrl.Finish() -// }() - -// miner := minerBor.Miner -// mux := minerBor.Mux - -// // Start with a 'bad' mining address -// miner.Start() -// waitForMiningState(t, miner, true) - -// // Start the downloader -// mux.Post(downloader.StartEvent{}) -// waitForMiningState(t, miner, false) - -// // Now user tries to configure proper mining address -// miner.Start() -// // Stop the downloader and wait for the update loop to run -// mux.Post(downloader.DoneEvent{}) -// waitForMiningState(t, miner, true) - -// coinbase := common.HexToAddress("0xdeedbeef") -// miner.SetEtherbase(coinbase) - -// if addr := miner.worker.etherbase(); addr != coinbase { -// t.Fatalf("Unexpected etherbase want %x got %x", coinbase, addr) -// } -// } +func TestMinerSetEtherbase(t *testing.T) { + t.Parallel() + + minerBor := NewBorDefaultMiner(t) + defer func() { + minerBor.Cleanup(false) + minerBor.Ctrl.Finish() + }() + + miner := minerBor.Miner + mux := minerBor.Mux + + // Start with a 'bad' mining address + miner.Start() + waitForMiningState(t, miner, true) + + // Start the downloader + mux.Post(downloader.StartEvent{}) + waitForMiningState(t, miner, false) + + // Now user tries to configure proper mining address + miner.Start() + // Stop the downloader and wait for the update loop to run + mux.Post(downloader.DoneEvent{}) + waitForMiningState(t, miner, true) + + coinbase := common.HexToAddress("0xdeedbeef") + miner.SetEtherbase(coinbase) + + if addr := miner.worker.etherbase(); addr != coinbase { + t.Fatalf("Unexpected etherbase want %x got %x", coinbase, addr) + } +} // waitForMiningState waits until either // * the desired mining state was reached diff --git a/miner/payload_building_test.go b/miner/payload_building_test.go index 7dfdc2226a..821d0854af 100644 --- a/miner/payload_building_test.go +++ b/miner/payload_building_test.go @@ -37,7 +37,7 @@ func TestBuildPayload(t *testing.T) { recipient = common.HexToAddress("0xdeadbeef") ) - w, b := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0) + w, b, _ := newTestWorker(t, params.TestChainConfig, ethash.NewFaker(), db, 0, false, 0, 0) defer w.close() timestamp := uint64(time.Now().Unix()) diff --git a/miner/test_backend.go b/miner/test_backend.go index afab55b73e..5c5c217424 100644 --- a/miner/test_backend.go +++ b/miner/test_backend.go @@ -30,236 +30,6 @@ import ( lru "github.com/hashicorp/golang-lru" ) -const ( - // testCode is the testing contract binary code which will initialises some - // variables in constructor - testCode = "0x60806040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005534801561003457600080fd5b5060fc806100436000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80630c4dae8814603757806398a213cf146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055507fe9e44f9f7da8c559de847a3232b57364adc0354f15a2cd8dc636d54396f9587a6000546040518082815260200191505060405180910390a15056fea265627a7a723058208ae31d9424f2d0bc2a3da1a5dd659db2d71ec322a17db8f87e19e209e3a1ff4a64736f6c634300050a0032" - - // testGas is the gas required for contract deployment. - testGas = 144109 - storageContractByteCode = "608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea2646970667358221220322c78243e61b783558509c9cc22cb8493dde6925aa5e89a08cdf6e22f279ef164736f6c63430008120033" - storageContractTxCallData = "0x6057361d0000000000000000000000000000000000000000000000000000000000000001" - storageCallTxGas = 100000 -) - -func init() { - - // testTxPoolConfig = txpool.DefaultConfig - // testTxPoolConfig.Journal = "" - // ethashChainConfig = new(params.ChainConfig) - // *ethashChainConfig = *params.TestChainConfig - // cliqueChainConfig = new(params.ChainConfig) - // *cliqueChainConfig = *params.TestChainConfig - // cliqueChainConfig.Clique = ¶ms.CliqueConfig{ - // Period: 10, - // Epoch: 30000, - // } - - // signer := types.LatestSigner(params.TestChainConfig) - - // tx1 := types.MustSignNewTx(testBankKey, signer, &types.AccessListTx{ - // ChainID: params.TestChainConfig.ChainID, - // Nonce: 0, - // To: &testUserAddress, - // Value: big.NewInt(1000), - // Gas: params.TxGas, - // GasPrice: big.NewInt(params.InitialBaseFee), - // }) - - // pendingTxs = append(pendingTxs, tx1) - - // tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{ - // Nonce: 1, - // To: &testUserAddress, - // Value: big.NewInt(1000), - // Gas: params.TxGas, - // GasPrice: big.NewInt(params.InitialBaseFee), - // }) - - // newTxs = append(newTxs, tx2) -} - -// testWorkerBackend implements worker.Backend interfaces and wraps all information needed during the testing. -// type testWorkerBackend struct { -// DB ethdb.Database -// txPool *txpool.TxPool -// chain *core.BlockChain -// Genesis *core.Genesis -// uncleBlock *types.Block -// } - -// // PeerCount implements Backend. -// func (*testWorkerBackend) PeerCount() int { -// panic("unimplemented") -// } - -// func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, n int) *testWorkerBackend { -// var gspec = core.Genesis{ -// Config: chainConfig, -// Alloc: core.GenesisAlloc{TestBankAddress: {Balance: testBankFunds}}, -// GasLimit: 30_000_000, -// } - -// switch e := engine.(type) { -// case *bor.Bor: -// gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) -// copy(gspec.ExtraData[32:32+common.AddressLength], TestBankAddress.Bytes()) -// e.Authorize(TestBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) { -// return crypto.Sign(crypto.Keccak256(data), testBankKey) -// }) -// case *clique.Clique: -// gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) -// copy(gspec.ExtraData[32:32+common.AddressLength], TestBankAddress.Bytes()) -// e.Authorize(TestBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) { -// return crypto.Sign(crypto.Keccak256(data), testBankKey) -// }) -// case *ethash.Ethash: -// default: -// t.Fatalf("unexpected consensus engine type: %T", engine) -// } - -// genesis := gspec.MustCommit(db) - -// chain, _ := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, &gspec, nil, engine, vm.Config{}, nil, nil, nil) -// txpool := txpool.NewTxPool(testTxPoolConfig, chainConfig, chain) - -// // Generate a small n-block chain and an uncle block for it -// if n > 0 { -// blocks, _ := core.GenerateChain(chainConfig, genesis, engine, db, n, func(i int, gen *core.BlockGen) { -// gen.SetCoinbase(TestBankAddress) -// }) -// if _, err := chain.InsertChain(blocks); err != nil { -// t.Fatalf("failed to insert origin chain: %v", err) -// } -// } - -// parent := genesis -// if n > 0 { -// parent = chain.GetBlockByHash(chain.CurrentBlock().ParentHash) -// } - -// blocks, _ := core.GenerateChain(chainConfig, parent, engine, db, 1, func(i int, gen *core.BlockGen) { -// gen.SetCoinbase(testUserAddress) -// }) - -// return &testWorkerBackend{ -// DB: db, -// chain: chain, -// txPool: txpool, -// Genesis: &gspec, -// uncleBlock: blocks[0], -// } -// } - -// func (b *testWorkerBackend) BlockChain() *core.BlockChain { return b.chain } -// func (b *testWorkerBackend) TxPool() *txpool.TxPool { return b.txPool } -// func (b *testWorkerBackend) StateAtBlock(block *types.Block, reexec uint64, base *state.StateDB, checkLive bool, preferDisk bool) (statedb *state.StateDB, err error) { -// return nil, errors.New("not supported") -// } - -// func (b *testWorkerBackend) newRandomUncle() (*types.Block, error) { -// var parent *types.Block - -// cur := b.chain.CurrentBlock() - -// if cur.Number.Uint64() == 0 { -// parent = b.chain.Genesis() -// } else { -// parent = b.chain.GetBlockByHash(b.chain.CurrentBlock().ParentHash) -// } - -// var err error - -// blocks, _ := core.GenerateChain(b.chain.Config(), parent, b.chain.Engine(), b.DB, 1, func(i int, gen *core.BlockGen) { -// var addr = make([]byte, common.AddressLength) - -// _, err = rand.Read(addr) -// if err != nil { -// return -// } - -// gen.SetCoinbase(common.BytesToAddress(addr)) -// }) - -// return blocks[0], err -// } - -// // newRandomTx creates a new transaction. -// func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction { -// var tx *types.Transaction - -// gasPrice := big.NewInt(10 * params.InitialBaseFee) - -// if creation { -// tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(TestBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey) -// } else { -// tx, _ = types.SignTx(types.NewTransaction(b.txPool.Nonce(TestBankAddress), testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey) -// } - -// return tx -// } - -// // newRandomTxWithNonce creates a new transaction with the given nonce. -// func (b *testWorkerBackend) newRandomTxWithNonce(creation bool, nonce uint64) *types.Transaction { -// var tx *types.Transaction - -// gasPrice := big.NewInt(100 * params.InitialBaseFee) - -// if creation { -// tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(TestBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey) -// } else { -// tx, _ = types.SignTx(types.NewTransaction(nonce, testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey) -// } - -// return tx -// } - -// // newStorageCreateContractTx creates a new transaction to deploy a storage smart contract. -// func (b *testWorkerBackend) newStorageCreateContractTx() (*types.Transaction, common.Address) { -// var tx *types.Transaction - -// gasPrice := big.NewInt(10 * params.InitialBaseFee) - -// tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(TestBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(storageContractByteCode)), types.HomesteadSigner{}, testBankKey) -// contractAddr := crypto.CreateAddress(TestBankAddress, b.txPool.Nonce(TestBankAddress)) - -// return tx, contractAddr -// } - -// // newStorageContractCallTx creates a new transaction to call a storage smart contract. -// func (b *testWorkerBackend) newStorageContractCallTx(to common.Address, nonce uint64) *types.Transaction { -// var tx *types.Transaction - -// gasPrice := big.NewInt(10 * params.InitialBaseFee) - -// tx, _ = types.SignTx(types.NewTransaction(nonce, to, nil, storageCallTxGas, gasPrice, common.FromHex(storageContractTxCallData)), types.HomesteadSigner{}, testBankKey) - -// return tx -// } - -// // NewTestWorker creates a new test worker with the given parameters. -// func NewTestWorker(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int, noempty bool, delay uint, opcodeDelay uint) (*worker, *testWorkerBackend, func()) { -// backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks) -// backend.txPool.AddLocals(pendingTxs) - -// var w *worker - -// if delay != 0 || opcodeDelay != 0 { -// //nolint:staticcheck -// w = newWorkerWithDelay(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false, delay, opcodeDelay) -// } else { -// //nolint:staticcheck -// w = newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false) -// } - -// w.setEtherbase(TestBankAddress) - -// // enable empty blocks -// w.noempty.Store(noempty) - -// return w, backend, w.close -// } - // newWorkerWithDelay is newWorker() with extra params to induce artficial delays for tests such as commit-interrupt. // nolint:staticcheck func newWorkerWithDelay(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(header *types.Header) bool, init bool, delay uint, opcodeDelay uint) *worker { @@ -367,50 +137,6 @@ func (w *worker) mainLoopWithDelay(ctx context.Context, delay uint, opcodeDelay req.result <- &payload } - // case ev := <-w.chainSideCh: - // // Short circuit for duplicate side blocks - // if _, exist := w.localUncles[ev.Block.Hash()]; exist { - // continue - // } - - // if _, exist := w.remoteUncles[ev.Block.Hash()]; exist { - // continue - // } - - // // Add side block to possible uncle block set depending on the author. - // if w.isLocalBlock != nil && w.isLocalBlock(ev.Block.Header()) { - // w.localUncles[ev.Block.Hash()] = ev.Block - // } else { - // w.remoteUncles[ev.Block.Hash()] = ev.Block - // } - - // // If our sealing block contains less than 2 uncle blocks, - // // add the new uncle block if valid and regenerate a new - // // sealing block for higher profit. - // if w.isRunning() && w.current != nil && len(w.current.uncles) < 2 { - // start := time.Now() - // if err := w.commitUncle(w.current, ev.Block.Header()); err == nil { - // commitErr := w.commit(ctx, w.current.copy(), nil, true, start) - // if commitErr != nil { - // log.Error("error while committing work for mining", "err", commitErr) - // } - // } - // } - - // case <-cleanTicker.C: - // chainHead := w.chain.CurrentBlock() - // for hash, uncle := range w.localUncles { - // if uncle.NumberU64()+staleThreshold <= chainHead.Number.Uint64() { - // delete(w.localUncles, hash) - // } - // } - - // for hash, uncle := range w.remoteUncles { - // if uncle.NumberU64()+staleThreshold <= chainHead.Number.Uint64() { - // delete(w.remoteUncles, hash) - // } - // } - case ev := <-w.txsCh: // Apply transactions to the pending state if we're not sealing // diff --git a/miner/worker.go b/miner/worker.go index 2af7742e5b..88a67ae68f 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1027,31 +1027,30 @@ mainloop: // during transaction acceptance is the transaction pool. from, _ := types.Sender(env.signer, tx.Tx) - // TODO - Arpit // not prioritising conditional transaction, yet. //nolint:nestif - // if options := tx.GetOptions(); options != nil { - // if err := env.header.ValidateBlockNumberOptions4337(options.BlockNumberMin, options.BlockNumberMax); err != nil { - // log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err) - // txs.Pop() + if options := tx.Tx.GetOptions(); options != nil { + if err := env.header.ValidateBlockNumberOptions4337(options.BlockNumberMin, options.BlockNumberMax); err != nil { + log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Tx.Hash(), "reason", err) + txs.Pop() - // continue - // } + continue + } - // if err := env.header.ValidateTimestampOptions4337(options.TimestampMin, options.TimestampMax); err != nil { - // log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err) - // txs.Pop() + if err := env.header.ValidateTimestampOptions4337(options.TimestampMin, options.TimestampMax); err != nil { + log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Tx.Hash(), "reason", err) + txs.Pop() - // continue - // } + continue + } - // if err := env.state.ValidateKnownAccounts(options.KnownAccounts); err != nil { - // log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Hash(), "reason", err) - // txs.Pop() + if err := env.state.ValidateKnownAccounts(options.KnownAccounts); err != nil { + log.Trace("Dropping conditional transaction", "from", from, "hash", tx.Tx.Hash(), "reason", err) + txs.Pop() - // continue - // } - // } + continue + } + } // Check whether the tx is replay protected. If we're not in the EIP155 hf // phase, start ignoring the sender until we do. @@ -1477,7 +1476,6 @@ func (w *worker) fillTransactions(ctx context.Context, interrupt *atomic.Int32, ) }) - // TODO - Arpit whether commitTransaction with delay? tracing.Exec(ctx, "", "worker.LocalCommitTransactions", func(ctx context.Context, span trace.Span) { err = w.commitTransactions(env, txs, interrupt, interruptCtx) }) diff --git a/miner/worker_test.go b/miner/worker_test.go index a31d1aa1ea..68f752d281 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -18,6 +18,7 @@ package miner import ( "math/big" + "os" "sync/atomic" "testing" "time" @@ -25,6 +26,9 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/bor" + "github.com/ethereum/go-ethereum/consensus/bor/api" + "github.com/ethereum/go-ethereum/consensus/bor/valset" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/core" @@ -36,171 +40,155 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/tests/bor/mocks" + "github.com/golang/mock/gomock" + "gotest.tools/assert" ) -// TODO(raneet10): Duplicate initialization from miner/test_backend.go . Recheck whether we need both -// func init() { -// testTxPoolConfig = txpool.DefaultConfig -// testTxPoolConfig.Journal = "" -// ethashChainConfig = new(params.ChainConfig) -// *ethashChainConfig = *params.TestChainConfig -// cliqueChainConfig = new(params.ChainConfig) -// *cliqueChainConfig = *params.TestChainConfig -// cliqueChainConfig.Clique = ¶ms.CliqueConfig{ -// Period: 10, -// Epoch: 30000, -// } +// nolint : paralleltest +func TestGenerateBlockAndImportEthash(t *testing.T) { + testGenerateBlockAndImport(t, false, false) +} -// signer := types.LatestSigner(params.TestChainConfig) -// tx1 := types.MustSignNewTx(testBankKey, signer, &types.AccessListTx{ -// ChainID: params.TestChainConfig.ChainID, -// Nonce: 0, -// To: &testUserAddress, -// Value: big.NewInt(1000), -// Gas: params.TxGas, -// GasPrice: big.NewInt(params.InitialBaseFee), -// }) -// pendingTxs = append(pendingTxs, tx1) - -// tx2 := types.MustSignNewTx(testBankKey, signer, &types.LegacyTx{ -// Nonce: 1, -// To: &testUserAddress, -// Value: big.NewInt(1000), -// Gas: params.TxGas, -// GasPrice: big.NewInt(params.InitialBaseFee), -// }) -// newTxs = append(newTxs, tx2) -// } +// nolint : paralleltest +func TestGenerateBlockAndImportClique(t *testing.T) { + testGenerateBlockAndImport(t, true, false) +} -// newTestWorker creates a new test worker with the given parameters. -// nolint:unparam -// func newTestWorker(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int, noempty bool, delay uint, opcodeDelay uint) (*worker, *testWorkerBackend, func()) { -// backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks) -// backend.txPool.addLocals(pendingTxs) +// nolint : paralleltest +func TestGenerateBlockAndImportBor(t *testing.T) { + testGenerateBlockAndImport(t, false, true) +} -// var w *worker +//nolint:thelper +func testGenerateBlockAndImport(t *testing.T, isClique bool, isBor bool) { + var ( + engine consensus.Engine + chainConfig params.ChainConfig + db = rawdb.NewMemoryDatabase() + ctrl *gomock.Controller + ) -// if delay != 0 || opcodeDelay != 0 { -// //nolint:staticcheck -// w = newWorkerWithDelay(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false, delay, opcodeDelay) -// } else { -// //nolint:staticcheck -// w = newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false) -// } + if isBor { + chainConfig = *params.BorUnittestChainConfig -// w.setEtherbase(TestBankAddress) + engine, ctrl = getFakeBorFromConfig(t, &chainConfig) + defer ctrl.Finish() + } else { + if isClique { + chainConfig = *params.AllCliqueProtocolChanges + chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000} + engine = clique.New(chainConfig.Clique, db) + } else { + chainConfig = *params.AllEthashProtocolChanges + engine = ethash.NewFaker() + } + } -// // enable empty blocks -// w.noempty.Store(noempty) + defer engine.Close() -// return w, backend, w.close -// } + w, b, _ := newTestWorker(t, &chainConfig, engine, db, 0, false, 0, 0) + defer w.close() -// TODO - Arpit -// // nolint : paralleltest -// func TestGenerateBlockAndImportEthash(t *testing.T) { -// testGenerateBlockAndImport(t, false, false) -// } + // This test chain imports the mined blocks. + chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, b.genesis, nil, engine, vm.Config{}, nil, nil, nil) + defer chain.Stop() -// // nolint : paralleltest -// func TestGenerateBlockAndImportClique(t *testing.T) { -// testGenerateBlockAndImport(t, true, false) -// } + // Ignore empty commit here for less noise. + w.skipSealHook = func(task *task) bool { + return len(task.receipts) == 0 + } -// // nolint : paralleltest -// func TestGenerateBlockAndImportBor(t *testing.T) { -// testGenerateBlockAndImport(t, false, true) -// } + // Wait for mined blocks. + sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) + defer sub.Unsubscribe() -// //nolint:thelper -// func testGenerateBlockAndImport(t *testing.T, isClique bool, isBor bool) { -// var ( -// engine consensus.Engine -// chainConfig params.ChainConfig -// db = rawdb.NewMemoryDatabase() -// ctrl *gomock.Controller -// ) + // Start mining! + w.start() -// if isBor { -// chainConfig = *params.BorUnittestChainConfig + var ( + err error + ) -// engine, ctrl = getFakeBorFromConfig(t, &chainConfig) -// defer ctrl.Finish() -// } else { -// if isClique { -// chainConfig = *params.AllCliqueProtocolChanges -// chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000} -// engine = clique.New(chainConfig.Clique, db) -// } else { -// chainConfig = *params.AllEthashProtocolChanges -// engine = ethash.NewFaker() -// } -// } + for i := 0; i < 5; i++ { + err = b.txPool.Add([]*txpool.Transaction{{Tx: b.newRandomTx(true)}}, true, false)[0] + if err != nil { + t.Fatal("while adding a local transaction", err) + } -// defer engine.Close() + err = b.txPool.Add([]*txpool.Transaction{{Tx: b.newRandomTx(false)}}, true, false)[0] + if err != nil { + t.Fatal("while adding a remote transaction", err) + } -// w, b, _ := newTestWorker(t, &chainConfig, engine, db, 0, false, 0, 0) -// defer w.close() + // TODO - Arpit, Check if required + // uncle, err = b.newRandomUncle() + // if err != nil { + // t.Fatal("while making an uncle block", err) + // } -// // This test chain imports the mined blocks. -// chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, b.Genesis, nil, engine, vm.Config{}, nil, nil, nil) -// defer chain.Stop() + // w.postSideBlock(core.ChainSideEvent{Block: uncle}) -// // Ignore empty commit here for less noise. -// w.skipSealHook = func(task *task) bool { -// return len(task.receipts) == 0 -// } + // uncle, err = b.newRandomUncle() + // if err != nil { + // t.Fatal("while making an uncle block", err) + // } -// // Wait for mined blocks. -// sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) -// defer sub.Unsubscribe() + // w.postSideBlock(core.ChainSideEvent{Block: uncle}) -// // Start mining! -// w.start() + select { + case ev := <-sub.Chan(): + block := ev.Data.(core.NewMinedBlockEvent).Block + if _, err := chain.InsertChain([]*types.Block{block}); err != nil { + t.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) + } + case <-time.After(3 * time.Second): // Worker needs 1s to include new changes. + t.Fatalf("timeout") + } + } +} -// var ( -// err error -// uncle *types.Block -// ) +// func (b *testWorkerBackend) newRandomUncle() (*types.Block, error) { +// var parent *types.Block -// for i := 0; i < 5; i++ { -// err = b.txPool.AddLocal(b.newRandomTx(true)) -// if err != nil { -// t.Fatal("while adding a local transaction", err) -// } +// cur := b.chain.CurrentBlock() -// err = b.txPool.AddLocal(b.newRandomTx(false)) -// if err != nil { -// t.Fatal("while adding a remote transaction", err) -// } +// if cur.Number.Uint64() == 0 { +// parent = b.chain.Genesis() +// } else { +// parent = b.chain.GetBlockByHash(b.chain.CurrentBlock().ParentHash) +// } -// uncle, err = b.newRandomUncle() -// if err != nil { -// t.Fatal("while making an uncle block", err) -// } +// var err error -// w.postSideBlock(core.ChainSideEvent{Block: uncle}) +// blocks, _ := core.GenerateChain(b.chain.Config(), parent, b.chain.Engine(), b.DB, 1, func(i int, gen *core.BlockGen) { +// var addr = make([]byte, common.AddressLength) -// uncle, err = b.newRandomUncle() +// _, err = rand.Read(addr) // if err != nil { -// t.Fatal("while making an uncle block", err) +// return // } -// w.postSideBlock(core.ChainSideEvent{Block: uncle}) +// gen.SetCoinbase(common.BytesToAddress(addr)) +// }) -// select { -// case ev := <-sub.Chan(): -// block := ev.Data.(core.NewMinedBlockEvent).Block -// if _, err := chain.InsertChain([]*types.Block{block}); err != nil { -// t.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) -// } -// case <-time.After(3 * time.Second): // Worker needs 1s to include new changes. -// t.Fatalf("timeout") -// } -// } +// return blocks[0], err // } +const ( + // testCode is the testing contract binary code which will initialises some + // variables in constructor + testCode = "0x60806040527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0060005534801561003457600080fd5b5060fc806100436000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80630c4dae8814603757806398a213cf146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506084565b005b60005481565b806000819055507fe9e44f9f7da8c559de847a3232b57364adc0354f15a2cd8dc636d54396f9587a6000546040518082815260200191505060405180910390a15056fea265627a7a723058208ae31d9424f2d0bc2a3da1a5dd659db2d71ec322a17db8f87e19e209e3a1ff4a64736f6c634300050a0032" + + // testGas is the gas required for contract deployment. + testGas = 144109 + storageContractByteCode = "608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100a1565b60405180910390f35b610073600480360381019061006e91906100ed565b61007e565b005b60008054905090565b8060008190555050565b6000819050919050565b61009b81610088565b82525050565b60006020820190506100b66000830184610092565b92915050565b600080fd5b6100ca81610088565b81146100d557600080fd5b50565b6000813590506100e7816100c1565b92915050565b600060208284031215610103576101026100bc565b5b6000610111848285016100d8565b9150509291505056fea2646970667358221220322c78243e61b783558509c9cc22cb8493dde6925aa5e89a08cdf6e22f279ef164736f6c63430008120033" + storageContractTxCallData = "0x6057361d0000000000000000000000000000000000000000000000000000000000000001" + storageCallTxGas = 100000 +) + var ( // Test chain configurations testTxPoolConfig legacypool.Config @@ -267,12 +255,18 @@ type testWorkerBackend struct { genesis *core.Genesis } -func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, n int) *testWorkerBackend { +func newTestWorkerBackend(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database) *testWorkerBackend { var gspec = &core.Genesis{ Config: chainConfig, Alloc: core.GenesisAlloc{testBankAddress: {Balance: testBankFunds}}, } switch e := engine.(type) { + case *bor.Bor: + gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) + copy(gspec.ExtraData[32:32+common.AddressLength], TestBankAddress.Bytes()) + e.Authorize(TestBankAddress, func(account accounts.Account, s string, data []byte) ([]byte, error) { + return crypto.Sign(crypto.Keccak256(data), testBankKey) + }) case *clique.Clique: gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength) copy(gspec.ExtraData[32:32+common.AddressLength], testBankAddress.Bytes()) @@ -283,6 +277,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine default: t.Fatalf("unexpected consensus engine type: %T", engine) } + // genesis := gspec.MustCommit(db) chain, err := core.NewBlockChain(db, &core.CacheConfig{TrieDirtyDisabled: true}, gspec, nil, engine, vm.Config{}, nil, nil, nil) if err != nil { t.Fatalf("core.NewBlockChain failed: %v", err) @@ -315,12 +310,58 @@ func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction { return tx } -func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int) (*worker, *testWorkerBackend) { - backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks) +// newRandomTxWithNonce creates a new transaction with the given nonce. +func (b *testWorkerBackend) newRandomTxWithNonce(creation bool, nonce uint64) *types.Transaction { + var tx *types.Transaction + + gasPrice := big.NewInt(100 * params.InitialBaseFee) + + if creation { + tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(TestBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(testCode)), types.HomesteadSigner{}, testBankKey) + } else { + tx, _ = types.SignTx(types.NewTransaction(nonce, testUserAddress, big.NewInt(1000), params.TxGas, gasPrice, nil), types.HomesteadSigner{}, testBankKey) + } + + return tx +} + +// newStorageCreateContractTx creates a new transaction to deploy a storage smart contract. +func (b *testWorkerBackend) newStorageCreateContractTx() (*types.Transaction, common.Address) { + var tx *types.Transaction + + gasPrice := big.NewInt(10 * params.InitialBaseFee) + + tx, _ = types.SignTx(types.NewContractCreation(b.txPool.Nonce(TestBankAddress), big.NewInt(0), testGas, gasPrice, common.FromHex(storageContractByteCode)), types.HomesteadSigner{}, testBankKey) + contractAddr := crypto.CreateAddress(TestBankAddress, b.txPool.Nonce(TestBankAddress)) + + return tx, contractAddr +} + +// newStorageContractCallTx creates a new transaction to call a storage smart contract. +func (b *testWorkerBackend) newStorageContractCallTx(to common.Address, nonce uint64) *types.Transaction { + var tx *types.Transaction + + gasPrice := big.NewInt(10 * params.InitialBaseFee) + + tx, _ = types.SignTx(types.NewTransaction(nonce, to, nil, storageCallTxGas, gasPrice, common.FromHex(storageContractTxCallData)), types.HomesteadSigner{}, testBankKey) + + return tx +} + +func newTestWorker(t TensingObject, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int, noempty bool, delay uint, opcodeDelay uint) (*worker, *testWorkerBackend, func()) { + backend := newTestWorkerBackend(t, chainConfig, engine, db) backend.txPool.Add(pendingTxs, true, false) - w := newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false) + var w *worker + if delay != 0 || opcodeDelay != 0 { + //nolint:staticcheck + w = newWorkerWithDelay(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false, delay, opcodeDelay) + } else { + //nolint:staticcheck + w = newWorker(testConfig, chainConfig, engine, backend, new(event.TypeMux), nil, false) + } w.setEtherbase(testBankAddress) - return w, backend + // enable empty blocks + return w, backend, w.close } func TestGenerateAndImportBlock(t *testing.T) { @@ -331,7 +372,7 @@ func TestGenerateAndImportBlock(t *testing.T) { config.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000} engine := clique.New(config.Clique, db) - w, b := newTestWorker(t, &config, engine, db, 0) + w, b, _ := newTestWorker(t, &config, engine, db, 0, false, 0, 0) defer w.close() // This test chain imports the mined blocks. @@ -366,36 +407,35 @@ func TestGenerateAndImportBlock(t *testing.T) { } } -// TODO - Arpit -// func getFakeBorFromConfig(t *testing.T, chainConfig *params.ChainConfig) (consensus.Engine, *gomock.Controller) { -// t.Helper() +func getFakeBorFromConfig(t *testing.T, chainConfig *params.ChainConfig) (consensus.Engine, *gomock.Controller) { + t.Helper() -// ctrl := gomock.NewController(t) + ctrl := gomock.NewController(t) -// ethAPIMock := api.NewMockCaller(ctrl) -// ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + ethAPIMock := api.NewMockCaller(ctrl) + ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() -// spanner := bor.NewMockSpanner(ctrl) -// spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ -// { -// ID: 0, -// Address: TestBankAddress, -// VotingPower: 100, -// ProposerPriority: 0, -// }, -// }, nil).AnyTimes() + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: TestBankAddress, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() -// heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) -// heimdallClientMock.EXPECT().Close().Times(1) + heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) + heimdallClientMock.EXPECT().Close().Times(1) -// contractMock := bor.NewMockGenesisContract(ctrl) + contractMock := bor.NewMockGenesisContract(ctrl) -// db, _, _ := NewDBForFakes(t) + db, _, _ := NewDBForFakes(t) -// engine := NewFakeBor(t, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) + engine := NewFakeBor(t, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) -// return engine, ctrl -// } + return engine, ctrl +} func TestEmptyWorkEthash(t *testing.T) { t.Skip() @@ -410,7 +450,7 @@ func testEmptyWork(t *testing.T, chainConfig *params.ChainConfig, engine consens t.Helper() defer engine.Close() - w, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) + w, _, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) defer w.close() taskCh := make(chan struct{}, 2) @@ -457,7 +497,7 @@ func TestAdjustIntervalClique(t *testing.T) { func testAdjustInterval(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { defer engine.Close() - w, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) + w, _, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) defer w.close() w.skipSealHook = func(task *task) bool { @@ -559,7 +599,7 @@ func TestGetSealingWorkPostMerge(t *testing.T) { func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine) { defer engine.Close() - w, b := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) + w, b, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) defer w.close() w.setExtra([]byte{0x01, 0x02}) @@ -678,348 +718,348 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co } } -// // TODO - Arpit -// // nolint : paralleltest -// // TestCommitInterruptExperimentBor tests the commit interrupt experiment for bor consensus by inducing an artificial delay at transaction level. -// func TestCommitInterruptExperimentBor(t *testing.T) { -// // with 1 sec block time and 200 millisec tx delay we should get 5 txs per block -// testCommitInterruptExperimentBor(t, 200, 5, 0) +// nolint : paralleltest +// TestCommitInterruptExperimentBor tests the commit interrupt experiment for bor consensus by inducing an artificial delay at transaction level. +func TestCommitInterruptExperimentBor(t *testing.T) { + // with 1 sec block time and 200 millisec tx delay we should get 5 txs per block + testCommitInterruptExperimentBor(t, 200, 5, 0) -// time.Sleep(2 * time.Second) + time.Sleep(2 * time.Second) -// // with 1 sec block time and 100 millisec tx delay we should get 10 txs per block -// testCommitInterruptExperimentBor(t, 100, 10, 0) -// } + // with 1 sec block time and 100 millisec tx delay we should get 10 txs per block + testCommitInterruptExperimentBor(t, 100, 10, 0) +} -// // TODO - Arpit -// // nolint : paralleltest -// // TestCommitInterruptExperimentBorContract tests the commit interrupt experiment for bor consensus by inducing an artificial delay at OPCODE level. -// func TestCommitInterruptExperimentBorContract(t *testing.T) { -// // pre-calculated number of OPCODES = 123. 7*123=861 < 1000, 1 tx is possible but 2 tx per block will not be possible. -// testCommitInterruptExperimentBorContract(t, 0, 1, 7) -// time.Sleep(2 * time.Second) -// // pre-calculated number of OPCODES = 123. 2*123=246 < 1000, 4 tx is possible but 5 tx per block will not be possible. But 3 happen due to other overheads. -// testCommitInterruptExperimentBorContract(t, 0, 3, 2) -// time.Sleep(2 * time.Second) -// // pre-calculated number of OPCODES = 123. 3*123=369 < 1000, 2 tx is possible but 3 tx per block will not be possible. -// testCommitInterruptExperimentBorContract(t, 0, 2, 3) -// } +// nolint : paralleltest +// TestCommitInterruptExperimentBorContract tests the commit interrupt experiment for bor consensus by inducing an artificial delay at OPCODE level. +func TestCommitInterruptExperimentBorContract(t *testing.T) { + // pre-calculated number of OPCODES = 123. 7*123=861 < 1000, 1 tx is possible but 2 tx per block will not be possible. + testCommitInterruptExperimentBorContract(t, 0, 1, 7) + time.Sleep(2 * time.Second) + // pre-calculated number of OPCODES = 123. 2*123=246 < 1000, 4 tx is possible but 5 tx per block will not be possible. But 3 happen due to other overheads. + testCommitInterruptExperimentBorContract(t, 0, 3, 2) + time.Sleep(2 * time.Second) + // pre-calculated number of OPCODES = 123. 3*123=369 < 1000, 2 tx is possible but 3 tx per block will not be possible. + testCommitInterruptExperimentBorContract(t, 0, 2, 3) +} -// // TODO - Arpit -// // nolint : thelper -// // testCommitInterruptExperimentBorContract is a helper function for testing the commit interrupt experiment for bor consensus. -// func testCommitInterruptExperimentBorContract(t *testing.T, delay uint, txCount int, opcodeDelay uint) { -// var ( -// engine consensus.Engine -// chainConfig *params.ChainConfig -// db = rawdb.NewMemoryDatabase() -// ctrl *gomock.Controller -// txInTxpool = 100 -// txs = make([]*types.Transaction, 0, txInTxpool) -// ) - -// chainConfig = params.BorUnittestChainConfig - -// log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - -// engine, ctrl = getFakeBorFromConfig(t, chainConfig) - -// w, b := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0) -// defer w.close() - -// // nonce 0 tx -// tx, addr := b.newStorageCreateContractTx() -// if err := b.TxPool().AddRemote(tx); err != nil { -// t.Fatal(err) -// } +// nolint : thelper +// testCommitInterruptExperimentBorContract is a helper function for testing the commit interrupt experiment for bor consensus. +func testCommitInterruptExperimentBorContract(t *testing.T, delay uint, txCount int, opcodeDelay uint) { + var ( + engine consensus.Engine + chainConfig *params.ChainConfig + txInTxpool = 100 + txs = make([]*types.Transaction, 0, txInTxpool) + ) -// time.Sleep(4 * time.Second) + chainConfig = params.BorUnittestChainConfig -// // nonce starts from 1 because we already have one tx -// initNonce := uint64(1) + log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) -// for i := 0; i < txInTxpool; i++ { -// tx := b.newStorageContractCallTx(addr, initNonce+uint64(i)) -// txs = append(txs, tx) -// } + engine, _ = getFakeBorFromConfig(t, chainConfig) -// b.TxPool().AddRemotes(txs) + w, b, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) + defer w.close() -// // Start mining! -// w.start() -// time.Sleep(5 * time.Second) -// w.stop() + // nonce 0 tx + tx, addr := b.newStorageCreateContractTx() + if err := b.txPool.Add([]*txpool.Transaction{{Tx: tx}}, false, false)[0]; err != nil { + t.Fatal(err) + } -// currentBlockNumber := w.current.header.Number.Uint64() -// assert.Check(t, txCount >= w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()) -// assert.Check(t, 0 < w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()+1) -// } + time.Sleep(4 * time.Second) + + // nonce starts from 1 because we already have one tx + initNonce := uint64(1) + + for i := 0; i < txInTxpool; i++ { + tx := b.newStorageContractCallTx(addr, initNonce+uint64(i)) + txs = append(txs, tx) + } + + wrapped := make([]*txpool.Transaction, len(txs)) + for i, tx := range txs { + wrapped[i] = &txpool.Transaction{Tx: tx} + } + + b.TxPool().Add(wrapped, false, false) + + // Start mining! + w.start() + time.Sleep(5 * time.Second) + w.stop() + + currentBlockNumber := w.current.header.Number.Uint64() + assert.Check(t, txCount >= w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()) + assert.Check(t, 0 < w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()+1) +} -// // TODO - Arpit // // nolint : thelper -// // testCommitInterruptExperimentBor is a helper function for testing the commit interrupt experiment for bor consensus. -// func testCommitInterruptExperimentBor(t *testing.T, delay uint, txCount int, opcodeDelay uint) { -// var ( -// engine consensus.Engine -// chainConfig *params.ChainConfig -// db = rawdb.NewMemoryDatabase() -// ctrl *gomock.Controller -// txInTxpool = 100 -// txs = make([]*types.Transaction, 0, txInTxpool) -// ) - -// chainConfig = params.BorUnittestChainConfig - -// log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) - -// engine, ctrl = getFakeBorFromConfig(t, chainConfig) - -// w, b, _ := newTestWorker(t, chainConfig, engine, db, 0, true, delay, opcodeDelay) -// defer func() { -// w.close() -// engine.Close() -// db.Close() -// ctrl.Finish() -// }() - -// // nonce starts from 0 because have no txs yet -// initNonce := uint64(0) - -// for i := 0; i < txInTxpool; i++ { -// tx := b.newRandomTxWithNonce(false, initNonce+uint64(i)) -// txs = append(txs, tx) -// } +// testCommitInterruptExperimentBor is a helper function for testing the commit interrupt experiment for bor consensus. +func testCommitInterruptExperimentBor(t *testing.T, delay uint, txCount int, opcodeDelay uint) { + var ( + engine consensus.Engine + chainConfig *params.ChainConfig + db = rawdb.NewMemoryDatabase() + ctrl *gomock.Controller + txInTxpool = 100 + txs = make([]*types.Transaction, 0, txInTxpool) + ) -// b.TxPool().AddRemotes(txs) + chainConfig = params.BorUnittestChainConfig -// // Start mining! -// w.start() -// time.Sleep(5 * time.Second) -// w.stop() + log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) -// currentBlockNumber := w.current.header.Number.Uint64() -// assert.Check(t, txCount >= w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()) -// assert.Check(t, 0 < w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()) -// } + engine, ctrl = getFakeBorFromConfig(t, chainConfig) -// TODO - Arpit -// func BenchmarkBorMining(b *testing.B) { -// chainConfig := params.BorUnittestChainConfig + w, b, _ := newTestWorker(t, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) + defer func() { + w.close() + engine.Close() + db.Close() + ctrl.Finish() + }() -// ctrl := gomock.NewController(b) -// defer ctrl.Finish() + // nonce starts from 0 because have no txs yet + initNonce := uint64(0) -// ethAPIMock := api.NewMockCaller(ctrl) -// ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + for i := 0; i < txInTxpool; i++ { + tx := b.newRandomTxWithNonce(false, initNonce+uint64(i)) + txs = append(txs, tx) + } -// spanner := bor.NewMockSpanner(ctrl) -// spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ -// { -// ID: 0, -// Address: TestBankAddress, -// VotingPower: 100, -// ProposerPriority: 0, -// }, -// }, nil).AnyTimes() + wrapped := make([]*txpool.Transaction, len(txs)) + for i, tx := range txs { + wrapped[i] = &txpool.Transaction{Tx: tx} + } -// heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) -// heimdallClientMock.EXPECT().Close().Times(1) + b.TxPool().Add(wrapped, false, false) -// contractMock := bor.NewMockGenesisContract(ctrl) + // Start mining! + w.start() + time.Sleep(5 * time.Second) + w.stop() -// db, _, _ := NewDBForFakes(b) + currentBlockNumber := w.current.header.Number.Uint64() + assert.Check(t, txCount >= w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()) + assert.Check(t, 0 < w.chain.GetBlockByNumber(currentBlockNumber-1).Transactions().Len()) +} -// engine := NewFakeBor(b, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) -// defer engine.Close() +func BenchmarkBorMining(b *testing.B) { + chainConfig := params.BorUnittestChainConfig -// chainConfig.LondonBlock = big.NewInt(0) + ctrl := gomock.NewController(b) + defer ctrl.Finish() -// w, back, _ := newTestWorker(b, chainConfig, engine, db, 0, false, 0, 0) -// defer w.close() + ethAPIMock := api.NewMockCaller(ctrl) + ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() -// chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, back.Genesis, nil, engine, vm.Config{}, nil, nil, nil) -// defer chain.Stop() + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: TestBankAddress, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() -// // fulfill tx pool -// const ( -// totalGas = testGas + params.TxGas -// totalBlocks = 10 -// ) + heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) + heimdallClientMock.EXPECT().Close().Times(1) -// var err error + contractMock := bor.NewMockGenesisContract(ctrl) -// txInBlock := int(back.Genesis.GasLimit/totalGas) + 1 + db, _, _ := NewDBForFakes(b) -// // a bit risky -// for i := 0; i < 2*totalBlocks*txInBlock; i++ { -// err = back.txPool.AddLocal(back.newRandomTx(true)) -// if err != nil { -// b.Fatal("while adding a local transaction", err) -// } + engine := NewFakeBor(b, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) + defer engine.Close() -// err = back.txPool.AddLocal(back.newRandomTx(false)) -// if err != nil { -// b.Fatal("while adding a remote transaction", err) -// } -// } + chainConfig.LondonBlock = big.NewInt(0) -// // Wait for mined blocks. -// sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) -// defer sub.Unsubscribe() + w, back, _ := newTestWorker(b, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) + defer w.close() -// b.ResetTimer() + chain, _ := core.NewBlockChain(rawdb.NewMemoryDatabase(), nil, back.genesis, nil, engine, vm.Config{}, nil, nil, nil) + defer chain.Stop() -// prev := uint64(time.Now().Unix()) + // fulfill tx pool + const ( + totalGas = testGas + params.TxGas + totalBlocks = 10 + ) -// // Start mining! -// w.start() + var err error -// blockPeriod, ok := back.Genesis.Config.Bor.Period["0"] -// if !ok { -// blockPeriod = 1 -// } + txInBlock := int(back.genesis.GasLimit/totalGas) + 1 -// for i := 0; i < totalBlocks; i++ { -// select { -// case ev := <-sub.Chan(): -// block := ev.Data.(core.NewMinedBlockEvent).Block + // a bit risky + for i := 0; i < 2*totalBlocks*txInBlock; i++ { + err = back.txPool.Add([]*txpool.Transaction{{Tx: back.newRandomTx(true)}}, true, false)[0] + if err != nil { + b.Fatal("while adding a local transaction", err) + } -// if _, err := chain.InsertChain([]*types.Block{block}); err != nil { -// b.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) -// } + err = back.txPool.Add([]*txpool.Transaction{{Tx: back.newRandomTx(false)}}, false, false)[0] + if err != nil { + b.Fatal("while adding a remote transaction", err) + } + } -// b.Log("block", block.NumberU64(), "time", block.Time()-prev, "txs", block.Transactions().Len(), "gasUsed", block.GasUsed(), "gasLimit", block.GasLimit()) + // Wait for mined blocks. + sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) + defer sub.Unsubscribe() -// prev = block.Time() -// case <-time.After(time.Duration(blockPeriod) * time.Second): -// b.Fatalf("timeout") -// } -// } -// } + b.ResetTimer() + + prev := uint64(time.Now().Unix()) + + // Start mining! + w.start() + + blockPeriod, ok := back.genesis.Config.Bor.Period["0"] + if !ok { + blockPeriod = 1 + } + + for i := 0; i < totalBlocks; i++ { + select { + case ev := <-sub.Chan(): + block := ev.Data.(core.NewMinedBlockEvent).Block + + if _, err := chain.InsertChain([]*types.Block{block}); err != nil { + b.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) + } + + b.Log("block", block.NumberU64(), "time", block.Time()-prev, "txs", block.Transactions().Len(), "gasUsed", block.GasUsed(), "gasLimit", block.GasLimit()) + + prev = block.Time() + case <-time.After(time.Duration(blockPeriod) * time.Second): + b.Fatalf("timeout") + } + } +} -// TODO - Arpit // uses core.NewParallelBlockChain to use the dependencies present in the block header // params.BorUnittestChainConfig contains the ParallelUniverseBlock ad big.NewInt(5), so the first 4 blocks will not have metadata. // nolint: gocognit -// func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) { -// chainConfig := params.BorUnittestChainConfig +func BenchmarkBorMiningBlockSTMMetadata(b *testing.B) { + chainConfig := params.BorUnittestChainConfig -// ctrl := gomock.NewController(b) -// defer ctrl.Finish() + ctrl := gomock.NewController(b) + defer ctrl.Finish() -// ethAPIMock := api.NewMockCaller(ctrl) -// ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() + ethAPIMock := api.NewMockCaller(ctrl) + ethAPIMock.EXPECT().Call(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() -// spanner := bor.NewMockSpanner(ctrl) -// spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ -// { -// ID: 0, -// Address: TestBankAddress, -// VotingPower: 100, -// ProposerPriority: 0, -// }, -// }, nil).AnyTimes() + spanner := bor.NewMockSpanner(ctrl) + spanner.EXPECT().GetCurrentValidatorsByHash(gomock.Any(), gomock.Any(), gomock.Any()).Return([]*valset.Validator{ + { + ID: 0, + Address: TestBankAddress, + VotingPower: 100, + ProposerPriority: 0, + }, + }, nil).AnyTimes() -// heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) -// heimdallClientMock.EXPECT().Close().Times(1) + heimdallClientMock := mocks.NewMockIHeimdallClient(ctrl) + heimdallClientMock.EXPECT().Close().Times(1) -// contractMock := bor.NewMockGenesisContract(ctrl) + contractMock := bor.NewMockGenesisContract(ctrl) -// db, _, _ := NewDBForFakes(b) + db, _, _ := NewDBForFakes(b) -// engine := NewFakeBor(b, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) -// defer engine.Close() + engine := NewFakeBor(b, db, chainConfig, ethAPIMock, spanner, heimdallClientMock, contractMock) + defer engine.Close() -// chainConfig.LondonBlock = big.NewInt(0) + chainConfig.LondonBlock = big.NewInt(0) -// w, back := newTestWorker(b, chainConfig, engine, db, 0) + w, back, _ := newTestWorker(b, chainConfig, engine, rawdb.NewMemoryDatabase(), 0, false, 0, 0) + defer w.close() -// // w, back, _ := NewTestWorker(b, chainConfig, engine, db, 0, false, 0, 0) -// defer w.close() + // This test chain imports the mined blocks. + db2 := rawdb.NewMemoryDatabase() + back.genesis.MustCommit(db2) -// // This test chain imports the mined blocks. -// db2 := rawdb.NewMemoryDatabase() -// back.Genesis.MustCommit(db2) + chain, _ := core.NewParallelBlockChain(db2, nil, back.genesis, nil, engine, vm.Config{ParallelEnable: true, ParallelSpeculativeProcesses: 8}, nil, nil, nil) + defer chain.Stop() -// chain, _ := core.NewParallelBlockChain(db2, nil, back.Genesis, nil, engine, vm.Config{ParallelEnable: true, ParallelSpeculativeProcesses: 8}, nil, nil, nil) -// defer chain.Stop() + // Ignore empty commit here for less noise. + w.skipSealHook = func(task *task) bool { + return len(task.receipts) == 0 + } -// // Ignore empty commit here for less noise. -// w.skipSealHook = func(task *task) bool { -// return len(task.receipts) == 0 -// } + // fulfill tx pool + const ( + totalGas = testGas + params.TxGas + totalBlocks = 10 + ) -// // fulfill tx pool -// const ( -// totalGas = testGas + params.TxGas -// totalBlocks = 10 -// ) + var err error -// var err error + txInBlock := int(back.genesis.GasLimit/totalGas) + 1 -// txInBlock := int(back.Genesis.GasLimit/totalGas) + 1 + // a bit risky + for i := 0; i < 2*totalBlocks*txInBlock; i++ { + err = back.txPool.Add([]*txpool.Transaction{{Tx: back.newRandomTx(true)}}, true, false)[0] + if err != nil { + b.Fatal("while adding a local transaction", err) + } -// // a bit risky -// for i := 0; i < 2*totalBlocks*txInBlock; i++ { -// err = back.txPool.AddLocal(back.newRandomTx(true)) -// if err != nil { -// b.Fatal("while adding a local transaction", err) -// } + err = back.txPool.Add([]*txpool.Transaction{{Tx: back.newRandomTx(false)}}, false, false)[0] + if err != nil { + b.Fatal("while adding a remote transaction", err) + } + } -// err = back.txPool.AddLocal(back.newRandomTx(false)) -// if err != nil { -// b.Fatal("while adding a remote transaction", err) -// } -// } + // Wait for mined blocks. + sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) + defer sub.Unsubscribe() -// // Wait for mined blocks. -// sub := w.mux.Subscribe(core.NewMinedBlockEvent{}) -// defer sub.Unsubscribe() + b.ResetTimer() -// b.ResetTimer() + prev := uint64(time.Now().Unix()) -// prev := uint64(time.Now().Unix()) + // Start mining! + w.start() -// // Start mining! -// w.start() + blockPeriod, ok := back.genesis.Config.Bor.Period["0"] + if !ok { + blockPeriod = 1 + } -// blockPeriod, ok := back.Genesis.Config.Bor.Period["0"] -// if !ok { -// blockPeriod = 1 -// } + for i := 0; i < totalBlocks; i++ { + select { + case ev := <-sub.Chan(): + block := ev.Data.(core.NewMinedBlockEvent).Block -// for i := 0; i < totalBlocks; i++ { -// select { -// case ev := <-sub.Chan(): -// block := ev.Data.(core.NewMinedBlockEvent).Block - -// if _, err := chain.InsertChain([]*types.Block{block}); err != nil { -// b.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) -// } - -// // check for dependencies for block number > 4 -// if block.NumberU64() <= 4 { -// if block.GetTxDependency() != nil { -// b.Fatalf("dependency not nil") -// } -// } else { -// deps := block.GetTxDependency() -// if len(deps[0]) != 0 { -// b.Fatalf("wrong dependency") -// } - -// for i := 1; i < block.Transactions().Len(); i++ { -// if deps[i][0] != uint64(i-1) || len(deps[i]) != 1 { -// b.Fatalf("wrong dependency") -// } -// } -// } - -// b.Log("block", block.NumberU64(), "time", block.Time()-prev, "txs", block.Transactions().Len(), "gasUsed", block.GasUsed(), "gasLimit", block.GasLimit()) - -// prev = block.Time() -// case <-time.After(time.Duration(blockPeriod) * time.Second): -// b.Fatalf("timeout") -// } -// } -// } + if _, err := chain.InsertChain([]*types.Block{block}); err != nil { + b.Fatalf("failed to insert new mined block %d: %v", block.NumberU64(), err) + } + + // check for dependencies for block number > 4 + if block.NumberU64() <= 4 { + if block.GetTxDependency() != nil { + b.Fatalf("dependency not nil") + } + } else { + deps := block.GetTxDependency() + if len(deps[0]) != 0 { + b.Fatalf("wrong dependency") + } + + for i := 1; i < block.Transactions().Len(); i++ { + if deps[i][0] != uint64(i-1) || len(deps[i]) != 1 { + b.Fatalf("wrong dependency") + } + } + } + + b.Log("block", block.NumberU64(), "time", block.Time()-prev, "txs", block.Transactions().Len(), "gasUsed", block.GasUsed(), "gasLimit", block.GasLimit()) + + prev = block.Time() + case <-time.After(time.Duration(blockPeriod) * time.Second): + b.Fatalf("timeout") + } + } +}