Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrated multikey in consensus #4463

Merged
merged 5 commits into from
Sep 20, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 7 additions & 31 deletions consensus/broadcast/commonMessenger.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package broadcast

import (
"bytes"
"strings"
"time"

Expand Down Expand Up @@ -40,28 +39,25 @@ type commonMessenger struct {
marshalizer marshal.Marshalizer
hasher hashing.Hasher
messenger consensus.P2PMessenger
privateKey crypto.PrivateKey
shardCoordinator sharding.Coordinator
peerSignatureHandler crypto.PeerSignatureHandler
delayedBlockBroadcaster delayedBroadcaster
keysHolder consensus.KeysHolder
currentPublicKeyBytes []byte
keysHandler consensus.KeysHandler
}

// CommonMessengerArgs holds the arguments for creating commonMessenger instance
type CommonMessengerArgs struct {
Marshalizer marshal.Marshalizer
Hasher hashing.Hasher
Messenger consensus.P2PMessenger
PrivateKey crypto.PrivateKey
ShardCoordinator sharding.Coordinator
PeerSignatureHandler crypto.PeerSignatureHandler
HeadersSubscriber consensus.HeadersPoolSubscriber
InterceptorsContainer process.InterceptorsContainer
MaxDelayCacheSize uint32
MaxValidatorDelayCacheSize uint32
AlarmScheduler core.TimersScheduler
KeysHolder consensus.KeysHolder
KeysHandler consensus.KeysHandler
}

func checkCommonMessengerNilParameters(
Expand All @@ -76,9 +72,6 @@ func checkCommonMessengerNilParameters(
if check.IfNil(args.Messenger) {
return spos.ErrNilMessenger
}
if check.IfNil(args.PrivateKey) {
return spos.ErrNilPrivateKey
}
if check.IfNil(args.ShardCoordinator) {
return spos.ErrNilShardCoordinator
}
Expand All @@ -97,16 +90,16 @@ func checkCommonMessengerNilParameters(
if args.MaxDelayCacheSize == 0 || args.MaxValidatorDelayCacheSize == 0 {
return spos.ErrInvalidCacheSize
}
if check.IfNil(args.KeysHolder) {
return ErrNilKeysHolder
if check.IfNil(args.KeysHandler) {
return ErrNilKeysHandler
}

return nil
}

// BroadcastConsensusMessage will send on consensus topic the consensus message
func (cm *commonMessenger) BroadcastConsensusMessage(message *consensus.Message) error {
privateKey := cm.getPrivateKey(message)
privateKey := cm.keysHandler.GetHandledPrivateKey(message.PubKey)
signature, err := cm.peerSignatureHandler.GetPeerSignature(privateKey, message.OriginatorPid)
if err != nil {
return err
Expand All @@ -127,23 +120,6 @@ func (cm *commonMessenger) BroadcastConsensusMessage(message *consensus.Message)
return nil
}

func (cm *commonMessenger) getPrivateKey(message *consensus.Message) crypto.PrivateKey {
publicKey := message.PubKey
if !cm.keysHolder.IsKeyManagedByCurrentNode(publicKey) {
return cm.privateKey
}

privateKey, err := cm.keysHolder.GetPrivateKey(publicKey)
if err != nil {
log.Error("setup error in commonMessenger.getPrivateKey - public key is managed but does not contain a private key",
"pk", publicKey, "error", err)

return cm.privateKey
}

return privateKey
}

// BroadcastMiniBlocks will send on miniblocks topic the cross-shard miniblocks
func (cm *commonMessenger) BroadcastMiniBlocks(miniBlocks map[uint32][]byte, pkBytes []byte) error {
for k, v := range miniBlocks {
Expand Down Expand Up @@ -251,12 +227,12 @@ func (cm *commonMessenger) extractMetaMiniBlocksAndTransactions(
}

func (cm *commonMessenger) broadcast(topic string, data []byte, pkBytes []byte) {
if bytes.Equal(pkBytes, cm.currentPublicKeyBytes) {
if cm.keysHandler.IsOriginalPublicKeyOfTheNode(pkBytes) {
cm.messenger.Broadcast(topic, data)
return
}

skBytes, pid, err := cm.keysHolder.GetP2PIdentity(pkBytes)
skBytes, pid, err := cm.keysHandler.GetP2PIdentity(pkBytes)
if err != nil {
log.Error("setup error in commonMessenger.broadcast - public key is managed but does not contain p2p sign info",
"pk", pkBytes, "error", err)
Expand Down
160 changes: 22 additions & 138 deletions consensus/broadcast/commonMessenger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ func TestCommonMessenger_BroadcastConsensusMessageShouldErrWhenSignMessageFail(t
err := errors.New("sign message error")
marshalizerMock := &mock.MarshalizerMock{}
messengerMock := &mock.MessengerStub{}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
Expand All @@ -52,10 +51,9 @@ func TestCommonMessenger_BroadcastConsensusMessageShouldErrWhenSignMessageFail(t
cm, _ := broadcast.NewCommonMessenger(
marshalizerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
&testscommon.KeysHandlerStub{},
)

msg := &consensus.Message{}
Expand All @@ -69,7 +67,6 @@ func TestCommonMessenger_BroadcastConsensusMessageShouldWork(t *testing.T) {
BroadcastCalled: func(topic string, buff []byte) {
},
}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
Expand All @@ -81,44 +78,16 @@ func TestCommonMessenger_BroadcastConsensusMessageShouldWork(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshalizerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
&testscommon.KeysHandlerStub{},
)

msg := &consensus.Message{}
err := cm.BroadcastConsensusMessage(msg)
assert.Nil(t, err)
}

func TestCommonMessenger_SignMessageShouldErrWhenSignFail(t *testing.T) {
err := errors.New("sign message error")
marshalizerMock := &mock.MarshalizerMock{}
messengerMock := &mock.MessengerStub{}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
return nil, err
},
}
peerSigHandler := &mock.PeerSignatureHandler{Signer: singleSignerMock}

cm, _ := broadcast.NewCommonMessenger(
marshalizerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
)

msg := &consensus.Message{}
_, err2 := cm.SignMessage(msg)
assert.Equal(t, err, err2)
}

func TestSubroundEndRound_ExtractMiniBlocksAndTransactionsShouldWork(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -152,7 +121,6 @@ func TestSubroundEndRound_ExtractMiniBlocksAndTransactionsShouldWork(t *testing.
BroadcastCalled: func(topic string, buff []byte) {
},
}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
Expand All @@ -164,10 +132,9 @@ func TestSubroundEndRound_ExtractMiniBlocksAndTransactionsShouldWork(t *testing.
cm, _ := broadcast.NewCommonMessenger(
marshalizerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
&testscommon.KeysHandlerStub{},
)

metaMiniBlocks, metaTransactions := cm.ExtractMetaMiniBlocksAndTransactions(miniBlocks, transactions)
Expand Down Expand Up @@ -200,7 +167,6 @@ func TestCommonMessenger_BroadcastBlockData(t *testing.T) {
mutCounters.Unlock()
},
}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
Expand All @@ -212,10 +178,13 @@ func TestCommonMessenger_BroadcastBlockData(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshalizerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
&testscommon.KeysHandlerStub{
IsOriginalPublicKeyOfTheNodeCalled: func(pkBytes []byte) bool {
return bytes.Equal(pkBytes, nodePkBytes)
},
},
)

miniBlocks := map[uint32][]byte{0: []byte("mbs data1"), 1: []byte("mbs data2")}
Expand All @@ -227,8 +196,7 @@ func TestCommonMessenger_BroadcastBlockData(t *testing.T) {
countersBroadcast = make(map[string]int)
mutCounters.Unlock()

pkBytes, _ := privateKeyMock.GeneratePublic().ToByteArray()
cm.BroadcastBlockData(miniBlocks, transactions, pkBytes, delay)
cm.BroadcastBlockData(miniBlocks, transactions, nodePkBytes, delay)
time.Sleep(delay * 2)

mutCounters.Lock()
Expand Down Expand Up @@ -284,7 +252,6 @@ func TestCommonMessenger_broadcast(t *testing.T) {
mutCounters.Unlock()
},
}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
Expand All @@ -298,17 +265,20 @@ func TestCommonMessenger_broadcast(t *testing.T) {
countersBroadcast = make(map[string]int)
mutCounters.Unlock()

pkBytesProvided := []byte("public key")
cm, _ := broadcast.NewCommonMessenger(
marshallerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
&testscommon.KeysHandlerStub{
IsOriginalPublicKeyOfTheNodeCalled: func(pkBytes []byte) bool {
return bytes.Equal(pkBytesProvided, pkBytes)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use nodePkBytes you already defined and used in tests above and remove L268

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},
},
)

pkBytes, _ := privateKeyMock.GeneratePublic().ToByteArray()
cm.Broadcast(testTopic, []byte("data"), pkBytes)
cm.Broadcast(testTopic, []byte("data"), pkBytesProvided)

mutCounters.Lock()
assert.Equal(t, 1, countersBroadcast[broadcastMethodPrefix+testTopic])
Expand All @@ -323,10 +293,13 @@ func TestCommonMessenger_broadcast(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshallerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
&testscommon.KeysHandlerStub{
IsOriginalPublicKeyOfTheNodeCalled: func(pkBytes []byte) bool {
return false
},
},
)

cm.Broadcast(testTopic, []byte("data"), []byte("managed key"))
Expand All @@ -344,10 +317,9 @@ func TestCommonMessenger_broadcast(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshallerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{
&testscommon.KeysHandlerStub{
GetP2PIdentityCalled: func(pkBytes []byte) ([]byte, core.PeerID, error) {
return nil, "", expectedErr
},
Expand All @@ -362,91 +334,3 @@ func TestCommonMessenger_broadcast(t *testing.T) {
mutCounters.Unlock()
})
}

func TestCommonMessenger_getPrivateKey(t *testing.T) {
t.Parallel()

expectedErr := errors.New("expected error")
marshallerMock := &mock.MarshalizerMock{}

messengerMock := &mock.MessengerStub{}
privateKeyMock := &mock.PrivateKeyMock{}
shardCoordinatorMock := &mock.ShardCoordinatorMock{}
singleSignerMock := &mock.SingleSignerMock{
SignStub: func(private crypto.PrivateKey, msg []byte) ([]byte, error) {
return []byte(""), nil
},
}
peerSigHandler := &mock.PeerSignatureHandler{Signer: singleSignerMock}
managedKeyBytes := []byte("managed key")
managedPrivateKey := &mock.PrivateKeyMock{}

t.Run("using the original public key bytes of the node", func(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshallerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{},
)

pkBytes, _ := privateKeyMock.GeneratePublic().ToByteArray()
retrievedPrivateKey := cm.GetPrivateKey(&consensus.Message{
PubKey: pkBytes,
})

assert.True(t, privateKeyMock == retrievedPrivateKey) // pointer testing
})
t.Run("using a managed key", func(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshallerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{
GetPrivateKeyCalled: func(pkBytes []byte) (crypto.PrivateKey, error) {
if bytes.Equal(pkBytes, managedKeyBytes) {
return managedPrivateKey, nil
}

return privateKeyMock, nil
},
IsKeyManagedByCurrentNodeCalled: func(pkBytes []byte) bool {
return bytes.Equal(pkBytes, managedKeyBytes)
},
},
)

retrievedPrivateKey := cm.GetPrivateKey(&consensus.Message{
PubKey: managedKeyBytes,
})

assert.True(t, managedPrivateKey == retrievedPrivateKey) // pointer testing
})
t.Run("keys holder fails", func(t *testing.T) {
cm, _ := broadcast.NewCommonMessenger(
marshallerMock,
messengerMock,
privateKeyMock,
shardCoordinatorMock,
peerSigHandler,
&testscommon.KeysHolderStub{
GetPrivateKeyCalled: func(pkBytes []byte) (crypto.PrivateKey, error) {
if bytes.Equal(pkBytes, managedKeyBytes) {
return nil, expectedErr
}

return privateKeyMock, nil
},
},
)

retrievedPrivateKey := cm.GetPrivateKey(&consensus.Message{
PubKey: managedKeyBytes,
})

assert.True(t, privateKeyMock == retrievedPrivateKey) // pointer testing with the original private key node
})
}
4 changes: 2 additions & 2 deletions consensus/broadcast/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package broadcast

import "errors"

// ErrNilKeysHolder signals that a nil keys holder was provided
var ErrNilKeysHolder = errors.New("nil keys holder")
// ErrNilKeysHandler signals that a nil keys handler was provided
var ErrNilKeysHandler = errors.New("nil keys handler")