aboutsummaryrefslogtreecommitdiffstats
path: root/core/leader-selector.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/leader-selector.go')
-rw-r--r--core/leader-selector.go92
1 files changed, 83 insertions, 9 deletions
diff --git a/core/leader-selector.go b/core/leader-selector.go
index cea31ce..4295050 100644
--- a/core/leader-selector.go
+++ b/core/leader-selector.go
@@ -18,26 +18,100 @@
package core
import (
- "sort"
+ "fmt"
+ "math/big"
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
+ "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
+// Errors for leader module.
+var (
+ ErrIncorrectCRSSignature = fmt.Errorf("incorrect CRS signature")
+)
+
+// 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 {
- common.Hashes
+ hashCRS common.Hash
+ numCRS *big.Int
+ minCRSBlock *big.Int
+ minBlockHash common.Hash
+
+ sigToPub SigToPubFn
}
-func newLeaderSelector() *leaderSelector {
- return &leaderSelector{}
+func newGenesisLeaderSelector(
+ crs string,
+ sigToPub SigToPubFn) *leaderSelector {
+ hash := crypto.Keccak256Hash([]byte(crs[:]))
+ return newLeaderSelector(hash, sigToPub)
+}
+
+func newLeaderSelector(
+ crs common.Hash,
+ sigToPub SigToPubFn) *leaderSelector {
+ numCRS := big.NewInt(0)
+ numCRS.SetBytes(crs[:])
+ return &leaderSelector{
+ numCRS: numCRS,
+ hashCRS: crs,
+ minCRSBlock: maxHash,
+ sigToPub: sigToPub,
+ }
+}
+
+func (l *leaderSelector) distance(sig crypto.Signature) *big.Int {
+ hash := crypto.Keccak256Hash(sig[:])
+ 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) leaderBlockHash() common.Hash {
- // TODO(jimmy-dexon): return leader based on paper.
- sort.Sort(l.Hashes)
- return l.Hashes[len(l.Hashes)-1]
+ return l.minBlockHash
+}
+
+func (l *leaderSelector) prepareBlock(
+ block *types.Block, prv crypto.PrivateKey) (err error) {
+ block.CRSSignature, err = prv.Sign(hashCRS(block, l.hashCRS))
+ return
}
-func (l *leaderSelector) processBlock(block *types.Block) {
- l.Hashes = append(l.Hashes, block.Hash)
+func (l *leaderSelector) processBlock(block *types.Block) error {
+ ok, err := verifyCRSSignature(block, l.hashCRS, l.sigToPub)
+ if err != nil {
+ return err
+ }
+ if !ok {
+ return ErrIncorrectCRSSignature
+ }
+ dist := l.distance(block.CRSSignature)
+ if l.minCRSBlock.Cmp(dist) == 1 {
+ l.minCRSBlock = dist
+ l.minBlockHash = block.Hash
+ }
+ return nil
}