Skip to content

Commit 1f88bea

Browse files
ArtObrashcherbakov
authored andcommitted
[INDY-992] Move bls tests to sdk (#564)
* Initial test integration Signed-off-by: ArtObr <[email protected]> * Two more files done Signed-off-by: ArtObr <[email protected]> * new test Signed-off-by: ArtObr <[email protected]> * 4 more folders done Signed-off-by: ArtObr <[email protected]> * two more files Signed-off-by: ArtObr <[email protected]> * some changes Signed-off-by: ArtObr <[email protected]> * More tests integrated. Problems: validator functions of client in test_state_proof; problem with wrong bls keys Signed-off-by: ArtObr <[email protected]> * Script fix. bls validation fix Signed-off-by: ArtObr <[email protected]> * little fix Signed-off-by: ArtObr <[email protected]> * Fix for bls validation tests. Not done: update_incorrect test and state_proof test Signed-off-by: ArtObr <[email protected]> * Only state_proof test left Signed-off-by: ArtObr <[email protected]> * Tests integration done Signed-off-by: ArtObr <[email protected]> * Import deletion. flake8 error fix. Signed-off-by: ArtObr <[email protected]> * Review fixes Signed-off-by: ArtObr <[email protected]> * Little fix Signed-off-by: ArtObr <[email protected]>
1 parent 96b21b2 commit 1f88bea

21 files changed

+415
-256
lines changed

plenum/common/messages/client_request.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
ChooseField, ConstantField, DestNodeField, VerkeyField, DestNymField, \
88
RoleField, TxnSeqNoField, IdentifierField, \
99
NonNegativeNumberField, SignatureField, MapField, LimitedLengthStringField, \
10-
ProtocolVersionField, LedgerIdField
10+
ProtocolVersionField, LedgerIdField, Base58Field
1111
from plenum.common.messages.message_base import MessageValidator
1212
from plenum.common.types import OPERATION, f
1313
from plenum.config import ALIAS_FIELD_LIMIT, DIGEST_FIELD_LIMIT, \
@@ -22,7 +22,7 @@ class ClientNodeOperationData(MessageValidator):
2222
(CLIENT_PORT, NetworkPortField(optional=True)),
2323
(ALIAS, LimitedLengthStringField(max_length=ALIAS_FIELD_LIMIT)),
2424
(SERVICES, IterableField(ChooseField(values=(VALIDATOR,)), optional=True)),
25-
(BLS_KEY, LimitedLengthStringField(max_length=BLS_KEY_LIMIT, optional=True)),
25+
(BLS_KEY, Base58Field(byte_lengths=(128,), optional=True)),
2626
)
2727

2828
def _validate_message(self, dct):

plenum/test/bls/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from plenum.common.constants import DOMAIN_LEDGER_ID
55
from plenum.common.util import get_utc_epoch
66
from plenum.test.bls.helper import generate_state_root
7-
7+
from plenum.test.pool_transactions.conftest import looper
88

99
participants = ["Node1", "Node2", "Node3"]
1010
signature = "somefakesignaturesomefakesignaturesomefakesignature"

plenum/test/bls/helper.py

Lines changed: 141 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
11
import base58
22
import os
33

