Skip to content

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

Merged
merged 18 commits into from
Sep 13, 2019
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plenum/bls/bls_bft_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def create_bls_bft_replica(self, is_master) -> BlsBftReplica:
return BlsBftReplicaPlenum(self._node.name,
self._node.bls_bft,
is_master,
self._node.db_manager,
self._node.metrics)


Expand Down
49 changes: 48 additions & 1 deletion plenum/bls/bls_bft_replica_plenum.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
from crypto.bls.bls_bft import BlsBft
from crypto.bls.bls_bft_replica import BlsBftReplica
from crypto.bls.bls_multi_signature import MultiSignature, MultiSignatureValue
from plenum.common.constants import DOMAIN_LEDGER_ID, BLS_PREFIX, POOL_LEDGER_ID
from plenum.common.constants import DOMAIN_LEDGER_ID, BLS_PREFIX, POOL_LEDGER_ID, AUDIT_LEDGER_ID, TXN_PAYLOAD, \
TXN_PAYLOAD_DATA, AUDIT_TXN_LEDGER_ROOT, AUDIT_TXN_STATE_ROOT
from plenum.common.messages.node_messages import PrePrepare, Prepare, Commit
from plenum.common.metrics_collector import MetricsCollector, NullMetricsCollector, measure_time, MetricsName
from plenum.common.types import f
from plenum.common.util import compare_3PC_keys
from plenum.server.database_manager import DatabaseManager
from stp_core.common.log import getlogger

logger = getlogger()
Expand All @@ -19,10 +21,13 @@ def __init__(self,
node_id,
bls_bft: BlsBft,
is_master,
database_manager: DatabaseManager,
metrics: MetricsCollector = NullMetricsCollector()):
super().__init__(bls_bft, is_master)
self.node_id = node_id
self._database_manager = database_manager
self._signatures = {}
self._all_signatures = {}
Copy link
Contributor

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)?

Copy link
Contributor Author

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.

self._bls_latest_multi_sig = None # MultiSignature
self.state_root_serializer = state_roots_serializer
self.metrics = metrics
Expand Down Expand Up @@ -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)
Copy link
Contributor

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?

if audit_ledger is not None:
last_audit_txn = audit_ledger.get_last_txn()
res = {}
payload_data = last_audit_txn[TXN_PAYLOAD][TXN_PAYLOAD_DATA]
for ledger_id in payload_data[AUDIT_TXN_STATE_ROOT].keys():
params = [
pre_prepare.instId,
pre_prepare.viewNo,
pre_prepare.ppSeqNo,
pre_prepare.ppTime,
pre_prepare.reqIdr,
pre_prepare.discarded,
pre_prepare.digest,
ledger_id,
payload_data[AUDIT_TXN_STATE_ROOT].get(ledger_id),
payload_data[AUDIT_TXN_LEDGER_ROOT].get(ledger_id),
pre_prepare.sub_seq_no,
pre_prepare.final,
pre_prepare.poolStateRootHash,
pre_prepare.auditTxnRootHash
]

fake_pp = PrePrepare(*params)
bls_signature = self._sign_state(fake_pp)
res[ledger_id] = bls_signature
commit_params.append(None) # for plugin fields
commit_params.append(res)

return commit_params

# ----PROCESS----
Expand All @@ -115,6 +150,18 @@ 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:
Copy link
Contributor

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 ?

return
if commit.blsSigs is None:
return

if key_3PC not in self._all_signatures:
self._all_signatures[key_3PC] = {}
for ledger_id in commit.blsSigs.keys():
if ledger_id not in self._all_signatures[key_3PC]:
self._all_signatures[key_3PC][ledger_id] = {}
self._all_signatures[key_3PC][ledger_id][self.get_node_name(sender)] = commit.blsSigs[ledger_id]

def process_order(self, key, quorums, pre_prepare):
if not self._can_process_ledger(pre_prepare.ledgerId):
return
Expand Down
8 changes: 6 additions & 2 deletions plenum/common/messages/node_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
SerializedValueField, SignatureField, TieAmongField, AnyValueField, TimestampField, \
LedgerIdField, MerkleRootField, Base58Field, LedgerInfoField, AnyField, ChooseField, AnyMapField, \
LimitedLengthStringField, BlsMultiSignatureField, ProtocolVersionField, BooleanField, \
IntegerField, BatchIDField, ViewChangeField
IntegerField, BatchIDField, ViewChangeField, MapField
from plenum.common.messages.message_base import \
MessageBase
from plenum.common.types import f
Expand Down Expand Up @@ -132,6 +132,7 @@ class PrePrepare(MessageBase):
# TODO: support multiple multi-sigs for multiple previous batches
(f.BLS_MULTI_SIG.nm, BlsMultiSignatureField(optional=True,
nullable=True)),
# TODO field for a support of multiple signatures of a single batch
(f.PLUGIN_FIELDS.nm, AnyMapField(optional=True, nullable=True)),
)
typename = PREPREPARE
Expand Down Expand Up @@ -173,7 +174,10 @@ class Commit(MessageBase):
optional=True)),
# PLUGIN_FIELDS is not used in Commit as of now but adding for
# consistency
(f.PLUGIN_FIELDS.nm, AnyMapField(optional=True, nullable=True))
(f.PLUGIN_FIELDS.nm, AnyMapField(optional=True, nullable=True)),
(f.BLS_SIGS.nm, MapField(optional=True,
key_field=LedgerIdField(),
value_field=LimitedLengthStringField(max_length=BLS_SIG_LIMIT)))
)


Expand Down
1 change: 1 addition & 0 deletions plenum/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class f: # provides a namespace for reusable field constants
AUDIT_TXN_ROOT_HASH = Field("auditTxnRootHash", str)
TXN_ROOT = Field("txnRootHash", str)
BLS_SIG = Field("blsSig", str)
BLS_SIGS = Field("blsSigs", Dict[int, str])
BLS_MULTI_SIG = Field("blsMultiSig", str)
BLS_MULTI_SIG_STATE_ROOT = Field("blsMultiSigStateRoot", str)
MERKLE_ROOT = Field("merkleRoot", str)
Expand Down
2 changes: 1 addition & 1 deletion plenum/server/database_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def get_database(self, lid):
return None
return self.databases[lid]

def get_ledger(self, lid):
def get_ledger(self, lid) -> Ledger:
if lid not in self.databases:
return None
return self.databases[lid].ledger
Expand Down