aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/dexon-foundation/dexon-consensus/core/leader-selector.go
diff options
context:
space:
mode:
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.go136
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
+ }
+}