diff options
author | Jimmy Hu <jimmy.hu@dexon.org> | 2018-10-05 22:10:55 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-05 22:10:55 +0800 |
commit | b74b8c092dcc10a7792d92c64c6dc22d94edb295 (patch) | |
tree | 25d249774f2e116c357674693dd4633c11c55582 | |
parent | a23f81165db3071131ef67e70a54bbc78b8a0af1 (diff) | |
download | dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.tar dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.tar.gz dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.tar.bz2 dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.tar.lz dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.tar.xz dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.tar.zst dexon-consensus-b74b8c092dcc10a7792d92c64c6dc22d94edb295.zip |
core: General tsig (#177)
-rw-r--r-- | core/configuration-chain.go | 52 | ||||
-rw-r--r-- | core/configuration-chain_test.go | 102 | ||||
-rw-r--r-- | core/consensus.go | 63 | ||||
-rw-r--r-- | core/consensus_test.go | 12 | ||||
-rw-r--r-- | core/crypto.go | 5 | ||||
-rw-r--r-- | core/dkg-tsig-protocol.go | 13 | ||||
-rw-r--r-- | core/dkg-tsig-protocol_test.go | 12 | ||||
-rw-r--r-- | core/interfaces.go | 6 | ||||
-rw-r--r-- | core/types/block-randomness.go | 37 | ||||
-rw-r--r-- | core/types/block.go | 3 | ||||
-rw-r--r-- | core/types/block_test.go | 1 | ||||
-rw-r--r-- | core/types/dkg.go | 21 | ||||
-rw-r--r-- | simulation/marshaller.go | 16 | ||||
-rw-r--r-- | simulation/network.go | 17 |
14 files changed, 287 insertions, 73 deletions
diff --git a/core/configuration-chain.go b/core/configuration-chain.go index aca1a84..c9dbab9 100644 --- a/core/configuration-chain.go +++ b/core/configuration-chain.go @@ -31,6 +31,8 @@ import ( var ( ErrDKGNotRegistered = fmt.Errorf( "not yet registered in DKG protocol") + ErrTSigAlreadyRunning = fmt.Errorf( + "tsig is already running") ErrDKGNotReady = fmt.Errorf( "DKG is not ready") ) @@ -44,10 +46,10 @@ type configurationChain struct { dkgSigner map[uint64]*dkgShareSecret gpk map[uint64]*DKGGroupPublicKey dkgResult sync.RWMutex - tsig *tsigProtocol + tsig map[common.Hash]*tsigProtocol tsigReady *sync.Cond // TODO(jimmy-dexon): add timeout to pending psig. - pendingPsig []*types.DKGPartialSignature + pendingPsig map[common.Hash][]*types.DKGPartialSignature prevHash common.Hash } @@ -56,12 +58,14 @@ func newConfigurationChain( recv dkgReceiver, gov Governance) *configurationChain { return &configurationChain{ - ID: ID, - recv: recv, - gov: gov, - dkgSigner: make(map[uint64]*dkgShareSecret), - gpk: make(map[uint64]*DKGGroupPublicKey), - tsigReady: sync.NewCond(&sync.Mutex{}), + ID: ID, + recv: recv, + gov: gov, + dkgSigner: make(map[uint64]*dkgShareSecret), + gpk: make(map[uint64]*DKGGroupPublicKey), + tsig: make(map[common.Hash]*tsigProtocol), + tsigReady: sync.NewCond(&sync.Mutex{}), + pendingPsig: make(map[common.Hash][]*types.DKGPartialSignature), } } @@ -148,8 +152,7 @@ func (cc *configurationChain) runDKG(round uint64) error { } func (cc *configurationChain) preparePartialSignature( - round uint64, hash common.Hash, psigType types.DKGPartialSignatureType) ( - *types.DKGPartialSignature, error) { + round uint64, hash common.Hash) (*types.DKGPartialSignature, error) { signer, exist := func() (*dkgShareSecret, bool) { cc.dkgResult.RLock() defer cc.dkgResult.RUnlock() @@ -162,13 +165,13 @@ func (cc *configurationChain) preparePartialSignature( return &types.DKGPartialSignature{ ProposerID: cc.ID, Round: round, - Type: psigType, + Hash: hash, PartialSignature: signer.sign(hash), }, nil } func (cc *configurationChain) runTSig( - round uint64, hash common.Hash, psigType types.DKGPartialSignatureType) ( + round uint64, hash common.Hash) ( crypto.Signature, error) { gpk, exist := func() (*DKGGroupPublicKey, bool) { cc.dkgResult.RLock() @@ -181,12 +184,12 @@ func (cc *configurationChain) runTSig( } cc.tsigReady.L.Lock() defer cc.tsigReady.L.Unlock() - for cc.tsig != nil { - cc.tsigReady.Wait() + if _, exist := cc.tsig[hash]; exist { + return crypto.Signature{}, ErrTSigAlreadyRunning } - cc.tsig = newTSigProtocol(gpk, hash, psigType) - pendingPsig := cc.pendingPsig - cc.pendingPsig = []*types.DKGPartialSignature{} + cc.tsig[hash] = newTSigProtocol(gpk, hash) + pendingPsig := cc.pendingPsig[hash] + delete(cc.pendingPsig, hash) go func() { for _, psig := range pendingPsig { if err := cc.processPartialSignature(psig); err != nil { @@ -197,13 +200,12 @@ func (cc *configurationChain) runTSig( var signature crypto.Signature var err error for func() bool { - signature, err = cc.tsig.signature() + signature, err = cc.tsig[hash].signature() return err == ErrNotEnoughtPartialSignatures }() { cc.tsigReady.Wait() } - cc.tsig = nil - cc.tsigReady.Broadcast() + delete(cc.tsig, hash) if err != nil { return crypto.Signature{}, err } @@ -212,7 +214,7 @@ func (cc *configurationChain) runTSig( func (cc *configurationChain) runBlockTSig( round uint64, hash common.Hash) (crypto.Signature, error) { - sig, err := cc.runTSig(round, hash, types.TSigConfigurationBlock) + sig, err := cc.runTSig(round, hash) if err != nil { return crypto.Signature{}, err } @@ -222,7 +224,7 @@ func (cc *configurationChain) runBlockTSig( func (cc *configurationChain) runCRSTSig( round uint64, crs common.Hash) ([]byte, error) { - sig, err := cc.runTSig(round, crs, types.TSigCRS) + sig, err := cc.runTSig(round, crs) log.Printf("[%s] CRS(%d): %s\n", cc.ID, round+1, sig) return sig.Signature[:], err } @@ -241,7 +243,7 @@ func (cc *configurationChain) processPartialSignature( psig *types.DKGPartialSignature) error { cc.tsigReady.L.Lock() defer cc.tsigReady.L.Unlock() - if cc.tsig == nil || psig.Type != cc.tsig.psigType { + if _, exist := cc.tsig[psig.Hash]; !exist { ok, err := verifyDKGPartialSignatureSignature(psig) if err != nil { return err @@ -249,10 +251,10 @@ func (cc *configurationChain) processPartialSignature( if !ok { return ErrIncorrectPartialSignatureSignature } - cc.pendingPsig = append(cc.pendingPsig, psig) + cc.pendingPsig[psig.Hash] = append(cc.pendingPsig[psig.Hash], psig) return nil } - if err := cc.tsig.processPartialSignature(psig); err != nil { + if err := cc.tsig[psig.Hash].processPartialSignature(psig); err != nil { return err } cc.tsigReady.Broadcast() diff --git a/core/configuration-chain_test.go b/core/configuration-chain_test.go index 7ebc502..45120b4 100644 --- a/core/configuration-chain_test.go +++ b/core/configuration-chain_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/suite" + "github.com/dexon-foundation/dexon-consensus-core/common" "github.com/dexon-foundation/dexon-consensus-core/core/crypto" "github.com/dexon-foundation/dexon-consensus-core/core/crypto/dkg" "github.com/dexon-foundation/dexon-consensus-core/core/crypto/ecdsa" @@ -141,14 +142,8 @@ func (s *ConfigurationChainTestSuite) setupNodes(n int) { } } -// TestConfigurationChain will test the entire DKG+TISG protocol including -// exchanging private shares, recovering share secret, creating partial sign and -// recovering threshold signature. -// All participants are good people in this test. -func (s *ConfigurationChainTestSuite) TestConfigurationChain() { - k := 3 - n := 10 - round := uint64(1) +func (s *ConfigurationChainTestSuite) runDKG( + k, n int, round uint64) map[types.NodeID]*configurationChain { s.setupNodes(n) cfgChains := make(map[types.NodeID]*configurationChain) @@ -183,14 +178,20 @@ func (s *ConfigurationChainTestSuite) TestConfigurationChain() { for range cfgChains { s.Require().NoError(<-errs) } + return cfgChains +} - psigs := make([]*types.DKGPartialSignature, 0, n) - hash := crypto.Keccak256Hash([]byte("🌚🌝")) +func (s *ConfigurationChainTestSuite) preparePartialSignature( + hash common.Hash, + round uint64, + cfgChains map[types.NodeID]*configurationChain) ( + psigs []*types.DKGPartialSignature) { + psigs = make([]*types.DKGPartialSignature, 0, len(cfgChains)) for nID, cc := range cfgChains { if _, exist := cc.gpk[round].qualifyNodeIDs[nID]; !exist { continue } - psig, err := cc.preparePartialSignature(round, hash, types.TSigCRS) + psig, err := cc.preparePartialSignature(round, hash) s.Require().NoError(err) prvKey, exist := s.prvKeys[cc.ID] s.Require().True(exist) @@ -198,16 +199,31 @@ func (s *ConfigurationChainTestSuite) TestConfigurationChain() { s.Require().NoError(err) psigs = append(psigs, psig) } + return +} + +// TestConfigurationChain will test the entire DKG+TISG protocol including +// exchanging private shares, recovering share secret, creating partial sign and +// recovering threshold signature. +// All participants are good people in this test. +func (s *ConfigurationChainTestSuite) TestConfigurationChain() { + k := 3 + n := 10 + round := uint64(1) + cfgChains := s.runDKG(k, n, round) + + hash := crypto.Keccak256Hash([]byte("🌚🌝")) + psigs := s.preparePartialSignature(hash, round, cfgChains) tsigs := make([]crypto.Signature, 0, n) - errs = make(chan error, n) + errs := make(chan error, n) tsigChan := make(chan crypto.Signature, n) for nID, cc := range cfgChains { if _, exist := cc.gpk[round].qualifyNodeIDs[nID]; !exist { continue } go func(cc *configurationChain) { - tsig, err := cc.runTSig(round, hash, types.TSigCRS) + tsig, err := cc.runTSig(round, hash) // Prevent racing by collecting errors and check in main thread. errs <- err tsigChan <- tsig @@ -229,6 +245,66 @@ func (s *ConfigurationChainTestSuite) TestConfigurationChain() { } } +func (s *ConfigurationChainTestSuite) TestMultipleTSig() { + k := 2 + n := 7 + round := uint64(1) + cfgChains := s.runDKG(k, n, round) + + hash1 := crypto.Keccak256Hash([]byte("Hash1")) + hash2 := crypto.Keccak256Hash([]byte("Hash2")) + + psigs1 := s.preparePartialSignature(hash1, round, cfgChains) + psigs2 := s.preparePartialSignature(hash2, round, cfgChains) + + tsigs1 := make([]crypto.Signature, 0, n) + tsigs2 := make([]crypto.Signature, 0, n) + + errs := make(chan error, n*2) + tsigChan1 := make(chan crypto.Signature, n) + tsigChan2 := make(chan crypto.Signature, n) + for nID, cc := range cfgChains { + if _, exist := cc.gpk[round].qualifyNodeIDs[nID]; !exist { + continue + } + go func(cc *configurationChain) { + tsig1, err := cc.runTSig(round, hash1) + // Prevent racing by collecting errors and check in main thread. + errs <- err + tsigChan1 <- tsig1 + }(cc) + go func(cc *configurationChain) { + tsig2, err := cc.runTSig(round, hash2) + // Prevent racing by collecting errors and check in main thread. + errs <- err + tsigChan2 <- tsig2 + }(cc) + for _, psig := range psigs1 { + err := cc.processPartialSignature(psig) + s.Require().NoError(err) + } + for _, psig := range psigs2 { + err := cc.processPartialSignature(psig) + s.Require().NoError(err) + } + } + for nID, cc := range cfgChains { + if _, exist := cc.gpk[round].qualifyNodeIDs[nID]; !exist { + continue + } + s.Require().NoError(<-errs) + tsig1 := <-tsigChan1 + for _, prevTsig := range tsigs1 { + s.Equal(prevTsig, tsig1) + } + s.Require().NoError(<-errs) + tsig2 := <-tsigChan2 + for _, prevTsig := range tsigs2 { + s.Equal(prevTsig, tsig2) + } + } +} + func TestConfigurationChain(t *testing.T) { suite.Run(t, new(ConfigurationChainTestSuite)) } diff --git a/core/consensus.go b/core/consensus.go index b1615a2..c53d151 100644 --- a/core/consensus.go +++ b/core/consensus.go @@ -44,6 +44,12 @@ var ( "unknown block is proposed") ErrUnknownBlockConfirmed = fmt.Errorf( "unknown block is confirmed") + ErrIncorrectAgreementResultPosition = fmt.Errorf( + "incorrect agreement result position") + ErrNotEnoughVotes = fmt.Errorf( + "not enought votes") + ErrIncorrectVoteProposer = fmt.Errorf( + "incorrect vote proposer") ) // consensusBAReceiver implements agreementReceiver. @@ -385,7 +391,7 @@ func (con *Consensus) runDKGTSIG() { common.Hash{}, con.cfgModule.prevHash) psig, err := con.cfgModule.preparePartialSignature( - round, hash, types.TSigConfigurationBlock) + round, hash) if err != nil { panic(err) } @@ -405,7 +411,7 @@ func (con *Consensus) runDKGTSIG() { func (con *Consensus) runCRS() { // Start running next round CRS. psig, err := con.cfgModule.preparePartialSignature( - con.round, con.gov.CRS(con.round), types.TSigCRS) + con.round, con.gov.CRS(con.round)) if err != nil { log.Println(err) } else if err = con.authModule.SignDKGPartialSignature(psig); err != nil { @@ -471,6 +477,14 @@ func (con *Consensus) processMsg(msgChan <-chan interface{}) { if err := con.ProcessVote(val); err != nil { log.Println(err) } + case *types.AgreementResult: + if err := con.ProcessAgreementResult(val); err != nil { + log.Println(err) + } + case *types.BlockRandomnessResult: + if err := con.ProcessBlockRandomnessResult(val); err != nil { + log.Println(err) + } case *types.DKGPrivateShare: if err := con.cfgModule.processPrivateShare(val); err != nil { log.Println(err) @@ -504,6 +518,51 @@ func (con *Consensus) ProcessVote(vote *types.Vote) (err error) { return err } +// ProcessAgreementResult processes the randomness request. +func (con *Consensus) ProcessAgreementResult( + rand *types.AgreementResult) error { + if con.round != rand.Round { + return nil + } + dkgSet, err := con.nodeSetCache.GetDKGSet(rand.Round) + if err != nil { + return err + } + if _, exist := dkgSet[con.ID]; !exist { + return nil + } + if len(rand.Votes) <= con.currentConfig.NumNotarySet/3*2 { + return ErrNotEnoughVotes + } + if rand.Position.ChainID >= con.currentConfig.NumChains { + return ErrIncorrectAgreementResultPosition + } + notarySet, err := con.nodeSetCache.GetNotarySet( + rand.Round, rand.Position.ChainID) + if err != nil { + return err + } + for _, vote := range rand.Votes { + if _, exist := notarySet[vote.ProposerID]; !exist { + return ErrIncorrectVoteProposer + } + ok, err := verifyVoteSignature(&vote) + if err != nil { + return nil + } + if !ok { + return ErrIncorrectVoteSignature + } + } + return nil +} + +// ProcessBlockRandomnessResult processes the randomness result. +func (con *Consensus) ProcessBlockRandomnessResult( + rand *types.BlockRandomnessResult) error { + return nil +} + // preProcessBlock performs Byzantine Agreement on the block. func (con *Consensus) preProcessBlock(b *types.Block) (err error) { if err = con.lattice.SanityCheck(b); err != nil { diff --git a/core/consensus_test.go b/core/consensus_test.go index e8615a2..6827352 100644 --- a/core/consensus_test.go +++ b/core/consensus_test.go @@ -47,6 +47,18 @@ func (n *network) BroadcastBlock(block *types.Block) { n.conn.broadcast(n.nID, block) } +// BroadcastRandomnessRequest broadcasts rand request to DKG set. +func (n *network) BroadcastRandomnessRequest( + randRequest *types.AgreementResult) { + n.conn.broadcast(n.nID, randRequest) +} + +// BroadcastRandomnessResult broadcasts rand request to Notary set. +func (n *network) BroadcastRandomnessResult( + randResult *types.BlockRandomnessResult) { + n.conn.broadcast(n.nID, randResult) +} + // SendDKGPrivateShare sends PrivateShare to a DKG participant. func (n *network) SendDKGPrivateShare( recv crypto.PublicKey, prvShare *types.DKGPrivateShare) { diff --git a/core/crypto.go b/core/crypto.go index 6fc0d1b..bc6463f 100644 --- a/core/crypto.go +++ b/core/crypto.go @@ -217,13 +217,10 @@ func hashDKGPartialSignature(psig *types.DKGPartialSignature) common.Hash { binaryRound := make([]byte, 8) binary.LittleEndian.PutUint64(binaryRound, psig.Round) - binaryType := make([]byte, 4) - binary.LittleEndian.PutUint32(binaryType, uint32(psig.Type)) - return crypto.Keccak256Hash( psig.ProposerID.Hash[:], binaryRound, - binaryType, + psig.Hash[:], psig.PartialSignature.Signature[:], ) } diff --git a/core/dkg-tsig-protocol.go b/core/dkg-tsig-protocol.go index 9c0c476..3853468 100644 --- a/core/dkg-tsig-protocol.go +++ b/core/dkg-tsig-protocol.go @@ -38,8 +38,8 @@ var ( "threshold not reach") ErrIncorrectPrivateShareSignature = fmt.Errorf( "incorrect private share signature") - ErrMismatchPartialSignatureType = fmt.Errorf( - "mismatch partialSignature type") + ErrMismatchPartialSignatureHash = fmt.Errorf( + "mismatch partialSignature hash") ErrIncorrectPartialSignatureSignature = fmt.Errorf( "incorrect partialSignature signature") ErrIncorrectPartialSignature = fmt.Errorf( @@ -95,7 +95,6 @@ type DKGGroupPublicKey struct { type tsigProtocol struct { groupPublicKey *DKGGroupPublicKey hash common.Hash - psigType types.DKGPartialSignatureType sigs map[dkg.ID]dkg.PartialSignature threshold int } @@ -398,12 +397,10 @@ func (gpk *DKGGroupPublicKey) VerifySignature( func newTSigProtocol( gpk *DKGGroupPublicKey, - hash common.Hash, - psigType types.DKGPartialSignatureType) *tsigProtocol { + hash common.Hash) *tsigProtocol { return &tsigProtocol{ groupPublicKey: gpk, hash: hash, - psigType: psigType, sigs: make(map[dkg.ID]dkg.PartialSignature, gpk.threshold+1), } } @@ -420,8 +417,8 @@ func (tsig *tsigProtocol) sanityCheck(psig *types.DKGPartialSignature) error { if !ok { return ErrIncorrectPartialSignatureSignature } - if psig.Type != tsig.psigType { - return ErrMismatchPartialSignatureType + if psig.Hash != tsig.hash { + return ErrMismatchPartialSignatureHash } return nil } diff --git a/core/dkg-tsig-protocol_test.go b/core/dkg-tsig-protocol_test.go index 9743531..a3a0acc 100644 --- a/core/dkg-tsig-protocol_test.go +++ b/core/dkg-tsig-protocol_test.go @@ -211,12 +211,12 @@ func (s *DKGTSIGProtocolTestSuite) TestDKGTSIGProtocol() { } msgHash := crypto.Keccak256Hash([]byte("🏖🍹")) - tsig := newTSigProtocol(gpk, msgHash, types.TSigConfigurationBlock) + tsig := newTSigProtocol(gpk, msgHash) for nID, shareSecret := range shareSecrets { psig := &types.DKGPartialSignature{ ProposerID: nID, Round: round, - Type: types.TSigConfigurationBlock, + Hash: msgHash, PartialSignature: shareSecret.sign(msgHash), } var err error @@ -578,14 +578,14 @@ func (s *DKGTSIGProtocolTestSuite) TestPartialSignature() { } msgHash := crypto.Keccak256Hash([]byte("🏖🍹")) - tsig := newTSigProtocol(gpk, msgHash, types.TSigConfigurationBlock) + tsig := newTSigProtocol(gpk, msgHash) byzantineID2 := s.nIDs[1] byzantineID3 := s.nIDs[2] for nID, shareSecret := range shareSecrets { psig := &types.DKGPartialSignature{ ProposerID: nID, Round: round, - Type: types.TSigConfigurationBlock, + Hash: msgHash, PartialSignature: shareSecret.sign(msgHash), } switch nID { @@ -593,7 +593,7 @@ func (s *DKGTSIGProtocolTestSuite) TestPartialSignature() { psig.PartialSignature = shareSecret.sign( crypto.Keccak256Hash([]byte("💣"))) case byzantineID3: - psig.Type = types.TSigNotaryAck + psig.Hash = common.NewRandomHash() } var err error psig.Signature, err = s.prvKeys[nID].Sign(hashDKGPartialSignature(psig)) @@ -605,7 +605,7 @@ func (s *DKGTSIGProtocolTestSuite) TestPartialSignature() { case byzantineID2: s.Require().Equal(ErrIncorrectPartialSignature, err) case byzantineID3: - s.Require().Equal(ErrMismatchPartialSignatureType, err) + s.Require().Equal(ErrMismatchPartialSignatureHash, err) default: s.Require().NoError(err) } diff --git a/core/interfaces.go b/core/interfaces.go index c367933..710550f 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -64,6 +64,12 @@ type Network interface { // BroadcastBlock broadcasts block to all nodes in DEXON network. BroadcastBlock(block *types.Block) + // BroadcastRandomnessRequest broadcasts rand request to DKG set. + BroadcastRandomnessRequest(randRequest *types.AgreementResult) + + // BroadcastRandomnessResult broadcasts rand request to Notary set. + BroadcastRandomnessResult(randResult *types.BlockRandomnessResult) + // SendDKGPrivateShare sends PrivateShare to a DKG participant. SendDKGPrivateShare(pub crypto.PublicKey, prvShare *types.DKGPrivateShare) diff --git a/core/types/block-randomness.go b/core/types/block-randomness.go new file mode 100644 index 0000000..896904a --- /dev/null +++ b/core/types/block-randomness.go @@ -0,0 +1,37 @@ +// Copyright 2018 The dexon-consensus-core Authors +// This file is part of the dexon-consensus-core library. +// +// The dexon-consensus-core 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-core 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-core library. If not, see +// <http://www.gnu.org/licenses/>. + +package types + +import ( + "github.com/dexon-foundation/dexon-consensus-core/common" +) + +// AgreementResult describes an agremeent result. +type AgreementResult struct { + BlockHash common.Hash `json:"block_hash"` + Round uint64 `json:"round"` + Position Position `json:"position"` + Votes []Vote `json:"votes"` +} + +// BlockRandomnessResult describes a block randomness result +type BlockRandomnessResult struct { + BlockHash common.Hash `json:"block_hash"` + Round uint64 `json:"round"` + Randomness []byte `json:"randomness"` +} diff --git a/core/types/block.go b/core/types/block.go index 297f479..fc69481 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -68,6 +68,7 @@ type Block struct { Timestamp time.Time `json:"timestamps"` Acks common.SortedHashes `json:"acks"` Payload []byte `json:"payload"` + Randomness []byte `json:"randomness"` ConsensusTimestamp time.Time `json:"consensus_timestamp"` ConsensusHeight uint64 `json:"consensus_height"` Witness Witness `json:"witness"` @@ -102,6 +103,8 @@ func (b *Block) Clone() (bcopy *Block) { copy(bcopy.Acks, b.Acks) bcopy.Payload = make([]byte, len(b.Payload)) copy(bcopy.Payload, b.Payload) + bcopy.Randomness = make([]byte, len(b.Randomness)) + copy(bcopy.Randomness, b.Randomness) return } diff --git a/core/types/block_test.go b/core/types/block_test.go index 3e601b6..07d27ab 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -60,6 +60,7 @@ func (s *BlockTestSuite) createRandomBlock() *Block { ConsensusHeight: rand.Uint64(), ConsensusTimestamp: time.Now().Add(time.Duration(rand.Int())), Payload: s.randomBytes(), + Randomness: s.randomBytes(), Signature: crypto.Signature{Signature: s.randomBytes()}, CRSSignature: crypto.Signature{Signature: s.randomBytes()}, } diff --git a/core/types/dkg.go b/core/types/dkg.go index df9d8e3..a4c6bf1 100644 --- a/core/types/dkg.go +++ b/core/types/dkg.go @@ -20,6 +20,7 @@ package types import ( "fmt" + "github.com/dexon-foundation/dexon-consensus-core/common" "github.com/dexon-foundation/dexon-consensus-core/core/crypto" "github.com/dexon-foundation/dexon-consensus-core/core/crypto/dkg" ) @@ -66,23 +67,13 @@ type DKGComplaint struct { Signature crypto.Signature `json:"signature"` } -// DKGPartialSignatureType specifies ths threshold signature type. -type DKGPartialSignatureType uint32 - -// TSig enums. -const ( - TSigConfigurationBlock DKGPartialSignatureType = iota - TSigNotaryAck - TSigCRS -) - // DKGPartialSignature describe a partial signature in DKG protocol. type DKGPartialSignature struct { - ProposerID NodeID `json:"proposerID"` - Round uint64 `json:"round"` - Type DKGPartialSignatureType `json:"type"` - PartialSignature dkg.PartialSignature `json:"partial_signature"` - Signature crypto.Signature `json:"signature"` + ProposerID NodeID `json:"proposerID"` + Round uint64 `json:"round"` + Hash common.Hash `json:"hash"` + PartialSignature dkg.PartialSignature `json:"partial_signature"` + Signature crypto.Signature `json:"signature"` } // IsNack returns true if it's a nack complaint in DKG protocol. diff --git a/simulation/marshaller.go b/simulation/marshaller.go index cdf080b..d677c1f 100644 --- a/simulation/marshaller.go +++ b/simulation/marshaller.go @@ -63,6 +63,18 @@ func (m *jsonMarshaller) Unmarshal( break } msg = vote + case "block-randomness-request": + request := &types.AgreementResult{} + if err = json.Unmarshal(payload, request); err != nil { + break + } + msg = request + case "block-randomness-result": + result := &types.BlockRandomnessResult{} + if err = json.Unmarshal(payload, result); err != nil { + break + } + msg = result case "dkg-private-share": privateShare := &types.DKGPrivateShare{} if err = json.Unmarshal(payload, privateShare); err != nil { @@ -111,6 +123,10 @@ func (m *jsonMarshaller) Marshal(msg interface{}) ( msgType = "block" case *types.Vote: msgType = "vote" + case *types.AgreementResult: + msgType = "block-randomness-request" + case *types.BlockRandomnessResult: + msgType = "block-randomness-result" case *types.DKGPrivateShare: msgType = "dkg-private-share" case *types.DKGMasterPublicKey: diff --git a/simulation/network.go b/simulation/network.go index 0faacf7..ab3b4fa 100644 --- a/simulation/network.go +++ b/simulation/network.go @@ -132,6 +132,22 @@ func (n *network) BroadcastBlock(block *types.Block) { } } +// BroadcastRandomnessRequest implements core.Network interface. +func (n *network) BroadcastRandomnessRequest( + randRequest *types.AgreementResult) { + if err := n.trans.Broadcast(randRequest); err != nil { + panic(err) + } +} + +// BroadcastRandomnessResult implements core.Network interface. +func (n *network) BroadcastRandomnessResult( + randResult *types.BlockRandomnessResult) { + if err := n.trans.Broadcast(randResult); err != nil { + panic(err) + } +} + // broadcast message to all other nodes in the network. func (n *network) broadcast(message interface{}) { if err := n.trans.Broadcast(message); err != nil { @@ -199,6 +215,7 @@ func (n *network) run() { disp := func(e *test.TransportEnvelope) { switch e.Msg.(type) { case *types.Block, *types.Vote, + *types.AgreementResult, *types.BlockRandomnessResult, *types.DKGPrivateShare, *types.DKGPartialSignature: n.toConsensus <- e.Msg default: |