diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 13e8bb878e50..51acff97093c 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -47,7 +47,8 @@ const ( inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory inmemorySignatures = 4096 // Number of recent block signatures to keep in memory - wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers + wiggleTime = 500 * time.Millisecond // Random delay (per signer) to allow concurrent signers + genesisCoinBase = "0x0000000000000000000000000000000000000000" ) // Clique proof-of-authority protocol constants. @@ -374,6 +375,26 @@ func (c *Clique) GetSnapshot(chain consensus.ChainReader, header *types.Header) return snap, nil } +func position(list []common.Address, x common.Address) int { + for i, item := range list { + if item == x { + return i + } + } + return -1 +} + +func YourTurn(snap *Snapshot, header *types.Header, cur common.Address) (bool, error) { + pre, err := ecrecover(header, snap.sigcache) + if err != nil { + return false, err + } + preIndex := position(snap.signers(), pre) + curIndex := position(snap.signers(), cur) + log.Info("Debugging info", "number of masternodes", len(snap.signers()), "previous", pre, "position", preIndex, "current", cur, "position", curIndex) + return (preIndex+1)%len(snap.signers()) == curIndex || pre.String() == genesisCoinBase, nil +} + // snapshot retrieves the authorization snapshot at a given point in time. func (c *Clique) snapshot(chain consensus.ChainReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) { // Search for a snapshot in memory or on disk for checkpoints diff --git a/miner/worker.go b/miner/worker.go index 7b106aeb00ba..fdd69a03019c 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" @@ -397,6 +398,29 @@ func (self *worker) commitNewWork() { tstart := time.Now() parent := self.chain.CurrentBlock() + // Only try to commit new work if we are mining + if atomic.LoadInt32(&self.mining) == 1 { + // check if we are right after parent's coinbase in the list + // only go with Clique + if self.config.Clique != nil { + c := self.engine.(*clique.Clique) + snap, err := c.GetSnapshot(self.chain, parent.Header()) + if err != nil { + log.Error("Failed when trying to commit new work", "err", err) + return + } + ok, err := clique.YourTurn(snap, parent.Header(), self.coinbase) + if err != nil { + log.Error("Failed when trying to commit new work", "err", err) + return + } + if !ok { + log.Info("Not our turn to commit block. Wait for next time") + return + } + } + } + tstamp := tstart.Unix() if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 { tstamp = parent.Time().Int64() + 1