4-
from common.serializers.serialization import state_roots_serializer
5-
from plenum.common.constants import DOMAIN_LEDGER_ID, ALIAS, BLS_KEY
4+
from crypto.bls.bls_crypto import BlsCryptoVerifier
5+
from plenum.bls.bls_crypto_factory import create_default_bls_crypto_factory
6+
from plenum.server.quorums import Quorums
7+
from crypto.bls.bls_multi_signature import MultiSignatureValue
8+
from state.pruning_state import PruningState
9+
from common.serializers.serialization import state_roots_serializer, proof_nodes_serializer
10+
from plenum.common.constants import DOMAIN_LEDGER_ID, ALIAS, BLS_KEY, STATE_PROOF, TXN_TYPE, MULTI_SIGNATURE, \
11+
MULTI_SIGNATURE_PARTICIPANTS, MULTI_SIGNATURE_SIGNATURE, MULTI_SIGNATURE_VALUE
612
from plenum.common.keygen_utils import init_bls_keys
713
from plenum.common.messages.node_messages import Commit, Prepare, PrePrepare
8-
from plenum.common.util import get_utc_epoch, randomString, random_from_alphabet
9-
from plenum.test.helper import sendRandomRequests, waitForSufficientRepliesForRequests
14+
from plenum.common.util import get_utc_epoch, randomString, random_from_alphabet, hexToFriendly
15+
from plenum.test.helper import sendRandomRequests, waitForSufficientRepliesForRequests, sdk_send_random_and_check
1016
from plenum.test.node_catchup.helper import waitNodeDataEquality, ensureClientConnectedToNodesAndPoolLedgerSame
11-
from plenum.test.pool_transactions.helper import updateNodeData, new_client
17+
from plenum.test.node_request.helper import sdk_ensure_pool_functional
18+
from plenum.test.pool_transactions.helper import updateNodeData, sdk_send_update_node, \
19+
sdk_pool_refresh
20+
from stp_core.common.log import getlogger
21+
22+
logger = getlogger()
1223

1324

1425
def generate_state_root():
1526
return base58.b58encode(os.urandom(32))
1627

1728

