diff options
author | Wei-Ning Huang <w@dexon.org> | 2018-11-02 12:04:20 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-12 17:27:17 +0800 |
commit | 248fdaa5ccca535ddce93173f2f0f3bc60b9381d (patch) | |
tree | ea99eebff0db5294e222adc7920f8a5f47a7c2ba /vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go | |
parent | 7ef2bd6a1544d3b92cf2b2119935b425279b4e59 (diff) | |
download | go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.tar go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.tar.gz go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.tar.bz2 go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.tar.lz go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.tar.xz go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.tar.zst go-tangerine-248fdaa5ccca535ddce93173f2f0f3bc60b9381d.zip |
Rename import due to dexon-consensus rename
Diffstat (limited to 'vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go')
-rw-r--r-- | vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go b/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go new file mode 100644 index 000000000..2be596abc --- /dev/null +++ b/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go @@ -0,0 +1,136 @@ +// Copyright 2018 The dexon-consensus Authors +// This file is part of the dexon-consensus library. +// +// The dexon-consensus library is free software: you can redistribute it +// and/or modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The dexon-consensus library is distributed in the hope that it will be +// useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the dexon-consensus library. If not, see +// <http://www.gnu.org/licenses/>. + +package core + +import ( + "fmt" + "math/big" + "sync" + + "github.com/dexon-foundation/dexon-consensus/common" + "github.com/dexon-foundation/dexon-consensus/core/crypto" + "github.com/dexon-foundation/dexon-consensus/core/types" +) + +// Errors for leader module. +var ( + ErrIncorrectCRSSignature = fmt.Errorf("incorrect CRS signature") +) + +type validLeaderFn func(*types.Block) bool + +// Some constant value. +var ( + maxHash *big.Int + one *big.Rat +) + +func init() { + hash := make([]byte, common.HashLength) + for i := range hash { + hash[i] = 0xff + } + maxHash = big.NewInt(0).SetBytes(hash) + one = big.NewRat(1, 1) +} + +type leaderSelector struct { + hashCRS common.Hash + numCRS *big.Int + minCRSBlock *big.Int + minBlockHash common.Hash + pendingBlocks []*types.Block + validLeader validLeaderFn + lock sync.Mutex +} + +func newLeaderSelector( + crs common.Hash, validLeader validLeaderFn) *leaderSelector { + numCRS := big.NewInt(0) + numCRS.SetBytes(crs[:]) + return &leaderSelector{ + numCRS: numCRS, + hashCRS: crs, + minCRSBlock: maxHash, + validLeader: validLeader, + } +} + +func (l *leaderSelector) distance(sig crypto.Signature) *big.Int { + hash := crypto.Keccak256Hash(sig.Signature[:]) + num := big.NewInt(0) + num.SetBytes(hash[:]) + num.Abs(num.Sub(l.numCRS, num)) + return num +} + +func (l *leaderSelector) probability(sig crypto.Signature) float64 { + dis := l.distance(sig) + prob := big.NewRat(1, 1).SetFrac(dis, maxHash) + p, _ := prob.Sub(one, prob).Float64() + return p +} + +func (l *leaderSelector) restart() { + l.lock.Lock() + defer l.lock.Unlock() + l.minCRSBlock = maxHash + l.minBlockHash = common.Hash{} + l.pendingBlocks = []*types.Block{} +} + +func (l *leaderSelector) leaderBlockHash() common.Hash { + l.lock.Lock() + defer l.lock.Unlock() + newPendingBlocks := []*types.Block{} + for _, b := range l.pendingBlocks { + if l.validLeader(b) { + l.updateLeader(b) + } else { + newPendingBlocks = append(newPendingBlocks, b) + } + } + l.pendingBlocks = newPendingBlocks + return l.minBlockHash +} + +func (l *leaderSelector) processBlock(block *types.Block) error { + ok, err := verifyCRSSignature(block, l.hashCRS) + if err != nil { + return err + } + if !ok { + return ErrIncorrectCRSSignature + } + l.lock.Lock() + defer l.lock.Unlock() + if !l.validLeader(block) { + l.pendingBlocks = append(l.pendingBlocks, block) + return nil + } + l.updateLeader(block) + return nil +} +func (l *leaderSelector) updateLeader(block *types.Block) { + dist := l.distance(block.CRSSignature) + cmp := l.minCRSBlock.Cmp(dist) + if cmp > 0 || (cmp == 0 && block.Hash.Less(l.minBlockHash)) { + l.minCRSBlock = dist + l.minBlockHash = block.Hash + } +} |