set block difficulty belong to creator turn

This commit is contained in:
Nguyen Ba Tam 2018-12-08 11:33:00 +07:00
parent 8bcb58b070
commit 6af064ec32
4 changed files with 62 additions and 60 deletions

View file

@ -352,12 +352,12 @@ func (c *Posv) verifyHeader(chain consensus.ChainReader, header *types.Header, p
if header.UncleHash != uncleHash { if header.UncleHash != uncleHash {
return errInvalidUncleHash return errInvalidUncleHash
} }
// Ensure that the block's difficulty is meaningful (may not be correct at this point) //// Ensure that the block's difficulty is meaningful (may not be correct at this point)
if number > 0 { //if number > 0 {
if header.Difficulty == nil || (header.Difficulty.Cmp(diffInTurn) != 0 && header.Difficulty.Cmp(diffNoTurn) != 0) { // if header.Difficulty.Int64() != 1 {
return errInvalidDifficulty // return errInvalidDifficulty
} // }
} //}
// If all checks passed, validate any special fields for hard forks // If all checks passed, validate any special fields for hard forks
if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil { if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
return err return err
@ -483,30 +483,35 @@ func WhoIsCreator(snap *Snapshot, header *types.Header) (common.Address, error)
return m, nil return m, nil
} }
func YourTurn(masternodes []common.Address, snap *Snapshot, header *types.Header, cur common.Address) (int, int, bool, error) { func (c *Posv) YourTurn(chain consensus.ChainReader, parent *types.Header) (int, int, int, bool, error) {
masternodes := c.GetMasternodes(chain, parent)
snap, err := c.GetSnapshot(chain, parent)
if err != nil {
log.Error("Failed when trying to commit new work", "err", err)
return 0, -1, -1, false, err
}
if len(masternodes) == 0 { if len(masternodes) == 0 {
return -1, -1, true, nil return 0, -1, -1, false, errors.New("Not found master nodes")
} }
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
preIndex := -1 preIndex := -1
if header.Number.Uint64() != 0 { if parent.Number.Uint64() != 0 {
pre, err = WhoIsCreator(snap, header) pre, err = WhoIsCreator(snap, parent)
if err != nil { if err != nil {
return 0, 0, false, err return 0, 0, 0, false, err
} }
preIndex = position(masternodes, pre) preIndex = position(masternodes, pre)
} }
curIndex := position(masternodes, cur) curIndex := position(masternodes, c.signer)
log.Info("Masternodes cycle info", "number of masternodes", len(masternodes), "previous", pre, "position", preIndex, "current", cur, "position", curIndex) log.Info("Masternodes cycle info", "number of masternodes", len(masternodes), "previous", pre, "position", preIndex, "current", c.signer, "position", curIndex)
for i, s := range masternodes { for i, s := range masternodes {
fmt.Printf("%d - %s\n", i, s.String()) fmt.Printf("%d - %s\n", i, s.String())
} }
if (preIndex+1)%len(masternodes) == curIndex { if (preIndex+1)%len(masternodes) == curIndex {
return preIndex, curIndex, true, nil return len(masternodes), preIndex, curIndex, true, nil
} }
return preIndex, curIndex, false, nil return len(masternodes), preIndex, curIndex, false, nil
} }
// snapshot retrieves the authorization snapshot at a given point in time. // snapshot retrieves the authorization snapshot at a given point in time.
@ -625,6 +630,7 @@ func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, par
if err != nil { if err != nil {
return err return err
} }
log.Debug("verify seal block", "number", header.Number, "hash", header.Hash(), "difficulty", header.Difficulty)
masternodes := c.GetMasternodes(chain, header) masternodes := c.GetMasternodes(chain, header)
mstring := []string{} mstring := []string{}
for _, m := range masternodes { for _, m := range masternodes {
@ -742,9 +748,13 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
} }
c.lock.RUnlock() c.lock.RUnlock()
} }
parent := chain.GetHeader(header.ParentHash, number-1)
if parent == nil {
return consensus.ErrUnknownAncestor
}
// Set the correct difficulty // Set the correct difficulty
header.Difficulty = big.NewInt(1) header.Difficulty = c.CalcDifficulty(chain, 0, parent)
log.Debug("CalcDifficulty ", "number", header.Number, "difficulty", header.Difficulty)
// Ensure the extra data has all it's components // Ensure the extra data has all it's components
if len(header.Extra) < extraVanity { if len(header.Extra) < extraVanity {
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...) header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
@ -782,10 +792,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
header.MixDigest = common.Hash{} header.MixDigest = common.Hash{}
// Ensure the timestamp has the correct delay // Ensure the timestamp has the correct delay
parent := chain.GetHeader(header.ParentHash, number-1)
if parent == nil {
return consensus.ErrUnknownAncestor
}
header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(c.config.Period)) header.Time = new(big.Int).Add(parent.Time, new(big.Int).SetUint64(c.config.Period))
if header.Time.Int64() < time.Now().Unix() { if header.Time.Int64() < time.Now().Unix() {
header.Time = big.NewInt(time.Now().Unix()) header.Time = big.NewInt(time.Now().Unix())
@ -928,22 +935,23 @@ func (c *Posv) Seal(chain consensus.ChainReader, block *types.Block, stop <-chan
// that a new block should have based on the previous blocks in the chain and the // that a new block should have based on the previous blocks in the chain and the
// current signer. // current signer.
func (c *Posv) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int { func (c *Posv) CalcDifficulty(chain consensus.ChainReader, time uint64, parent *types.Header) *big.Int {
snap, err := c.snapshot(chain, parent.Number.Uint64(), parent.Hash(), nil) len, preIndex, curIndex, _, err := c.YourTurn(chain, parent)
if err != nil { if err != nil {
return nil return big.NewInt(int64(len + curIndex - preIndex))
} }
return CalcDifficulty(snap, c.signer) return big.NewInt(int64(len - Hop(len, preIndex, curIndex)))
} }
// CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // 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 // that a new block should have based on the previous blocks in the chain and the
// current signer. // current signer.
func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { //func CalcDifficulty(snap *Snapshot, parent *types.Header, signer common.Address) *big.Int {
if snap.inturn(snap.Number+1, signer) { //
return new(big.Int).Set(diffInTurn) // if snap.inturn(snap.Number+1, signer) {
} // return new(big.Int).Set(diffInTurn)
return new(big.Int).Set(diffNoTurn) // }
} // return new(big.Int).Set(diffNoTurn)
//}
// APIs implements consensus.Engine, returning the user facing RPC API to allow // APIs implements consensus.Engine, returning the user facing RPC API to allow
// controlling the signer voting. // controlling the signer voting.
@ -1057,3 +1065,14 @@ func ExtractValidatorsFromBytes(byteValidators []byte) []int64 {
return validators return validators
} }
func Hop(len, pre, cur int) int {
switch {
case pre < cur:
return cur - (pre + 1)
case pre > cur:
return (len - pre) + (cur - 1)
default:
return len - 1
}
}

View file

@ -906,7 +906,7 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
defer bc.mu.Unlock() defer bc.mu.Unlock()
currentBlock := bc.CurrentBlock() currentBlock := bc.CurrentBlock()
//localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) localTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
externTd := new(big.Int).Add(block.Difficulty(), ptd) externTd := new(big.Int).Add(block.Difficulty(), ptd)
// Irrelevant of the canonical status, write the block itself to the database // Irrelevant of the canonical status, write the block itself to the database
@ -980,8 +980,12 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
// If the total difficulty is higher than our known, add it to the canonical chain // If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining. // Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf // Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
reorg := externTd.Cmp(localTd) > 0
reorg := block.NumberU64() > currentBlock.NumberU64() currentBlock = bc.CurrentBlock()
if !reorg && externTd.Cmp(localTd) == 0 {
// Split same-difficulty blocks by number
reorg = block.NumberU64() > currentBlock.NumberU64()
}
if reorg { if reorg {
// Reorganise the chain if the parent is not the head block // Reorganise the chain if the parent is not the head block
if block.ParentHash() != currentBlock.Hash() { if block.ParentHash() != currentBlock.Hash() {

View file

@ -657,17 +657,14 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
trueTD = new(big.Int).Sub(request.TD, request.Block.Difficulty()) trueTD = new(big.Int).Sub(request.TD, request.Block.Difficulty())
) )
// Update the peers total difficulty if better than the previous // Update the peers total difficulty if better than the previous
_, td := p.Head() if _, td := p.Head(); trueTD.Cmp(td) > 0 {
currentBlock := pm.blockchain.CurrentBlock()
currentTd := pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())
log.Debug("NewBlockMsg", "p", p, "number", request.Block.NumberU64(), "trueTD", trueTD, "td", td, "currentTd", currentTd)
if trueTD.Cmp(td) > 0 {
p.SetHead(trueHead, trueTD) p.SetHead(trueHead, trueTD)
// Schedule a sync if above ours. Note, this will not fire a sync for a gap of // Schedule a sync if above ours. Note, this will not fire a sync for a gap of
// a singe block (as the true TD is below the propagated block), however this // a singe block (as the true TD is below the propagated block), however this
// scenario should easily be covered by the fetcher. // scenario should easily be covered by the fetcher.
if trueTD.Cmp(currentTd) > 0 { currentBlock := pm.blockchain.CurrentBlock()
if trueTD.Cmp(pm.blockchain.GetTd(currentBlock.Hash(), currentBlock.NumberU64())) > 0 {
go pm.synchronise(p) go pm.synchronise(p)
} }
} }

View file

@ -472,17 +472,6 @@ func abs(x int64) int64 {
return x return x
} }
func hop(len, pre, cur int) int {
switch {
case pre < cur:
return cur - (pre + 1)
case pre > cur:
return (len - pre) + (cur - 1)
default:
return len - 1
}
}
func (self *worker) commitNewWork() { func (self *worker) commitNewWork() {
self.mu.Lock() self.mu.Lock()
defer self.mu.Unlock() defer self.mu.Unlock()
@ -508,14 +497,7 @@ func (self *worker) commitNewWork() {
if self.config.Posv != nil { if self.config.Posv != nil {
// get masternodes set from latest checkpoint // get masternodes set from latest checkpoint
c := self.engine.(*posv.Posv) c := self.engine.(*posv.Posv)
masternodes := c.GetMasternodes(self.chain, parent.Header()) len, preIndex, curIndex, ok, err := c.YourTurn(self.chain, parent.Header())
snap, err := c.GetSnapshot(self.chain, parent.Header())
if err != nil {
log.Error("Failed when trying to commit new work", "err", err)
return
}
signers = snap.Signers
preIndex, curIndex, ok, err := posv.YourTurn(masternodes, snap, parent.Header(), self.coinbase)
if err != nil { if err != nil {
log.Error("Failed when trying to commit new work", "err", err) log.Error("Failed when trying to commit new work", "err", err)
return return
@ -531,7 +513,7 @@ func (self *worker) commitNewWork() {
// you're not allowed to create this block // you're not allowed to create this block
return return
} }
h := hop(len(masternodes), preIndex, curIndex) h := posv.Hop(len, preIndex, curIndex)
gap := waitPeriod * int64(h) gap := waitPeriod * int64(h)
// Check nearest checkpoint block in hop range. // Check nearest checkpoint block in hop range.
nearest := self.config.Posv.Epoch - (parent.Header().Number.Uint64() % self.config.Posv.Epoch) nearest := self.config.Posv.Epoch - (parent.Header().Number.Uint64() % self.config.Posv.Epoch)