aboutsummaryrefslogtreecommitdiffstats
path: root/core/utils
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-01-07 17:21:08 +0800
committerGitHub <noreply@github.com>2019-01-07 17:21:08 +0800
commit21c420db895b1aa48709982cd145a119c74de6fa (patch)
treea8cd9a9bc5e8c22a21812f0e00939f3fbd92db89 /core/utils
parent8d1069b61d847662d37f504937a346c56d6cb0eb (diff)
downloaddexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.tar
dexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.tar.gz
dexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.tar.bz2
dexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.tar.lz
dexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.tar.xz
dexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.tar.zst
dexon-consensus-21c420db895b1aa48709982cd145a119c74de6fa.zip
core: BA 3.0 (#408)
* Add v3 enum * Add BA leader calculation * Fast BA * Add unittest for Fast BA * Add comment * Select leader in notarySet
Diffstat (limited to 'core/utils')
-rw-r--r--core/utils/nodeset-cache.go41
-rw-r--r--core/utils/nodeset-cache_test.go12
2 files changed, 50 insertions, 3 deletions
diff --git a/core/utils/nodeset-cache.go b/core/utils/nodeset-cache.go
index 6d4f7b0..35828b7 100644
--- a/core/utils/nodeset-cache.go
+++ b/core/utils/nodeset-cache.go
@@ -38,9 +38,11 @@ var (
)
type sets struct {
- nodeSet *types.NodeSet
- notarySet []map[types.NodeID]struct{}
- dkgSet map[types.NodeID]struct{}
+ crs common.Hash
+ nodeSet *types.NodeSet
+ notarySet []map[types.NodeID]struct{}
+ dkgSet map[types.NodeID]struct{}
+ leaderNode []map[uint64]types.NodeID
}
// NodeSetCacheInterface interface specifies interface used by NodeSetCache.
@@ -146,6 +148,33 @@ func (cache *NodeSetCache) GetDKGSet(
return cache.cloneMap(IDs.dkgSet), nil
}
+// GetLeaderNode returns the BA leader of the position.
+func (cache *NodeSetCache) GetLeaderNode(pos types.Position) (
+ types.NodeID, error) {
+ IDs, err := cache.getOrUpdate(pos.Round)
+ if err != nil {
+ return types.NodeID{}, err
+ }
+ if pos.ChainID >= uint32(len(IDs.leaderNode)) {
+ return types.NodeID{}, ErrInvalidChainID
+ }
+ cache.lock.Lock()
+ defer cache.lock.Unlock()
+ if _, exist := IDs.leaderNode[pos.ChainID][pos.Height]; !exist {
+ notarySet := types.NewNodeSetFromMap(IDs.notarySet[pos.ChainID])
+ leader :=
+ notarySet.GetSubSet(1, types.NewNodeLeaderTarget(IDs.crs, pos))
+ if len(leader) != 1 {
+ panic(errors.New("length of leader is not one"))
+ }
+ for nID := range leader {
+ IDs.leaderNode[pos.ChainID][pos.Height] = nID
+ break
+ }
+ }
+ return IDs.leaderNode[pos.ChainID][pos.Height], nil
+}
+
func (cache *NodeSetCache) cloneMap(
nIDs map[types.NodeID]struct{}) map[types.NodeID]struct{} {
nIDsCopy := make(map[types.NodeID]struct{}, len(nIDs))
@@ -207,15 +236,21 @@ func (cache *NodeSetCache) update(
return
}
nIDs = &sets{
+ crs: crs,
nodeSet: nodeSet,
notarySet: make([]map[types.NodeID]struct{}, cfg.NumChains),
dkgSet: nodeSet.GetSubSet(
int(cfg.DKGSetSize), types.NewDKGSetTarget(crs)),
+ leaderNode: make([]map[uint64]types.NodeID, cfg.NumChains),
}
for i := range nIDs.notarySet {
nIDs.notarySet[i] = nodeSet.GetSubSet(
int(cfg.NotarySetSize), types.NewNotarySetTarget(crs, uint32(i)))
}
+ nodesPerChain := cfg.RoundInterval / (cfg.LambdaBA * 4)
+ for i := range nIDs.leaderNode {
+ nIDs.leaderNode[i] = make(map[uint64]types.NodeID, nodesPerChain)
+ }
cache.rounds[round] = nIDs
// Purge older rounds.
diff --git a/core/utils/nodeset-cache_test.go b/core/utils/nodeset-cache_test.go
index 27c8c83..9e6ceee 100644
--- a/core/utils/nodeset-cache_test.go
+++ b/core/utils/nodeset-cache_test.go
@@ -19,6 +19,7 @@ package utils
import (
"testing"
+ "time"
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/crypto"
@@ -38,6 +39,8 @@ func (g *nsIntf) Configuration(round uint64) (cfg *types.Config) {
NotarySetSize: 7,
DKGSetSize: 7,
NumChains: 4,
+ LambdaBA: 250 * time.Millisecond,
+ RoundInterval: 60 * time.Second,
}
}
func (g *nsIntf) CRS(round uint64) (b common.Hash) { return g.crs }
@@ -91,6 +94,15 @@ func (s *NodeSetCacheTestSuite) TestBasicUsage() {
dkgSet, err := cache.GetDKGSet(0)
req.NoError(err)
chk(cache, 0, dkgSet)
+ leaderNode, err := cache.GetLeaderNode(types.Position{
+ Round: uint64(0),
+ ChainID: uint32(3),
+ Height: uint64(10),
+ })
+ req.NoError(err)
+ chk(cache, 0, map[types.NodeID]struct{}{
+ leaderNode: struct{}{},
+ })
// Try to get round 1.
nodeSet1, err := cache.GetNodeSet(1)
req.NoError(err)