diff options
-rw-r--r-- | Gopkg.lock | 59 | ||||
-rw-r--r-- | Gopkg.toml | 4 | ||||
-rwxr-xr-x | bin/install_dkg_dep.sh | 8 | ||||
-rw-r--r-- | core/consensus.go | 184 | ||||
-rw-r--r-- | core/consensus_test.go | 5 | ||||
-rw-r--r-- | core/dkg-tsig-protocol.go | 5 | ||||
-rw-r--r-- | core/dkg-tsig-protocol_test.go | 33 | ||||
-rw-r--r-- | core/interfaces.go | 3 | ||||
-rw-r--r-- | core/test/governance.go | 9 | ||||
-rw-r--r-- | core/ticker.go | 24 | ||||
-rw-r--r-- | core/types/config.go | 5 | ||||
-rw-r--r-- | core/types/dkg.go | 11 | ||||
-rw-r--r-- | crypto/dkg/constant.go | 2 | ||||
-rw-r--r-- | crypto/dkg/dkg.go | 61 | ||||
-rw-r--r-- | crypto/dkg/utils.go | 2 | ||||
-rw-r--r-- | simulation/config/config.go | 6 | ||||
-rw-r--r-- | simulation/governance.go | 9 | ||||
-rw-r--r-- | simulation/kubernetes/config.toml.in | 3 | ||||
-rw-r--r-- | simulation/marshaller.go | 5 | ||||
-rw-r--r-- | simulation/network.go | 8 |
20 files changed, 377 insertions, 69 deletions
@@ -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 @@ -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 |