def get_result(self, request: Request): self._validate_request_type(request) req_ts = request.operation.get(TIMESTAMP) revoc_reg_def_id = request.operation.get(REVOC_REG_DEF_ID) # Get root hash corresponding with given timestamp past_root = self.database_manager.ts_store.get_equal_or_prev(req_ts) # Path to corresponding ACCUM record in state path = RevocRegEntryHandler.make_state_path_for_revoc_reg_entry_accum(revoc_reg_def_id=revoc_reg_def_id) entry_state = StateValue() if past_root is not None: encoded_entry, proof = self._get_value_from_state(path, head_hash=past_root, with_proof=True) entry_state.proof = proof if encoded_entry: revoc_reg_entry_accum, seq_no, last_update_time = decode_state_value(encoded_entry) entry_state = StateValue(root_hash=past_root, value=revoc_reg_entry_accum, seq_no=seq_no, update_time=last_update_time, proof=proof) return self.make_result(request=request, data=entry_state.value, last_seq_no=entry_state.seq_no, update_time=entry_state.update_time, proof=entry_state.proof)
def _return_txn_author_agreement_aml(self, request, proof, data=None): if data is not None: value, last_seq_no, last_update_time = decode_state_value( data, serializer=config_state_serializer) return self.make_result(request, value, last_seq_no, last_update_time, proof) return self.make_result(request, None, proof=proof)
def get_frozen_ledgers(config_state, is_committed=True): if not config_state: return {} encoded = config_state.get(StaticLedgersFreezeHelper.make_state_path_for_frozen_ledgers(), isCommitted=is_committed) if not encoded: return {} state_frozen_ledgers, _, _ = decode_state_value(encoded) frozen_ledgers = {int(key): value for (key, value) in state_frozen_ledgers.items()} return frozen_ledgers
def _return_txn_author_agreement(self, request, proof, head_hash=None, digest=None, data=None): if digest is not None: head_hash = head_hash if head_hash else self.state.committedHeadHash data = self.state.get_for_root_hash(head_hash, self._state_path_taa_digest(digest.decode())) if data is not None: value, last_seq_no, last_update_time = decode_state_value(data, serializer=config_state_serializer) return self.make_config_result(request, value, last_seq_no, last_update_time, proof) return self.make_config_result(request, None, proof=proof)
def get_taa_data(self, digest: Optional[str] = None, version: Optional[str] = None, isCommitted: bool = True) -> Optional[Tuple[Dict, str]]: data = None if digest is None: digest = self.get_taa_digest(version=version, isCommitted=isCommitted) if digest is not None: data = self.config_state.get(self._state_path_taa_digest(digest), isCommitted=isCommitted) if data is not None: data = decode_state_value(data, serializer=config_state_serializer) return None if data is None else (data, digest)
def lookup(self, path, is_committed=True, with_proof=False) -> (str, int): """ Queries state for data on specified path :param path: path to data :param is_committed: queries the committed state root if True else the uncommitted root :param with_proof: creates proof if True :return: data """ assert path is not None head_hash = self.state.committedHeadHash if is_committed else self.state.headHash encoded, proof = self._get_value_from_state(path, head_hash, with_proof=with_proof) if encoded: value, last_seq_no, last_update_time = decode_state_value(encoded) return value, last_seq_no, last_update_time, proof return None, None, None, proof
def _get_reg_entry_by_timestamp(self, timestamp, path_to_reg_entry): reg_entry = None seq_no = None last_update_time = None reg_entry_proof = None past_root = self.database_manager.ts_store.get_equal_or_prev(timestamp) if past_root: encoded_entry, reg_entry_proof = self._get_value_from_state( path_to_reg_entry, head_hash=past_root, with_proof=True) if encoded_entry: reg_entry, seq_no, last_update_time = decode_state_value( encoded_entry) return StateValue(root_hash=past_root, value=reg_entry, seq_no=seq_no, update_time=last_update_time, proof=reg_entry_proof)
def get_result(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 """ self._validate_request_type(request) 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 = RevocRegEntryHandler.make_state_path_for_revoc_reg_entry( revoc_reg_def_id=revoc_reg_def_id) path_to_reg_entry_accum = RevocRegEntryHandler.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, _, _ = 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: 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 if reply is None and req_ts_from is not None: # TODO: change this according to INDY-2115 reply = {} accum_from = self._get_reg_entry_accum_by_timestamp( req_ts_from, path_to_reg_entry_accum) reply[STATE_PROOF_FROM] = accum_from.proof reply[VALUE] = {} reply[VALUE][ACCUM_TO] = None reply[VALUE][ACCUM_FROM] = accum_from.value 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 _decode_state_value(self, encoded): if encoded: value, last_seq_no, last_update_time = decode_state_value(encoded) return value, last_seq_no, last_update_time return None, None, None
def _decode_state_value(self, encoded): if encoded: value, last_seq_no, last_update_time = decode_state_value( encoded, serializer=config_state_serializer) return value, last_seq_no, last_update_time return None, None, None