Merge pull request #132 from ngtuna/update-m1

directly set mns to snapshot
This commit is contained in:
Tuna 2018-08-16 11:51:10 +07:00 committed by GitHub
commit f9d15d7e9d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 61 additions and 27 deletions

View file

@ -44,7 +44,6 @@ import (
) )
const ( const (
checkpointInterval = 1024 // Number of blocks after which to save the vote snapshot to the database
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
inmemorySignatures = 4096 // Number of recent block signatures 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
@ -395,14 +394,25 @@ func position(list []common.Address, x common.Address) int {
} }
func (c *Clique) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address { func (c *Clique) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address {
lastCheckpointNumber := header.Number.Uint64() - (header.Number.Uint64() % c.config.Epoch) n := header.Number.Uint64()
preCheckpointHeader := chain.GetHeaderByNumber(lastCheckpointNumber) e := c.config.Epoch
return c.GetMasternodesFromCheckpointHeader(preCheckpointHeader) switch {
case n%e == 0:
return c.GetMasternodesFromCheckpointHeader(header, n, e)
case n%e != 0:
h := chain.GetHeaderByNumber(n - (n % e))
return c.GetMasternodesFromCheckpointHeader(h, n, e)
default:
return []common.Address{}
}
} }
func (c *Clique) GetPeriod() uint64 { return c.config.Period } func (c *Clique) GetPeriod() uint64 { return c.config.Period }
func YourTurn(masternodes []common.Address, snap *Snapshot, header *types.Header, cur common.Address) (int, int, bool, error) { func YourTurn(masternodes []common.Address, snap *Snapshot, header *types.Header, cur common.Address) (int, int, bool, error) {
if len(masternodes) == 0 {
return -1, -1, true, nil
}
pre := common.Address{} pre := common.Address{}
// masternode[0] has chance to create block 1 // masternode[0] has chance to create block 1
var err error var err error
@ -439,7 +449,8 @@ func (c *Clique) snapshot(chain consensus.ChainReader, number uint64, hash commo
break break
} }
// If an on-disk checkpoint snapshot can be found, use that // If an on-disk checkpoint snapshot can be found, use that
if number%checkpointInterval == 0 { // checkpoint snapshot = checkpoint - gap
if (number+c.config.Gap)%c.config.Epoch == 0 {
if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil { if s, err := loadSnapshot(c.config, c.signatures, c.db, hash); err == nil {
log.Trace("Loaded voting snapshot form disk", "number", number, "hash", hash) log.Trace("Loaded voting snapshot form disk", "number", number, "hash", hash)
snap = s snap = s
@ -493,7 +504,7 @@ func (c *Clique) snapshot(chain consensus.ChainReader, number uint64, hash commo
c.recents.Add(snap.Hash, snap) c.recents.Add(snap.Hash, snap)
// If we've generated a new checkpoint snapshot, save to disk // If we've generated a new checkpoint snapshot, save to disk
if snap.Number%checkpointInterval == 0 && len(headers) > 0 { if (snap.Number+c.config.Gap)%c.config.Epoch == 0 {
if err = snap.store(c.db); err != nil { if err = snap.store(c.db); err != nil {
return nil, err return nil, err
} }
@ -538,9 +549,17 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p
if err != nil { if err != nil {
return err return err
} }
masternodes := c.GetMasternodes(chain, header)
mstring := []string{}
for _, m := range masternodes {
mstring = append(mstring, m.String())
}
nstring := []string{}
for _, n := range snap.signers() {
nstring = append(nstring, n.String())
}
if _, ok := snap.Signers[signer]; !ok { if _, ok := snap.Signers[signer]; !ok {
valid := false valid := false
masternodes := c.GetMasternodes(chain, header)
for _, m := range masternodes { for _, m := range masternodes {
if m == signer { if m == signer {
valid = true valid = true
@ -548,24 +567,20 @@ func (c *Clique) verifySeal(chain consensus.ChainReader, header *types.Header, p
} }
} }
if !valid { if !valid {
log.Debug("Unauthorized signer found", "block number", number, "signer", signer.String(), "masternodes", mstring, "snapshot from parent block", nstring)
return errUnauthorized return errUnauthorized
} }
} }
for seen, recent := range snap.Recents { for seen, recent := range snap.Recents {
if recent == signer { if recent == signer {
// Signer is among recents, only fail if the current block doesn't shift it out // Signer is among recents, only fail if the current block doesn't shift it out
if limit := uint64(len(snap.Signers)/2 + 1); seen > number-limit { if limit := uint64(len(masternodes)/2 + 1); seen > number-limit {
// Only take into account the non-epoch blocks
if number%c.config.Epoch != 0 {
return errUnauthorized return errUnauthorized
} }
} }
} }
// Ensure that the difficulty corresponds to the turn-ness of the signer
inturn := snap.inturn(header.Number.Uint64(), signer)
if inturn && header.Difficulty.Cmp(diffInTurn) != 0 {
return errInvalidDifficulty
}
if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 {
return errInvalidDifficulty
} }
return nil return nil
} }
@ -638,6 +653,7 @@ func (c *Clique) Prepare(chain consensus.ChainReader, header *types.Header) erro
func (c *Clique) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []Masternode) error { func (c *Clique) UpdateMasternodes(chain consensus.ChainReader, header *types.Header, ms []Masternode) error {
number := header.Number.Uint64() number := header.Number.Uint64()
log.Trace("take snapshot", "number", number, "hash", header.Hash()) log.Trace("take snapshot", "number", number, "hash", header.Hash())
// get snapshot
snap, err := c.snapshot(chain, number, header.Hash(), nil) snap, err := c.snapshot(chain, number, header.Hash(), nil)
if err != nil { if err != nil {
return err return err
@ -647,14 +663,21 @@ func (c *Clique) UpdateMasternodes(chain consensus.ChainReader, header *types.He
// count all addresses in ms to be masternode // count all addresses in ms to be masternode
for _, m := range ms { for _, m := range ms {
proposedSigners[m.Address] = struct{}{} proposedSigners[m.Address] = struct{}{}
c.proposals[m.Address] = true snap.Signers[m.Address] = struct{}{}
} }
// deactivate current masternodes which aren't in ms // deactivate current masternodes which aren't in ms
for _, s := range currentSigners { for _, s := range currentSigners {
if _, ok := proposedSigners[s]; !ok { if _, ok := proposedSigners[s]; !ok {
c.proposals[s] = false delete(snap.Signers, s)
} }
} }
nm := []string{}
newSigners := snap.signers()
for _, n := range newSigners {
nm = append(nm, n.String())
}
c.recents.Add(snap.Hash, snap)
log.Info("New set of masternodes has been updated to snapshot", "number", snap.Number, "hash", snap.Hash, "new masternodes", nm)
return nil return nil
} }
@ -714,10 +737,9 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, stop <-ch
if err != nil { if err != nil {
return nil, err return nil, err
} }
masternodes := []common.Address{} masternodes := c.GetMasternodes(chain, header)
if _, authorized := snap.Signers[signer]; !authorized { if _, authorized := snap.Signers[signer]; !authorized {
valid := false valid := false
masternodes = c.GetMasternodes(chain, header)
for _, m := range masternodes { for _, m := range masternodes {
if m == signer { if m == signer {
valid = true valid = true
@ -733,17 +755,21 @@ func (c *Clique) Seal(chain consensus.ChainReader, block *types.Block, stop <-ch
if recent == signer { if recent == signer {
// Signer is among recents, only wait if the current block doesn't shift it out // Signer is among recents, only wait if the current block doesn't shift it out
if limit := uint64(len(masternodes)/2 + 1); number < limit || seen > number-limit { if limit := uint64(len(masternodes)/2 + 1); number < limit || seen > number-limit {
// Only take into account the non-epoch blocks
if number%c.config.Epoch != 0 {
log.Info("Debugging", "len(masternodes)", len(masternodes), "number", number, "limit", limit, "seen", seen, "recent", recent.String(), "snap.Recents", snap.Recents)
log.Info("Signed recently, must wait for others") log.Info("Signed recently, must wait for others")
<-stop <-stop
return nil, nil return nil, nil
} }
} }
} }
}
// Sweet, the protocol permits us to sign the block, wait for our time // Sweet, the protocol permits us to sign the block, wait for our time
delay := time.Unix(header.Time.Int64(), 0).Sub(time.Now()) // nolint: gosimple delay := time.Unix(header.Time.Int64(), 0).Sub(time.Now()) // nolint: gosimple
if header.Difficulty.Cmp(diffNoTurn) == 0 { if header.Difficulty.Cmp(diffNoTurn) == 0 {
// It's not our turn explicitly to sign, delay it a bit // It's not our turn explicitly to sign, delay it a bit
wiggle := time.Duration(len(snap.Signers)/2+1) * wiggleTime wiggle := time.Duration(len(masternodes)/2+1) * wiggleTime
delay += time.Duration(rand.Int63n(int64(wiggle))) delay += time.Duration(rand.Int63n(int64(wiggle)))
log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle)) log.Trace("Out-of-turn signing requested", "wiggle", common.PrettyDuration(wiggle))
@ -802,7 +828,11 @@ func (c *Clique) RecoverSigner(header *types.Header) (common.Address, error) {
} }
// Get master nodes over extra data of previous checkpoint block. // Get master nodes over extra data of previous checkpoint block.
func (c *Clique) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header) []common.Address { func (c *Clique) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Header, n, e uint64) []common.Address {
if preCheckpointHeader == nil {
log.Info("Previous checkpoint's header is empty", "block number", n, "epoch", e)
return []common.Address{}
}
masternodes := make([]common.Address, (len(preCheckpointHeader.Extra)-extraVanity-extraSeal)/common.AddressLength) masternodes := make([]common.Address, (len(preCheckpointHeader.Extra)-extraVanity-extraSeal)/common.AddressLength)
for i := 0; i < len(masternodes); i++ { for i := 0; i < len(masternodes); i++ {
copy(masternodes[i][:], preCheckpointHeader.Extra[extraVanity+i*common.AddressLength:]) copy(masternodes[i][:], preCheckpointHeader.Extra[extraVanity+i*common.AddressLength:])

View file

@ -867,7 +867,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
lastCheckpointNumber := rpc.BlockNumber(b.Number().Uint64() - (b.Number().Uint64() % s.b.ChainConfig().Clique.Epoch)) lastCheckpointNumber := rpc.BlockNumber(b.Number().Uint64() - (b.Number().Uint64() % s.b.ChainConfig().Clique.Epoch))
prevCheckpointBlock, _ := s.b.BlockByNumber(ctx, lastCheckpointNumber) prevCheckpointBlock, _ := s.b.BlockByNumber(ctx, lastCheckpointNumber)
if prevCheckpointBlock != nil { if prevCheckpointBlock != nil {
masternodes := engine.(*clique.Clique).GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header()) masternodes := engine.(*clique.Clique).GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), b.Number().Uint64(), s.b.ChainConfig().Clique.Epoch)
countFinality := 0 countFinality := 0
for _, masternode := range masternodes { for _, masternode := range masternodes {
for _, signer := range signers { for _, signer := range signers {

View file

@ -471,6 +471,10 @@ func (self *worker) commitNewWork() {
// first block // first block
return return
} }
if curIndex == -1 {
// you're not allowed to create this block
return
}
h := hop(len(masternodes), preIndex, curIndex) h := hop(len(masternodes), preIndex, curIndex)
gap := int64(c.GetPeriod()) * int64(h) gap := int64(c.GetPeriod()) * int64(h)
log.Info("Distance from the parent block", "seconds", gap, "hops", h) log.Info("Distance from the parent block", "seconds", gap, "hops", h)