def test_get_last_ordered_timestamp_after_catchup(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, tconf, tdir, allPluginsPath): node_to_disconnect = txnPoolNodeSet[-1] reply_before = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1)[0][1] looper.runFor(2) disconnect_node_and_ensure_disconnected(looper, txnPoolNodeSet, node_to_disconnect) looper.removeProdable(name=node_to_disconnect.name) reply = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1)[0][1] node_to_disconnect = start_stopped_node(node_to_disconnect, looper, tconf, tdir, allPluginsPath) txnPoolNodeSet[-1] = node_to_disconnect looper.run(checkNodesConnected(txnPoolNodeSet)) waitNodeDataEquality(looper, node_to_disconnect, *txnPoolNodeSet[:-1]) ts_from_state = node_to_disconnect.master_replica._get_last_timestamp_from_state(DOMAIN_LEDGER_ID) assert ts_from_state == get_txn_time(reply['result']) assert ts_from_state != get_txn_time(reply_before['result'])
def test_get_last_ordered_timestamp_after_catchup(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, tconf, tdir, allPluginsPath): node_to_disconnect = txnPoolNodeSet[-1] reply_before = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1)[0][1] looper.runFor(2) disconnect_node_and_ensure_disconnected(looper, txnPoolNodeSet, node_to_disconnect) looper.removeProdable(name=node_to_disconnect.name) reply = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1)[0][1] node_to_disconnect = start_stopped_node(node_to_disconnect, looper, tconf, tdir, allPluginsPath) txnPoolNodeSet[-1] = node_to_disconnect looper.run(checkNodesConnected(txnPoolNodeSet)) waitNodeDataEquality(looper, node_to_disconnect, *txnPoolNodeSet[:-1], exclude_from_check=['check_last_ordered_3pc_backup']) ts_from_state = node_to_disconnect.master_replica._get_last_timestamp_from_state( DOMAIN_LEDGER_ID) assert ts_from_state == get_txn_time(reply['result']) assert ts_from_state != get_txn_time(reply_before['result'])
def test_get_fees_txn(helpers, fees_paid, nodeSetWithIntegratedTokenPlugin): seq_no = get_seq_no(fees_paid[FEES]) request = helpers.request.get_txn(TOKEN_LEDGER_ID, seq_no) responses = helpers.sdk.send_and_check_request_objects([request, ]) result = helpers.sdk.get_first_result(responses) data = result[DATA] for node in nodeSetWithIntegratedTokenPlugin: token_ledger = node.getLedger(TOKEN_LEDGER_ID) fee_txn = token_ledger.getBySeqNo(seq_no) assert get_payload_data(fee_txn) == get_payload_data(data) assert get_seq_no(fee_txn) == get_seq_no(data) assert get_txn_time(fee_txn) == get_txn_time(data)
def test_replicas_prepare_time(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): # Check that each replica's PREPARE time is same as the PRE-PREPARE time sent_batches = 5 for i in range(sent_batches): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, count=2) looper.runFor(1) for node in txnPoolNodeSet: for r in node.replicas: rec_prps = defaultdict(list) for p in recvd_prepares(r): rec_prps[(p.viewNo, p.ppSeqNo)].append(p) pp_coll = r.sentPrePrepares if r.isPrimary else r.prePrepares for key, pp in pp_coll.items(): for p in rec_prps[key]: assert pp.ppTime == p.ppTime # `last_accepted_pre_prepare_time` is the time of the last PRE-PREPARE assert r.last_accepted_pre_prepare_time == pp_coll.peekitem( -1)[1].ppTime # The ledger should store time for each txn and it should be same # as the time for that PRE-PREPARE if r.isMaster: for iv in node.txn_seq_range_to_3phase_key[DOMAIN_LEDGER_ID]: three_pc_key = iv.data for seq_no in range(iv.begin, iv.end): assert get_txn_time(node.domainLedger.getBySeqNo(seq_no))\ == pp_coll[three_pc_key].ppTime
def test_replicas_prepare_time(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): # Check that each replica's PREPARE time is same as the PRE-PREPARE time sent_batches = 5 for i in range(sent_batches): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, count=2) looper.runFor(1) for node in txnPoolNodeSet: for r in node.replicas.values(): rec_prps = defaultdict(list) for p in recvd_prepares(r): rec_prps[(p.viewNo, p.ppSeqNo)].append(p) pp_coll = r.sentPrePrepares if r.isPrimary else r.prePrepares for key, pp in pp_coll.items(): for p in rec_prps[key]: assert pp.ppTime == p.ppTime # `last_accepted_pre_prepare_time` is the time of the last PRE-PREPARE assert r.last_accepted_pre_prepare_time == pp_coll.peekitem(-1)[ 1].ppTime # The ledger should store time for each txn and it should be same # as the time for that PRE-PREPARE if r.isMaster: for iv in node.txn_seq_range_to_3phase_key[DOMAIN_LEDGER_ID]: three_pc_key = iv.data for seq_no in range(iv.begin, iv.end): assert get_txn_time(node.domainLedger.getBySeqNo(seq_no))\ == pp_coll[three_pc_key].ppTime
def test_fill_ts_store_after_catchup(txnPoolNodeSet, looper, sdk_pool_handle, sdk_wallet_steward, tconf, tdir, allPluginsPath): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 5) node_to_disconnect = txnPoolNodeSet[-1] disconnect_node_and_ensure_disconnected(looper, txnPoolNodeSet, node_to_disconnect) looper.removeProdable(name=node_to_disconnect.name) sdk_replies = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 2) node_to_disconnect = start_stopped_node(node_to_disconnect, looper, tconf, tdir, allPluginsPath) txnPoolNodeSet[-1] = node_to_disconnect looper.run(checkNodesConnected(txnPoolNodeSet)) waitNodeDataEquality(looper, node_to_disconnect, *txnPoolNodeSet, exclude_from_check=['check_last_ordered_3pc_backup']) req_handler = node_to_disconnect.read_manager.request_handlers[GET_BUY] for reply in sdk_replies: key = BuyHandler.prepare_buy_key(get_from(reply[1]['result']), get_req_id(reply[1]['result'])) root_hash = req_handler.database_manager.ts_store.get_equal_or_prev( get_txn_time(reply[1]['result'])) assert root_hash from_state = req_handler.state.get_for_root_hash(root_hash=root_hash, key=key) assert domain_state_serializer.deserialize(from_state)['amount'] == \ get_payload_data(reply[1]['result'])['amount']
def update_state(self, txn, prev_result, request, is_committed=False) -> None: self._validate_txn_type(txn) txn_data = get_payload_data(txn) primary_key = txn_data[RS_ID].encode() secondary_key = self.make_secondary_key(txn_data[RS_TYPE], txn_data[RS_NAME], txn_data[RS_VERSION]) value = { RS_ID: txn_data[RS_ID], RS_TYPE: txn_data[RS_TYPE], RS_NAME: txn_data[RS_NAME], RS_VERSION: txn_data[RS_VERSION], RS_CONTENT: txn_data[RS_CONTENT], TXN_PAYLOAD_METADATA_FROM: get_from(txn), TXN_PAYLOAD_METADATA_ENDORSER: get_endorser(txn), TXN_PAYLOAD_VERSION: get_payload_txn_version(txn), } seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(value, seq_no, txn_time) self.state.set(primary_key, value_bytes) self.state.set(secondary_key, primary_key)
def test_get_delta_with_other_reg_def_in_state( looper, create_node_and_not_start, reg_entry_with_other_reg_id, build_txn_for_revoc_def_entry_by_default, build_get_revoc_reg_delta): entry_second_id = build_txn_for_revoc_def_entry_by_default delta_req = build_get_revoc_reg_delta node = create_node_and_not_start # need for different txnTime looper.runFor(2) req_handler = node.getDomainReqHandler() txn = append_txn_metadata(reqToTxn(entry_second_id), txn_time=SECOND_TS_ID, seq_no=node.domainLedger.seqNo + 1) req_handler._addRevocRegEntry(txn) req_handler.ts_store.set(get_txn_time(txn), req_handler.state.headHash) # timestamp beetween FIRST_ID_TS and SECOND_ID_TS delta_req['operation'][FROM] = FIRST_ID_TS + 10 path_to_reg_entry = domain.make_state_path_for_revoc_reg_entry( revoc_reg_def_id=entry_second_id['operation'][REVOC_REG_DEF_ID]) reg_entry = req_handler._get_reg_entry_by_timestamp( delta_req['operation'][FROM], path_to_reg_entry) # we found root_hash in txRevoc storage but there is not corresponded reg_entry by path assert reg_entry.root_hash is not None assert reg_entry.value is None path_to_reg_entry_accum = domain.make_state_path_for_revoc_reg_entry( revoc_reg_def_id=entry_second_id['operation'][REVOC_REG_DEF_ID]) reg_entry_accum = req_handler._get_reg_entry_accum_by_timestamp( delta_req['operation'][FROM], path_to_reg_entry_accum) assert reg_entry_accum.root_hash is not None assert reg_entry_accum.value is None
def updateNym(self, nym, txn, isCommitted=True): existingData = self.getNymDetails(self.state, nym, isCommitted=isCommitted) txn_data = get_payload_data(txn) newData = {} if not existingData: # New nym being added to state, set the TrustAnchor newData[f.IDENTIFIER.nm] = get_from(txn) # New nym being added to state, set the role and verkey to None, this makes # the state data always have a value for `role` and `verkey` since we allow # clients to omit specifying `role` and `verkey` in the request consider a # default value of None newData[ROLE] = None newData[VERKEY] = None if ROLE in txn_data: newData[ROLE] = txn_data[ROLE] if VERKEY in txn_data: newData[VERKEY] = txn_data[VERKEY] newData[F.seqNo.name] = get_seq_no(txn) newData[TXN_TIME] = get_txn_time(txn) existingData.update(newData) val = self.stateSerializer.serialize(existingData) key = self.nym_to_state_key(nym) self.state.set(key, val) return existingData
def update_state(self, txn, prev_result, request, is_committed=False): self._validate_txn_type(txn) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) _, taa_list = self.state.generate_state_proof_for_keys_with_prefix( StaticTAAHelper.state_path_taa_digest(""), serialize=False, get_value=True) for encode_key, encode_data in taa_list.items(): taa = rlp_decode(encode_data) taa, last_seq_no, last_update_time = self._decode_state_value( taa[0]) digest = StaticTAAHelper.get_digest_from_state_key(encode_key) if TXN_AUTHOR_AGREEMENT_RETIREMENT_TS not in taa or taa.get( TXN_AUTHOR_AGREEMENT_RETIREMENT_TS, 0) > txn_time: self._set_taa_to_state( digest, seq_no, txn_time, taa[TXN_AUTHOR_AGREEMENT_TEXT], taa[TXN_AUTHOR_AGREEMENT_VERSION], taa.get(TXN_AUTHOR_AGREEMENT_RATIFICATION_TS, last_update_time), retirement_ts=txn_time) self.state.remove(StaticTAAHelper.state_path_taa_latest())
def test_proof_in_write_reply(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): resp = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) req = resp[0][0] result = resp[0][1]['result'] assert result assert get_type(result) == "buy" assert get_from(result) == req[f.IDENTIFIER.nm] assert get_req_id(result) == req[f.REQ_ID.nm] assert get_seq_no(result) assert get_txn_time(result) assert STATE_PROOF in result state_proof = result[STATE_PROOF] assert ROOT_HASH in state_proof assert MULTI_SIGNATURE in state_proof assert PROOF_NODES in state_proof multi_sig = state_proof[MULTI_SIGNATURE] assert MULTI_SIGNATURE_SIGNATURE in multi_sig assert MULTI_SIGNATURE_PARTICIPANTS in multi_sig assert MULTI_SIGNATURE_VALUE in multi_sig multi_sig_value = multi_sig[MULTI_SIGNATURE_VALUE] assert MULTI_SIGNATURE_VALUE_LEDGER_ID in multi_sig_value assert MULTI_SIGNATURE_VALUE_STATE_ROOT in multi_sig_value assert MULTI_SIGNATURE_VALUE_TXN_ROOT in multi_sig_value assert MULTI_SIGNATURE_VALUE_POOL_STATE_ROOT in multi_sig_value assert MULTI_SIGNATURE_VALUE_TIMESTAMP in multi_sig_value assert validate_multi_signature(state_proof, txnPoolNodeSet) assert validate_proof_for_write(result)
def test_proof_in_write_reply(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client): resp = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_client, 1) req = resp[0][0] result = resp[0][1]['result'] assert result assert get_type(result) == "buy" assert get_from(result) == req[f.IDENTIFIER.nm] assert get_req_id(result) == req[f.REQ_ID.nm] assert get_seq_no(result) assert get_txn_time(result) assert STATE_PROOF in result state_proof = result[STATE_PROOF] assert ROOT_HASH in state_proof assert MULTI_SIGNATURE in state_proof assert PROOF_NODES in state_proof multi_sig = state_proof[MULTI_SIGNATURE] assert MULTI_SIGNATURE_SIGNATURE in multi_sig assert MULTI_SIGNATURE_PARTICIPANTS in multi_sig assert MULTI_SIGNATURE_VALUE in multi_sig multi_sig_value = multi_sig[MULTI_SIGNATURE_VALUE] assert MULTI_SIGNATURE_VALUE_LEDGER_ID in multi_sig_value assert MULTI_SIGNATURE_VALUE_STATE_ROOT in multi_sig_value assert MULTI_SIGNATURE_VALUE_TXN_ROOT in multi_sig_value assert MULTI_SIGNATURE_VALUE_POOL_STATE_ROOT in multi_sig_value assert MULTI_SIGNATURE_VALUE_TIMESTAMP in multi_sig_value assert validate_multi_signature(state_proof, txnPoolNodeSet) assert validate_proof_for_write(result)
def update_state(self, txn, prev_result, request, is_committed=False): self._validate_txn_type(txn) payload = get_payload_data(txn) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) self._update_txn_author_agreement_acceptance_mechanisms( payload, seq_no, txn_time)
def apply_request(self, request: Request, batch_ts, prev_result): txn_type = request.operation[TXN_TYPE] seq_no = get_seq_no(prev_result) cons_time = get_txn_time(prev_result) if FeesAuthorizer.has_fees(request): inputs, outputs, signatures = getattr(request, f.FEES.nm) # This is correct since FEES is changed from config ledger whose # transactions have no fees fees = FeesAuthorizer.calculate_fees_from_req( self.utxo_cache, request) sigs = {i[ADDRESS]: s for i, s in zip(inputs, signatures)} txn = { OPERATION: { TXN_TYPE: FEE_TXN, INPUTS: inputs, OUTPUTS: outputs, REF: self._get_ref_for_txn_fees(seq_no), FEES: fees, }, f.SIGS.nm: sigs, f.REQ_ID.nm: get_req_id(prev_result), f.PROTOCOL_VERSION.nm: 2, } txn = reqToTxn(txn) self.token_ledger.append_txns_metadata([txn], txn_time=cons_time) _, txns = self.token_ledger.appendTxns([txn]) self.update_token_state(txn, request) self._fees_tracker.fees_in_current_batch += 1 self._fees_tracker.add_deducted_fees(txn_type, seq_no, fees) return None, None, prev_result
def update_state(self, txn, prev_result, request, is_committed=False): self._validate_txn_type(txn) nym = get_payload_data(txn).get(TARGET_NYM) existing_data = get_nym_details(self.state, nym, is_committed=is_committed) txn_data = get_payload_data(txn) new_data = {} if not existing_data: # New nym being added to state, set the TrustAnchor new_data[f.IDENTIFIER.nm] = get_from(txn) # New nym being added to state, set the role and verkey to None, this makes # the state data always have a value for `role` and `verkey` since we allow # clients to omit specifying `role` and `verkey` in the request consider a # default value of None new_data[ROLE] = None new_data[VERKEY] = None new_data[ROLE] = txn_data.get(ROLE, None) if VERKEY in txn_data: new_data[VERKEY] = txn_data[VERKEY] new_data[F.seqNo.name] = get_seq_no(txn) new_data[TXN_TIME] = get_txn_time(txn) self.__update_steward_count(new_data, existing_data) existing_data.update(new_data) val = self.state_serializer.serialize(existing_data) key = self.gen_state_key(txn) self.state.set(key, val) return existing_data
def test_idr_cache_update_after_catchup(txnPoolNodeSet, looper, sdk_pool_handle, sdk_wallet_steward, tconf, tdir, allPluginsPath): wallet_handle, identifier = sdk_wallet_steward node_to_disconnect = txnPoolNodeSet[-1] disconnect_node_and_ensure_disconnected(looper, txnPoolNodeSet, node_to_disconnect.name, stopNode=True) looper.removeProdable(node_to_disconnect) idr, verkey = createHalfKeyIdentifierAndAbbrevVerkey() request = looper.loop.run_until_complete(build_nym_request(identifier, idr, verkey, None, None)) req_signed = looper.loop.run_until_complete(sign_request(wallet_handle, identifier, request)) result = json.loads(looper.loop.run_until_complete(submit_request(sdk_pool_handle, req_signed))) restarted_node = start_stopped_node(node_to_disconnect, looper, tconf, tdir, allPluginsPath) txnPoolNodeSet[-1] = restarted_node waitNodeDataEquality(looper, restarted_node, *txnPoolNodeSet[:-1]) req_handler = restarted_node.getDomainReqHandler() root_hash = req_handler.ts_store.get_equal_or_prev(get_txn_time(result['result'])) key = domain.make_state_path_for_nym(idr) from_state = req_handler.state.get_for_root_hash(root_hash=root_hash, key=key) assert from_state deserialized = req_handler.stateSerializer.deserialize(from_state) assert deserialized items_after = req_handler.idrCache.get(idr) assert items_after
def test_get_delta_with_other_reg_def_in_state(looper, create_node_and_not_start, reg_entry_with_other_reg_id, build_txn_for_revoc_def_entry_by_default, build_get_revoc_reg_delta): entry_second_id = build_txn_for_revoc_def_entry_by_default delta_req = build_get_revoc_reg_delta node = create_node_and_not_start # need for different txnTime looper.runFor(2) req_handler = node.getDomainReqHandler() txn = append_txn_metadata(reqToTxn(entry_second_id), txn_time=SECOND_TS_ID, seq_no=node.domainLedger.seqNo + 1) req_handler._addRevocRegEntry(txn) req_handler.ts_store.set(get_txn_time(txn), req_handler.state.headHash) # timestamp beetween FIRST_ID_TS and SECOND_ID_TS delta_req['operation'][FROM] = FIRST_ID_TS + 10 path_to_reg_entry = domain.make_state_path_for_revoc_reg_entry( revoc_reg_def_id=entry_second_id['operation'][REVOC_REG_DEF_ID]) reg_entry = req_handler._get_reg_entry_by_timestamp( delta_req['operation'][FROM], path_to_reg_entry) # we found root_hash in txRevoc storage but there is not corresponded reg_entry by path assert reg_entry.root_hash is not None assert reg_entry.value is None path_to_reg_entry_accum = domain.make_state_path_for_revoc_reg_entry( revoc_reg_def_id=entry_second_id['operation'][REVOC_REG_DEF_ID]) reg_entry_accum = req_handler._get_reg_entry_accum_by_timestamp( delta_req['operation'][FROM], path_to_reg_entry_accum) assert reg_entry_accum.root_hash is not None assert reg_entry_accum.value is None
def test_idr_cache_update_after_catchup(txnPoolNodeSet, looper, sdk_pool_handle, sdk_wallet_steward, tconf, tdir, allPluginsPath): wallet_handle, identifier = sdk_wallet_steward node_to_disconnect = txnPoolNodeSet[-1] disconnect_node_and_ensure_disconnected(looper, txnPoolNodeSet, node_to_disconnect.name, stopNode=True) looper.removeProdable(node_to_disconnect) idr, verkey = createHalfKeyIdentifierAndAbbrevVerkey() request = looper.loop.run_until_complete( build_nym_request(identifier, idr, verkey, None, None)) req_signed = looper.loop.run_until_complete( sign_request(wallet_handle, identifier, request)) result = json.loads( looper.loop.run_until_complete( submit_request(sdk_pool_handle, req_signed))) restarted_node = start_stopped_node(node_to_disconnect, looper, tconf, tdir, allPluginsPath) txnPoolNodeSet[-1] = restarted_node waitNodeDataEquality(looper, restarted_node, *txnPoolNodeSet[:-1]) req_handler = restarted_node.get_req_handler(DOMAIN_LEDGER_ID) root_hash = req_handler.ts_store.get_equal_or_prev( get_txn_time(result['result'])) key = domain.make_state_path_for_nym(idr) from_state = req_handler.state.get_for_root_hash(root_hash=root_hash, key=key) assert from_state deserialized = req_handler.stateSerializer.deserialize(from_state) assert deserialized items_after = req_handler.idrCache.get(idr) assert items_after
def test_send_with_from_by_demand(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, send_revoc_reg_entry_by_demand, build_get_revoc_reg_delta): # We save timestamp of state changes. # looper and txnPoolNodeSet has "module", therefore, # when we send request with FROM section, it's not a clean situation looper.runFor(3) # Assume, that send_revoc_reg_entry_by_demand will add into issued [1,2,3,4,5] rev_reg_req1, rev_reg_reply1 = send_revoc_reg_entry_by_demand rev_reg_req1['operation'][VALUE][ISSUED] = [] # Revoked [1,2,3], Issued now must be [4,5] rev_reg_req1['operation'][VALUE][REVOKED] = [1, 2, 3] rev_reg_req1['operation'][VALUE][PREV_ACCUM] = rev_reg_req1['operation'][ VALUE][ACCUM] rev_reg_req1['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req2, rev_reg_reply2 = sdk_send_and_check([ json.dumps( sdk_sign_request_from_dict(looper, sdk_wallet_steward, rev_reg_req1['operation'])) ], looper, txnPoolNodeSet, sdk_pool_handle)[0] # Issued [10, 11] rev_reg_req2['operation'][VALUE][ISSUED] = [10, 11] rev_reg_req2['operation'][VALUE][REVOKED] = [] rev_reg_req2['operation'][VALUE][PREV_ACCUM] = rev_reg_req2['operation'][ VALUE][ACCUM] rev_reg_req2['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req3, rev_reg_reply3 = sdk_send_and_check([ json.dumps( sdk_sign_request_from_dict(looper, sdk_wallet_steward, rev_reg_req2['operation'])) ], looper, txnPoolNodeSet, sdk_pool_handle)[0] reg_delta_req = copy.deepcopy(build_get_revoc_reg_delta) reg_delta_req['operation'][REVOC_REG_DEF_ID] = rev_reg_req1['operation'][ REVOC_REG_DEF_ID] reg_delta_req['operation'][FROM] = get_txn_time(rev_reg_reply1['result']) reg_delta_req['operation'][TO] = get_txn_time( rev_reg_reply3['result']) + 1000 get_reply = sdk_send_and_check([json.dumps(reg_delta_req)], looper, txnPoolNodeSet, sdk_pool_handle)[0][1] assert get_reply['result'][DATA][STATE_PROOF_FROM] assert get_reply['result'][DATA][VALUE][REVOKED] == [1, 2, 3] assert get_reply['result'][DATA][VALUE][ISSUED] == [10, 11] assert get_reply['result'][DATA][VALUE][ACCUM_TO][VALUE][ ACCUM] == rev_reg_req3['operation'][VALUE][ACCUM] assert get_reply['result'][DATA][VALUE][ACCUM_FROM][VALUE][ACCUM] == \ get_payload_data(rev_reg_reply1['result'])[VALUE][ACCUM]
def update_state(self, txn, prev_result, request, is_committed=False): self._validate_txn_type(txn) payload = get_payload_data(txn) text = payload.get(TXN_AUTHOR_AGREEMENT_TEXT) version = payload[TXN_AUTHOR_AGREEMENT_VERSION] seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) self._update_txn_author_agreement(seq_no, txn_time, text, version)
def test_send_with_from_by_demand(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, send_revoc_reg_entry_by_demand, build_get_revoc_reg_delta): # We save timestamp of state changes. # looper and txnPoolNodeSet has "module", therefore, # when we send request with FROM section, it's not a clean situation looper.runFor(3) # Assume, that send_revoc_reg_entry_by_demand will add into issued [1,2,3,4,5] rev_reg_req1, rev_reg_reply1 = send_revoc_reg_entry_by_demand rev_reg_req1['operation'][VALUE][ISSUED] = [] # Revoked [1,2,3], Issued now must be [4,5] rev_reg_req1['operation'][VALUE][REVOKED] = [1, 2, 3] rev_reg_req1['operation'][VALUE][PREV_ACCUM] = rev_reg_req1['operation'][VALUE][ACCUM] rev_reg_req1['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req2, rev_reg_reply2 = sdk_send_and_check( [json.dumps(sdk_sign_request_from_dict( looper, sdk_wallet_steward, rev_reg_req1['operation']))], looper, txnPoolNodeSet, sdk_pool_handle)[0] # Issued [10, 11] rev_reg_req2['operation'][VALUE][ISSUED] = [10, 11] rev_reg_req2['operation'][VALUE][REVOKED] = [] rev_reg_req2['operation'][VALUE][PREV_ACCUM] = rev_reg_req2['operation'][VALUE][ACCUM] rev_reg_req2['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req3, rev_reg_reply3 = sdk_send_and_check( [json.dumps(sdk_sign_request_from_dict( looper, sdk_wallet_steward, rev_reg_req2['operation']))], looper, txnPoolNodeSet, sdk_pool_handle)[0] reg_delta_req = copy.deepcopy(build_get_revoc_reg_delta) reg_delta_req['operation'][REVOC_REG_DEF_ID] = rev_reg_req1['operation'][REVOC_REG_DEF_ID] reg_delta_req['operation'][FROM] = get_txn_time(rev_reg_reply1['result']) reg_delta_req['operation'][TO] = get_txn_time(rev_reg_reply3['result']) + 1000 get_reply = sdk_send_and_check([json.dumps(reg_delta_req)], looper, txnPoolNodeSet, sdk_pool_handle)[0][1] assert get_reply['result'][DATA][STATE_PROOF_FROM] assert get_reply['result'][DATA][VALUE][REVOKED] == [1, 2, 3] assert get_reply['result'][DATA][VALUE][ISSUED] == [10, 11] assert get_reply['result'][DATA][VALUE][ACCUM_TO][VALUE][ACCUM] == rev_reg_req3['operation'][VALUE][ACCUM] assert get_reply['result'][DATA][VALUE][ACCUM_FROM][VALUE][ACCUM] == \ get_payload_data(rev_reg_reply1['result'])[VALUE][ACCUM]
def update_state(self, txn, prev_result, request, is_committed=False): self._validate_txn_type(txn) payload = get_payload_data(txn) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) serialized_data = encode_state_value(payload, seq_no, txn_time, serializer=config_state_serializer) version = payload[AML_VERSION] self.state.set(StaticTAAHelper.state_path_taa_aml_latest(), serialized_data) self.state.set(StaticTAAHelper.state_path_taa_aml_version(version), serialized_data)
def updateNym(self, nym, txn, isCommitted=True): updatedData = super().updateNym(nym, txn, isCommitted=isCommitted) txn_time = get_txn_time(txn) self.idrCache.set(nym, seqNo=get_seq_no(txn), txnTime=txn_time, ta=updatedData.get(f.IDENTIFIER.nm), role=updatedData.get(ROLE), verkey=updatedData.get(VERKEY), isCommitted=isCommitted)
def update_state(self, txn, prev_result, request, is_committed=False): self._validate_txn_type(txn) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) ledgers_ids = get_payload_data(txn)[LEDGERS_IDS] frozen_ledgers = self.make_frozen_ledgers_list(ledgers_ids) self.state.set( StaticLedgersFreezeHelper.make_state_path_for_frozen_ledgers(), encode_state_value(frozen_ledgers, seq_no, txn_time)) return txn
def updateNym(self, nym, txn, isCommitted=True): updatedData = super().updateNym(nym, txn, isCommitted=isCommitted) txn_time = get_txn_time(txn) self.idrCache.set(nym, seqNo=get_seq_no(txn), txnTime=txn_time, ta=updatedData.get(f.IDENTIFIER.nm), role=updatedData.get(ROLE), verkey=updatedData.get(VERKEY), isCommitted=isCommitted)
def prepare_schema_for_state(txn): origin = get_from(txn) schema_name = get_txn_schema_name(txn) schema_version = get_txn_schema_version(txn) value = {SCHEMA_ATTR_NAMES: get_txn_schema_attr_names(txn)} path = make_state_path_for_schema(origin, schema_name, schema_version) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(value, seq_no, txn_time) return path, value_bytes
def update_state(self, txn, prev_result, request, is_committed=False): txn_time = get_txn_time(txn) nym = get_payload_data(txn).get(TARGET_NYM) self.database_manager.idr_cache.set(nym, seqNo=get_seq_no(txn), txnTime=txn_time, ta=prev_result.get(f.IDENTIFIER.nm), role=prev_result.get(ROLE), verkey=prev_result.get(VERKEY), isCommitted=is_committed)
def prepare_schema_for_state(txn): origin = get_from(txn) txn_data = get_payload_data(txn) data = deepcopy(txn_data.get(DATA)) schema_name = data.pop(NAME) schema_version = data.pop(VERSION) path = make_state_path_for_schema(origin, schema_name, schema_version) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(data, seq_no, txn_time) return path, value_bytes
def prepare_schema_for_state(txn): origin = get_from(txn) txn_data = get_payload_data(txn) data = deepcopy(txn_data.get(DATA)) schema_name = data.pop(NAME) schema_version = data.pop(VERSION) path = make_state_path_for_schema(origin, schema_name, schema_version) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(data, seq_no, txn_time) return path, value_bytes
def test_state_proof_returned_for_get_revoc_reg_delta(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, send_revoc_reg_entry_by_default, build_get_revoc_reg_delta): # We save timestamp of state changes. # looper and txnPoolNodeSet has "module" scope, therefore, # when we send request with FROM section, it's not a clean situation looper.runFor(3) # Assume, that send_revoc_reg_entry_by_default will add into revoked [1,2,3,4,5] rev_reg_req1, rev_reg_reply1 = send_revoc_reg_entry_by_default rev_reg_req1['operation'][VALUE][REVOKED] = [] # Issue [1,2,3], Revoked now must be [4,5] rev_reg_req1['operation'][VALUE][ISSUED] = [1, 2, 3] rev_reg_req1['operation'][VALUE][PREV_ACCUM] = rev_reg_req1['operation'][VALUE][ACCUM] rev_reg_req1['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req2, rev_reg_reply2 = sdk_send_and_check( [json.dumps(sdk_sign_request_from_dict( looper, sdk_wallet_steward, rev_reg_req1['operation']))], looper, txnPoolNodeSet, sdk_pool_handle)[0] # Revoke [10, 11] rev_reg_req2['operation'][VALUE][REVOKED] = [10, 11] rev_reg_req2['operation'][VALUE][ISSUED] = [] rev_reg_req2['operation'][VALUE][PREV_ACCUM] = rev_reg_req2['operation'][VALUE][ACCUM] rev_reg_req2['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req3, rev_reg_reply3 = sdk_send_and_check( [json.dumps(sdk_sign_request_from_dict( looper, sdk_wallet_steward, rev_reg_req2['operation']))], looper, txnPoolNodeSet, sdk_pool_handle)[0] reg_delta_req = copy.deepcopy(build_get_revoc_reg_delta) reg_delta_req['operation'][REVOC_REG_DEF_ID] = rev_reg_req1['operation'][REVOC_REG_DEF_ID] reg_delta_req['operation'][FROM] = get_txn_time(rev_reg_reply1['result']) reg_delta_req['operation'][TO] = get_txn_time(rev_reg_reply3['result']) + 1000 sdk_reply = sdk_send_and_check([json.dumps(reg_delta_req)], looper, txnPoolNodeSet, sdk_pool_handle) reply = sdk_reply[0][1] check_valid_proof(reply)
def test_state_proof_returned_for_get_revoc_reg_delta( looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, send_revoc_reg_entry_by_default, build_get_revoc_reg_delta): # We save timestamp of state changes. # looper and txnPoolNodeSet has "module" scope, therefore, # when we send request with FROM section, it's not a clean situation looper.runFor(3) # Assume, that send_revoc_reg_entry_by_default will add into revoked [1,2,3,4,5] rev_reg_req1, rev_reg_reply1 = send_revoc_reg_entry_by_default rev_reg_req1['operation'][VALUE][REVOKED] = [] # Issue [1,2,3], Revoked now must be [4,5] rev_reg_req1['operation'][VALUE][ISSUED] = [1, 2, 3] rev_reg_req1['operation'][VALUE][PREV_ACCUM] = rev_reg_req1['operation'][ VALUE][ACCUM] rev_reg_req1['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req2, rev_reg_reply2 = sdk_send_and_check([ json.dumps( sdk_sign_request_from_dict(looper, sdk_wallet_steward, rev_reg_req1['operation'])) ], looper, txnPoolNodeSet, sdk_pool_handle)[0] # Revoke [10, 11] rev_reg_req2['operation'][VALUE][REVOKED] = [10, 11] rev_reg_req2['operation'][VALUE][ISSUED] = [] rev_reg_req2['operation'][VALUE][PREV_ACCUM] = rev_reg_req2['operation'][ VALUE][ACCUM] rev_reg_req2['operation'][VALUE][ACCUM] = randomString(10) rev_reg_req3, rev_reg_reply3 = sdk_send_and_check([ json.dumps( sdk_sign_request_from_dict(looper, sdk_wallet_steward, rev_reg_req2['operation'])) ], looper, txnPoolNodeSet, sdk_pool_handle)[0] reg_delta_req = copy.deepcopy(build_get_revoc_reg_delta) reg_delta_req['operation'][REVOC_REG_DEF_ID] = rev_reg_req1['operation'][ REVOC_REG_DEF_ID] reg_delta_req['operation'][FROM] = get_txn_time(rev_reg_reply1['result']) reg_delta_req['operation'][TO] = get_txn_time( rev_reg_reply3['result']) + 1000 sdk_reply = sdk_send_and_check([json.dumps(reg_delta_req)], looper, txnPoolNodeSet, sdk_pool_handle) reply = sdk_reply[0][1] check_valid_proof(reply)
def test_choose_ts_from_state(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1) primary_node = get_master_primary_node(txnPoolNodeSet) excpected_ts = get_utc_epoch() + 30 req_handler = primary_node.get_req_handler(DOMAIN_LEDGER_ID) req_handler.ts_store.set(excpected_ts, req_handler.state.headHash) primary_node.master_replica.last_accepted_pre_prepare_time = None reply = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1)[0][1] assert abs(excpected_ts - int(get_txn_time(reply['result']))) < 3
def _addNym(self, txn, isCommitted=False) -> None: txn_data = get_payload_data(txn) nym = txn_data.get(TARGET_NYM) data = { f.IDENTIFIER.nm: get_from(txn), f.SEQ_NO.nm: get_seq_no(txn), TXN_TIME: get_txn_time(txn) } if ROLE in txn_data: data[ROLE] = txn_data.get(ROLE) if VERKEY in txn_data: data[VERKEY] = txn_data.get(VERKEY) self.updateNym(nym, txn, isCommitted=isCommitted)
def _addNym(self, txn, isCommitted=False) -> None: txn_data = get_payload_data(txn) nym = txn_data.get(TARGET_NYM) data = { f.IDENTIFIER.nm: get_from(txn), f.SEQ_NO.nm: get_seq_no(txn), TXN_TIME: get_txn_time(txn) } if ROLE in txn_data: data[ROLE] = txn_data.get(ROLE) if VERKEY in txn_data: data[VERKEY] = txn_data.get(VERKEY) self.updateNym(nym, txn, isCommitted=isCommitted)
def update_version(self, txn): if get_type(txn) == POOL_UPGRADE and get_payload_data(txn).get(ACTION) == START: N = len(get_payload_data(txn).get(SCHEDULE, {})) self._f = (N - 1) // 3 elif get_type(txn) == NODE_UPGRADE and get_payload_data(txn)[DATA][ACTION] == COMPLETE: version = get_payload_data(txn)[DATA][VERSION] self._votes_for_new_version.setdefault(version, set()) self._votes_for_new_version[version].add(get_from(txn)) if len(self._votes_for_new_version[version]) > self._f: self._versions[get_txn_time(txn)] = version self._votes_for_new_version = SortedDict({v: senders for v, senders in self._votes_for_new_version.items() if v > version})
def reg_entry_with_other_reg_id(looper, sdk_wallet_steward, add_another_reg_id, create_node_and_not_start): node = create_node_and_not_start revoc_def_txn = add_another_reg_id data = build_revoc_reg_entry_for_given_revoc_reg_def(revoc_def_txn) req = sdk_sign_request_from_dict(looper, sdk_wallet_steward, data) looper.runFor(2) req_handler = node.getDomainReqHandler() txn = append_txn_metadata(reqToTxn(Request(**req)), txn_time=FIRST_ID_TS, seq_no=node.domainLedger.seqNo + 1) req_handler._addRevocRegEntry(txn) req_handler.ts_store.set(get_txn_time(txn), req_handler.state.headHash) return txn
def prepare_context_for_state(txn, path_only=False): origin = get_from(txn) context_name = get_txn_context_name(txn) context_version = get_txn_context_version(txn) value = { CONTEXT_CONTEXT_ARRAY: get_txn_context_context_array(txn) } path = ContextHandler.make_state_path_for_context(origin, context_name, context_version) if path_only: return path seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(value, seq_no, txn_time) return path, value_bytes
def _get_handlers_by_version(self, txn): txn_type = get_type(txn) timestamp = get_txn_time(txn) version = self.database_manager.get_pool_version(timestamp) version = self.config.INDY_VERSION_MATCHING.get(version, version) if (txn_type, version) not in self._request_handlers_with_version: version = self.database_manager.get_txn_version(txn) handlers = self._request_handlers_with_version.get((txn_type, version)) \ if (txn_type, version) in self._request_handlers_with_version \ else self.request_handlers.get(txn_type, None) if handlers is None: raise LogicError return handlers
def restore_state(self, txn, ledger_id): self.database_manager.update_state_version(txn) # TODO: add to TxnVersionController function `get_version(txn)` # to use a version from the txn and update it in the internal TxnVersionController version handlers = self._get_handlers_by_version(get_type(txn), get_txn_time(txn)) updated_state = None for handler in handlers: updated_state = handler.update_state(txn, updated_state, None, is_committed=True) state = self.database_manager.get_state(ledger_id) if state: state.commit(rootHash=state.headHash)
def prepare_attr_for_state(txn): """ Make key(path)-value pair for state from ATTRIB or GET_ATTR :return: state path, state value, value for attribute store """ assert get_type(txn) == ATTRIB txn_data = get_payload_data(txn) nym = txn_data[TARGET_NYM] attr_type, attr_key, value = parse_attr_txn(txn_data) hashed_value = hash_of(value) if value else '' seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(hashed_value, seq_no, txn_time) path = make_state_path_for_attr(nym, attr_key, attr_type == HASH) return attr_type, path, value, hashed_value, value_bytes
def prepare_attr_for_state(txn): """ Make key(path)-value pair for state from ATTRIB or GET_ATTR :return: state path, state value, value for attribute store """ assert get_type(txn) == ATTRIB txn_data = get_payload_data(txn) nym = txn_data[TARGET_NYM] attr_type, attr_key, value = parse_attr_txn(txn_data) hashed_value = hash_of(value) if value else '' seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(hashed_value, seq_no, txn_time) path = make_state_path_for_attr(nym, attr_key, attr_type == HASH) return attr_type, path, value, hashed_value, value_bytes
def reg_entry_with_other_reg_id(looper, sdk_wallet_steward, add_another_reg_id, create_node_and_not_start): node = create_node_and_not_start revoc_def_txn = add_another_reg_id data = build_revoc_reg_entry_for_given_revoc_reg_def(revoc_def_txn) req = sdk_sign_request_from_dict(looper, sdk_wallet_steward, data) looper.runFor(2) req_handler = node.getDomainReqHandler() txn = append_txn_metadata(reqToTxn(Request(**req)), txn_time=FIRST_ID_TS, seq_no=node.domainLedger.seqNo + 1) req_handler._addRevocRegEntry(txn) req_handler.ts_store.set(get_txn_time(txn), req_handler.state.headHash) return txn
def prepare_claim_def_for_state(txn): txn_data = get_payload_data(txn) origin = get_from(txn) schema_seq_no = txn_data.get(REF) if schema_seq_no is None: raise ValueError("'{}' field is absent, " "but it must contain schema seq no".format(REF)) data = txn_data.get(DATA) if data is None: raise ValueError("'{}' field is absent, " "but it must contain components of keys" .format(DATA)) signature_type = txn_data.get(SIGNATURE_TYPE, 'CL') path = make_state_path_for_claim_def(origin, schema_seq_no, signature_type) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) value_bytes = encode_state_value(data, seq_no, txn_time) return path, value_bytes
def prepare_revoc_reg_entry_accum_for_state(txn): author_did = get_from(txn) txn_data = get_payload_data(txn) revoc_reg_def_id = txn_data.get(REVOC_REG_DEF_ID) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) assert author_did assert revoc_reg_def_id assert seq_no assert txn_time path = make_state_path_for_revoc_reg_entry_accum(revoc_reg_def_id=revoc_reg_def_id) # TODO: do not duplicate seqNo here # doing this now just for backward-compatibility txn_data = deepcopy(txn_data) txn_data[f.SEQ_NO.nm] = seq_no txn_data[TXN_TIME] = txn_time value_bytes = encode_state_value(txn_data, seq_no, txn_time) return path, value_bytes
def prepare_revoc_def_for_state(txn): author_did = get_from(txn) txn_data = get_payload_data(txn) cred_def_id = txn_data.get(CRED_DEF_ID) revoc_def_type = txn_data.get(REVOC_TYPE) revoc_def_tag = txn_data.get(TAG) assert author_did assert cred_def_id assert revoc_def_type assert revoc_def_tag path = make_state_path_for_revoc_def(author_did, cred_def_id, revoc_def_type, revoc_def_tag) seq_no = get_seq_no(txn) txn_time = get_txn_time(txn) assert seq_no assert txn_time value_bytes = encode_state_value(txn_data, seq_no, txn_time) return path, value_bytes
def test_choose_ts_from_state(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward): sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1) primary_node = get_master_primary_node(txnPoolNodeSet) excpected_ts = get_utc_epoch() + 30 req_handler = primary_node.get_req_handler(DOMAIN_LEDGER_ID) req_handler.ts_store.set(excpected_ts, req_handler.state.headHash) primary_node.master_replica.last_accepted_pre_prepare_time = None reply = sdk_send_random_and_check(looper, txnPoolNodeSet, sdk_pool_handle, sdk_wallet_steward, 1)[0][1] assert abs(excpected_ts - int(get_txn_time(reply['result']))) < 3
def test_get_txn_time_none(txn): txn["txnMetadata"].pop("txnTime", None) assert get_txn_time(txn) is None
def test_get_txn_time(txn): assert get_txn_time(txn) == 1513945121