From 5494d3a7d0bccc436ae5732d8bcc2eaa8181929c Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 30 May 2018 12:08:02 +0700 Subject: [PATCH 1/4] masternode takes turn (circle) to propose block --- consensus/clique/clique.go | 13 +++++++++++++ miner/worker.go | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 13e8bb878e50..69176ac2ff46 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -374,6 +374,19 @@ 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, pre, cur common.Address) bool { + return (position(snap.signers(), pre)+1) % len(snap.signers()) == position(snap.signers(), cur) +} + // 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..de5c162827ed 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -397,6 +397,24 @@ 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 + } + if !clique.YourTurn(snap, parent.Coinbase(), self.coinbase) { + log.Info("Not our turn to commit block", "wait") + return + } + } + } + tstamp := tstart.Unix() if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 { tstamp = parent.Time().Int64() + 1 From cfdde4333e40186f11594427ff81c7815e8f0a85 Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 30 May 2018 14:24:47 +0700 Subject: [PATCH 2/4] golint fix --- miner/worker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miner/worker.go b/miner/worker.go index de5c162827ed..40d2b63dadec 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -409,7 +409,7 @@ func (self *worker) commitNewWork() { return } if !clique.YourTurn(snap, parent.Coinbase(), self.coinbase) { - log.Info("Not our turn to commit block", "wait") + log.Info("Not our turn to commit block", "wait", nil) return } } From 789e03f167e08a75596a4361ec23c982b64b5f3e Mon Sep 17 00:00:00 2001 From: Tuna Date: Wed, 30 May 2018 14:52:15 +0700 Subject: [PATCH 3/4] block 1 - all masternodes race to create --- consensus/clique/clique.go | 11 ++++++++--- miner/worker.go | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 69176ac2ff46..d845734f1782 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. @@ -384,7 +385,10 @@ func position(list []common.Address, x common.Address) int { } func YourTurn(snap *Snapshot, pre, cur common.Address) bool { - return (position(snap.signers(), pre)+1) % len(snap.signers()) == position(snap.signers(), cur) + 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 } // snapshot retrieves the authorization snapshot at a given point in time. @@ -526,7 +530,8 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p // header for running the transactions on top. func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) error { // If the block isn't a checkpoint, cast a random vote (good enough for now) - header.Coinbase = common.Address{} + //FIXME: keep header.Coinbase == miner's address + //header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} number := header.Number.Uint64() diff --git a/miner/worker.go b/miner/worker.go index 40d2b63dadec..4f27e6d3cea3 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -409,7 +409,7 @@ func (self *worker) commitNewWork() { return } if !clique.YourTurn(snap, parent.Coinbase(), self.coinbase) { - log.Info("Not our turn to commit block", "wait", nil) + log.Info("Not our turn to commit block. Wait for next time") return } } From d91e00e170cdd6a969f03eab895d22f309846f28 Mon Sep 17 00:00:00 2001 From: Tuna Date: Thu, 31 May 2018 15:41:20 +0700 Subject: [PATCH 4/4] reuse Clique voting strategy for now, leave header.Coinbase empty --- consensus/clique/clique.go | 11 +++++++---- miner/worker.go | 8 +++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index d845734f1782..51acff97093c 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -384,11 +384,15 @@ func position(list []common.Address, x common.Address) int { return -1 } -func YourTurn(snap *Snapshot, pre, cur common.Address) bool { +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 + return (preIndex+1)%len(snap.signers()) == curIndex || pre.String() == genesisCoinBase, nil } // snapshot retrieves the authorization snapshot at a given point in time. @@ -530,8 +534,7 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p // header for running the transactions on top. func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) error { // If the block isn't a checkpoint, cast a random vote (good enough for now) - //FIXME: keep header.Coinbase == miner's address - //header.Coinbase = common.Address{} + header.Coinbase = common.Address{} header.Nonce = types.BlockNonce{} number := header.Number.Uint64() diff --git a/miner/worker.go b/miner/worker.go index 4f27e6d3cea3..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" @@ -408,7 +409,12 @@ func (self *worker) commitNewWork() { log.Error("Failed when trying to commit new work", "err", err) return } - if !clique.YourTurn(snap, parent.Coinbase(), self.coinbase) { + 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 }