From a0d9e5f2c716781f72700f5e68c326abfee9e7dc Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Thu, 5 Aug 2021 21:42:21 +0800 Subject: [PATCH 1/2] change Canon chain condition --- consensus/consensus.go | 1 + consensus/parlia/parlia.go | 28 ++++++++++++++++++++++++++++ core/blockchain.go | 6 +++++- miner/worker.go | 11 +++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/consensus/consensus.go b/consensus/consensus.go index 69a5f2f2ef..fc161390f9 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -140,4 +140,5 @@ type PoSA interface { IsSystemTransaction(tx *types.Transaction, header *types.Header) (bool, error) IsSystemContract(to *common.Address) bool EnoughDistance(chain ChainReader, header *types.Header) bool + IsLocalBlock(header *types.Header) bool } diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 62d109848f..14304fe2bc 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -882,6 +882,34 @@ func (p *Parlia) EnoughDistance(chain consensus.ChainReader, header *types.Heade return snap.enoughDistance(p.val, header) } +func (p *Parlia) IsLocalBlock(header *types.Header) bool { + return p.val == header.Coinbase +} + +func (p *Parlia) SignRecently(chain consensus.ChainReader, parent *types.Header) (bool, error) { + snap, err := p.snapshot(chain, parent.Number.Uint64(), parent.ParentHash, nil) + if err != nil { + return true, err + } + + // Bail out if we're unauthorized to sign a block + if _, authorized := snap.Validators[p.val]; !authorized { + return true, errUnauthorizedValidator + } + + // If we're amongst the recent signers, wait for the next block + number := parent.Number.Uint64() + 1 + for seen, recent := range snap.Recents { + if recent == p.val { + // Signer is among recents, only wait if the current block doesn't shift it out + if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit { + return true, nil + } + } + } + return false, nil +} + // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have based on the previous blocks in the chain and the // current signer. diff --git a/core/blockchain.go b/core/blockchain.go index 3cc44fc4e5..8b8b36b081 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1578,8 +1578,12 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. if !reorg && externTd.Cmp(localTd) == 0 { // Split same-difficulty blocks by number, then preferentially select // the block generated by the local miner as the canonical block. - if block.NumberU64() < currentBlock.NumberU64() { + if block.NumberU64() < currentBlock.NumberU64() || block.Time() < currentBlock.Time() { reorg = true + } else if p, ok := bc.engine.(consensus.PoSA); ok { + if p.IsLocalBlock(currentBlock.Header()) { + reorg = true + } } else if block.NumberU64() == currentBlock.NumberU64() { var currentPreserve, blockPreserve bool if bc.shouldPreserve != nil { diff --git a/miner/worker.go b/miner/worker.go index b93b8752af..984af7baaf 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -389,6 +389,17 @@ func (w *worker) newWorkLoop(recommit time.Duration) { } clearPending(head.Block.NumberU64()) timestamp = time.Now().Unix() + if p, ok := w.engine.(*parlia.Parlia); ok { + signedRecent, err := p.SignRecently(w.chain, head.Block.Header()) + if err != nil { + log.Info("Not allowed to propose block", "err", err) + continue + } + if signedRecent { + log.Info("Signed recently, must wait") + continue + } + } commit(true, commitInterruptNewHead) case <-timer.C: From 530ee7b3cd7767b18cff2b5f67cb8078633685a9 Mon Sep 17 00:00:00 2001 From: fudongbai <296179868@qq.com> Date: Mon, 9 Aug 2021 13:46:02 +0800 Subject: [PATCH 2/2] resolve comment --- core/blockchain.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 8b8b36b081..66f37914df 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1580,10 +1580,8 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. // the block generated by the local miner as the canonical block. if block.NumberU64() < currentBlock.NumberU64() || block.Time() < currentBlock.Time() { reorg = true - } else if p, ok := bc.engine.(consensus.PoSA); ok { - if p.IsLocalBlock(currentBlock.Header()) { - reorg = true - } + } else if p, ok := bc.engine.(consensus.PoSA); ok && p.IsLocalBlock(currentBlock.Header()) { + reorg = true } else if block.NumberU64() == currentBlock.NumberU64() { var currentPreserve, blockPreserve bool if bc.shouldPreserve != nil {