def _get_fees(self, is_committed=False, with_proof=False): fees = {} proof = None try: if with_proof: proof, serz = self.state.generate_state_proof( self.fees_state_key, serialize=True, get_value=True) if serz: serz = rlp_decode(serz)[0] root_hash = self.state.committedHeadHash if is_committed else self.state.headHash encoded_root_hash = state_roots_serializer.serialize( bytes(root_hash)) multi_sig = self.bls_store.get(encoded_root_hash) if multi_sig: encoded_proof = proof_nodes_serializer.serialize(proof) proof = { MULTI_SIGNATURE: multi_sig.as_dict(), ROOT_HASH: encoded_root_hash, PROOF_NODES: encoded_proof } else: proof = {} else: serz = self.state.get(self.fees_state_key, isCommitted=is_committed) if serz: fees = self.state_serializer.deserialize(serz) except KeyError: pass if with_proof: return fees, proof return fees
def make_proof(self, path, head_hash=None): ''' Creates a state proof for the given path in state trie. Returns None if there is no BLS multi-signature for the given state (it can be the case for txns added before multi-signature support). :param path: the path generate a state proof for :return: a state proof or None ''' root_hash = head_hash if head_hash else self.state.committedHeadHash encoded_root_hash = state_roots_serializer.serialize(bytes(root_hash)) multi_sig = self.bls_store.get(encoded_root_hash) if not multi_sig: return None proof = self.state.generate_state_proof(key=path, root=self.state.get_head_by_hash( root_hash), serialize=True) encoded_proof = proof_nodes_serializer.serialize(proof) return { ROOT_HASH: encoded_root_hash, MULTI_SIGNATURE: multi_sig.as_dict(), PROOF_NODES: encoded_proof }
def get_value_from_state(self, path, head_hash=None, with_proof=False, multi_sig=None): ''' Get a value (and proof optionally)for the given path in state trie. Does not return the proof is there is no aggregate signature for it. :param path: the path generate a state proof for :param head_hash: the root to create the proof against :param get_value: whether to return the value :return: a state proof or None ''' root_hash = head_hash if head_hash else self.state.committedHeadHash encoded_root_hash = state_roots_serializer.serialize(bytes(root_hash)) if not with_proof: return self.state.get_for_root_hash(root_hash, path), None if not multi_sig: # Just return the value and not proof try: return self.state.get_for_root_hash(root_hash, path), None except KeyError: return None, None else: try: proof, value = self.state.generate_state_proof( key=path, root=self.state.get_head_by_hash(root_hash), serialize=True, get_value=True) value = self.state.get_decoded(value) if value else value encoded_proof = proof_nodes_serializer.serialize(proof) proof = { ROOT_HASH: encoded_root_hash, MULTI_SIGNATURE: multi_sig.as_dict(), PROOF_NODES: encoded_proof } return value, proof except KeyError: return None, None
def get_all_utxo(self, request: Request): address = request.operation[ADDRESS] encoded_root_hash = state_roots_serializer.serialize( bytes(self.state.committedHeadHash)) proof, rv = self.state.generate_state_proof_for_keys_with_prefix( address, serialize=True, get_value=True) multi_sig = self.bls_store.get(encoded_root_hash) if multi_sig: encoded_proof = proof_nodes_serializer.serialize(proof) proof = { MULTI_SIGNATURE: multi_sig.as_dict(), ROOT_HASH: encoded_root_hash, PROOF_NODES: encoded_proof } else: proof = {} # The outputs need to be returned in sorted order since each node's reply should be same. # Since no of outputs can be large, a concious choice to not use `operator.attrgetter` on an # already constructed list was made outputs = SortedItems() for k, v in rv.items(): addr, seq_no = self.parse_state_key(k.decode()) amount = rlp_decode(v)[0] if not amount: continue outputs.add(Output(addr, int(seq_no), int(amount))) result = { f.IDENTIFIER.nm: request.identifier, f.REQ_ID.nm: request.reqId, OUTPUTS: outputs.sorted_list } if proof: result[STATE_PROOF] = proof result.update(request.operation) return result