-
Notifications
You must be signed in to change notification settings - Fork 205
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
Integrated multikey in consensus #4463
Conversation
# Conflicts: # integrationTests/testProcessorNode.go
Codecov ReportBase: 73.94% // Head: 73.89% // Decreases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## feat/multisigner #4463 +/- ##
====================================================
- Coverage 73.94% 73.89% -0.05%
====================================================
Files 698 698
Lines 88808 89033 +225
====================================================
+ Hits 65665 65789 +124
- Misses 18207 18285 +78
- Partials 4936 4959 +23
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
if sr.IsNodeInConsensusGroup(sr.SelfPubKey()) { | ||
selfJobDone = sr.IsSelfJobDone(sr.Current()) | ||
} | ||
allInOneJobDone := sr.IsMultiKeyJobDone(sr.Current()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
allInOneJobDone := sr.IsMultiKeyJobDone(sr.Current()) | |
multiKeyJobDone := sr.IsMultiKeyJobDone(sr.Current()) |
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
@@ -302,3 +310,71 @@ func (sr *subroundSignature) remainingTime() time.Duration { | |||
|
|||
return remainigTime | |||
} | |||
|
|||
func (sr *subroundSignature) doSignatureJobForManagedKeys() bool { | |||
isAllInOneLeader := sr.IsMultiKeyLeaderInCurrentRound() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isAllInOneLeader := sr.IsMultiKeyLeaderInCurrentRound() | |
isMultiKeyLeader := sr.IsMultiKeyLeaderInCurrentRound() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
consensus/spos/consensusState.go
Outdated
if cns.IsNodeInConsensusGroup(cns.SelfPubKey()) { | ||
selfJobDone = cns.IsSelfJobDone(currentSubroundId) | ||
} | ||
allInOneJobDone := cns.IsMultiKeyJobDone(currentSubroundId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
allInOneJobDone := cns.IsMultiKeyJobDone(currentSubroundId) | |
multiKeyJobDone := cns.IsMultiKeyJobDone(currentSubroundId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this approach?
multiKeyJobDone := true
if cns.IsMultiKeyInConsensusGroup() {
multiKeyJobDone := cns.IsMultiKeyJobDone(currentSubroundId)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refactored for consistency reasons
consensus/spos/roundConsensus.go
Outdated
} | ||
|
||
// IncrementRoundsWithoutReceivedMessages increments the number of rounds without received messages on a provided public key | ||
// TODO(jls) add tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed TODO as tests already exist
@@ -164,7 +164,7 @@ func (sender *multikeyHeartbeatSender) sendMessageForKey(pkBytes []byte) error { | |||
versionNumber, | |||
name, | |||
identity, | |||
uint32(core.RegularPeer), // force all in one peers to be of type regular peers | |||
uint32(core.RegularPeer), // force multi key handled peers to be of type regular peers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
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) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking if it is better to call cm.messenger.Broadcast(topic, data) before return. Exactly as the approach used in getPrivateKey method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thought about this. I think part of the messages will be discarded because it will broadcast data as an observer on topics on which data needs to be sent only by validators.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here you need to broadcast on behalf of someone else, but you cannot do it since you don't have the required p2p data, so I think it is fine to simply return. Otherwise the message would anyway fail on verification and be dropped.
if sr.IsNodeInConsensusGroup(sr.SelfPubKey()) { | ||
selfJobDone = sr.IsSelfJobDone(sr.Current()) | ||
} | ||
allInOneJobDone := sr.IsMultiKeyJobDone(sr.Current()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this approach?
multiKeyJobDone := true
if sr.IsMultiKeyInConsensusGroup() {
multiKeyJobDone := sr.IsMultiKeyJobDone(sr.Current())
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refactored
consensus/spos/consensusState.go
Outdated
if cns.IsNodeInConsensusGroup(cns.SelfPubKey()) { | ||
selfJobDone = cns.IsSelfJobDone(currentSubroundId) | ||
} | ||
allInOneJobDone := cns.IsMultiKeyJobDone(currentSubroundId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about this approach?
multiKeyJobDone := true
if cns.IsMultiKeyInConsensusGroup() {
multiKeyJobDone := cns.IsMultiKeyJobDone(currentSubroundId)
}
|
||
return nil | ||
} | ||
|
||
func (cm *commonMessenger) getPrivateKey(message *consensus.Message) crypto.PrivateKey { | ||
publicKey := message.PubKey | ||
if !cm.keysHolder.IsKeyManagedByCurrentNode(publicKey) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we extract the key management logic out of the consensus?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, will try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extracted
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) | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here you need to broadcast on behalf of someone else, but you cannot do it since you don't have the required p2p data, so I think it is fine to simply return. Otherwise the message would anyway fail on verification and be dropped.
integrationTests/testInitializer.go
Outdated
|
||
// SyncDelay is used so that nodes have enough time to sync | ||
var SyncDelay = time.Second / 5 | ||
var SyncDelay = time.Second * 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a large increase
I think we need to investigate where the increase comes from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reverted
@@ -204,6 +206,30 @@ func (sr *Subround) ConsensusChannel() chan bool { | |||
return sr.consensusStateChangedChannel | |||
} | |||
|
|||
// GetAssociatedPid returns the associated PeerID to the provided public key bytes | |||
func (sr *Subround) GetAssociatedPid(pkBytes []byte) core.PeerID { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic I think needs to be moved to a separate component, so consensus does not need to manage itself multiple peers, but delegate this to that component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, will try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
consensus/spos/consensusState.go
Outdated
// IsMultiKeyLeaderInCurrentRound method checks if one of the nodes which are controlled by this instance | ||
// is leader in the current round | ||
func (cns *ConsensusState) IsMultiKeyLeaderInCurrentRound() bool { | ||
managedKeys := cns.keysHolder.GetManagedKeysByCurrentNode() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this seems to be a bit heavy on mem alocations especially for scenarios with multiple keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will try to refactor in order to make the code more efficient
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refactored
consensus/spos/consensusState.go
Outdated
func (cns *ConsensusState) IsMultiKeyJobDone(currentSubroundId int) bool { | ||
managedKeys := cns.keysHolder.GetManagedKeysByCurrentNode() | ||
for pk := range managedKeys { | ||
if !cns.IsNodeInConsensusGroup(pk) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe move the filtering of keys in consensus group managed by current node in a separate component, then we can optimize here allocations and number of iterations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, will try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refactored
@@ -168,11 +171,28 @@ func (sr *subroundStartRound) initCurrentRound() bool { | |||
|
|||
pubKeys := sr.ConsensusGroup() | |||
|
|||
numMultiKeysInConsensusGroup := 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you create a separate method for the added functionality here? L174-L188
then you can also add some unit tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, will add
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
return false | ||
} | ||
|
||
log.Debug("step 2: signature has been sent") | ||
} | ||
isSelfLeader := sr.IsSelfLeaderInCurrentRound() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we do this on line 71 and then use it in the conditional and here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
if !isAllInOneLeader { | ||
cnsMsg := consensus.NewConsensusMessage( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this part looks very similar to L73-L118
can we extract some common functionality and use in both places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, will try
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refactored and eliminated duplicated code
|
||
keysHandler := &testscommon.KeysHandlerStub{} | ||
cns := internalInitConsensusStateWithKeysHandler(keysHandler) | ||
// managedKey := []byte("managed key") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
commented code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed
t.Parallel() | ||
|
||
container := mock.InitConsensusCore() | ||
keysHolder := &testscommon.KeysHandlerStub{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keysHolder := &testscommon.KeysHandlerStub{} | |
keysHandler := &testscommon.KeysHandlerStub{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
&testscommon.KeysHolderStub{}, | ||
&testscommon.KeysHandlerStub{ | ||
IsOriginalPublicKeyOfTheNodeCalled: func(pkBytes []byte) bool { | ||
return bytes.Equal(pkBytesProvided, pkBytes) |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
consensus/spos/bls/blsWorker_test.go
Outdated
} | ||
|
||
func initConsensusStateWithKeysHolder(keysHolder consensus.KeysHolder) *spos.ConsensusState { | ||
func initConsensusStateWithKeysHandler(keysHolder consensus.KeysHandler) *spos.ConsensusState { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
keysHandler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
} | ||
|
||
return sr.doSignatureJobForManagedKeys() | ||
} | ||
|
||
func (sr *subroundSignature) createAndSendSignatureMessage(signatureShare []byte, pkBytes []byte) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
return true | ||
} | ||
|
||
func (sr *subroundSignature) completeSignatureSubRound(pk string, shouldWaitForAllSigsAsync bool) bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
err = sr.BroadcastMessenger().BroadcastConsensusMessage(cnsMsg) | ||
if err != nil { | ||
log.Debug("doSignatureJob.BroadcastConsensusMessage", "error", err.Error()) | ||
numMultiKeysSignaturesSent++ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be moved to L364, when it is sure that the signature has been sent after execution with success of method createAndSendSignatureMessage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, thanks
return false | ||
} | ||
|
||
// UpdatePublicKeyLiveness update the provided public key liveness if the provided pid is not managed by the current node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is not managed? or is managed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not managed. As you want to update the liveness of the pk when the master node did not participated in the consensus even if it should have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, now I see the sense the "not managed" is used ihere
keysManagement/keysHandler.go
Outdated
|
||
// IsOriginalPublicKeyOfTheNode returns true if the provided public key bytes are the original ones used by the node | ||
func (handler *keysHandler) IsOriginalPublicKeyOfTheNode(pkBytes []byte) bool { | ||
return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return true ? to work correctly in single-sign mode until the implementation will be done?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed
testscommon/keysHandlerStub.go
Outdated
return stub.IsOriginalPublicKeyOfTheNodeCalled(pkBytes) | ||
} | ||
|
||
return false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return true ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done, simplified one mock creation
Description of the reasoning behind the pull request (what feature was missing / how the problem was manifesting itself / what was the motive behind the refactoring)
Proposed Changes
Testing procedure