mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-01 17:43:45 +00:00
feat(worker): seal block early if we're over target block time (#706)
* feat(worker): seal block early if we're over target block time * use current.header.Time * typo * break instead of return
This commit is contained in:
parent
d81a3308b1
commit
62926d4649
3 changed files with 77 additions and 1 deletions
|
|
@ -251,6 +251,7 @@ type worker struct {
|
|||
skipSealHook func(*task) bool // Method to decide whether skipping the sealing.
|
||||
fullTaskHook func() // Method to call before pushing the full sealing task.
|
||||
resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval.
|
||||
beforeTxHook func() // Method to call before processing a transaction.
|
||||
}
|
||||
|
||||
func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus.Engine, eth Backend, mux *event.TypeMux, isLocalBlock func(*types.Block) bool, init bool) *worker {
|
||||
|
|
@ -1034,6 +1035,10 @@ func (w *worker) commitTransactions(txs types.OrderedTransactionSet, coinbase co
|
|||
var loops int64
|
||||
loop:
|
||||
for {
|
||||
if w.beforeTxHook != nil {
|
||||
w.beforeTxHook()
|
||||
}
|
||||
|
||||
loops++
|
||||
// In the following three cases, we will interrupt the execution of the transaction.
|
||||
// (1) new head block event arrival, the interrupt signal is 1
|
||||
|
|
@ -1055,6 +1060,12 @@ loop:
|
|||
}
|
||||
return atomic.LoadInt32(interrupt) == commitInterruptNewHead, circuitCapacityReached
|
||||
}
|
||||
// seal block early if we're over time
|
||||
// note: current.header.Time = max(parent.Time + cliquePeriod, now())
|
||||
if w.current.tcount > 0 && w.chainConfig.Clique != nil && uint64(time.Now().Unix()) > w.current.header.Time {
|
||||
circuitCapacityReached = true // skip subsequent invocations of commitTransactions
|
||||
break
|
||||
}
|
||||
// If we don't have enough gas for any further transactions then we're done
|
||||
if w.current.gasPool.Gas() < params.TxGas {
|
||||
log.Trace("Not enough gas for further transactions", "have", w.current.gasPool, "want", params.TxGas)
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ func newTestWorkerBackend(t *testing.T, chainConfig *params.ChainConfig, engine
|
|||
switch e := engine.(type) {
|
||||
case *clique.Clique:
|
||||
gspec.ExtraData = make([]byte, 32+common.AddressLength+crypto.SignatureLength)
|
||||
gspec.Timestamp = uint64(time.Now().Unix())
|
||||
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)
|
||||
|
|
@ -1253,3 +1254,67 @@ func TestSkippedTransactionDatabaseEntries(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSealBlockAfterCliquePeriod(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
var (
|
||||
engine consensus.Engine
|
||||
chainConfig *params.ChainConfig
|
||||
db = rawdb.NewMemoryDatabase()
|
||||
)
|
||||
chainConfig = params.AllCliqueProtocolChanges
|
||||
chainConfig.Clique = ¶ms.CliqueConfig{Period: 1, Epoch: 30000}
|
||||
engine = clique.New(chainConfig.Clique, db)
|
||||
w, b := newTestWorker(t, chainConfig, engine, db, 0)
|
||||
defer w.close()
|
||||
|
||||
// This test chain imports the mined blocks.
|
||||
b.genesis.MustCommit(db)
|
||||
chain, _ := core.NewBlockChain(db, nil, b.chain.Config(), engine, vm.Config{
|
||||
Debug: true,
|
||||
Tracer: vm.NewStructLogger(&vm.LogConfig{EnableMemory: true, EnableReturnData: true})}, nil, nil)
|
||||
defer chain.Stop()
|
||||
|
||||
// Ignore empty commit here for less noise.
|
||||
w.skipSealHook = func(task *task) bool {
|
||||
return len(task.receipts) == 0
|
||||
}
|
||||
|
||||
// Add artificial delay to transaction processing.
|
||||
w.beforeTxHook = func() {
|
||||
time.Sleep(time.Duration(chainConfig.Clique.Period) * 1 * time.Second)
|
||||
}
|
||||
|
||||
// Wait for mined blocks.
|
||||
sub := w.mux.Subscribe(core.NewMinedBlockEvent{})
|
||||
defer sub.Unsubscribe()
|
||||
|
||||
// Insert 2 non-l1msg txs
|
||||
b.txPool.AddLocal(b.newRandomTx(true))
|
||||
b.txPool.AddLocal(b.newRandomTx(false))
|
||||
|
||||
// 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)
|
||||
}
|
||||
assert.Equal(1, len(block.Transactions())) // only packed 1 tx, not 2
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
assert.Equal(1, len(block.Transactions()))
|
||||
case <-time.After(5 * time.Second):
|
||||
t.Fatalf("timeout")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
const (
|
||||
VersionMajor = 5 // Major version component of the current release
|
||||
VersionMinor = 2 // Minor version component of the current release
|
||||
VersionPatch = 4 // Patch version component of the current release
|
||||
VersionPatch = 5 // Patch version component of the current release
|
||||
VersionMeta = "mainnet" // Version metadata to append to the version string
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue