-
Notifications
You must be signed in to change notification settings - Fork 377
ST-623 -- Init Commit multi-sig process #1325
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
Conversation
Signed-off-by: Nikita Khateev <[email protected]>
plenum/bls/bls_bft_replica_plenum.py
Outdated
@@ -92,6 +97,36 @@ def update_commit(self, commit_params, pre_prepare: PrePrepare): | |||
logger.debug("{}{} signed COMMIT {} for state {} with sig {}" | |||
.format(BLS_PREFIX, self, commit_params, state_root_hash, bls_signature)) | |||
commit_params.append(bls_signature) | |||
|
|||
audit_ledger = self._database_manager.get_ledger(AUDIT_LEDGER_ID) |
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.
Do we have unit tests for the new functionality?
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]> # Conflicts: # plenum/common/messages/node_messages.py
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
test me please |
test this please |
plenum/bls/bls_bft_replica_plenum.py
Outdated
@@ -48,6 +62,10 @@ def validate_prepare(self, prepare: Prepare, sender): | |||
|
|||
@measure_time(MetricsName.BLS_VALIDATE_COMMIT_TIME) | |||
def validate_commit(self, commit: Commit, sender, pre_prepare: PrePrepare): | |||
if f.BLS_MULTI_SIGS.nm in commit: | |||
if not list(filter(lambda sig: self._validate_signature(sender, sig, pre_prepare), commit.blsSigs)): |
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.
filter
here returns all signatures for which validation succeeded, so if it's empty then either none of them succeeded, or there were no sigs at all. So, according to existing logic:
- We return
CM_BLS_SIG_WRONG
if all sigs are valid - We return
CM_BLS_SIG_WRONG
if there are no sigs - We don't return
CM_BLS_SIG_WRONG
if some but not all sigs are invalid - We don't return
CM_BLS_SIG_WRONG
if all sigs are invalid
@@ -68,6 +86,8 @@ def update_pre_prepare(self, pre_prepare_params, ledger_id): | |||
pre_prepare_params.append(self._bls_latest_multi_sig.as_list()) | |||
self._bls_latest_multi_sig = None | |||
# Send signature in COMMITs only | |||
if self._all_bls_latest_multi_sigs is not None: |
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 it be that _bls_latest_multi_sig
is False/None (so that we call return
), but _all_bls_latest_multi_sigs
is not None?
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 this
plenum/bls/bls_bft_replica_plenum.py
Outdated
@@ -48,6 +62,10 @@ def validate_prepare(self, prepare: Prepare, sender): | |||
|
|||
@measure_time(MetricsName.BLS_VALIDATE_COMMIT_TIME) | |||
def validate_commit(self, commit: Commit, sender, pre_prepare: PrePrepare): | |||
if f.BLS_MULTI_SIGS.nm in commit: | |||
if not list(filter(lambda sig: self._validate_signature(sender, sig, pre_prepare), commit.blsSigs)): | |||
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.
We can not call return
here since f.BLS_SIG.nm
needs to be set latter
plenum/bls/bls_bft_replica_plenum.py
Outdated
@@ -115,6 +153,28 @@ def process_commit(self, commit: Commit, sender): | |||
self._signatures[key_3PC] = {} | |||
self._signatures[key_3PC][self.get_node_name(sender)] = commit.blsSig | |||
|
|||
if f.BLS_SIGS.nm not in commit: |
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 it be that commit.blsSig is None
(so we called return
), but commit.blsSigs is not None
?
self._signatures = {} | ||
self._all_signatures = {} |
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.
Do we really need self._all_signatures
and self._signatures
? (self._all_bls_latest_multi_sigs
and self._bls_latest_multi_sig
)?
Can we make self._signatures
(self._bls_latest_multi_sig
) to be a special case in self._all_signatures
(self._all_bls_latest_multi_sigs
)?
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.
I have thought about it. This way we will always need to fetch the correct ledger from _all_signatures
according to PrePrepare
. On the other hand we have some code duplication -- but it is pretty obvious and we will remove it with the next release and there will be no problems.
plenum/bls/bls_bft_replica_plenum.py
Outdated
) | ||
) | ||
if sigs_invalid: | ||
self._all_signatures.pop(key_3PC, None) |
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.
Method name can_do_something
needs to do only the checks, not modifications. So, code like self._all_signatures.pop
looks really suspicious here.
sigs_for_request = self._all_signatures[key_3PC] | ||
sigs_invalid = list( | ||
filter( | ||
lambda item: not quorums.bls_signatures.is_reached(len(list(item[1].values()))), |
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 the following is more clear:
lambda ledger_id, sigs: not quorums.bls_signatures.is_reached(len(sigs))
sigs_for_request.items() | ||
) | ||
) | ||
if sigs_invalid: |
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 if we have quorum for some ledgers, not for all? Currently False
is returned, but maybe we should be able to calculate multi-sig for the sigs we have quorum for?
@@ -339,6 +372,81 @@ def test_process_order(bls_bft_replicas, pre_prepare_no_bls, quorums): | |||
pre_prepare_no_bls) | |||
|
|||
|
|||
# ------ MULTIPLE MULTI_SIGS ------ |
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.
Do we have tests where we have a mix of multiple and one sigs?
create_audit_txn_with_multiple_ledgers): | ||
for sender_bls_bft_replica in bls_bft_replicas: | ||
for verifier_bls_bft_replica in bls_bft_replicas: | ||
assert not verifier_bls_bft_replica.validate_pre_prepare(pre_prepare_with_bls_multi, |
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.
Please add more tests for validation. For example, when we have multiple sigs, and some of them valid while some are not.
key = (0, 0) | ||
for sender_bls_bft in bls_bft_replicas: | ||
fake_sig = base58.b58encode(b"somefakesignaturesomefakesignaturesomefakesignature").decode("utf-8") | ||
commit = create_commit_with_bls_sigs(key, fake_sig) |
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.
Do we have multiple sigs here?
Please add more tests for validation:
- when we really have more than 1 sig
- when some of this sigs are valid and some are not
- when there is multi-sig field, but it's empty
plenum/test/helper.py
Outdated
@@ -1222,7 +1222,8 @@ def create_pre_prepare_params(state_root, | |||
pp_seq_no=0, | |||
inst_id=0, | |||
audit_txn_root=None, | |||
reqs=None): | |||
reqs=None, | |||
bls_multi_sigs=[]): |
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.
I think we need to include bls_multi_sigs
into all test helpers for creation of PrePrepare. If it's not specified, a defualt can be added (like [bls_sig]
).
plenum/test/helper.py
Outdated
@@ -1271,6 +1274,14 @@ def create_commit_with_bls_sig(req_key, bls_sig): | |||
return Commit(*params) | |||
|
|||
|
|||
def create_commit_with_bls_sigs(req_key, bls_sig): |
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.
I think we need to include bls_multi_sigs
into all test helpers for creation of Commit. If it's not specified, a defualt can be added (like [bls_sig]
).
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
plenum/bls/bls_bft_replica_plenum.py
Outdated
multi_sig = MultiSignature.from_list(*sig) | ||
if not self._validate_multi_sig(multi_sig): | ||
return BlsBftReplica.PPR_BLS_MULTISIG_WRONG | ||
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.
I think return
here needs to be removed sine we may have both BLS_MULTI_SIGS
and BLS_MULTI_SIG
@@ -68,6 +95,8 @@ def update_pre_prepare(self, pre_prepare_params, ledger_id): | |||
pre_prepare_params.append(self._bls_latest_multi_sig.as_list()) | |||
self._bls_latest_multi_sig = None | |||
# Send signature in COMMITs only | |||
if self._all_bls_latest_multi_sigs is not None: | |||
pre_prepare_params.append([val.as_list() for val in self._all_bls_latest_multi_sigs]) |
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.
Should we set _all_bls_latest_multi_sigs
to None like we do for _bls_latest_multi_sig
?
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
plenum/test/helper.py
Outdated
@@ -1241,6 +1242,8 @@ def create_pre_prepare_params(state_root, | |||
audit_txn_root or generate_state_root()] | |||
if bls_multi_sig: | |||
params.append(bls_multi_sig.as_list()) | |||
if bls_multi_sigs: |
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 bls_multi_sigs=[]
(default), then this code will not be called.
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 this as well
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
plenum/test/helper.py
Outdated
@@ -1244,6 +1244,8 @@ def create_pre_prepare_params(state_root, | |||
params.append(bls_multi_sig.as_list()) | |||
if bls_multi_sigs: |
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.
I believe this needs to be
create_pre_prepare_params(....., bls_multi_sigs=None)
......
if bls_multi_sigs is not None:
params.append(bls_multi_sig.as_list())
elif bls_multi_sig:
params.append([bls_multi_sig.as_list()])
Signed-off-by: Nikita Khateev <[email protected]>
Signed-off-by: Nikita Khateev <[email protected]>
@@ -62,7 +62,7 @@ def validate_prepare(self, prepare: Prepare, sender): | |||
@measure_time(MetricsName.BLS_VALIDATE_COMMIT_TIME) | |||
def validate_commit(self, commit: Commit, sender, pre_prepare: PrePrepare): | |||
if f.BLS_SIGS.nm in commit: | |||
audit_txn = self._get_correct_audit_transaction(pre_prepare.ledgerId, pre_prepare.stateRootHash) | |||
audit_txn = self._get_correct_audit_transaction(pre_prepare) |
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.
Should we check that audit_txn
contains the same number of changes (length of AUDIT_TXN_STATE_ROOT
) as blsSigs
? Otherwise a KeyError may be raised here.
Signed-off-by: Nikita Khateev <[email protected]>
test this please |
Signed-off-by: Nikita Khateev [email protected]