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_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 getRevocDefEntry(self, revoc_reg_def_id, isCommitted=True) -> (str, int, int, list): assert revoc_reg_def_id path = domain.make_state_path_for_revoc_reg_entry(revoc_reg_def_id=revoc_reg_def_id) try: keys, seqno, lastUpdateTime, proof = self.lookup(path, isCommitted, with_proof=False) return keys, seqno, lastUpdateTime, proof except KeyError: return None, None, None, None
def _get_revoc_def_entry(self, revoc_reg_def_id, is_committed=True) -> (str, int, int, list): assert revoc_reg_def_id path = domain.make_state_path_for_revoc_reg_entry( revoc_reg_def_id=revoc_reg_def_id) try: keys, seq_no, last_update_time, proof = self.lookup( path, is_committed, with_proof=True) return keys, seq_no, last_update_time, proof except KeyError: return None, None, None, None
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, sdk_wallet_steward): entry_second_id = build_txn_for_revoc_def_entry_by_default delta_req = build_get_revoc_reg_delta(looper, sdk_wallet_steward) node = create_node_and_not_start # need for different txnTime looper.runFor(2) txn = append_txn_metadata(reqToTxn(entry_second_id), txn_time=SECOND_TS_ID, seq_no=node.domainLedger.seqNo + 1) node.write_manager.update_state(txn) node.db_manager.ts_store.set(get_txn_time(txn), node.getState(DOMAIN_LEDGER_ID).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]) req_handler = None for h in node.read_manager.request_handlers.values(): if isinstance(h, GetRevocRegDeltaHandler): req_handler = h 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 handleGetRevocRegDelta(self, request: Request): """ For getting reply we need: 1. Get REVOC_REG_ENTRY by "TO" timestamp from state 2. If FROM is given in request, then Get REVOC_REG_ENTRY by "FROM" timestamp from state 3. Get ISSUANCE_TYPE for REVOC_REG_DEF (revoked/issued strategy) 4. Compute issued and revoked indices by corresponding strategy 5. Make result 5.1 Now, if "FROM" is presented in request, then STATE_PROOF_FROM and ACCUM (revocation entry for "FROM" timestamp) will added into data section 5.2 If not, then only STATE_PROOF for "TO" revocation entry will added :param request: :return: Reply """ req_ts_from = request.operation.get(FROM, None) req_ts_to = request.operation.get(TO) revoc_reg_def_id = request.operation.get(REVOC_REG_DEF_ID) author_did = request.identifier reply = None # Get root hash for "to" timestamp # Get REVOC_REG_ENTRY and ACCUM record for timestamp "to" path_to_reg_entry = domain.make_state_path_for_revoc_reg_entry( authors_did=author_did, revoc_reg_def_id=revoc_reg_def_id) path_to_reg_entry_accum = domain.make_state_path_for_revoc_reg_entry_accum( authors_did=author_did, revoc_reg_def_id=revoc_reg_def_id) past_root_to, reg_entry_to = self._get_reg_entry_by_timestamp( req_ts_to, path_to_reg_entry) reg_entry_accum_to, \ seq_no_to, \ last_update_time_to, \ reg_entry_accum_proof_to = self._get_reg_entry_accum_by_timestamp(req_ts_to, path_to_reg_entry_accum) if past_root_to: # Get issuance type from REVOC_REG_DEF encoded_revoc_reg_def = self.state.get_for_root_hash( past_root_to, revoc_reg_def_id) assert encoded_revoc_reg_def revoc_reg_def, _, _ = domain.decode_state_value( encoded_revoc_reg_def) strategy_cls = self.get_revocation_strategy( revoc_reg_def[VALUE][ISSUANCE_TYPE]) if req_ts_from: past_root_from, reg_entry_from = self._get_reg_entry_by_timestamp( req_ts_from, path_to_reg_entry) req_entry_accum_from, \ seq_no_from, \ last_update_time_from, \ reg_entry_accum_proof_from = self._get_reg_entry_accum_by_timestamp(req_ts_from, path_to_reg_entry_accum) # Compute issued/revoked lists corresponding with ISSUANCE_TYPE strategy result_issued, result_revoked = strategy_cls.get_delta( { ISSUED: reg_entry_to[VALUE][ISSUED], REVOKED: reg_entry_to[VALUE][REVOKED] }, { ISSUED: reg_entry_from[VALUE][ISSUED], REVOKED: reg_entry_from[VALUE][REVOKED] }) else: result_issued, result_revoked = strategy_cls.get_delta( { ISSUED: reg_entry_to[VALUE][ISSUED], REVOKED: reg_entry_to[VALUE][REVOKED] }, None) reply = { REVOC_REG_ID: str(path_to_reg_entry), REVOC_TYPE: revoc_reg_def.get(REVOC_TYPE), VALUE: { ACCUM_TO: reg_entry_accum_to, ISSUED: result_issued, REVOKED: result_revoked } } # If we got "from" timestamp, then add state proof into "data" section of reply if req_ts_from: reply[STATE_PROOF_FROM] = reg_entry_accum_proof_from reply[VALUE][ACCUM_FROM] = req_entry_accum_from return self.make_result(request=request, data=reply, last_seq_no=seq_no_to, update_time=last_update_time_to, proof=reg_entry_accum_proof_to)
def handleGetRevocRegDelta(self, request: Request): """ For getting reply we need: 1. Get REVOC_REG_ENTRY by "TO" timestamp from state 2. If FROM is given in request, then Get REVOC_REG_ENTRY by "FROM" timestamp from state 3. Get ISSUANCE_TYPE for REVOC_REG_DEF (revoked/issued strategy) 4. Compute issued and revoked indices by corresponding strategy 5. Make result 5.1 Now, if "FROM" is presented in request, then STATE_PROOF_FROM and ACCUM (revocation entry for "FROM" timestamp) will added into data section 5.2 If not, then only STATE_PROOF for "TO" revocation entry will added :param request: :return: Reply """ req_ts_from = request.operation.get(FROM, None) req_ts_to = request.operation.get(TO) revoc_reg_def_id = request.operation.get(REVOC_REG_DEF_ID) reply = None """ Get root hash for "to" timestamp Get REVOC_REG_ENTRY and ACCUM record for timestamp "to" """ path_to_reg_entry = domain.make_state_path_for_revoc_reg_entry(revoc_reg_def_id=revoc_reg_def_id) path_to_reg_entry_accum = domain.make_state_path_for_revoc_reg_entry_accum(revoc_reg_def_id=revoc_reg_def_id) entry_to = self._get_reg_entry_by_timestamp(req_ts_to, path_to_reg_entry) accum_to = self._get_reg_entry_accum_by_timestamp(req_ts_to, path_to_reg_entry_accum) entry_from = StateValue() accum_from = StateValue() if accum_to.value and entry_to.value: """Get issuance type from REVOC_REG_DEF""" encoded_revoc_reg_def = self.state.get_for_root_hash(entry_to.root_hash, revoc_reg_def_id) if encoded_revoc_reg_def: revoc_reg_def, _, _ = domain.decode_state_value(encoded_revoc_reg_def) strategy_cls = self.get_revocation_strategy(revoc_reg_def[VALUE][ISSUANCE_TYPE]) issued_to = entry_to.value[VALUE].get(ISSUED, []) revoked_to = entry_to.value[VALUE].get(REVOKED, []) if req_ts_from: """Get REVOC_REG_ENTRY and ACCUM records for timestamp from if exist""" entry_from = self._get_reg_entry_by_timestamp(req_ts_from, path_to_reg_entry) accum_from = self._get_reg_entry_accum_by_timestamp(req_ts_from, path_to_reg_entry_accum) if req_ts_from and entry_from.value and accum_from.value: """Compute issued/revoked lists corresponding with ISSUANCE_TYPE strategy""" issued_from = entry_from.value[VALUE].get(ISSUED, []) revoked_from = entry_from.value[VALUE].get(REVOKED, []) result_issued, result_revoked = strategy_cls.get_delta({ISSUED: issued_to, REVOKED: revoked_to}, {ISSUED: issued_from, REVOKED: revoked_from}) else: result_issued, result_revoked = strategy_cls.get_delta({ISSUED: issued_to, REVOKED: revoked_to}, None) reply = { REVOC_REG_DEF_ID: revoc_reg_def_id, REVOC_TYPE: revoc_reg_def.get(REVOC_TYPE), VALUE: { ACCUM_TO: accum_to.value if entry_from.value else entry_to.value, ISSUED: result_issued, REVOKED: result_revoked } } """If we got "from" timestamp, then add state proof into "data" section of reply""" if req_ts_from and accum_from.value: reply[STATE_PROOF_FROM] = accum_from.proof reply[VALUE][ACCUM_FROM] = accum_from.value if accum_to and entry_to: seq_no = accum_to.seq_no if entry_from.value else entry_to.seq_no update_time = accum_to.update_time if entry_from.value else entry_to.update_time proof = accum_to.proof if entry_from.value else entry_to.proof else: seq_no = None update_time = None proof = None return self.make_result(request=request, data=reply, last_seq_no=seq_no, update_time=update_time, proof=proof)
def handleGetRevocRegDelta(self, request: Request): """ For getting reply we need: 1. Get REVOC_REG_ENTRY by "TO" timestamp from state 2. If FROM is given in request, then Get REVOC_REG_ENTRY by "FROM" timestamp from state 3. Get ISSUANCE_TYPE for REVOC_REG_DEF (revoked/issued strategy) 4. Compute issued and revoked indices by corresponding strategy 5. Make result 5.1 Now, if "FROM" is presented in request, then STATE_PROOF_FROM and ACCUM (revocation entry for "FROM" timestamp) will added into data section 5.2 If not, then only STATE_PROOF for "TO" revocation entry will added :param request: :return: Reply """ req_ts_from = request.operation.get(FROM, None) req_ts_to = request.operation.get(TO) revoc_reg_def_id = request.operation.get(REVOC_REG_DEF_ID) reply = { REVOC_REG_DEF_ID: revoc_reg_def_id, } """ Get root hash for "to" timestamp Get REVOC_REG_ENTRY and ACCUM record for timestamp "to" """ path_to_reg_entry = domain.make_state_path_for_revoc_reg_entry(revoc_reg_def_id=revoc_reg_def_id) path_to_reg_entry_accum = domain.make_state_path_for_revoc_reg_entry_accum(revoc_reg_def_id=revoc_reg_def_id) entry_to = self._get_reg_entry_by_timestamp(req_ts_to, path_to_reg_entry) accum_to = self._get_reg_entry_accum_by_timestamp(req_ts_to, path_to_reg_entry_accum) entry_from = StateValue() accum_from = StateValue() if accum_to.value and entry_to.value: """Get issuance type from REVOC_REG_DEF""" encoded_revoc_reg_def = self.state.get_for_root_hash(entry_to.root_hash, revoc_reg_def_id) if encoded_revoc_reg_def: revoc_reg_def, _, _ = domain.decode_state_value(encoded_revoc_reg_def) strategy_cls = self.get_revocation_strategy(revoc_reg_def[VALUE][ISSUANCE_TYPE]) issued_to = entry_to.value[VALUE].get(ISSUED, []) revoked_to = entry_to.value[VALUE].get(REVOKED, []) if req_ts_from: """Get REVOC_REG_ENTRY and ACCUM records for timestamp from if exist""" entry_from = self._get_reg_entry_by_timestamp(req_ts_from, path_to_reg_entry) accum_from = self._get_reg_entry_accum_by_timestamp(req_ts_from, path_to_reg_entry_accum) if req_ts_from and entry_from.value and accum_from.value: """Compute issued/revoked lists corresponding with ISSUANCE_TYPE strategy""" issued_from = entry_from.value[VALUE].get(ISSUED, []) revoked_from = entry_from.value[VALUE].get(REVOKED, []) result_issued, result_revoked = strategy_cls.get_delta({ISSUED: issued_to, REVOKED: revoked_to}, {ISSUED: issued_from, REVOKED: revoked_from}) else: result_issued, result_revoked = strategy_cls.get_delta({ISSUED: issued_to, REVOKED: revoked_to}, None) reply = { REVOC_REG_DEF_ID: revoc_reg_def_id, REVOC_TYPE: revoc_reg_def.get(REVOC_TYPE), VALUE: { ACCUM_TO: accum_to.value if entry_from.value else entry_to.value, ISSUED: result_issued, REVOKED: result_revoked } } """If we got "from" timestamp, then add state proof into "data" section of reply""" if req_ts_from and accum_from.value: reply[STATE_PROOF_FROM] = accum_from.proof reply[VALUE][ACCUM_FROM] = accum_from.value if accum_to and entry_to: seq_no = accum_to.seq_no if entry_from.value else entry_to.seq_no update_time = accum_to.update_time if entry_from.value else entry_to.update_time proof = accum_to.proof if entry_from.value else entry_to.proof else: seq_no = None update_time = None proof = None return self.make_result(request=request, data=reply, last_seq_no=seq_no, update_time=update_time, proof=proof)