aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJimmy Hu <jimmy.hu@dexon.org>2019-04-11 16:45:38 +0800
committerGitHub <noreply@github.com>2019-04-11 16:45:38 +0800
commit5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63 (patch)
treebdbecd8695ed5225aa24f56b6a3c0acc7244f68f
parent269fed574986331e07bf931b2c9b1a495c40f8ac (diff)
downloaddexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.tar
dexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.tar.gz
dexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.tar.bz2
dexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.tar.lz
dexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.tar.xz
dexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.tar.zst
dexon-consensus-5b0aad05d7ccc1dabedfd1f3bfc0d584db849e63.zip
core: change CRSSignature with bls (#563)
-rw-r--r--core/agreement-mgr.go20
-rw-r--r--core/agreement-state_test.go2
-rw-r--r--core/agreement.go2
-rw-r--r--core/agreement_test.go72
-rw-r--r--core/consensus.go8
-rw-r--r--core/leader-selector.go20
-rw-r--r--core/leader-selector_test.go2
-rw-r--r--core/utils/crypto.go23
-rw-r--r--core/utils/crypto_test.go11
-rw-r--r--core/utils/signer.go23
-rw-r--r--core/utils/signer_test.go6
11 files changed, 104 insertions, 85 deletions
diff --git a/core/agreement-mgr.go b/core/agreement-mgr.go
index af0adf2..ac28955 100644
--- a/core/agreement-mgr.go
+++ b/core/agreement-mgr.go
@@ -36,17 +36,33 @@ var (
ErrRoundOutOfRange = errors.New("round out of range")
ErrInvalidBlock = errors.New("invalid block")
ErrNoValidLeader = errors.New("no valid leader")
+ ErrIncorrectCRSSignature = errors.New("incorrect CRS signature")
+ ErrBlockTooOld = errors.New("block too old")
)
const maxResultCache = 100
// genValidLeader generate a validLeader function for agreement modules.
func genValidLeader(
- mgr *agreementMgr) func(*types.Block) (bool, error) {
- return func(block *types.Block) (bool, error) {
+ mgr *agreementMgr) validLeaderFn {
+ return func(block *types.Block, crs common.Hash) (bool, error) {
if block.Timestamp.After(time.Now()) {
return false, nil
}
+ if block.Position.Round >= DKGDelayRound {
+ if mgr.recv.npks == nil {
+ return false, nil
+ }
+ if block.Position.Round > mgr.recv.npks.Round {
+ return false, nil
+ }
+ if block.Position.Round < mgr.recv.npks.Round {
+ return false, ErrBlockTooOld
+ }
+ }
+ if !utils.VerifyCRSSignature(block, crs, mgr.recv.npks) {
+ return false, ErrIncorrectCRSSignature
+ }
if err := mgr.bcModule.sanityCheck(block); err != nil {
if err == ErrRetrySanityCheckLater {
return false, nil
diff --git a/core/agreement-state_test.go b/core/agreement-state_test.go
index cbcbc63..43631ea 100644
--- a/core/agreement-state_test.go
+++ b/core/agreement-state_test.go
@@ -103,7 +103,7 @@ func (s *AgreementStateTestSuite) SetupTest() {
func (s *AgreementStateTestSuite) newAgreement(numNode int) *agreement {
logger := &common.NullLogger{}
- leader := newLeaderSelector(func(*types.Block) (bool, error) {
+ leader := newLeaderSelector(func(*types.Block, common.Hash) (bool, error) {
return true, nil
}, logger)
notarySet := make(map[types.NodeID]struct{})
diff --git a/core/agreement.go b/core/agreement.go
index b122a4d..a6fb074 100644
--- a/core/agreement.go
+++ b/core/agreement.go
@@ -690,7 +690,7 @@ func (a *agreement) processBlock(block *types.Block) error {
if !exist {
return true
}
- ok, err := a.data.leader.validLeader(block)
+ ok, err := a.data.leader.validLeader(block, a.data.leader.hashCRS)
if err != nil {
fmt.Println("Error checking validLeader for Fast BA",
"error", err, "block", block)
diff --git a/core/agreement_test.go b/core/agreement_test.go
index 9afc0f2..0854c7e 100644
--- a/core/agreement_test.go
+++ b/core/agreement_test.go
@@ -95,17 +95,18 @@ func (s *AgreementTestSuite) proposeBlock(
type AgreementTestSuite struct {
suite.Suite
- ID types.NodeID
- signers map[types.NodeID]*utils.Signer
- voteChan chan *types.Vote
- blockChan chan common.Hash
- confirmChan chan common.Hash
- forkVoteChan chan common.Hash
- forkBlockChan chan common.Hash
- block map[common.Hash]*types.Block
- pulledBlocks map[common.Hash]struct{}
- agreement []*agreement
- agreementID types.Position
+ ID types.NodeID
+ signers map[types.NodeID]*utils.Signer
+ voteChan chan *types.Vote
+ blockChan chan common.Hash
+ confirmChan chan common.Hash
+ forkVoteChan chan common.Hash
+ forkBlockChan chan common.Hash
+ block map[common.Hash]*types.Block
+ pulledBlocks map[common.Hash]struct{}
+ agreement []*agreement
+ agreementID types.Position
+ defaultValidLeader validLeaderFn
}
func (s *AgreementTestSuite) SetupTest() {
@@ -123,6 +124,9 @@ func (s *AgreementTestSuite) SetupTest() {
s.block = make(map[common.Hash]*types.Block)
s.pulledBlocks = make(map[common.Hash]struct{})
s.agreementID = types.Position{Height: types.GenesisHeight}
+ s.defaultValidLeader = func(*types.Block, common.Hash) (bool, error) {
+ return true, nil
+ }
}
func (s *AgreementTestSuite) newAgreement(
@@ -183,9 +187,7 @@ func (s *AgreementTestSuite) prepareVote(
}
func (s *AgreementTestSuite) TestSimpleConfirm() {
- a, leaderNode := s.newAgreement(4, 0, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, leaderNode := s.newAgreement(4, 0, s.defaultValidLeader)
s.Require().Equal(s.ID, leaderNode)
// FastState
a.nextState()
@@ -243,9 +245,7 @@ func (s *AgreementTestSuite) TestSimpleConfirm() {
}
func (s *AgreementTestSuite) TestPartitionOnCommitVote() {
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
// FastState
a.nextState()
// FastVoteState
@@ -287,9 +287,7 @@ func (s *AgreementTestSuite) TestPartitionOnCommitVote() {
}
func (s *AgreementTestSuite) TestFastConfirmLeader() {
- a, leaderNode := s.newAgreement(4, 0, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, leaderNode := s.newAgreement(4, 0, s.defaultValidLeader)
s.Require().Equal(s.ID, leaderNode)
// FastState
a.nextState()
@@ -327,9 +325,7 @@ func (s *AgreementTestSuite) TestFastConfirmLeader() {
}
func (s *AgreementTestSuite) TestFastConfirmNonLeader() {
- a, leaderNode := s.newAgreement(4, 1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, leaderNode := s.newAgreement(4, 1, s.defaultValidLeader)
s.Require().NotEqual(s.ID, leaderNode)
// FastState
a.nextState()
@@ -367,9 +363,7 @@ func (s *AgreementTestSuite) TestFastConfirmNonLeader() {
func (s *AgreementTestSuite) TestFastForwardCond1() {
votes := 0
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
a.data.lockIter = 1
a.data.period = 3
hash := common.NewRandomHash()
@@ -423,9 +417,7 @@ func (s *AgreementTestSuite) TestFastForwardCond1() {
func (s *AgreementTestSuite) TestFastForwardCond2() {
votes := 0
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
a.data.period = 1
done := a.done()
hash := common.NewRandomHash()
@@ -468,9 +460,7 @@ func (s *AgreementTestSuite) TestFastForwardCond2() {
func (s *AgreementTestSuite) TestFastForwardCond3() {
numVotes := 0
votes := []*types.Vote{}
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
a.data.period = 1
done := a.done()
for nID := range a.notarySet {
@@ -503,9 +493,7 @@ func (s *AgreementTestSuite) TestFastForwardCond3() {
func (s *AgreementTestSuite) TestDecide() {
votes := 0
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
a.data.period = 5
// No decide if com-vote on SKIP.
@@ -533,9 +521,7 @@ func (s *AgreementTestSuite) TestDecide() {
}
func (s *AgreementTestSuite) TestForkVote() {
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
a.data.period = 2
for nID := range a.notarySet {
v01 := s.prepareVote(nID, types.VotePreCom, common.NewRandomHash(), 2)
@@ -549,9 +535,7 @@ func (s *AgreementTestSuite) TestForkVote() {
}
func (s *AgreementTestSuite) TestForkBlock() {
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
for nID := range a.notarySet {
b01 := s.proposeBlock(nID, a.data.leader.hashCRS)
b02 := s.proposeBlock(nID, a.data.leader.hashCRS)
@@ -563,7 +547,7 @@ func (s *AgreementTestSuite) TestForkBlock() {
}
func (s *AgreementTestSuite) TestFindBlockInPendingSet() {
- a, leaderNode := s.newAgreement(4, 0, func(*types.Block) (bool, error) {
+ a, leaderNode := s.newAgreement(4, 0, func(*types.Block, common.Hash) (bool, error) {
return false, nil
})
block := s.proposeBlock(leaderNode, a.data.leader.hashCRS)
@@ -579,9 +563,7 @@ func (s *AgreementTestSuite) TestFindBlockInPendingSet() {
}
func (s *AgreementTestSuite) TestConfirmWithBlock() {
- a, _ := s.newAgreement(4, -1, func(*types.Block) (bool, error) {
- return true, nil
- })
+ a, _ := s.newAgreement(4, -1, s.defaultValidLeader)
block := &types.Block{
Hash: common.NewRandomHash(),
Position: a.agreementID(),
diff --git a/core/consensus.go b/core/consensus.go
index 966c70a..49f2db1 100644
--- a/core/consensus.go
+++ b/core/consensus.go
@@ -656,6 +656,14 @@ func newConsensusForRound(
}
cfgModule := newConfigurationChain(ID, recv, gov, nodeSetCache, db, logger)
recv.cfgModule = cfgModule
+ signer.SetBLSSigner(
+ func(round uint64, hash common.Hash) (crypto.Signature, error) {
+ _, signer, err := cfgModule.getDKGInfo(round, false)
+ if err != nil {
+ return crypto.Signature{}, err
+ }
+ return crypto.Signature(signer.sign(hash)), nil
+ })
appModule := app
if usingNonBlocking {
appModule = newNonBlocking(app, debugApp)
diff --git a/core/leader-selector.go b/core/leader-selector.go
index 8c06328..91b2e99 100644
--- a/core/leader-selector.go
+++ b/core/leader-selector.go
@@ -18,22 +18,15 @@
package core
import (
- "fmt"
"math/big"
"sync"
"github.com/dexon-foundation/dexon-consensus/common"
"github.com/dexon-foundation/dexon-consensus/core/crypto"
"github.com/dexon-foundation/dexon-consensus/core/types"
- "github.com/dexon-foundation/dexon-consensus/core/utils"
)
-// Errors for leader module.
-var (
- ErrIncorrectCRSSignature = fmt.Errorf("incorrect CRS signature")
-)
-
-type validLeaderFn func(*types.Block) (bool, error)
+type validLeaderFn func(block *types.Block, crs common.Hash) (bool, error)
// Some constant value.
var (
@@ -105,7 +98,7 @@ func (l *leaderSelector) leaderBlockHash() common.Hash {
if !ok {
continue
}
- ok, err := l.validLeader(b)
+ ok, err := l.validLeader(b, l.hashCRS)
if err != nil {
l.logger.Error("Error checking validLeader", "error", err, "block", b)
delete(l.pendingBlocks, b.Hash)
@@ -120,20 +113,13 @@ func (l *leaderSelector) leaderBlockHash() common.Hash {
}
func (l *leaderSelector) processBlock(block *types.Block) error {
- ok, err := utils.VerifyCRSSignature(block, l.hashCRS)
- if err != nil {
- return err
- }
- if !ok {
- return ErrIncorrectCRSSignature
- }
l.lock.Lock()
defer l.lock.Unlock()
ok, dist := l.potentialLeader(block)
if !ok {
return nil
}
- ok, err = l.validLeader(block)
+ ok, err := l.validLeader(block, l.hashCRS)
if err != nil {
return err
}
diff --git a/core/leader-selector_test.go b/core/leader-selector_test.go
index 9e09279..4738663 100644
--- a/core/leader-selector_test.go
+++ b/core/leader-selector_test.go
@@ -38,7 +38,7 @@ type LeaderSelectorTestSuite struct {
func (s *LeaderSelectorTestSuite) SetupTest() {
s.mockValidLeaderDefault = true
s.mockValidLeaderDB = make(map[common.Hash]bool)
- s.mockValidLeader = func(b *types.Block) (bool, error) {
+ s.mockValidLeader = func(b *types.Block, _ common.Hash) (bool, error) {
if ret, exist := s.mockValidLeaderDB[b.Hash]; exist {
return ret, nil
}
diff --git a/core/utils/crypto.go b/core/utils/crypto.go
index 7fd3a77..496944d 100644
--- a/core/utils/crypto.go
+++ b/core/utils/crypto.go
@@ -18,6 +18,7 @@
package utils
import (
+ "bytes"
"encoding/binary"
"github.com/dexon-foundation/dexon-consensus/common"
@@ -122,21 +123,27 @@ func VerifyVoteSignature(vote *types.Vote) (bool, error) {
func hashCRS(block *types.Block, crs common.Hash) common.Hash {
hashPos := HashPosition(block.Position)
+ if block.Position.Round < dkgDelayRound {
+ return crypto.Keccak256Hash(crs[:], hashPos[:], block.ProposerID.Hash[:])
+ }
return crypto.Keccak256Hash(crs[:], hashPos[:])
}
// VerifyCRSSignature verifies the CRS signature of types.Block.
-func VerifyCRSSignature(block *types.Block, crs common.Hash) (
- bool, error) {
+func VerifyCRSSignature(
+ block *types.Block, crs common.Hash, npks *typesDKG.NodePublicKeys) bool {
hash := hashCRS(block, crs)
- pubKey, err := crypto.SigToPub(hash, block.CRSSignature)
- if err != nil {
- return false, err
+ if block.Position.Round < dkgDelayRound {
+ return bytes.Compare(block.CRSSignature.Signature[:], hash[:]) == 0
}
- if block.ProposerID != types.NewNodeID(pubKey) {
- return false, nil
+ if npks == nil {
+ return false
}
- return true, nil
+ pubKey, exist := npks.PublicKeys[block.ProposerID]
+ if !exist {
+ return false
+ }
+ return pubKey.VerifySignature(hash, block.CRSSignature)
}
// HashPosition generates hash of a types.Position.
diff --git a/core/utils/crypto_test.go b/core/utils/crypto_test.go
index 5dfd82b..24ea68e 100644
--- a/core/utils/crypto_test.go
+++ b/core/utils/crypto_test.go
@@ -127,6 +127,7 @@ func (s *CryptoTestSuite) TestVoteSignature() {
}
func (s *CryptoTestSuite) TestCRSSignature() {
+ dkgDelayRound = 1
crs := common.NewRandomHash()
prv, err := ecdsa.NewPrivateKey()
s.Require().NoError(err)
@@ -135,14 +136,12 @@ func (s *CryptoTestSuite) TestCRSSignature() {
block := &types.Block{
ProposerID: nID,
}
- block.CRSSignature, err = prv.Sign(hashCRS(block, crs))
- s.Require().NoError(err)
- ok, err := VerifyCRSSignature(block, crs)
- s.Require().NoError(err)
+ hash := hashCRS(block, crs)
+ block.CRSSignature.Signature = hash[:]
+ ok := VerifyCRSSignature(block, crs, nil)
s.True(ok)
block.Position.Height++
- ok, err = VerifyCRSSignature(block, crs)
- s.Require().NoError(err)
+ ok = VerifyCRSSignature(block, crs, nil)
s.False(ok)
}
diff --git a/core/utils/signer.go b/core/utils/signer.go
index 7694dab..9904410 100644
--- a/core/utils/signer.go
+++ b/core/utils/signer.go
@@ -31,13 +31,17 @@ var (
ErrInvalidProposerID = errors.New("invalid proposer id")
ErrIncorrectHash = errors.New("hash of block is incorrect")
ErrIncorrectSignature = errors.New("signature of block is incorrect")
+ ErrNoBLSSigner = errors.New("bls signer not set")
)
+type blsSigner func(round uint64, hash common.Hash) (crypto.Signature, error)
+
// Signer signs a segment of data.
type Signer struct {
prvKey crypto.PrivateKey
pubKey crypto.PublicKey
proposerID types.NodeID
+ blsSign blsSigner
}
// NewSigner constructs an Signer instance.
@@ -50,6 +54,11 @@ func NewSigner(prvKey crypto.PrivateKey) (s *Signer) {
return
}
+// SetBLSSigner for signing CRSSignature
+func (s *Signer) SetBLSSigner(signer blsSigner) {
+ s.blsSign = signer
+}
+
// SignBlock signs a types.Block.
func (s *Signer) SignBlock(b *types.Block) (err error) {
b.ProposerID = s.proposerID
@@ -76,7 +85,19 @@ func (s *Signer) SignCRS(b *types.Block, crs common.Hash) (err error) {
err = ErrInvalidProposerID
return
}
- b.CRSSignature, err = s.prvKey.Sign(hashCRS(b, crs))
+ if b.Position.Round < dkgDelayRound {
+ hash := hashCRS(b, crs)
+ b.CRSSignature = crypto.Signature{
+ Type: "bls",
+ Signature: hash[:],
+ }
+ return
+ }
+ if s.blsSign == nil {
+ err = ErrNoBLSSigner
+ return
+ }
+ b.CRSSignature, err = s.blsSign(b.Position.Round, hashCRS(b, crs))
return
}
diff --git a/core/utils/signer_test.go b/core/utils/signer_test.go
index 3905352..0ee1c30 100644
--- a/core/utils/signer_test.go
+++ b/core/utils/signer_test.go
@@ -66,11 +66,12 @@ func (s *SignerTestSuite) TestVote() {
}
func (s *SignerTestSuite) TestCRS() {
+ dkgDelayRound = 1
k := s.setupSigner()
b := &types.Block{
ParentHash: common.NewRandomHash(),
Position: types.Position{
- Round: 8,
+ Round: 0,
Height: 9,
},
Timestamp: time.Now().UTC(),
@@ -80,9 +81,8 @@ func (s *SignerTestSuite) TestCRS() {
// Hash block before hash CRS.
s.NoError(k.SignBlock(b))
s.NoError(k.SignCRS(b, crs))
- ok, err := VerifyCRSSignature(b, crs)
+ ok := VerifyCRSSignature(b, crs, nil)
s.True(ok)
- s.NoError(err)
}
func TestSigner(t *testing.T) {