18-
def check_bls_multi_sig_after_send(looper, txnPoolNodeSet,
19-
client, wallet,
20-
saved_multi_sigs_count):
29+
def sdk_check_bls_multi_sig_after_send(looper, txnPoolNodeSet,
30+
sdk_pool_handle, sdk_wallet_handle,
31+
saved_multi_sigs_count):
2132
# at least two because first request could have no
2233
# signature since state can be clear
2334
number_of_requests = 3
@@ -26,8 +37,8 @@ def check_bls_multi_sig_after_send(looper, txnPoolNodeSet,
2637
# Using loop to avoid 3pc batching
2738
state_roots = []
2839
for i in range(number_of_requests):
29-
reqs = sendRandomRequests(wallet, client, 1)
30-
waitForSufficientRepliesForRequests(looper, client, requests=reqs)
40+
sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle,
41+
sdk_wallet_handle, 1)
3142
waitNodeDataEquality(looper, txnPoolNodeSet[0], *txnPoolNodeSet[:-1])
3243
state_roots.append(
3344
state_roots_serializer.serialize(
@@ -45,7 +56,7 @@ def check_bls_multi_sig_after_send(looper, txnPoolNodeSet,
4556

4657
# 3. check how many multi-sigs are saved
4758
for multi_sigs in multi_sigs_for_batch:
48-
assert len(multi_sigs) == saved_multi_sigs_count,\
59+
assert len(multi_sigs) == saved_multi_sigs_count, \
4960
"{} != {}".format(len(multi_sigs), saved_multi_sigs_count)
5061

5162
# 3. check that bls multi-sig is the same for all nodes we get PrePrepare for (that is for all expect the last one)
@@ -89,20 +100,20 @@ def calculate_multi_sig(creator, bls_bft_with_commits, quorums, pre_prepare):
89100

90101

91102
def create_pre_prepare_params(state_root,
92-
ledger_id = DOMAIN_LEDGER_ID,
103+
ledger_id=DOMAIN_LEDGER_ID,
93104
txn_root=None,
94105
timestamp=None,
95106
bls_multi_sig=None):
96-
params= [0,
97-
0,
98-
0,
99-
timestamp or get_utc_epoch(),
100-
[('1' * 16, 1)],
101-
0,
102-
"random digest",
103-
ledger_id,
104-
state_root,
105-
txn_root or '1' * 32]
107+
params = [0,
108+
0,
109+
0,
110+
timestamp or get_utc_epoch(),
111+
[('1' * 16, 1)],
112+
0,
113+
"random digest",
114+
ledger_id,
115+
state_root,
116+
txn_root or '1' * 32]
106117
if bls_multi_sig:
107118
params.append(bls_multi_sig.as_list())
108119
return params
@@ -122,12 +133,14 @@ def create_commit_no_bls_sig(req_key):
122133
params = create_commit_params(view_no, pp_seq_no)
123134
return Commit(*params)
124135

136+
125137
def create_commit_with_bls_sig(req_key, bls_sig):
126138
view_no, pp_seq_no = req_key
127139
params = create_commit_params(view_no, pp_seq_no)
128140
params.append(bls_sig)
129141
return Commit(*params)
130142

143+
131144
def create_commit_bls_sig(bls_bft, req_key, pre_prepare):
132145
view_no, pp_seq_no = req_key
133146
params = create_commit_params(view_no, pp_seq_no)
@@ -159,8 +172,8 @@ def change_bls_key(looper, txnPoolNodeSet,
159172

160173
key_in_txn = \
161174
new_blspk \
162-
if not add_wrong \
163-
else ''.join(random_from_alphabet(32, base58.alphabet))
175+
if not add_wrong \
176+
else ''.join(random_from_alphabet(32, base58.alphabet))
164177

165178
node_data = {
166179
ALIAS: node.name,
@@ -174,6 +187,32 @@ def change_bls_key(looper, txnPoolNodeSet,
174187
return new_blspk
175188

176189

190+
def sdk_change_bls_key(looper, txnPoolNodeSet,
191+
node,
192+
sdk_pool_handle,
193+
sdk_wallet_steward,
194+
add_wrong=False,
195+
new_bls=None):
196+
new_blspk = init_bls_keys(node.keys_dir, node.name)
197+
key_in_txn = new_bls or new_blspk \
198+
if not add_wrong \
199+
else base58.b58encode(randomString(128).encode())
200+
node_dest = hexToFriendly(node.nodestack.verhex)
201+
sdk_send_update_node(looper, sdk_wallet_steward,
202+
sdk_pool_handle,
203+
node_dest, node.name,
204+
None, None,
205+
None, None,
206+
bls_key=key_in_txn,
207+
services=None)
208+
poolSetExceptOne = list(txnPoolNodeSet)
209+
poolSetExceptOne.remove(node)
210+
waitNodeDataEquality(looper, node, *poolSetExceptOne)
211+
sdk_pool_refresh(looper, sdk_pool_handle)
212+
sdk_ensure_pool_functional(looper, txnPoolNodeSet, sdk_wallet_steward, sdk_pool_handle)
213+
return new_blspk
214+
215+
177216
def check_bls_key(blskey, node, nodes, add_wrong=False):
178217
'''
179218
Check that each node has the same and correct blskey for this node
@@ -195,24 +234,89 @@ def check_bls_key(blskey, node, nodes, add_wrong=False):
195234

196235
def check_update_bls_key(node_num, saved_multi_sigs_count,
197236
looper, txnPoolNodeSet,
198-
client_tdir,
199-
poolTxnClientData,
200-
stewards_and_wallets,
237+
sdk_wallet_stewards,
238+
sdk_wallet_client,
239+
sdk_pool_handle,
201240
add_wrong=False):
202241
# 1. Change BLS key for a specified NODE
203242
node = txnPoolNodeSet[node_num]
204-
steward_client, steward_wallet = stewards_and_wallets[node_num]
205-
new_blspk = change_bls_key(looper, txnPoolNodeSet, node,
206-
steward_client, steward_wallet,
207-
add_wrong)
243+
sdk_wallet_steward = sdk_wallet_stewards[node_num]
244+
new_blspk = sdk_change_bls_key(looper, txnPoolNodeSet,
245+
node,
246+
sdk_pool_handle,
247+
sdk_wallet_steward,
248+
add_wrong)
208249

209250
# 2. Check that all Nodes see the new BLS key value
210251
check_bls_key(new_blspk, node, txnPoolNodeSet, add_wrong)
211252

212253
# 3. Check that we can send new requests and have correct multisigs
213-
client, wallet = new_client(looper,
214-
poolTxnClientData,
215-
txnPoolNodeSet, client_tdir)
216-
check_bls_multi_sig_after_send(looper, txnPoolNodeSet,
217-
client, wallet,
218-
saved_multi_sigs_count=saved_multi_sigs_count)
254+
sdk_check_bls_multi_sig_after_send(looper, txnPoolNodeSet,
255+
sdk_pool_handle, sdk_wallet_client,
256+
saved_multi_sigs_count)
257+
258+
259+
def validate_proof(result):
260+
"""
261+
Validates state proof
262+
"""
263+
state_root_hash = result[STATE_PROOF]['root_hash']
264+
state_root_hash = state_roots_serializer.deserialize(state_root_hash)
265+
proof_nodes = result[STATE_PROOF]['proof_nodes']
266+
if isinstance(proof_nodes, str):
267+
proof_nodes = proof_nodes.encode()
268+
proof_nodes = proof_nodes_serializer.deserialize(proof_nodes)
269+
key, value = prepare_for_state(result)
270+
valid = PruningState.verify_state_proof(state_root_hash,
271+
key,
272+
value,
273+
proof_nodes,
274+
serialized=True)
275+
return valid
276+
277+
278+
def prepare_for_state(result):
279+
if result[TXN_TYPE] == "buy":
280+
from plenum.test.test_node import TestDomainRequestHandler
281+
key, value = TestDomainRequestHandler.prepare_buy_for_state(result)
282+
return key, value
283+
284+
285+
def validate_multi_signature(state_proof, txnPoolNodeSet):
286+
"""
287+
Validates multi signature
288+
"""
289+
multi_signature = state_proof[MULTI_SIGNATURE]
290+
if not multi_signature:
291+
logger.debug("There is a state proof, but no multi signature")
292+
return False
293+
294+
participants = multi_signature[MULTI_SIGNATURE_PARTICIPANTS]
295+
signature = multi_signature[MULTI_SIGNATURE_SIGNATURE]
296+
value = MultiSignatureValue(
297+
**(multi_signature[MULTI_SIGNATURE_VALUE])
298+
).as_single_value()
299+
quorums = Quorums(len(txnPoolNodeSet))
300+
if not quorums.bls_signatures.is_reached(len(participants)):
301+
logger.debug("There is not enough participants of "
302+
"multi-signature")
303+
return False
304+
public_keys = []
305+
for node_name in participants:
306+
key = next(node.bls_bft.bls_crypto_signer.pk for node
307+
in txnPoolNodeSet if node.name == node_name)
308+
if key is None:
309+
logger.debug("There is no bls key for node {}"
310+
.format(node_name))
311+
return False
312+
public_keys.append(key)
313+
_multi_sig_verifier = _create_multi_sig_verifier()
314+
return _multi_sig_verifier.verify_multi_sig(signature,
315+
value,
316+
public_keys)
317+
318+
319+
def _create_multi_sig_verifier() -> BlsCryptoVerifier:
320+
verifier = create_default_bls_crypto_factory() \
321+
.create_bls_crypto_verifier()
322+
return verifier

plenum/test/bls/test_add_bls_key.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from plenum.server.quorums import Quorum
22
from plenum.test.bls.helper import check_update_bls_key
3-
from plenum.test.pool_transactions.conftest import looper, clientAndWallet1, \
4-
client1, wallet1, client1Connected
53

64
nodeCount = 4
75
nodes_wth_bls = 0
@@ -10,37 +8,44 @@
108
# As we use tests with Module scope, results from previous tests are accumulated, so
119
# rotating BLS keys one by one, eventually we will have all keys changed
1210

13-
def test_add_bls_one_node(looper, txnPoolNodeSet, client_tdir,
14-
poolTxnClientData, stewards_and_wallets):
11+
def test_add_bls_one_node(looper,
12+
txnPoolNodeSet,
13+
sdk_pool_handle,
14+
sdk_wallet_stewards, sdk_wallet_client):
1515
'''
1616
Added BLS key for 1st Node;
1717
do not expect that BLS multi-sigs are applied since no consensus (n-f)
1818
'''
1919
check_update_bls_key(node_num=0,
2020
saved_multi_sigs_count=0,
2121
looper=looper, txnPoolNodeSet=txnPoolNodeSet,
22-
client_tdir=client_tdir,
23-
poolTxnClientData=poolTxnClientData,
24-
stewards_and_wallets=stewards_and_wallets)
22+
sdk_wallet_stewards=sdk_wallet_stewards,
23+
sdk_wallet_client=sdk_wallet_client,
24+
sdk_pool_handle=sdk_pool_handle)
2525

2626

27-
28-
def test_add_bls_two_nodes(looper, txnPoolNodeSet, client_tdir,
29-
poolTxnClientData, stewards_and_wallets):
27+
def test_add_bls_two_nodes(looper,
28+
txnPoolNodeSet,
29+
sdk_pool_handle,
30+
sdk_wallet_stewards,
31+
sdk_wallet_client):
3032
'''
3133
Added BLS key for 1st and 2d Nodes;
3234
do not expect that BLS multi-sigs are applied since no consensus (n-f)
3335
'''
3436
check_update_bls_key(node_num=1,
3537
saved_multi_sigs_count=0,
3638
looper=looper, txnPoolNodeSet=txnPoolNodeSet,
37-
client_tdir=client_tdir,
38-
poolTxnClientData=poolTxnClientData,
39-
stewards_and_wallets=stewards_and_wallets)
39+
sdk_wallet_stewards=sdk_wallet_stewards,
40+
sdk_wallet_client=sdk_wallet_client,
41+
sdk_pool_handle=sdk_pool_handle)
4042

4143

42-
def test_add_bls_three_nodes(looper, txnPoolNodeSet, client_tdir,
43-
poolTxnClientData, stewards_and_wallets):
44+
def test_add_bls_three_nodes(looper,
45+
txnPoolNodeSet,
46+
sdk_pool_handle,
47+
sdk_wallet_stewards,
48+
sdk_wallet_client):
4449
'''
4550
Added BLS key for 1st, 2d and 3d Nodes;
4651
expect that BLS multi-sigs are applied since we have consensus now (3=n-f)
@@ -52,20 +57,23 @@ def test_add_bls_three_nodes(looper, txnPoolNodeSet, client_tdir,
5257
check_update_bls_key(node_num=2,
5358
saved_multi_sigs_count=4,
5459
looper=looper, txnPoolNodeSet=txnPoolNodeSet,
55-
client_tdir=client_tdir,
56-
poolTxnClientData=poolTxnClientData,
57-
stewards_and_wallets=stewards_and_wallets)
60+
sdk_wallet_stewards=sdk_wallet_stewards,
61+
sdk_wallet_client=sdk_wallet_client,
62+
sdk_pool_handle=sdk_pool_handle)
5863

5964

60-
def test_add_bls_all_nodes(looper, txnPoolNodeSet, client_tdir,
61-
poolTxnClientData, stewards_and_wallets):
65+
def test_add_bls_all_nodes(looper,
66+
txnPoolNodeSet,
67+
sdk_pool_handle,
68+
sdk_wallet_stewards,
69+
sdk_wallet_client):
6270
'''
6371
Eventually added BLS key for all Nodes;
6472
expect that BLS multi-sigs are applied since we have consensus now (4 > n-f)
6573
'''
6674
check_update_bls_key(node_num=3,
6775
saved_multi_sigs_count=4,
6876
looper=looper, txnPoolNodeSet=txnPoolNodeSet,
69-
client_tdir=client_tdir,
70-
poolTxnClientData=poolTxnClientData,
71-
stewards_and_wallets=stewards_and_wallets)
77+
sdk_wallet_stewards=sdk_wallet_stewards,
78+
sdk_wallet_client=sdk_wallet_client,
79+
sdk_pool_handle=sdk_pool_handle)

0 commit comments

Comments
 (0)