aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/agreement-state_test.go4
-rw-r--r--core/agreement.go2
-rw-r--r--core/agreement_test.go4
-rw-r--r--core/authenticator.go (renamed from core/key-holder.go)52
-rw-r--r--core/authenticator_test.go (renamed from core/key-holder_test.go)24
-rw-r--r--core/compaction-chain.go2
-rw-r--r--core/compaction-chain_test.go2
-rw-r--r--core/configuration-chain.go2
-rw-r--r--core/configuration-chain_test.go13
-rw-r--r--core/consensus.go2
-rw-r--r--core/consensus_test.go2
-rw-r--r--core/crypto.go2
-rw-r--r--core/crypto/dkg/constant.go26
-rw-r--r--core/crypto/dkg/dkg.go381
-rw-r--r--core/crypto/dkg/dkg_test.go461
-rw-r--r--core/crypto/dkg/utils.go69
-rw-r--r--core/crypto/eth/eth.go120
-rw-r--r--core/crypto/eth/eth_test.go93
-rw-r--r--core/crypto/interfaces.go45
-rw-r--r--core/crypto/utils.go41
-rw-r--r--core/crypto/utils_test.go52
-rw-r--r--core/crypto_test.go6
-rw-r--r--core/dkg-tsig-protocol.go4
-rw-r--r--core/dkg-tsig-protocol_test.go6
-rw-r--r--core/interfaces.go36
-rw-r--r--core/leader-selector.go2
-rw-r--r--core/leader-selector_test.go2
-rw-r--r--core/shard.go2
-rw-r--r--core/shard_test.go2
-rw-r--r--core/test/blocks-generator.go4
-rw-r--r--core/test/governance.go4
-rw-r--r--core/types/block.go2
-rw-r--r--core/types/dkg.go4
-rw-r--r--core/types/node.go2
-rw-r--r--core/types/vote.go2
-rw-r--r--core/types/witness.go2
-rw-r--r--core/utils.go2
37 files changed, 1373 insertions, 108 deletions
diff --git a/core/agreement-state_test.go b/core/agreement-state_test.go
index 0142724..2aa50ac 100644
--- a/core/agreement-state_test.go
+++ b/core/agreement-state_test.go
@@ -24,9 +24,9 @@ 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/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
)
type AgreementStateTestSuite struct {
diff --git a/core/agreement.go b/core/agreement.go
index ffc4ba8..1b1cbde 100644
--- a/core/agreement.go
+++ b/core/agreement.go
@@ -24,8 +24,8 @@ import (
"time"
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// Errors for agreement module.
diff --git a/core/agreement_test.go b/core/agreement_test.go
index 681d7b6..4f8a3ac 100644
--- a/core/agreement_test.go
+++ b/core/agreement_test.go
@@ -21,9 +21,9 @@ import (
"testing"
"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/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
"github.com/stretchr/testify/suite"
)
diff --git a/core/key-holder.go b/core/authenticator.go
index 355c823..480d6cc 100644
--- a/core/key-holder.go
+++ b/core/authenticator.go
@@ -19,55 +19,57 @@ package core
import (
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
-type keyHolder struct {
+// Authenticator verify data owner.
+type Authenticator struct {
prvKey crypto.PrivateKey
pubKey crypto.PublicKey
sigToPub SigToPubFn
}
-func newKeyHolder(prvKey crypto.PrivateKey, sigToPub SigToPubFn) *keyHolder {
- return &keyHolder{
+// NewAuthenticator constructs an Authenticator instance.
+func NewAuthenticator(prvKey crypto.PrivateKey, sigToPub SigToPubFn) *Authenticator {
+ return &Authenticator{
prvKey: prvKey,
pubKey: prvKey.PublicKey(),
sigToPub: sigToPub,
}
}
-// SignBlock implements core.Signer.
-func (h *keyHolder) SignBlock(b *types.Block) (err error) {
- b.ProposerID = types.NewNodeID(h.pubKey)
+// SignBlock signs a types.Block.
+func (au *Authenticator) SignBlock(b *types.Block) (err error) {
+ b.ProposerID = types.NewNodeID(au.pubKey)
if b.Hash, err = hashBlock(b); err != nil {
return
}
- if b.Signature, err = h.prvKey.Sign(b.Hash); err != nil {
+ if b.Signature, err = au.prvKey.Sign(b.Hash); err != nil {
return
}
return
}
-// SignVote implements core.Signer.
-func (h *keyHolder) SignVote(v *types.Vote) (err error) {
- v.ProposerID = types.NewNodeID(h.pubKey)
- v.Signature, err = h.prvKey.Sign(hashVote(v))
+// SignVote signs a types.Vote.
+func (au *Authenticator) SignVote(v *types.Vote) (err error) {
+ v.ProposerID = types.NewNodeID(au.pubKey)
+ v.Signature, err = au.prvKey.Sign(hashVote(v))
return
}
-// SignCRS implements core.Signer
-func (h *keyHolder) SignCRS(b *types.Block, crs common.Hash) (err error) {
- if b.ProposerID != types.NewNodeID(h.pubKey) {
+// SignCRS signs CRS signature of types.Block.
+func (au *Authenticator) SignCRS(b *types.Block, crs common.Hash) (err error) {
+ if b.ProposerID != types.NewNodeID(au.pubKey) {
err = ErrInvalidProposerID
return
}
- b.CRSSignature, err = h.prvKey.Sign(hashCRS(b, crs))
+ b.CRSSignature, err = au.prvKey.Sign(hashCRS(b, crs))
return
}
-// VerifyBlock implements core.CryptoVerifier.
-func (h *keyHolder) VerifyBlock(b *types.Block) (err error) {
+// VerifyBlock verifies the signature of types.Block.
+func (au *Authenticator) VerifyBlock(b *types.Block) (err error) {
hash, err := hashBlock(b)
if err != nil {
return
@@ -76,7 +78,7 @@ func (h *keyHolder) VerifyBlock(b *types.Block) (err error) {
err = ErrIncorrectHash
return
}
- pubKey, err := h.sigToPub(b.Hash, b.Signature)
+ pubKey, err := au.sigToPub(b.Hash, b.Signature)
if err != nil {
return
}
@@ -87,12 +89,12 @@ func (h *keyHolder) VerifyBlock(b *types.Block) (err error) {
return
}
-// VerifyVote implements core.CryptoVerifier.
-func (h *keyHolder) VerifyVote(v *types.Vote) (bool, error) {
- return verifyVoteSignature(v, h.sigToPub)
+// VerifyVote verifies the signature of types.Vote.
+func (au *Authenticator) VerifyVote(v *types.Vote) (bool, error) {
+ return verifyVoteSignature(v, au.sigToPub)
}
-// VerifyWitness implements core.CryptoVerifier.
-func (h *keyHolder) VerifyCRS(b *types.Block, crs common.Hash) (bool, error) {
- return verifyCRSSignature(b, crs, h.sigToPub)
+// VerifyCRS verifies the CRS signature of types.Block.
+func (au *Authenticator) VerifyCRS(b *types.Block, crs common.Hash) (bool, error) {
+ return verifyCRSSignature(b, crs, au.sigToPub)
}
diff --git a/core/key-holder_test.go b/core/authenticator_test.go
index cb5fda7..40b5e0c 100644
--- a/core/key-holder_test.go
+++ b/core/authenticator_test.go
@@ -22,23 +22,23 @@ import (
"time"
"github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
"github.com/stretchr/testify/suite"
)
-type KeyHolderTestSuite struct {
+type AuthenticatorTestSuite struct {
suite.Suite
}
-func (s *KeyHolderTestSuite) setupKeyHolder() *keyHolder {
+func (s *AuthenticatorTestSuite) setupAuthenticator() *Authenticator {
k, err := eth.NewPrivateKey()
s.NoError(err)
- return newKeyHolder(k, eth.SigToPub)
+ return NewAuthenticator(k, eth.SigToPub)
}
-func (s *KeyHolderTestSuite) TestBlock() {
- k := s.setupKeyHolder()
+func (s *AuthenticatorTestSuite) TestBlock() {
+ k := s.setupAuthenticator()
b := &types.Block{
ParentHash: common.NewRandomHash(),
Position: types.Position{
@@ -52,8 +52,8 @@ func (s *KeyHolderTestSuite) TestBlock() {
s.NoError(k.VerifyBlock(b))
}
-func (s *KeyHolderTestSuite) TestVote() {
- k := s.setupKeyHolder()
+func (s *AuthenticatorTestSuite) TestVote() {
+ k := s.setupAuthenticator()
v := &types.Vote{
ProposerID: types.NodeID{Hash: common.NewRandomHash()},
Type: types.VoteConfirm,
@@ -70,8 +70,8 @@ func (s *KeyHolderTestSuite) TestVote() {
s.NoError(err)
}
-func (s *KeyHolderTestSuite) TestCRS() {
- k := s.setupKeyHolder()
+func (s *AuthenticatorTestSuite) TestCRS() {
+ k := s.setupAuthenticator()
b := &types.Block{
ParentHash: common.NewRandomHash(),
Position: types.Position{
@@ -91,6 +91,6 @@ func (s *KeyHolderTestSuite) TestCRS() {
s.NoError(err)
}
-func TestKeyHolder(t *testing.T) {
- suite.Run(t, new(KeyHolderTestSuite))
+func TestAuthenticator(t *testing.T) {
+ suite.Run(t, new(AuthenticatorTestSuite))
}
diff --git a/core/compaction-chain.go b/core/compaction-chain.go
index 4405bbc..4bb3ffb 100644
--- a/core/compaction-chain.go
+++ b/core/compaction-chain.go
@@ -26,8 +26,8 @@ import (
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// Errors for compaction chain.
diff --git a/core/compaction-chain_test.go b/core/compaction-chain_test.go
index 3603fb6..ed02b78 100644
--- a/core/compaction-chain_test.go
+++ b/core/compaction-chain_test.go
@@ -23,8 +23,8 @@ import (
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
"github.com/stretchr/testify/suite"
)
diff --git a/core/configuration-chain.go b/core/configuration-chain.go
index a6c0f39..46f02cc 100644
--- a/core/configuration-chain.go
+++ b/core/configuration-chain.go
@@ -23,8 +23,8 @@ import (
"sync"
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// Errors for configuration chain..
diff --git a/core/configuration-chain_test.go b/core/configuration-chain_test.go
index ae82e42..fc3f48e 100644
--- a/core/configuration-chain_test.go
+++ b/core/configuration-chain_test.go
@@ -25,11 +25,11 @@ import (
"github.com/stretchr/testify/suite"
+ "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/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/test"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
)
type ConfigurationChainTestSuite struct {
@@ -113,7 +113,12 @@ func (r *testCCReceiver) ProposeDKGAntiNackComplaint(
prv.Signature, err = prvKey.Sign(hashDKGPrivateShare(prv))
r.s.Require().NoError(err)
for _, cc := range r.nodes {
- err = cc.processPrivateShare(prv)
+ // Use Marshal/Unmarshal to do deep copy.
+ data, err := json.Marshal(prv)
+ r.s.Require().NoError(err)
+ prvCopy := &types.DKGPrivateShare{}
+ r.s.Require().NoError(json.Unmarshal(data, prvCopy))
+ err = cc.processPrivateShare(prvCopy)
r.s.Require().NoError(err)
}
}()
diff --git a/core/consensus.go b/core/consensus.go
index c7eea32..b8c8f77 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -27,8 +27,8 @@ import (
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// SigToPubFn is a function to recover public key from signature.
diff --git a/core/consensus_test.go b/core/consensus_test.go
index a58d3e8..799698e 100644
--- a/core/consensus_test.go
+++ b/core/consensus_test.go
@@ -24,9 +24,9 @@ import (
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/test"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
"github.com/stretchr/testify/suite"
)
diff --git a/core/crypto.go b/core/crypto.go
index 26e44f9..2a1e3c5 100644
--- a/core/crypto.go
+++ b/core/crypto.go
@@ -21,8 +21,8 @@ import (
"encoding/binary"
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
func hashWitness(block *types.Block) (common.Hash, error) {
diff --git a/core/crypto/dkg/constant.go b/core/crypto/dkg/constant.go
new file mode 100644
index 0000000..119613b
--- /dev/null
+++ b/core/crypto/dkg/constant.go
@@ -0,0 +1,26 @@
+// 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 dkg
+
+import (
+ "github.com/Spiderpowa/bls/ffi/go/bls"
+)
+
+const (
+ curve = bls.CurveFp382_2
+)
diff --git a/core/crypto/dkg/dkg.go b/core/crypto/dkg/dkg.go
new file mode 100644
index 0000000..fe05e96
--- /dev/null
+++ b/core/crypto/dkg/dkg.go
@@ -0,0 +1,381 @@
+// 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 dkg
+
+import (
+ "encoding/json"
+ "fmt"
+
+ "github.com/Spiderpowa/bls/ffi/go/bls"
+
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+)
+
+var (
+ // ErrDuplicatedShare is reported when adding an private key share of same id.
+ ErrDuplicatedShare = fmt.Errorf("invalid share")
+ // ErrNoIDToRecover is reported when no id is provided for recovering private
+ // key.
+ ErrNoIDToRecover = fmt.Errorf("no id to recover private key")
+ // ErrShareNotFound is reported when the private key share of id is not found
+ // when recovering private key.
+ ErrShareNotFound = fmt.Errorf("share not found")
+)
+
+var publicKeyLength int
+
+func init() {
+ bls.Init(curve)
+
+ pubKey := &bls.PublicKey{}
+ publicKeyLength = len(pubKey.Serialize())
+}
+
+// PrivateKey represents a private key structure implments
+// Crypto.PrivateKey interface.
+type PrivateKey struct {
+ privateKey bls.SecretKey
+ 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
+
+// IDs is an array of ID.
+type IDs []ID
+
+// PublicKey represents a public key structure implements
+// Crypto.PublicKey interface.
+type PublicKey struct {
+ publicKey bls.PublicKey
+}
+
+// PrivateKeyShares represents a private key shares for DKG protocol.
+type PrivateKeyShares struct {
+ shares []PrivateKey
+ shareIndex map[ID]int
+ masterPrivateKey []bls.SecretKey
+}
+
+// PublicKeyShares represents a public key shares for DKG protocol.
+type PublicKeyShares struct {
+ shares []PublicKey
+ shareIndex map[ID]int
+ 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
+ blsID.SetLittleEndian(id)
+ return blsID
+}
+
+// NewPrivateKey creates a new PrivateKey structure.
+func NewPrivateKey() *PrivateKey {
+ var key bls.SecretKey
+ key.SetByCSPRNG()
+ return &PrivateKey{
+ privateKey: key,
+ publicKey: *newPublicKey(&key),
+ }
+}
+
+// NewPrivateKeyShares creates a DKG private key shares of threshold t.
+func NewPrivateKeyShares(t int) (*PrivateKeyShares, *PublicKeyShares) {
+ var prv bls.SecretKey
+ prv.SetByCSPRNG()
+ msk := prv.GetMasterSecretKey(t)
+ mpk := bls.GetMasterPublicKey(msk)
+ return &PrivateKeyShares{
+ masterPrivateKey: msk,
+ shareIndex: make(map[ID]int),
+ }, &PublicKeyShares{
+ shareIndex: make(map[ID]int),
+ masterPublicKey: mpk,
+ }
+}
+
+// NewEmptyPrivateKeyShares creates an empty private key shares.
+func NewEmptyPrivateKeyShares() *PrivateKeyShares {
+ return &PrivateKeyShares{
+ shareIndex: make(map[ID]int),
+ }
+}
+
+// SetParticipants sets the DKG participants.
+func (prvs *PrivateKeyShares) SetParticipants(IDs IDs) {
+ prvs.shares = make([]PrivateKey, len(IDs))
+ prvs.shareIndex = make(map[ID]int, len(IDs))
+ for idx, ID := range IDs {
+ prvs.shares[idx].privateKey.Set(prvs.masterPrivateKey, &ID)
+ prvs.shareIndex[ID] = idx
+ }
+}
+
+// AddShare adds a share.
+func (prvs *PrivateKeyShares) AddShare(ID ID, share *PrivateKey) error {
+ if idx, exist := prvs.shareIndex[ID]; exist {
+ if !share.privateKey.IsEqual(&prvs.shares[idx].privateKey) {
+ return ErrDuplicatedShare
+ }
+ return nil
+ }
+ prvs.shareIndex[ID] = len(prvs.shares)
+ prvs.shares = append(prvs.shares, *share)
+ return nil
+}
+
+// RecoverPrivateKey recovers private key from the shares.
+func (prvs *PrivateKeyShares) RecoverPrivateKey(qualifyIDs IDs) (
+ *PrivateKey, error) {
+ var prv PrivateKey
+ if len(qualifyIDs) == 0 {
+ return nil, ErrNoIDToRecover
+ }
+ for i, ID := range qualifyIDs {
+ idx, exist := prvs.shareIndex[ID]
+ if !exist {
+ return nil, ErrShareNotFound
+ }
+ if i == 0 {
+ prv.privateKey = prvs.shares[idx].privateKey
+ continue
+ }
+ prv.privateKey.Add(&prvs.shares[idx].privateKey)
+ }
+ return &prv, nil
+}
+
+// RecoverPublicKey recovers public key from the shares.
+func (prvs *PrivateKeyShares) RecoverPublicKey(qualifyIDs IDs) (
+ *PublicKey, error) {
+ var pub PublicKey
+ if len(qualifyIDs) == 0 {
+ return nil, ErrNoIDToRecover
+ }
+ for i, ID := range qualifyIDs {
+ idx, exist := prvs.shareIndex[ID]
+ if !exist {
+ return nil, ErrShareNotFound
+ }
+ if i == 0 {
+ pub.publicKey = *prvs.shares[idx].privateKey.GetPublicKey()
+ continue
+ }
+ pub.publicKey.Add(prvs.shares[idx].privateKey.GetPublicKey())
+ }
+ return &pub, nil
+}
+
+// Share returns the share for the ID.
+func (prvs *PrivateKeyShares) Share(ID ID) (*PrivateKey, bool) {
+ idx, exist := prvs.shareIndex[ID]
+ if !exist {
+ return nil, false
+ }
+ return &prvs.shares[idx], true
+}
+
+// NewEmptyPublicKeyShares creates an empty public key shares.
+func NewEmptyPublicKeyShares() *PublicKeyShares {
+ return &PublicKeyShares{
+ shareIndex: make(map[ID]int),
+ }
+}
+
+// Share returns the share for the ID.
+func (pubs *PublicKeyShares) Share(ID ID) (*PublicKey, error) {
+ idx, exist := pubs.shareIndex[ID]
+ if exist {
+ return &pubs.shares[idx], nil
+ }
+ var pk PublicKey
+ if err := pk.publicKey.Set(pubs.masterPublicKey, &ID); err != nil {
+ return nil, err
+ }
+ pubs.AddShare(ID, &pk)
+ return &pk, nil
+}
+
+// AddShare adds a share.
+func (pubs *PublicKeyShares) AddShare(ID ID, share *PublicKey) error {
+ if idx, exist := pubs.shareIndex[ID]; exist {
+ if !share.publicKey.IsEqual(&pubs.shares[idx].publicKey) {
+ return ErrDuplicatedShare
+ }
+ return nil
+ }
+ pubs.shareIndex[ID] = len(pubs.shares)
+ pubs.shares = append(pubs.shares, *share)
+ return nil
+}
+
+// VerifyPrvShare verifies if the private key shares is valid.
+func (pubs *PublicKeyShares) VerifyPrvShare(ID ID, share *PrivateKey) (
+ bool, error) {
+ var pk bls.PublicKey
+ if err := pk.Set(pubs.masterPublicKey, &ID); err != nil {
+ return false, err
+ }
+ return pk.IsEqual(share.privateKey.GetPublicKey()), nil
+}
+
+// VerifyPubShare verifies if the public key shares is valid.
+func (pubs *PublicKeyShares) VerifyPubShare(ID ID, share *PublicKey) (
+ bool, error) {
+ var pk bls.PublicKey
+ if err := pk.Set(pubs.masterPublicKey, &ID); err != nil {
+ return false, err
+ }
+ return pk.IsEqual(&share.publicKey), nil
+}
+
+// RecoverPublicKey recovers private key from the shares.
+func (pubs *PublicKeyShares) RecoverPublicKey(qualifyIDs IDs) (
+ *PublicKey, error) {
+ var pub PublicKey
+ if len(qualifyIDs) == 0 {
+ return nil, ErrNoIDToRecover
+ }
+ for i, ID := range qualifyIDs {
+ idx, exist := pubs.shareIndex[ID]
+ if !exist {
+ return nil, ErrShareNotFound
+ }
+ if i == 0 {
+ pub.publicKey = pubs.shares[idx].publicKey
+ continue
+ }
+ pub.publicKey.Add(&pubs.shares[idx].publicKey)
+ }
+ return &pub, nil
+}
+
+// MasterKeyBytes returns []byte representation of master public key.
+func (pubs *PublicKeyShares) MasterKeyBytes() []byte {
+ bytes := make([]byte, 0, len(pubs.masterPublicKey)*publicKeyLength)
+ for _, pk := range pubs.masterPublicKey {
+ bytes = append(bytes, pk.Serialize()...)
+ }
+ return bytes
+}
+
+// newPublicKey creates a new PublicKey structure.
+func newPublicKey(prvKey *bls.SecretKey) *PublicKey {
+ return &PublicKey{
+ publicKey: *prvKey.GetPublicKey(),
+ }
+}
+
+// PublicKey returns the public key associate this private key.
+func (prv *PrivateKey) PublicKey() crypto.PublicKey {
+ return prv.publicKey
+}
+
+// Sign calculates a signature.
+func (prv *PrivateKey) Sign(hash common.Hash) (crypto.Signature, error) {
+ msg := string(hash[:])
+ sign := prv.privateKey.Sign(msg)
+ return crypto.Signature(sign.Serialize()), nil
+}
+
+// Bytes returns []byte representation of private key.
+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 {
+ if len(signature) == 0 {
+ return false
+ }
+ var sig bls.Sign
+ if err := sig.Deserialize(signature[:]); err != nil {
+ fmt.Println(err)
+ return false
+ }
+ msg := string(hash[:])
+ return sig.Verify(&pub.publicKey, msg)
+}
+
+// Bytes returns []byte representation of public key.
+func (pub PublicKey) Bytes() []byte {
+ var bytes []byte
+ pub.publicKey.Deserialize(bytes)
+ return bytes
+}
diff --git a/core/crypto/dkg/dkg_test.go b/core/crypto/dkg/dkg_test.go
new file mode 100644
index 0000000..9488dcc
--- /dev/null
+++ b/core/crypto/dkg/dkg_test.go
@@ -0,0 +1,461 @@
+// 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 dkg
+
+import (
+ "encoding/binary"
+ "math/rand"
+ "sort"
+ "sync"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+)
+
+type DKGTestSuite struct {
+ suite.Suite
+}
+
+type member struct {
+ id ID
+ prvShares *PrivateKeyShares
+ pubShares *PublicKeyShares
+ receivedPrvShares *PrivateKeyShares
+ receivedPubShares map[ID]*PublicKeyShares
+}
+
+func (s *DKGTestSuite) genID(k int) IDs {
+ IDs := make(IDs, 0, k)
+ for i := 0; i < k; i++ {
+ id := make([]byte, 8)
+ binary.LittleEndian.PutUint64(id, rand.Uint64())
+ IDs = append(IDs, NewID(id))
+ }
+ return IDs
+}
+
+func (s *DKGTestSuite) sendKey(senders []member, receivers []member) {
+ receiveFrom := make(map[ID][]member)
+ for _, sender := range senders {
+ for _, receiver := range receivers {
+ // Here's the demonstration of DKG protocol. `pubShares` is broadcasted
+ // and all the receiver would save it to the `receivedPubShares`.
+ // Do not optimize the memory usage of this part.
+ receiver.receivedPubShares[sender.id] = sender.pubShares
+ prvShare, ok := sender.prvShares.Share(receiver.id)
+ s.Require().True(ok)
+ pubShare, err := sender.pubShares.Share(receiver.id)
+ s.Require().NoError(err)
+ valid, err := receiver.receivedPubShares[sender.id].
+ VerifyPrvShare(receiver.id, prvShare)
+ s.Require().NoError(err)
+ s.Require().True(valid)
+ valid, err = receiver.receivedPubShares[sender.id].
+ VerifyPubShare(receiver.id, pubShare)
+ s.Require().NoError(err)
+ s.Require().True(valid)
+ receiveFrom[receiver.id] = append(receiveFrom[receiver.id], sender)
+ }
+ }
+ // The received order do not need to be the same.
+ for _, receiver := range receivers {
+ rand.Shuffle(len(senders), func(i, j int) {
+ receiveFrom[receiver.id][i], receiveFrom[receiver.id][j] =
+ receiveFrom[receiver.id][j], receiveFrom[receiver.id][i]
+ })
+ for _, sender := range receiveFrom[receiver.id] {
+ prvShare, ok := sender.prvShares.Share(receiver.id)
+ s.Require().True(ok)
+ err := receiver.receivedPrvShares.AddShare(sender.id, prvShare)
+ s.Require().NoError(err)
+ }
+ }
+}
+
+func (s *DKGTestSuite) signWithQualifyIDs(
+ member member, qualifyIDs IDs, hash common.Hash) PartialSignature {
+ prvKey, err := member.receivedPrvShares.RecoverPrivateKey(qualifyIDs)
+ s.Require().NoError(err)
+ sig, err := prvKey.Sign(hash)
+ s.Require().NoError(err)
+ return PartialSignature(sig)
+}
+
+func (s *DKGTestSuite) verifySigWithQualifyIDs(
+ members []member, qualifyIDs IDs,
+ signer ID, hash common.Hash, sig PartialSignature) bool {
+ membersIdx := make(map[ID]int)
+ for idx, member := range members {
+ membersIdx[member.id] = idx
+ }
+ pubShares := NewEmptyPublicKeyShares()
+ for _, id := range qualifyIDs {
+ idx, exist := membersIdx[id]
+ s.Require().True(exist)
+ member := members[idx]
+ pubShare, err := member.pubShares.Share(signer)
+ s.Require().NoError(err)
+ err = pubShares.AddShare(id, pubShare)
+ s.Require().NoError(err)
+ }
+ pubKey, err := pubShares.RecoverPublicKey(qualifyIDs)
+ s.Require().NoError(err)
+ return pubKey.VerifySignature(hash, crypto.Signature(sig))
+}
+
+func (s *DKGTestSuite) TestVerifyKeyShares() {
+ invalidID := NewID([]byte{0})
+ ids := []ID{NewID([]byte{1}), NewID([]byte{2}), NewID([]byte{3})}
+ members := []member{}
+ for _, id := range ids {
+ members = append(members, member{
+ id: id,
+ receivedPubShares: make(map[ID]*PublicKeyShares),
+ })
+ }
+
+ prvShares, pubShares := NewPrivateKeyShares(2)
+ prvShares.SetParticipants(ids)
+
+ _, ok := prvShares.Share(invalidID)
+ s.False(ok)
+ for _, id := range ids {
+ prvShare, ok := prvShares.Share(id)
+ s.Require().True(ok)
+ valid, err := pubShares.VerifyPrvShare(id, prvShare)
+ s.Require().NoError(err)
+ s.True(valid)
+ pubShare, err := pubShares.Share(id)
+ s.Require().NoError(err)
+ valid, err = pubShares.VerifyPubShare(id, pubShare)
+ s.Require().NoError(err)
+ s.True(valid)
+ }
+
+ // Test of faulty private/public key.
+ invalidPrvShare := NewPrivateKey()
+ valid, err := pubShares.VerifyPrvShare(ids[0], invalidPrvShare)
+ s.Require().NoError(err)
+ s.False(valid)
+
+ invalidPubShare, ok := invalidPrvShare.PublicKey().(PublicKey)
+ s.Require().True(ok)
+ valid, err = pubShares.VerifyPubShare(ids[0], &invalidPubShare)
+ s.Require().NoError(err)
+ s.False(valid)
+
+ // Test of faulty signature.
+ for idx := range members {
+ members[idx].prvShares, members[idx].pubShares = NewPrivateKeyShares(2)
+ members[idx].prvShares.SetParticipants(ids)
+ members[idx].receivedPrvShares = NewEmptyPrivateKeyShares()
+ }
+ s.sendKey(members, members)
+ hash := crypto.Keccak256Hash([]byte("πŸ‘ΎπŸ‘ΎπŸ‘ΎπŸ‘ΎπŸ‘ΎπŸ‘Ύ"))
+ sig, err := invalidPrvShare.Sign(hash)
+ s.Require().NoError(err)
+ psig := PartialSignature(sig)
+ for _, member := range members {
+ valid = s.verifySigWithQualifyIDs(members, ids, member.id, hash, psig)
+ s.False(valid)
+ }
+
+ // Test of faulty group signature.
+ groupPubShares := make([]*PublicKeyShares, 0, len(members))
+ sigs := make([]PartialSignature, 0, len(members))
+ for _, member := range members {
+ sigs = append(sigs, s.signWithQualifyIDs(member, ids, hash))
+ groupPubShares = append(groupPubShares, member.pubShares)
+ }
+ sigs[0] = psig
+ recoverSig, err := RecoverSignature(sigs, ids)
+ s.Require().NoError(err)
+
+ pubKey := RecoverGroupPublicKey(groupPubShares)
+ s.False(pubKey.VerifySignature(hash, recoverSig))
+}
+
+func (s *DKGTestSuite) TestDKGProtocol() {
+ k := 5
+ members := []member{}
+ ids := s.genID((k + 1) * 2)
+ for _, id := range ids {
+ members = append(members, member{
+ id: id,
+ receivedPubShares: make(map[ID]*PublicKeyShares),
+ })
+ }
+
+ for idx := range members {
+ members[idx].prvShares, members[idx].pubShares = NewPrivateKeyShares(k)
+ members[idx].prvShares.SetParticipants(ids)
+ members[idx].receivedPrvShares = NewEmptyPrivateKeyShares()
+ }
+ // Randomly select non-disqualified members.
+ nums := make([]int, len(members))
+ for i := range nums {
+ nums[i] = i
+ }
+ rand.Shuffle(len(nums), func(i, j int) {
+ nums[i], nums[j] = nums[j], nums[i]
+ })
+ nums = nums[:rand.Intn(len(members))]
+ sort.Ints(nums)
+ qualify := make([]member, 0, len(nums))
+ for _, idx := range nums {
+ qualify = append(qualify, members[idx])
+ }
+ // TODO(jimmy-dexon): Remove below line after finishing test of random select.
+ qualify = members
+ // Members are partitioned into two groups.
+ grp1, grp2 := members[:k+1], members[k+1:]
+ collectIDs := func(members []member) IDs {
+ IDs := make(IDs, 0, len(members))
+ for _, member := range members {
+ IDs = append(IDs, member.id)
+ }
+ return IDs
+ }
+ signMsg := func(
+ members []member, qualify []member, hash common.Hash) []PartialSignature {
+ ids := collectIDs(qualify)
+ sigs := make([]PartialSignature, 0, len(members))
+ for _, member := range members {
+ sig := s.signWithQualifyIDs(member, ids, hash)
+ sigs = append(sigs, sig)
+ }
+ return sigs
+ }
+ verifySig := func(
+ members []member,
+ signer []ID, sig []PartialSignature, qualify []member, hash common.Hash) bool {
+ ids := collectIDs(qualify)
+ for i := range sig {
+ if !s.verifySigWithQualifyIDs(members, ids, signer[i], hash, sig[i]) {
+ return false
+ }
+ }
+ return true
+ }
+ s.sendKey(qualify, grp1)
+ s.sendKey(qualify, grp2)
+ hash := crypto.Keccak256Hash([]byte("πŸ›«"))
+ sig1 := signMsg(grp1, qualify, hash)
+ sig2 := signMsg(grp2, qualify, hash)
+ s.True(verifySig(members, collectIDs(grp1), sig1, qualify, hash))
+ s.True(verifySig(members, collectIDs(grp2), sig2, qualify, hash))
+ recoverSig1, err := RecoverSignature(sig1, collectIDs(grp1))
+ s.Require().NoError(err)
+ recoverSig2, err := RecoverSignature(sig2, collectIDs(grp2))
+ s.Require().NoError(err)
+ s.Equal(recoverSig1, recoverSig2)
+
+ pubShares := make([]*PublicKeyShares, 0, len(members))
+ for _, member := range members {
+ pubShares = append(pubShares, member.pubShares)
+ }
+ groupPK := RecoverGroupPublicKey(pubShares)
+ s.True(groupPK.VerifySignature(hash, recoverSig1))
+ s.True(groupPK.VerifySignature(hash, recoverSig2))
+}
+
+func (s *DKGTestSuite) TestSignature() {
+ prvKey := NewPrivateKey()
+ pubKey := prvKey.PublicKey()
+ hash := crypto.Keccak256Hash([]byte("πŸ›«"))
+ sig, err := prvKey.Sign(hash)
+ s.Require().NoError(err)
+ s.True(pubKey.VerifySignature(hash, sig))
+ sig[0]++
+ s.False(pubKey.VerifySignature(hash, sig))
+ sig = crypto.Signature{}
+ s.False(pubKey.VerifySignature(hash, sig))
+}
+
+func TestDKG(t *testing.T) {
+ suite.Run(t, new(DKGTestSuite))
+}
+
+func BenchmarkDKGProtocol(b *testing.B) {
+ t := 33
+ n := 100
+ s := new(DKGTestSuite)
+
+ self := member{}
+ members := make([]*member, n-1)
+ ids := make(IDs, n)
+
+ b.Run("DKG", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ self.id = s.genID(1)[0]
+ self.receivedPubShares = make(map[ID]*PublicKeyShares, n)
+ for idx, id := range s.genID(n - 1) {
+ ids[idx] = id
+ }
+ for idx := range members {
+ members[idx] = &member{
+ id: ids[idx],
+ receivedPubShares: make(map[ID]*PublicKeyShares),
+ receivedPrvShares: NewEmptyPrivateKeyShares(),
+ }
+ }
+ ids[n-1] = self.id
+ prvShares := make(map[ID]*PrivateKey, n)
+ for idx := range members {
+ members[idx].prvShares, members[idx].pubShares = NewPrivateKeyShares(t)
+ members[idx].prvShares.SetParticipants(ids)
+ prvShare, ok := members[idx].prvShares.Share(self.id)
+ if !ok {
+ b.FailNow()
+ }
+ prvShares[members[idx].id] = prvShare
+ }
+
+ b.StartTimer()
+ self.prvShares, self.pubShares = NewPrivateKeyShares(t)
+ self.prvShares.SetParticipants(ids)
+ self.receivedPrvShares = NewEmptyPrivateKeyShares()
+ for _, member := range members {
+ self.receivedPubShares[member.id] = member.pubShares
+ }
+ self.receivedPubShares[self.id] = self.pubShares
+ prvShare, ok := self.prvShares.Share(self.id)
+ if !ok {
+ b.FailNow()
+ }
+ prvShares[self.id] = prvShare
+ for id, prvShare := range prvShares {
+ ok, err := self.receivedPubShares[id].VerifyPrvShare(self.id, prvShare)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ if !ok {
+ b.FailNow()
+ }
+ if err := self.receivedPrvShares.AddShare(id, prvShare); err != nil {
+ b.Fatalf("%v", err)
+ }
+ }
+ if _, err := self.receivedPrvShares.RecoverPrivateKey(ids); err != nil {
+ b.Fatalf("%v", err)
+ }
+ }
+ })
+
+ hash := crypto.Keccak256Hash([]byte("πŸ–"))
+ b.Run("Share-Sign", func(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ b.StopTimer()
+ prvKey, err := self.receivedPrvShares.RecoverPrivateKey(ids)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ b.StartTimer()
+ if _, err := prvKey.Sign(hash); err != nil {
+ b.Fatalf("%v", err)
+ }
+ }
+ })
+
+ sendKey := func(sender *member, receiver *member, b *testing.B) {
+ receiver.receivedPubShares[sender.id] = sender.pubShares
+ prvShare, ok := sender.prvShares.Share(receiver.id)
+ if !ok {
+ b.FailNow()
+ }
+ ok, err := receiver.receivedPubShares[sender.id].VerifyPrvShare(
+ receiver.id, prvShare)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ if !ok {
+ b.FailNow()
+ }
+ if err := receiver.receivedPrvShares.AddShare(sender.id, prvShare); err != nil {
+ b.Fatalf("%v", err)
+ }
+ }
+
+ members = append(members, &self)
+
+ for _, sender := range members {
+ wg := sync.WaitGroup{}
+ for _, receiver := range members {
+ if sender == receiver {
+ continue
+ }
+ wg.Add(1)
+ go func(receiver *member) {
+ sendKey(sender, receiver, b)
+ wg.Done()
+ }(receiver)
+ }
+ wg.Wait()
+ }
+ wg := sync.WaitGroup{}
+ for _, m := range members {
+ wg.Add(1)
+ go func(member *member) {
+ sendKey(member, member, b)
+ wg.Done()
+ }(m)
+ }
+ wg.Wait()
+
+ sign := func(member *member) PartialSignature {
+ prvKey, err := member.receivedPrvShares.RecoverPrivateKey(ids)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ sig, err := prvKey.Sign(hash)
+ if err != nil {
+ b.Fatalf("%v", err)
+ }
+ return PartialSignature(sig)
+ }
+
+ b.Run("Combine-Sign", func(b *testing.B) {
+ b.StopTimer()
+ sigs := make([]PartialSignature, n)
+ for idx, member := range members {
+ sigs[idx] = sign(member)
+ }
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ if _, err := RecoverSignature(sigs, ids); err != nil {
+ b.Fatalf("%v", err)
+ }
+ }
+ })
+
+ b.Run("Recover-GroupPK", func(b *testing.B) {
+ b.StopTimer()
+ pubShares := make([]*PublicKeyShares, 0, len(members))
+ for _, member := range members {
+ pubShares = append(pubShares, member.pubShares)
+ }
+ b.StartTimer()
+ for i := 0; i < b.N; i++ {
+ RecoverGroupPublicKey(pubShares)
+ }
+ })
+}
diff --git a/core/crypto/dkg/utils.go b/core/crypto/dkg/utils.go
new file mode 100644
index 0000000..967973d
--- /dev/null
+++ b/core/crypto/dkg/utils.go
@@ -0,0 +1,69 @@
+// 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 dkg
+
+import (
+ "fmt"
+
+ "github.com/Spiderpowa/bls/ffi/go/bls"
+
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+)
+
+// PartialSignature is a partial signature in DKG+TSIG protocol.
+type PartialSignature crypto.Signature
+
+var (
+ // ErrEmptySignature is reported if the signature is empty.
+ ErrEmptySignature = fmt.Errorf("invalid empty signature")
+)
+
+// RecoverSignature recovers TSIG signature.
+func RecoverSignature(sigs []PartialSignature, signerIDs IDs) (
+ crypto.Signature, error) {
+ blsSigs := make([]bls.Sign, len(sigs))
+ for i, sig := range sigs {
+ if len(sig) == 0 {
+ return nil, ErrEmptySignature
+ }
+ if err := blsSigs[i].Deserialize([]byte(sig)); err != nil {
+ return nil, err
+ }
+ }
+ var recoverSig bls.Sign
+ if err := recoverSig.Recover(blsSigs, []bls.ID(signerIDs)); err != nil {
+ return nil, err
+ }
+ return crypto.Signature(recoverSig.Serialize()), nil
+}
+
+// RecoverGroupPublicKey recovers group public key.
+func RecoverGroupPublicKey(pubShares []*PublicKeyShares) *PublicKey {
+ var pub *PublicKey
+ for _, pubShare := range pubShares {
+ pk0 := pubShare.masterPublicKey[0]
+ if pub == nil {
+ pub = &PublicKey{
+ publicKey: pk0,
+ }
+ } else {
+ pub.publicKey.Add(&pk0)
+ }
+ }
+ return pub
+}
diff --git a/core/crypto/eth/eth.go b/core/crypto/eth/eth.go
new file mode 100644
index 0000000..e82ac29
--- /dev/null
+++ b/core/crypto/eth/eth.go
@@ -0,0 +1,120 @@
+// 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 eth
+
+import (
+ "crypto/ecdsa"
+
+ ethcrypto "github.com/ethereum/go-ethereum/crypto"
+
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+)
+
+// PrivateKey represents a private key structure used in geth and implments
+// Crypto.PrivateKey interface.
+type PrivateKey struct {
+ privateKey ecdsa.PrivateKey
+ publicKey publicKey
+}
+
+// publicKey represents a public key structure used in geth and implements
+// Crypto.PublicKey interface.
+type publicKey struct {
+ publicKey []byte
+}
+
+// NewPrivateKey creates a new PrivateKey structure.
+func NewPrivateKey() (*PrivateKey, error) {
+ key, err := ethcrypto.GenerateKey()
+ if err != nil {
+ return nil, err
+ }
+ return &PrivateKey{
+ privateKey: *key,
+ publicKey: *newPublicKey(key),
+ }, nil
+}
+
+// newPublicKey creates a new PublicKey structure.
+func newPublicKey(prvKey *ecdsa.PrivateKey) *publicKey {
+ return &publicKey{
+ publicKey: ethcrypto.CompressPubkey(&prvKey.PublicKey),
+ }
+}
+
+// decompressPubkey parses a public key in the 33-byte compressed format.
+func decompressPubkey(pubkey []byte) (publicKey, error) {
+ _, err := ethcrypto.DecompressPubkey(pubkey)
+ return publicKey{
+ publicKey: pubkey,
+ }, err
+}
+
+// PublicKey returns the public key associate this private key.
+func (prv *PrivateKey) PublicKey() crypto.PublicKey {
+ return prv.publicKey
+}
+
+// Sign calculates an ECDSA signature.
+//
+// This function is susceptible to chosen plaintext attacks that can leak
+// information about the private key that is used for signing. Callers must
+// be aware that the given hash cannot be chosen by an adversery. Common
+// solution is to hash any input before calculating the signature.
+//
+// The produced signature is in the [R || S || V] format where V is 0 or 1.
+func (prv *PrivateKey) Sign(hash common.Hash) (
+ sig crypto.Signature, err error) {
+ s, err := ethcrypto.Sign(hash[:], &prv.privateKey)
+ sig = crypto.Signature(s)
+ return
+}
+
+// VerifySignature checks that the given public key created signature over hash.
+// The public key should be in compressed (33 bytes) or uncompressed (65 bytes)
+// format.
+// The signature should have the 64 byte [R || S] format.
+func (pub publicKey) VerifySignature(
+ hash common.Hash, signature crypto.Signature) bool {
+ if len(signature) == 65 {
+ // The last byte is for ecrecover.
+ signature = signature[:64]
+ }
+ return ethcrypto.VerifySignature(pub.publicKey, hash[:], signature)
+}
+
+// Compress encodes a public key to the 33-byte compressed format.
+func (pub publicKey) Compress() []byte {
+ return pub.publicKey
+}
+
+// Bytes returns the []byte representation of public key.
+func (pub publicKey) Bytes() []byte {
+ return pub.Compress()
+}
+
+// SigToPub returns the PublicKey that created the given signature.
+func SigToPub(
+ hash common.Hash, signature crypto.Signature) (crypto.PublicKey, error) {
+ key, err := ethcrypto.SigToPub(hash[:], signature[:])
+ if err != nil {
+ return publicKey{}, err
+ }
+ return publicKey{publicKey: ethcrypto.CompressPubkey(key)}, nil
+}
diff --git a/core/crypto/eth/eth_test.go b/core/crypto/eth/eth_test.go
new file mode 100644
index 0000000..acda1a8
--- /dev/null
+++ b/core/crypto/eth/eth_test.go
@@ -0,0 +1,93 @@
+// 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 eth
+
+import (
+ "testing"
+
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+ "github.com/stretchr/testify/suite"
+)
+
+type ETHCryptoTestSuite struct {
+ suite.Suite
+}
+
+func (s *ETHCryptoTestSuite) TestSignature() {
+ prv1, err := NewPrivateKey()
+ s.Require().Nil(err)
+ hash1 := common.NewRandomHash()
+ hash2 := common.NewRandomHash()
+
+ // Test that same private key should produce same signature.
+ sig11, err := prv1.Sign(hash1)
+ s.Require().Nil(err)
+ sig112, err := prv1.Sign(hash1)
+ s.Require().Nil(err)
+ s.Equal(sig11, sig112)
+
+ // Test that different private key should produce different signature.
+ prv2, err := NewPrivateKey()
+ s.Require().Nil(err)
+ sig21, err := prv2.Sign(hash1)
+ s.Require().Nil(err)
+ s.NotEqual(sig11, sig21)
+
+ // Test that different hash should produce different signature.
+ sig12, err := prv1.Sign(hash2)
+ s.Require().Nil(err)
+ s.NotEqual(sig11, sig12)
+
+ // Test VerifySignature with correct public key.
+ pub1, ok := prv1.PublicKey().(publicKey)
+ s.Require().True(ok)
+ s.True(pub1.VerifySignature(hash1, sig11))
+
+ // Test VerifySignature with wrong hash.
+ s.False(pub1.VerifySignature(hash2, sig11))
+ // Test VerifySignature with wrong signature.
+ s.False(pub1.VerifySignature(hash1, sig21))
+ // Test VerifySignature with wrong public key.
+ pub2 := prv2.PublicKey()
+ s.False(pub2.VerifySignature(hash1, sig11))
+
+ // Test compress and decompress of public key.
+ compressPub1 := pub1.Compress()
+ decompressPub1, err := decompressPubkey(compressPub1)
+ s.Require().Nil(err)
+ s.Equal(pub1, decompressPub1)
+ s.True(decompressPub1.VerifySignature(hash1, sig11))
+}
+
+func (s *ETHCryptoTestSuite) TestSigToPub() {
+ prv, err := NewPrivateKey()
+ s.Require().Nil(err)
+ data := "DEXON is infinitely scalable and low-latency."
+ hash := crypto.Keccak256Hash([]byte(data))
+ sigmsg, err := prv.Sign(hash)
+ s.Require().Nil(err)
+
+ pubkey, err := SigToPub(hash, sigmsg)
+ s.Require().Nil(err)
+ s.Equal(pubkey, prv.PublicKey())
+}
+
+func TestCrypto(t *testing.T) {
+ suite.Run(t, new(ETHCryptoTestSuite))
+}
diff --git a/core/crypto/interfaces.go b/core/crypto/interfaces.go
new file mode 100644
index 0000000..ac2754d
--- /dev/null
+++ b/core/crypto/interfaces.go
@@ -0,0 +1,45 @@
+// 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 crypto
+
+import (
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+)
+
+// Signature is the basic signature type in DEXON.
+type Signature []byte
+
+// PrivateKey describes the asymmetric cryptography interface that interacts
+// with the private key.
+type PrivateKey interface {
+ // PublicKey returns the public key associate this private key.
+ PublicKey() PublicKey
+
+ // Sign calculates a signature.
+ Sign(hash common.Hash) (Signature, error)
+}
+
+// PublicKey describes the asymmetric cryptography interface that interacts
+// with the public key.
+type PublicKey interface {
+ // VerifySignature checks that the given public key created signature over hash.
+ VerifySignature(hash common.Hash, signature Signature) bool
+
+ // Bytes returns the []byte representation of public key.
+ Bytes() []byte
+}
diff --git a/core/crypto/utils.go b/core/crypto/utils.go
new file mode 100644
index 0000000..07a8b2b
--- /dev/null
+++ b/core/crypto/utils.go
@@ -0,0 +1,41 @@
+// 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 crypto
+
+import (
+ "encoding/hex"
+
+ "github.com/ethereum/go-ethereum/crypto"
+
+ "github.com/dexon-foundation/dexon-consensus-core/common"
+)
+
+// Keccak256Hash calculates and returns the Keccak256 hash of the input data,
+// converting it to an internal Hash data structure.
+func Keccak256Hash(data ...[]byte) (h common.Hash) {
+ return common.Hash(crypto.Keccak256Hash(data...))
+}
+
+// Clone returns a deep copy of a signature.
+func (sig Signature) Clone() Signature {
+ return append(Signature{}, sig...)
+}
+
+func (sig Signature) String() string {
+ return hex.EncodeToString([]byte(sig[:]))
+}
diff --git a/core/crypto/utils_test.go b/core/crypto/utils_test.go
new file mode 100644
index 0000000..977027a
--- /dev/null
+++ b/core/crypto/utils_test.go
@@ -0,0 +1,52 @@
+// 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 crypto
+
+import (
+ "encoding/hex"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+)
+
+type CryptoTestSuite struct {
+ suite.Suite
+}
+
+func (s *CryptoTestSuite) TestHash() {
+ cases := []struct {
+ input string
+ output string
+ }{
+ {"DEXON ROCKS!",
+ "1a3f3a424aaa464e51b693585bba3a0c439d5f1ad3b5868e46d9f830225983bd"},
+ {"Dexon Foundation",
+ "25ed4237aa978bfe706cc11c7a46a95de1a46302faea7ff6e900b03fa2b7b480"},
+ {"INFINITELY SCALABLE AND LOW-LATENCY",
+ "ed3384c58a434fbc0bc887a85659eddf997e7da978ab66565ac865f995b77cf1"},
+ }
+ for _, testcase := range cases {
+ hash := Keccak256Hash([]byte(testcase.input))
+ output := hex.EncodeToString(hash[:])
+ s.Equal(testcase.output, output)
+ }
+}
+
+func TestCrypto(t *testing.T) {
+ suite.Run(t, new(CryptoTestSuite))
+}
diff --git a/core/crypto_test.go b/core/crypto_test.go
index 6c807da..4ff4606 100644
--- a/core/crypto_test.go
+++ b/core/crypto_test.go
@@ -22,10 +22,10 @@ import (
"time"
"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/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
"github.com/stretchr/testify/suite"
)
diff --git a/core/dkg-tsig-protocol.go b/core/dkg-tsig-protocol.go
index 0f5cb0b..a69cdd2 100644
--- a/core/dkg-tsig-protocol.go
+++ b/core/dkg-tsig-protocol.go
@@ -21,9 +21,9 @@ 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"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
)
// Errors for dkg module.
diff --git a/core/dkg-tsig-protocol_test.go b/core/dkg-tsig-protocol_test.go
index 0c938f7..97d9d34 100644
--- a/core/dkg-tsig-protocol_test.go
+++ b/core/dkg-tsig-protocol_test.go
@@ -23,11 +23,11 @@ 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/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/test"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
)
type DKGTSIGProtocolTestSuite struct {
diff --git a/core/interfaces.go b/core/interfaces.go
index 7f6ff2b..eebf8ff 100644
--- a/core/interfaces.go
+++ b/core/interfaces.go
@@ -21,8 +21,8 @@ import (
"time"
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// Application describes the application interface that interacts with DEXON
@@ -56,7 +56,7 @@ type Debug interface {
// TotalOrderingDelivered is called when the total ordering algorithm deliver
// a set of block.
- TotalOrderingDelivered(blockHashes common.Hashes, early bool)
+ TotalOrderingDelivered(common.Hashes, bool)
}
// Network describs the network interface that interacts with DEXON consensus
@@ -101,7 +101,7 @@ type Governance interface {
ProposeThresholdSignature(round uint64, signature crypto.Signature)
// Get a ThresholdSignature of round.
- GetThresholdSignature(round uint64) (sig crypto.Signature, exist bool)
+ GetThresholdSignature(round uint64) (crypto.Signature, bool)
//// DKG-related methods.
@@ -126,33 +126,3 @@ type Ticker interface {
// Stop the ticker.
Stop()
}
-
-// Signer defines a role to sign data.
-type Signer interface {
- // SignBlock signs a block.
- SignBlock(b *types.Block) error
-
- // SignVote signs a vote.
- SignVote(v *types.Vote) error
-
- // SignCRS sign a block's CRS signature.
- SignCRS(b *types.Block, crs common.Hash) error
-}
-
-// CryptoVerifier defines a role to verify data in crypto's way.
-type CryptoVerifier interface {
- // VerifyBlock verifies if a block is properly signed or not.
- VerifyBlock(b *types.Block) (ok bool, err error)
-
- // VerifyVote verfies if a vote is properly signed or not.
- VerifyVote(v *types.Vote) (ok bool, err error)
-
- // VerifyCRS verifies if a CRS signature of one block is valid or not.
- VerifyCRS(b *types.Block, crs common.Hash) (ok bool, err error)
-}
-
-// Authenticator verify/sign who own the data.
-type Authenticator interface {
- Signer
- CryptoVerifier
-}
diff --git a/core/leader-selector.go b/core/leader-selector.go
index ce5134a..8a20055 100644
--- a/core/leader-selector.go
+++ b/core/leader-selector.go
@@ -22,8 +22,8 @@ import (
"math/big"
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// Errors for leader module.
diff --git a/core/leader-selector_test.go b/core/leader-selector_test.go
index 211680d..02562ba 100644
--- a/core/leader-selector_test.go
+++ b/core/leader-selector_test.go
@@ -23,8 +23,8 @@ import (
"github.com/stretchr/testify/suite"
"github.com/dexon-foundation/dexon-consensus-core/common"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
)
type LeaderSelectorTestSuite struct {
diff --git a/core/shard.go b/core/shard.go
index 270b070..28b64f1 100644
--- a/core/shard.go
+++ b/core/shard.go
@@ -23,8 +23,8 @@ import (
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
// Shard represents a unit to produce a global ordering from multiple chains.
diff --git a/core/shard_test.go b/core/shard_test.go
index 42c8d7b..2a9016b 100644
--- a/core/shard_test.go
+++ b/core/shard_test.go
@@ -23,9 +23,9 @@ import (
"time"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/test"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
"github.com/stretchr/testify/suite"
)
diff --git a/core/test/blocks-generator.go b/core/test/blocks-generator.go
index 4038450..eacc436 100644
--- a/core/test/blocks-generator.go
+++ b/core/test/blocks-generator.go
@@ -25,9 +25,9 @@ import (
"github.com/dexon-foundation/dexon-consensus-core/common"
"github.com/dexon-foundation/dexon-consensus-core/core/blockdb"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
)
// TODO(mission): blocks generator should generate blocks based on chain,
diff --git a/core/test/governance.go b/core/test/governance.go
index 137662f..81b71e5 100644
--- a/core/test/governance.go
+++ b/core/test/governance.go
@@ -22,9 +22,9 @@ import (
"sync"
"time"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/eth"
"github.com/dexon-foundation/dexon-consensus-core/core/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/eth"
)
var (
diff --git a/core/types/block.go b/core/types/block.go
index ddd0abd..e4b4466 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -27,7 +27,7 @@ import (
"time"
"github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
)
var (
diff --git a/core/types/dkg.go b/core/types/dkg.go
index a21c983..16737c6 100644
--- a/core/types/dkg.go
+++ b/core/types/dkg.go
@@ -20,8 +20,8 @@ package types
import (
"fmt"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
- "github.com/dexon-foundation/dexon-consensus-core/crypto/dkg"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto/dkg"
)
// DKGPrivateShare describe a secret share in DKG protocol.
diff --git a/core/types/node.go b/core/types/node.go
index 8a856de..177e407 100644
--- a/core/types/node.go
+++ b/core/types/node.go
@@ -21,7 +21,7 @@ import (
"bytes"
"github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
)
// NodeID is the ID type for nodes.
diff --git a/core/types/vote.go b/core/types/vote.go
index e92aa67..294bc74 100644
--- a/core/types/vote.go
+++ b/core/types/vote.go
@@ -21,7 +21,7 @@ import (
"fmt"
"github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
)
// VoteType is the type of vote.
diff --git a/core/types/witness.go b/core/types/witness.go
index 46aa1cc..3c455d8 100644
--- a/core/types/witness.go
+++ b/core/types/witness.go
@@ -23,7 +23,7 @@ import (
"time"
"github.com/dexon-foundation/dexon-consensus-core/common"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
+ "github.com/dexon-foundation/dexon-consensus-core/core/crypto"
)
// WitnessAck represents the acking to the compaction chain.
diff --git a/core/utils.go b/core/utils.go
index 30456ef..3c1d211 100644
--- a/core/utils.go
+++ b/core/utils.go
@@ -25,8 +25,8 @@ import (
"time"
"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/types"
- "github.com/dexon-foundation/dexon-consensus-core/crypto"
)
var (