aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2018-10-05 22:10:55 +0800
committerGitHub <noreply@github.com>2018-10-05 22:10:55 +0800
commitb74b8c092dcc10a7792d92c64c6dc22d94edb295 (patch)
tree25d249774f2e116c357674693dd4633c11c55582
parenta23f81165db3071131ef67e70a54bbc78b8a0af1 (diff)
downloaddexon-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.go52
-rw-r--r--core/configuration-chain_test.go102
-rw-r--r--core/consensus.go63
-rw-r--r--core/consensus_test.go12
-rw-r--r--core/crypto.go5
-rw-r--r--core/dkg-tsig-protocol.go13
-rw-r--r--core/dkg-tsig-protocol_test.go12
-rw-r--r--core/interfaces.go6
-rw-r--r--core/types/block-randomness.go37
-rw-r--r--core/types/block.go3
-rw-r--r--core/types/block_test.go1
-rw-r--r--core/types/dkg.go21
-rw-r--r--simulation/marshaller.go16
-rw-r--r--simulation/network.go17
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: