Implemented fix for bad block sync bug

During mining, commit is called twice, to generate an empty block for
concurrent sealing. This resulted in inadvertent double-slashing of
out-of-turn validators during block creation leading to bad blocks.
This commit is contained in:
Shane Bammel 2021-12-16 21:44:04 -06:00
parent 8c6a10133b
commit 1926e96f78
7 changed files with 8 additions and 8 deletions

View File

@ -579,7 +579,7 @@ func (c *Clique) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (c *Clique) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB,
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, finalUpdate bool) (*types.Block, []*types.Receipt, error) {
// Finalize block
c.Finalize(chain, header, state, &txs, uncles, nil, nil, nil)

View File

@ -100,7 +100,7 @@ type Engine interface {
// Note: The block header and state database might be updated to reflect any
// consensus rules that happen at finalization (e.g. block rewards).
FinalizeAndAssemble(chain ChainHeaderReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error)
uncles []*types.Header, receipts []*types.Receipt, finalUpdate bool) (*types.Block, []*types.Receipt, error)
// Seal generates a new sealing request for the given input block and pushes
// the result into the given channel.

View File

@ -597,7 +597,7 @@ func (ethash *Ethash) Finalize(chain consensus.ChainHeaderReader, header *types.
// FinalizeAndAssemble implements consensus.Engine, accumulating the block and
// uncle rewards, setting the final state and assembling the block.
func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB,
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, finalUpdate bool) (*types.Block, []*types.Receipt, error) {
ethash.Finalize(chain, header, state, &txs, uncles, nil, nil, nil)

View File

@ -810,7 +810,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set,
// nor block rewards given, and returns the final block.
func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB,
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt) (*types.Block, []*types.Receipt, error) {
txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, finalUpdate bool) (*types.Block, []*types.Receipt, error) {
// No block rewards in PoA, so the state remains as is and uncles are dropped
cx := chainContext{Chain: chain, parlia: p}
if txs == nil {
@ -844,7 +844,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
}
}
if header.Difficulty.Cmp(diffInTurn) != 0 {
if finalUpdate && header.Difficulty.Cmp(diffInTurn) != 0 {
snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
if err != nil {
panic(err)

View File

@ -227,7 +227,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
}
if b.engine != nil {
// Finalize and seal the block
block, _, _ := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts)
block, _, _ := b.engine.FinalizeAndAssemble(chainreader, b.header, statedb, b.txs, b.uncles, b.receipts, true)
// Write state changes to db
root, err := statedb.Commit(config.IsEIP158(b.header.Number))

View File

@ -211,7 +211,7 @@ func (api *consensusAPI) AssembleBlock(params assembleBlockParams) (*executableD
}
// Create the block.
block, _, err := api.eth.Engine().FinalizeAndAssemble(bc, header, env.state, transactions, nil /* uncles */, env.receipts)
block, _, err := api.eth.Engine().FinalizeAndAssemble(bc, header, env.state, transactions, nil /* uncles */, env.receipts, true)
if err != nil {
return nil, err
}

View File

@ -1035,7 +1035,7 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st
// Deep copy receipts here to avoid interaction between different tasks.
receipts := copyReceipts(w.current.receipts)
s := w.current.state.Copy()
block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, receipts)
block, receipts, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, receipts, update)
if err != nil {
return err
}