aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2018-09-23 20:51:05 +0800
committerGitHub <noreply@github.com>2018-09-23 20:51:05 +0800
commit0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89 (patch)
tree626db6969aee92702001e5c9f3de56e2a439ccac
parent2c71e8448a9c03e924a7869351eebf2def1af057 (diff)
downloaddexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.tar
dexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.tar.gz
dexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.tar.bz2
dexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.tar.lz
dexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.tar.xz
dexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.tar.zst
dexon-consensus-0ab5a2d4f63ece79a4df32c6fb3ac710a954fd89.zip
core: run first DKG at startup. (#129)
-rw-r--r--Gopkg.lock59
-rw-r--r--Gopkg.toml4
-rwxr-xr-xbin/install_dkg_dep.sh8
-rw-r--r--core/consensus.go184
-rw-r--r--core/consensus_test.go5
-rw-r--r--core/dkg-tsig-protocol.go5
-rw-r--r--core/dkg-tsig-protocol_test.go33
-rw-r--r--core/interfaces.go3
-rw-r--r--core/test/governance.go9
-rw-r--r--core/ticker.go24
-rw-r--r--core/types/config.go5
-rw-r--r--core/types/dkg.go11
-rw-r--r--crypto/dkg/constant.go2
-rw-r--r--crypto/dkg/dkg.go61
-rw-r--r--crypto/dkg/utils.go2
-rw-r--r--simulation/config/config.go6
-rw-r--r--simulation/governance.go9
-rw-r--r--simulation/kubernetes/config.toml.in3
-rw-r--r--simulation/marshaller.go5
-rw-r--r--simulation/network.go8
20 files changed, 377 insertions, 69 deletions
diff --git a/Gopkg.lock b/Gopkg.lock
index dc96c77..4d9b12d 100644
--- a/Gopkg.lock
+++ b/Gopkg.lock
@@ -2,18 +2,31 @@
[[projects]]
+ branch = "dev"
+ digest = "1:5a9cebf2fc674675971f1ef67a67af7d682f04bd9ce46f19adaed3fb38b8c358"
+ name = "github.com/Spiderpowa/bls"
+ packages = ["ffi/go/bls"]
+ pruneopts = "UT"
+ revision = "95f2449c4fb0925fd9206d5b8d7efea118b33398"
+
+[[projects]]
branch = "master"
+ digest = "1:2c00f064ba355903866cbfbf3f7f4c0fe64af6638cc7d1b8bdcf3181bc67f1d8"
name = "github.com/btcsuite/btcd"
packages = ["btcec"]
- revision = "cf05f92c3f815bbd5091ed6c73eff51f7b1945e8"
+ pruneopts = "UT"
+ revision = "92494a5188cd5fb1056d55ce597f38d5db4e343d"
[[projects]]
+ digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
- revision = "346938d642f2ec3594ed81d874461961cd0faa76"
- version = "v1.1.0"
+ pruneopts = "UT"
+ revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
+ version = "v1.1.1"
[[projects]]
+ digest = "1:32282b2f1ea5689b7d684abc2f0c3839ddbcb99101f053456f50f33e45106cde"
name = "github.com/ethereum/go-ethereum"
packages = [
"common",
@@ -22,56 +35,70 @@
"crypto",
"crypto/secp256k1",
"crypto/sha3",
- "rlp"
+ "rlp",
]
- revision = "225171a4bfcc16bd12a1906b1e0d43d0b18c353b"
- version = "v1.8.13"
+ pruneopts = "UT"
+ revision = "89451f7c382ad2185987ee369f16416f89c28a7d"
+ version = "v1.8.15"
[[projects]]
branch = "master"
+ digest = "1:4a0c6bb4805508a6287675fac876be2ac1182539ca8a32468d8128882e9d5009"
name = "github.com/golang/snappy"
packages = ["."]
+ pruneopts = "UT"
revision = "2e65f85255dbc3072edf28d6b5b8efc472979f5a"
[[projects]]
branch = "master"
+ digest = "1:575eb8ef612810bdfc3787cab5583a81278e81c060ae7d68ed7486ad55d0a5a6"
name = "github.com/herumi/bls"
packages = ["ffi/go/bls"]
- revision = "1fea3145f1a595de561527888ffc961bdf7907af"
+ pruneopts = "UT"
+ revision = "1c36a87da5bbc1cd6dc0e9d9c0e5fbf2e4640dad"
[[projects]]
+ digest = "1:b56c589214f01a5601e0821387db484617392d0042f26234bf2da853a2f498a1"
name = "github.com/naoina/go-stringutil"
packages = ["."]
+ pruneopts = "UT"
revision = "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b"
version = "v0.1.0"
[[projects]]
+ digest = "1:f58c3d0e46b64878d00652fedba24ee879725191ab919dca7b62586859281c04"
name = "github.com/naoina/toml"
packages = [
".",
- "ast"
+ "ast",
]
+ pruneopts = "UT"
revision = "e6f5723bf2a66af014955e0888881314cf294129"
version = "v0.1.1"
[[projects]]
+ digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
+ pruneopts = "UT"
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
+ digest = "1:5110e3d4f130772fd39e6ce8208ad1955b242ccfcc8ad9d158857250579c82f4"
name = "github.com/stretchr/testify"
packages = [
"assert",
"require",
- "suite"
+ "suite",
]
+ pruneopts = "UT"
revision = "f35b8ab0b5a2cef36673838d662e249dd9c94686"
version = "v1.2.2"
[[projects]]
branch = "master"
+ digest = "1:f2ffd421680b0a3f7887501b3c6974bcf19217ecd301d0e2c9b681940ec363d5"
name = "github.com/syndtr/goleveldb"
packages = [
"leveldb",
@@ -85,13 +112,21 @@
"leveldb/opt",
"leveldb/storage",
"leveldb/table",
- "leveldb/util"
+ "leveldb/util",
]
- revision = "c4c61651e9e37fa117f53c5a906d3b63090d8445"
+ pruneopts = "UT"
+ revision = "ae2bd5eed72d46b28834ec3f60db3a3ebedd8dbd"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
- inputs-digest = "b4f4eb52c1215d859e89bac7082b1840c5c44cf20af57c19b41d7566c72dbe70"
+ input-imports = [
+ "github.com/Spiderpowa/bls/ffi/go/bls",
+ "github.com/ethereum/go-ethereum/crypto",
+ "github.com/herumi/bls/ffi/go/bls",
+ "github.com/naoina/toml",
+ "github.com/stretchr/testify/suite",
+ "github.com/syndtr/goleveldb/leveldb",
+ ]
solver-name = "gps-cdcl"
solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
index 7f32948..b495aa6 100644
--- a/Gopkg.toml
+++ b/Gopkg.toml
@@ -42,8 +42,8 @@
name = "github.com/syndtr/goleveldb"
[[constraint]]
- branch = "master"
- name = "github.com/herumi/bls"
+ branch = "dev"
+ name = "github.com/Spiderpowa/bls"
[prune]
go-tests = true
diff --git a/bin/install_dkg_dep.sh b/bin/install_dkg_dep.sh
index 9120941..af5e83e 100755
--- a/bin/install_dkg_dep.sh
+++ b/bin/install_dkg_dep.sh
@@ -10,7 +10,7 @@ if [ ! -d .dep/dkg ]; then
cd .dep/dkg
git clone --depth 1 git://github.com/herumi/xbyak.git &
git clone --depth 1 git://github.com/herumi/cybozulib.git &
- git clone --depth 1 git://github.com/herumi/bls.git &
+ git clone --depth 1 --single-branch -b dev git://github.com/Spiderpowa/bls.git &
git clone --depth 1 git://github.com/herumi/mcl.git &
wait
if [ "$(uname -o)" = "Darwin" ] && [ "$(brew --prefix)" != "/usr/local" ]; then
@@ -23,7 +23,7 @@ if [ ! -d .dep/dkg ]; then
cd ../../../
fi
cp -r .dep/dkg/* \
- vendor/github.com/herumi
-mkdir lib > /dev/null
+ vendor/github.com/Spiderpowa
+mkdir -p lib
cd lib
-ln -s ../vendor/github.com/herumi/bls/lib/* .
+ln -sf ../vendor/github.com/Spiderpowa/bls/lib/* .
diff --git a/core/consensus.go b/core/consensus.go
index 7700296..dc5bbba 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -111,26 +111,87 @@ func (recv *consensusReceiver) ConfirmBlock(hash common.Hash) {
recv.restart <- struct{}{}
}
+// consensusDKGReceiver implements dkgReceiver.
+type consensusDKGReceiver struct {
+ ID types.NodeID
+ gov Governance
+ prvKey crypto.PrivateKey
+ network Network
+}
+
+// ProposeDKGComplaint proposes a DKGComplaint.
+func (recv *consensusDKGReceiver) ProposeDKGComplaint(
+ complaint *types.DKGComplaint) {
+ var err error
+ complaint.Signature, err = recv.prvKey.Sign(hashDKGComplaint(complaint))
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ recv.gov.AddDKGComplaint(complaint)
+}
+
+// ProposeDKGMasterPublicKey propose a DKGMasterPublicKey.
+func (recv *consensusDKGReceiver) ProposeDKGMasterPublicKey(
+ mpk *types.DKGMasterPublicKey) {
+ var err error
+ mpk.Signature, err = recv.prvKey.Sign(hashDKGMasterPublicKey(mpk))
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ recv.gov.AddDKGMasterPublicKey(mpk)
+}
+
+// ProposeDKGPrivateShare propose a DKGPrivateShare.
+func (recv *consensusDKGReceiver) ProposeDKGPrivateShare(
+ prv *types.DKGPrivateShare) {
+ var err error
+ prv.Signature, err = recv.prvKey.Sign(hashDKGPrivateShare(prv))
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ recv.network.SendDKGPrivateShare(prv.ReceiverID, prv)
+}
+
+// ProposeDKGAntiNackComplaint propose a DKGPrivateShare as an anti complaint.
+func (recv *consensusDKGReceiver) ProposeDKGAntiNackComplaint(
+ prv *types.DKGPrivateShare) {
+ if prv.ProposerID == recv.ID {
+ var err error
+ prv.Signature, err = recv.prvKey.Sign(hashDKGPrivateShare(prv))
+ if err != nil {
+ log.Println(err)
+ return
+ }
+ }
+ recv.network.BroadcastDKGPrivateShare(prv)
+}
+
// Consensus implements DEXON Consensus algorithm.
type Consensus struct {
- ID types.NodeID
- app Application
- gov Governance
- config *types.Config
- baModules []*agreement
- receivers []*consensusReceiver
- rbModule *reliableBroadcast
- toModule *totalOrdering
- ctModule *consensusTimestamp
- ccModule *compactionChain
- db blockdb.BlockDatabase
- network Network
- tickerObj Ticker
- prvKey crypto.PrivateKey
- sigToPub SigToPubFn
- lock sync.RWMutex
- ctx context.Context
- ctxCancel context.CancelFunc
+ ID types.NodeID
+ app Application
+ gov Governance
+ config *types.Config
+ baModules []*agreement
+ receivers []*consensusReceiver
+ rbModule *reliableBroadcast
+ toModule *totalOrdering
+ ctModule *consensusTimestamp
+ ccModule *compactionChain
+ db blockdb.BlockDatabase
+ network Network
+ tickerObj Ticker
+ prvKey crypto.PrivateKey
+ dkgRunning int32
+ dkgReady *sync.Cond
+ dkgModule *dkgProtocol
+ sigToPub SigToPubFn
+ lock sync.RWMutex
+ ctx context.Context
+ ctxCancel context.CancelFunc
}
// NewConsensus construct an Consensus instance.
@@ -144,6 +205,7 @@ func NewConsensus(
config := gov.GetConfiguration(0)
notarySet := gov.GetNotarySet()
+ ID := types.NewNodeID(prv.PublicKey())
// Setup acking by information returned from Governace.
rb := newReliableBroadcast()
@@ -164,8 +226,21 @@ func NewConsensus(
uint64(float32(len(notarySet)-1)*config.PhiRatio+1),
config.NumChains)
+ // Setup DKG Protocol.
+ dkgModule := newDKGProtocol(
+ ID,
+ &consensusDKGReceiver{
+ ID: ID,
+ gov: gov,
+ prvKey: prv,
+ network: network,
+ },
+ 0,
+ len(gov.GetNotarySet())/3,
+ sigToPub)
+
con := &Consensus{
- ID: types.NewNodeID(prv.PublicKey()),
+ ID: ID,
rbModule: rb,
toModule: to,
ctModule: newConsensusTimestamp(),
@@ -175,8 +250,10 @@ func NewConsensus(
config: config,
db: db,
network: network,
- tickerObj: newTicker(gov),
+ tickerObj: newTicker(gov, TickerBA),
prvKey: prv,
+ dkgReady: sync.NewCond(&sync.Mutex{}),
+ dkgModule: dkgModule,
sigToPub: sigToPub,
ctx: ctx,
ctxCancel: ctxCancel,
@@ -210,13 +287,19 @@ func NewConsensus(
// Run starts running DEXON Consensus.
func (con *Consensus) Run() {
+ go con.processMsg(con.network.ReceiveChan(), con.PreProcessBlock)
+ con.runDKG()
+ con.dkgReady.L.Lock()
+ defer con.dkgReady.L.Unlock()
+ for con.dkgRunning != 2 {
+ con.dkgReady.Wait()
+ }
ticks := make([]chan struct{}, 0, con.config.NumChains)
for i := uint32(0); i < con.config.NumChains; i++ {
tick := make(chan struct{})
ticks = append(ticks, tick)
go con.runBA(i, tick)
}
- go con.processMsg(con.network.ReceiveChan(), con.PreProcessBlock)
go con.processWitnessData()
// Reset ticker.
@@ -271,6 +354,58 @@ BALoop:
}
}
+// runDKG starts running DKG protocol.
+func (con *Consensus) runDKG() {
+ con.dkgReady.L.Lock()
+ defer con.dkgReady.L.Unlock()
+ if con.dkgRunning != 0 {
+ return
+ }
+ con.dkgRunning = 1
+ go func() {
+ defer func() {
+ con.dkgReady.L.Lock()
+ defer con.dkgReady.L.Unlock()
+ con.dkgReady.Broadcast()
+ con.dkgRunning = 2
+ }()
+ ticker := newTicker(con.gov, TickerDKG)
+ round := con.dkgModule.round
+ <-ticker.Tick()
+ // Phase 2(T = 0): Exchange DKG secret key share.
+ con.dkgModule.processMasterPublicKeys(con.gov.DKGMasterPublicKeys(round))
+ // Phase 3(T = 0~λ): Propose complaint.
+ // Propose complaint is done in `processMasterPublicKeys`.
+ <-ticker.Tick()
+ // Phase 4(T = λ): Propose nack complaints.
+ con.dkgModule.proposeNackComplaints()
+ <-ticker.Tick()
+ // Phase 5(T = 2λ): Propose Anti nack complaint.
+ con.dkgModule.processNackComplaints(con.gov.DKGComplaints(round))
+ <-ticker.Tick()
+ // Phase 6(T = 3λ): Rebroadcast anti nack complaint.
+ // Rebroadcast is done in `processPrivateShare`.
+ <-ticker.Tick()
+ // Phase 7(T = 4λ): Enforce complaints and nack complaints.
+ con.dkgModule.enforceNackComplaints(con.gov.DKGComplaints(round))
+ // Enforce complaint is done in `processPrivateShare`.
+ // Phase 8(T = 5λ): DKG is ready.
+ gpk, err := newDKGGroupPublicKey(round,
+ con.gov.DKGMasterPublicKeys(round),
+ con.gov.DKGComplaints(round),
+ con.dkgModule.threshold, con.sigToPub)
+ if err != nil {
+ panic(err)
+ }
+ qualifies := ""
+ for _, nID := range gpk.qualifyNodeIDs {
+ qualifies += fmt.Sprintf("%s ", nID.String()[:6])
+ }
+ log.Printf("[%s] Qualify Nodes(%d): %s\n",
+ con.ID, len(gpk.qualifyIDs), qualifies)
+ }()
+}
+
// RunLegacy starts running Legacy DEXON Consensus.
func (con *Consensus) RunLegacy() {
go con.processMsg(con.network.ReceiveChan(), con.processBlock)
@@ -356,6 +491,13 @@ func (con *Consensus) processMsg(
if err := con.ProcessVote(val); err != nil {
log.Println(err)
}
+ case *types.DKGPrivateShare:
+ if con.dkgRunning == 0 {
+ break
+ }
+ if err := con.dkgModule.processPrivateShare(val); err != nil {
+ log.Println(err)
+ }
}
}
}
diff --git a/core/consensus_test.go b/core/consensus_test.go
index 701ee00..c5ef452 100644
--- a/core/consensus_test.go
+++ b/core/consensus_test.go
@@ -50,6 +50,11 @@ func (n *network) SendDKGPrivateShare(
recv types.NodeID, prvShare *types.DKGPrivateShare) {
}
+// BroadcastDKGPrivateShare broadcasts PrivateShare to all DKG participants.
+func (n *network) BroadcastDKGPrivateShare(
+ prvShare *types.DKGPrivateShare) {
+}
+
// ReceiveChan returns a channel to receive messages from DEXON network.
func (n *network) ReceiveChan() <-chan interface{} {
return make(chan interface{})
diff --git a/core/dkg-tsig-protocol.go b/core/dkg-tsig-protocol.go
index dc4e630..ccd2439 100644
--- a/core/dkg-tsig-protocol.go
+++ b/core/dkg-tsig-protocol.go
@@ -83,6 +83,7 @@ type dkgShareSecret struct {
type dkgGroupPublicKey struct {
round uint64
qualifyIDs dkg.IDs
+ qualifyNodeIDs types.NodeIDs
idMap map[types.NodeID]dkg.ID
publicKeys map[types.NodeID]*dkg.PublicKey
groupPublicKey *dkg.PublicKey
@@ -282,6 +283,7 @@ func (d *dkgProtocol) processPrivateShare(
if _, exist := d.antiComplaintReceived[prvShare.ReceiverID]; !exist {
d.antiComplaintReceived[prvShare.ReceiverID] =
make(map[types.NodeID]struct{})
+ d.recv.ProposeDKGAntiNackComplaint(prvShare)
}
d.antiComplaintReceived[prvShare.ReceiverID][prvShare.ProposerID] =
struct{}{}
@@ -330,6 +332,7 @@ func newDKGGroupPublicKey(
}
}
qualifyIDs := make(dkg.IDs, 0, len(mpks)-len(disqualifyIDs))
+ qualifyNodeIDs := make(types.NodeIDs, 0, cap(qualifyIDs))
mpkMap := make(map[dkg.ID]*types.DKGMasterPublicKey, cap(qualifyIDs))
idMap := make(map[types.NodeID]dkg.ID)
for _, mpk := range mpks {
@@ -339,6 +342,7 @@ func newDKGGroupPublicKey(
mpkMap[mpk.DKGID] = mpk
idMap[mpk.ProposerID] = mpk.DKGID
qualifyIDs = append(qualifyIDs, mpk.DKGID)
+ qualifyNodeIDs = append(qualifyNodeIDs, mpk.ProposerID)
}
// Recover qualify members' public key.
pubKeys := make(map[types.NodeID]*dkg.PublicKey, len(qualifyIDs))
@@ -368,6 +372,7 @@ func newDKGGroupPublicKey(
return &dkgGroupPublicKey{
round: round,
qualifyIDs: qualifyIDs,
+ qualifyNodeIDs: qualifyNodeIDs,
idMap: idMap,
publicKeys: pubKeys,
threshold: threshold,
diff --git a/core/dkg-tsig-protocol_test.go b/core/dkg-tsig-protocol_test.go
index 2bcbe9e..63b47ec 100644
--- a/core/dkg-tsig-protocol_test.go
+++ b/core/dkg-tsig-protocol_test.go
@@ -193,6 +193,13 @@ func (s *DKGTSIGProtocolTestSuite) TestDKGTSIGProtocol() {
qualifyIDs[id] = struct{}{}
}
+ for _, nID := range gpk.qualifyNodeIDs {
+ id, exist := gpk.idMap[nID]
+ s.Require().True(exist)
+ _, exist = qualifyIDs[id]
+ s.Require().True(exist)
+ }
+
shareSecrets := make(
map[types.NodeID]*dkgShareSecret, len(qualifyIDs))
@@ -299,21 +306,26 @@ func (s *DKGTSIGProtocolTestSuite) TestComplaint() {
ReceiverID: targetID,
Round: round,
})
- s.Error(ErrNotDKGParticipant, err)
- err = protocol.processPrivateShare(&types.DKGPrivateShare{
+ s.Equal(ErrNotDKGParticipant, err)
+ receivers[byzantineID].ProposeDKGPrivateShare(&types.DKGPrivateShare{
ProposerID: byzantineID,
ReceiverID: targetID,
Round: round,
})
- s.Error(ErrIncorrectPrivateShareSignature, err)
+ invalidShare := receivers[byzantineID].prvShare[targetID]
+ invalidShare.Signature[1]++
+ err = protocol.processPrivateShare(invalidShare)
+ s.Equal(ErrIncorrectPrivateShareSignature, err)
+ delete(receivers[byzantineID].prvShare, targetID)
// Byzantine node is sending incorrect private share.
receivers[byzantineID].ProposeDKGPrivateShare(&types.DKGPrivateShare{
- ProposerID: byzantineID,
- ReceiverID: targetID,
- Round: round,
+ ProposerID: byzantineID,
+ ReceiverID: targetID,
+ Round: round,
+ PrivateShare: *dkg.NewPrivateKey(),
})
- invalidShare := receivers[byzantineID].prvShare[targetID]
+ invalidShare = receivers[byzantineID].prvShare[targetID]
s.Require().NoError(protocol.processPrivateShare(invalidShare))
s.Require().Len(receiver.complaints, 1)
complaint, exist := receiver.complaints[byzantineID]
@@ -575,16 +587,17 @@ func (s *DKGTSIGProtocolTestSuite) TestPartialSignature() {
PartialSignature: shareSecret.sign(msgHash),
}
if nID == byzantineID2 {
- psig.PartialSignature[0]++
+ psig.PartialSignature = shareSecret.sign(
+ crypto.Keccak256Hash([]byte("💣")))
}
var err error
psig.Signature, err = s.prvKeys[nID].Sign(hashDKGPartialSignature(psig))
s.Require().NoError(err)
err = tsig.processPartialSignature(msgHash, psig)
if nID == byzantineID {
- s.Require().Error(ErrNotQualifyDKGParticipant, err)
+ s.Require().Equal(ErrNotQualifyDKGParticipant, err)
} else if nID == byzantineID2 {
- s.Require().Error(ErrIncorrectPartialSignature, err)
+ s.Require().Equal(ErrIncorrectPartialSignature, err)
} else {
s.Require().NoError(err)
}
diff --git a/core/interfaces.go b/core/interfaces.go
index 8ecfb3c..36b0160 100644
--- a/core/interfaces.go
+++ b/core/interfaces.go
@@ -69,6 +69,9 @@ type Network interface {
// SendDKGPrivateShare sends PrivateShare to a DKG participant.
SendDKGPrivateShare(recv types.NodeID, prvShare *types.DKGPrivateShare)
+ // BroadcastDKGPrivateShare broadcasts PrivateShare to all DKG participants.
+ BroadcastDKGPrivateShare(prvShare *types.DKGPrivateShare)
+
// ReceiveChan returns a channel to receive messages from DEXON network.
ReceiveChan() <-chan interface{}
}
diff --git a/core/test/governance.go b/core/test/governance.go
index 63462d0..e486afe 100644
--- a/core/test/governance.go
+++ b/core/test/governance.go
@@ -34,7 +34,8 @@ var (
// Governance is an implementation of Goverance for testing purpose.
type Governance struct {
- lambda time.Duration
+ lambdaBA time.Duration
+ lambdaDKG time.Duration
notarySet map[types.NodeID]struct{}
privateKeys map[types.NodeID]crypto.PrivateKey
DKGComplaint map[uint64][]*types.DKGComplaint
@@ -45,7 +46,8 @@ type Governance struct {
func NewGovernance(nodeCount int, lambda time.Duration) (
g *Governance, err error) {
g = &Governance{
- lambda: lambda,
+ lambdaBA: lambda,
+ lambdaDKG: lambda * 10,
notarySet: make(map[types.NodeID]struct{}),
privateKeys: make(map[types.NodeID]crypto.PrivateKey),
DKGComplaint: make(map[uint64][]*types.DKGComplaint),
@@ -80,7 +82,8 @@ func (g *Governance) GetConfiguration(blockHeight uint64) *types.Config {
NumShards: 1,
NumChains: uint32(len(g.notarySet)),
GenesisCRS: "__ DEXON",
- Lambda: g.lambda,
+ LambdaBA: g.lambdaBA,
+ LambdaDKG: g.lambdaDKG,
K: 0,
PhiRatio: 0.667,
}
diff --git a/core/ticker.go b/core/ticker.go
index bb5afb4..5dbbc2a 100644
--- a/core/ticker.go
+++ b/core/ticker.go
@@ -19,6 +19,15 @@ package core
import "time"
+// TickerType is the type of ticker.
+type TickerType int
+
+// TickerType enum.
+const (
+ TickerBA TickerType = iota
+ TickerDKG
+)
+
// defaultTicker is a wrapper to implement ticker interface based on
// time.Ticker.
type defaultTicker struct {
@@ -43,16 +52,23 @@ func (t *defaultTicker) Stop() {
// newTicker is a helper to setup a ticker by giving an Governance. If
// the governace object implements a ticker generator, a ticker from that
// generator would be returned, else constructs a default one.
-func newTicker(gov Governance) (t Ticker) {
+func newTicker(gov Governance, tickerType TickerType) (t Ticker) {
type tickerGenerator interface {
- NewTicker() Ticker
+ NewTicker(TickerType) Ticker
}
if gen, ok := gov.(tickerGenerator); ok {
- t = gen.NewTicker()
+ t = gen.NewTicker(tickerType)
}
if t == nil {
- t = newDefaultTicker(gov.GetConfiguration(0).Lambda)
+ var duration time.Duration
+ switch tickerType {
+ case TickerBA:
+ duration = gov.GetConfiguration(0).LambdaBA
+ case TickerDKG:
+ duration = gov.GetConfiguration(0).LambdaDKG
+ }
+ t = newDefaultTicker(duration)
}
return
}
diff --git a/core/types/config.go b/core/types/config.go
index 1392ec5..4f5bd6e 100644
--- a/core/types/config.go
+++ b/core/types/config.go
@@ -26,8 +26,9 @@ type Config struct {
NumChains uint32
GenesisCRS string
- // Byzantine agreement related.
- Lambda time.Duration
+ // Lambda related.
+ LambdaBA time.Duration
+ LambdaDKG time.Duration
// Total ordering related.
K int
diff --git a/core/types/dkg.go b/core/types/dkg.go
index d70bf98..ff0aa75 100644
--- a/core/types/dkg.go
+++ b/core/types/dkg.go
@@ -18,6 +18,8 @@
package types
import (
+ "fmt"
+
"github.com/dexon-foundation/dexon-consensus-core/crypto"
"github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
)
@@ -31,6 +33,15 @@ type DKGPrivateShare struct {
Signature crypto.Signature `json:"signature"`
}
+func (p *DKGPrivateShare) String() string {
+ return fmt.Sprintf("prvShare(%d:%s->%s:%s:%s)",
+ p.Round,
+ p.ProposerID.String()[:6],
+ p.ReceiverID.String()[:6],
+ p.PrivateShare.String(),
+ p.Signature.String()[:6])
+}
+
// DKGMasterPublicKey decrtibe a master public key in DKG protocol.
type DKGMasterPublicKey struct {
ProposerID NodeID `json:"proposer_id"`
diff --git a/crypto/dkg/constant.go b/crypto/dkg/constant.go
index 97ab008..119613b 100644
--- a/crypto/dkg/constant.go
+++ b/crypto/dkg/constant.go
@@ -18,7 +18,7 @@
package dkg
import (
- "github.com/herumi/bls/ffi/go/bls"
+ "github.com/Spiderpowa/bls/ffi/go/bls"
)
const (
diff --git a/crypto/dkg/dkg.go b/crypto/dkg/dkg.go
index df01078..f2a2f3a 100644
--- a/crypto/dkg/dkg.go
+++ b/crypto/dkg/dkg.go
@@ -18,9 +18,10 @@
package dkg
import (
+ "encoding/json"
"fmt"
- "github.com/herumi/bls/ffi/go/bls"
+ "github.com/Spiderpowa/bls/ffi/go/bls"
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/crypto"
@@ -50,10 +51,19 @@ func init() {
// Crypto.PrivateKey interface.
type PrivateKey struct {
privateKey bls.SecretKey
- id bls.ID
publicKey PublicKey
}
+// MarshalJSON implements json.Marshaller.
+func (prv *PrivateKey) MarshalJSON() ([]byte, error) {
+ return json.Marshal(&prv.privateKey)
+}
+
+// UnmarshalJSON implements json.Unmarshaller.
+func (prv *PrivateKey) UnmarshalJSON(data []byte) error {
+ return json.Unmarshal(data, &prv.privateKey)
+}
+
// ID is the id for DKG protocol.
type ID = bls.ID
@@ -80,6 +90,37 @@ type PublicKeyShares struct {
masterPublicKey []bls.PublicKey
}
+// MarshalJSON implements json.Marshaller.
+func (pubs *PublicKeyShares) MarshalJSON() ([]byte, error) {
+ type Alias PublicKeyShares
+ data := &struct {
+ MasterPublicKeys []*bls.PublicKey `json:"master_public_keys"`
+ }{
+ make([]*bls.PublicKey, len(pubs.masterPublicKey)),
+ }
+ for i := range pubs.masterPublicKey {
+ data.MasterPublicKeys[i] = &pubs.masterPublicKey[i]
+ }
+ return json.Marshal(data)
+}
+
+// UnmarshalJSON implements json.Unmarshaller.
+func (pubs *PublicKeyShares) UnmarshalJSON(data []byte) error {
+ type Alias PublicKeyShares
+ aux := &struct {
+ MasterPublicKeys []*bls.PublicKey `json:"master_public_keys"`
+ }{}
+ if err := json.Unmarshal(data, &aux); err != nil {
+ return err
+ }
+ mpk := make([]bls.PublicKey, len(aux.MasterPublicKeys))
+ for i, pk := range aux.MasterPublicKeys {
+ mpk[i] = *pk
+ }
+ pubs.masterPublicKey = mpk
+ return nil
+}
+
// NewID creates a ew ID structure.
func NewID(id []byte) ID {
var blsID bls.ID
@@ -301,6 +342,22 @@ func (prv *PrivateKey) Bytes() []byte {
return prv.privateKey.GetLittleEndian()
}
+// SetBytes sets the private key data to []byte.
+func (prv *PrivateKey) SetBytes(bytes []byte) error {
+ var key bls.SecretKey
+ if err := key.SetLittleEndian(bytes); err != nil {
+ return err
+ }
+ prv.privateKey = key
+ prv.publicKey = *newPublicKey(&prv.privateKey)
+ return nil
+}
+
+// String returns string representation of privat key.
+func (prv *PrivateKey) String() string {
+ return prv.privateKey.GetHexString()
+}
+
// VerifySignature checks that the given public key created signature over hash.
func (pub PublicKey) VerifySignature(
hash common.Hash, signature crypto.Signature) bool {
diff --git a/crypto/dkg/utils.go b/crypto/dkg/utils.go
index dddb546..3684964 100644
--- a/crypto/dkg/utils.go
+++ b/crypto/dkg/utils.go
@@ -20,7 +20,7 @@ package dkg
import (
"fmt"
- "github.com/herumi/bls/ffi/go/bls"
+ "github.com/Spiderpowa/bls/ffi/go/bls"
"github.com/dexon-foundation/dexon-consensus-core/crypto"
)
diff --git a/simulation/config/config.go b/simulation/config/config.go
index 6c7b584..8bc4ab7 100644
--- a/simulation/config/config.go
+++ b/simulation/config/config.go
@@ -40,7 +40,8 @@ type Consensus struct {
K int
ChainNum uint32
GenesisCRS string `toml:"genesis_crs"`
- Lambda int
+ LambdaBA int `toml:"lambda_ba"`
+ LambdaDKG int `toml:"lambda_dkg"`
}
// Legacy config.
@@ -96,7 +97,8 @@ func GenerateDefault(path string) error {
K: 1,
ChainNum: 7,
GenesisCRS: "In DEXON we trust.",
- Lambda: 250,
+ LambdaBA: 250,
+ LambdaDKG: 1000,
},
Legacy: Legacy{
ProposeIntervalMean: 500,
diff --git a/simulation/governance.go b/simulation/governance.go
index 0f2bbbf..613205d 100644
--- a/simulation/governance.go
+++ b/simulation/governance.go
@@ -39,7 +39,8 @@ type simGovernance struct {
crs string
dkgComplaint map[uint64][]*types.DKGComplaint
dkgMasterPublicKey map[uint64][]*types.DKGMasterPublicKey
- lambda time.Duration
+ lambdaBA time.Duration
+ lambdaDKG time.Duration
network *network
}
@@ -57,7 +58,8 @@ func newSimGovernance(
crs: consensusConfig.GenesisCRS,
dkgComplaint: make(map[uint64][]*types.DKGComplaint),
dkgMasterPublicKey: make(map[uint64][]*types.DKGMasterPublicKey),
- lambda: time.Duration(consensusConfig.Lambda) * time.Millisecond,
+ lambdaBA: time.Duration(consensusConfig.LambdaBA) * time.Millisecond,
+ lambdaDKG: time.Duration(consensusConfig.LambdaDKG) * time.Millisecond,
}
}
@@ -84,7 +86,8 @@ func (g *simGovernance) GetConfiguration(blockHeight uint64) *types.Config {
NumShards: 1,
NumChains: g.chainNum,
GenesisCRS: g.crs,
- Lambda: g.lambda,
+ LambdaBA: g.lambdaBA,
+ LambdaDKG: g.lambdaDKG,
K: g.k,
PhiRatio: g.phiRatio,
}
diff --git a/simulation/kubernetes/config.toml.in b/simulation/kubernetes/config.toml.in
index 546fa8e..dee1fe2 100644
--- a/simulation/kubernetes/config.toml.in
+++ b/simulation/kubernetes/config.toml.in
@@ -2,7 +2,8 @@ title = "DEXON Consensus Simulation Config"
[node]
num = {{numNode}}
-lambda = 250
+lambda_ba = 250
+lambda_dkg = 1000
max_block = 1000
[node.consensus]
diff --git a/simulation/marshaller.go b/simulation/marshaller.go
index 45a186d..d1b2793 100644
--- a/simulation/marshaller.go
+++ b/simulation/marshaller.go
@@ -22,6 +22,7 @@ import (
"fmt"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
+ "github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
)
// jsonMarshaller implements test.Marshaller to marshal simulation related
@@ -76,7 +77,9 @@ func (m *jsonMarshaller) Unmarshal(
}
msg = privateShare
case "dkg-master-public-key":
- masterPublicKey := &types.DKGMasterPublicKey{}
+ masterPublicKey := &types.DKGMasterPublicKey{
+ PublicKeyShares: *dkg.NewEmptyPublicKeyShares(),
+ }
if err = json.Unmarshal(payload, masterPublicKey); err != nil {
break
}
diff --git a/simulation/network.go b/simulation/network.go
index d14f07e..938d785 100644
--- a/simulation/network.go
+++ b/simulation/network.go
@@ -153,6 +153,14 @@ func (n *network) SendDKGPrivateShare(
}
}
+// BroadcastDKGPrivateShare implements core.Network interface.
+func (n *network) BroadcastDKGPrivateShare(
+ prvShare *types.DKGPrivateShare) {
+ if err := n.trans.Broadcast(prvShare); err != nil {
+ panic(err)
+ }
+}
+
// ReceiveChan implements core.Network interface.
func (n *network) ReceiveChan() <-chan interface{} {
return n.toConsensus