diff --git a/src/qrl/core/ChainManager.py b/src/qrl/core/ChainManager.py index 000ec782b..636a6984e 100644 --- a/src/qrl/core/ChainManager.py +++ b/src/qrl/core/ChainManager.py @@ -100,56 +100,61 @@ def get_address_is_used(self, address: bytes) -> bool: with self.lock: return self._state.get_address_is_used(address) - def get_address_state(self, address: bytes) -> AddressState: + def get_address_state(self, + address: bytes, + exclude_ots_bitfield: bool = False, + exclude_transaction_hashes: bool = False) -> AddressState: """ Transform Optimized Address State into Older Address State format This should only be used by API. """ optimized_address_state = self.get_optimized_address_state(address) - ots_bitfield = [b'\x00'] * max(1024, int(ceil((2 ** optimized_address_state.height) / 8))) + ots_bitfield = [] transaction_hashes = list() tokens = OrderedDict() slave_pks_access_type = OrderedDict() max_bitfield_page = ceil((2 ** optimized_address_state.height) / config.dev.ots_tracking_per_page) - - for page in range(1, max_bitfield_page + 1): - offset = (page - 1) * config.dev.ots_tracking_per_page - page_data = self.get_bitfield(address, page) - for data in page_data: - if offset >= len(ots_bitfield): - break - ots_bitfield[offset] = data - offset += 1 - - max_transaction_hash_page = ceil(optimized_address_state.transaction_hash_count() / config.dev.data_per_page) - - for page in range(0, max_transaction_hash_page + 1): - page_data = self.get_transaction_hashes(address, page * config.dev.data_per_page) - transaction_hashes.extend(page_data) - - max_token_page = ceil(optimized_address_state.tokens_count() / config.dev.data_per_page) - - for page in range(0, max_token_page + 1): - page_data = self.get_token_transaction_hashes(address, page * config.dev.data_per_page) - for token_txn_hash in page_data: - token_balance = self.get_token(address, token_txn_hash) - # token_balance None is only possible when the token transaction - # is done by a QRL address as an owner, which has not been - # assigned any token balance. - if token_balance is None: - continue - tokens[token_txn_hash] = token_balance.balance - - max_slave_page = ceil(optimized_address_state.slaves_count() / config.dev.data_per_page) - - for page in range(0, max_slave_page + 1): - page_data = self.get_slave_transaction_hashes(address, page * config.dev.data_per_page) - for slave_txn_hash in page_data: - tx, _ = self.get_tx_metadata(slave_txn_hash) - for slave_pk in tx.slave_pks: - slave_meta_data = self.get_slave_pk_access_type(address, slave_pk) - slave_pks_access_type[str(slave_pk)] = slave_meta_data.access_type + if not exclude_ots_bitfield: + ots_bitfield = [b'\x00'] * max(1024, int(ceil((2 ** optimized_address_state.height) / 8))) + for page in range(1, max_bitfield_page + 1): + offset = (page - 1) * config.dev.ots_tracking_per_page + page_data = self.get_bitfield(address, page) + for data in page_data: + if offset >= len(ots_bitfield): + break + ots_bitfield[offset] = data + offset += 1 + + if not exclude_transaction_hashes: + max_transaction_hash_page = ceil(optimized_address_state.transaction_hash_count() / config.dev.data_per_page) + + for page in range(0, max_transaction_hash_page + 1): + page_data = self.get_transaction_hashes(address, page * config.dev.data_per_page) + transaction_hashes.extend(page_data) + + max_token_page = ceil(optimized_address_state.tokens_count() / config.dev.data_per_page) + + for page in range(0, max_token_page + 1): + page_data = self.get_token_transaction_hashes(address, page * config.dev.data_per_page) + for token_txn_hash in page_data: + token_balance = self.get_token(address, token_txn_hash) + # token_balance None is only possible when the token transaction + # is done by a QRL address as an owner, which has not been + # assigned any token balance. + if token_balance is None: + continue + tokens[token_txn_hash] = token_balance.balance + + max_slave_page = ceil(optimized_address_state.slaves_count() / config.dev.data_per_page) + + for page in range(0, max_slave_page + 1): + page_data = self.get_slave_transaction_hashes(address, page * config.dev.data_per_page) + for slave_txn_hash in page_data: + tx, _ = self.get_tx_metadata(slave_txn_hash) + for slave_pk in tx.slave_pks: + slave_meta_data = self.get_slave_pk_access_type(address, slave_pk) + slave_pks_access_type[str(slave_pk)] = slave_meta_data.access_type addr_state = AddressState.create(address=optimized_address_state.address, nonce=optimized_address_state.nonce, diff --git a/src/qrl/core/qrlnode.py b/src/qrl/core/qrlnode.py index 5052fe1dc..47536e801 100644 --- a/src/qrl/core/qrlnode.py +++ b/src/qrl/core/qrlnode.py @@ -372,11 +372,16 @@ def get_address_is_used(self, address: bytes) -> bool: return self._chain_manager.get_address_is_used(address) - def get_address_state(self, address: bytes) -> AddressState: + def get_address_state(self, + address: bytes, + exclude_ots_bitfield: bool = False, + exclude_transaction_hashes: bool = False) -> AddressState: if address != config.dev.coinbase_address and not AddressState.address_is_valid(address): raise ValueError("Invalid Address") - address_state = self._chain_manager.get_address_state(address) + address_state = self._chain_manager.get_address_state(address, + exclude_ots_bitfield, + exclude_transaction_hashes) return address_state @@ -697,11 +702,11 @@ def get_tokens_by_address(self, address: bytes, item_per_page: int, page_number: response = qrl_pb2.GetTokensByAddressResp() for tx_hash in token_hashes: tx, _ = self._chain_manager.get_tx_metadata(tx_hash) - balance = self._chain_manager.get_token(address, tx.txhash) + token_balance = self._chain_manager.get_token(address, tx.txhash) transaction_detail = qrl_pb2.TokenDetail(token_txhash=tx.txhash, name=tx.name, symbol=tx.symbol, - balance=balance) + balance=token_balance.balance) response.tokens_detail.extend([transaction_detail]) return response diff --git a/src/qrl/services/PublicAPIService.py b/src/qrl/services/PublicAPIService.py index afb90f034..1347b90ba 100644 --- a/src/qrl/services/PublicAPIService.py +++ b/src/qrl/services/PublicAPIService.py @@ -106,7 +106,9 @@ def ParseAddress(self, request: qrl_pb2.ParseAddressReq, context) -> qrl_pb2.Par @GrpcExceptionWrapper(qrl_pb2.GetAddressStateResp) def GetAddressState(self, request: qrl_pb2.GetAddressStateReq, context) -> qrl_pb2.GetAddressStateResp: - address_state = self.qrlnode.get_address_state(request.address) + address_state = self.qrlnode.get_address_state(request.address, + request.exclude_ots_bitfield, + request.exclude_transaction_hashes) return qrl_pb2.GetAddressStateResp(state=address_state.pbdata) @GrpcExceptionWrapper(qrl_pb2.GetOptimizedAddressStateResp)