def from_spend_bundle(cls, bundle: SpendBundle) -> "Offer": # Because of the `to_spend_bundle` method, we need to parse the dummy CoinSpends as `requested_payments` requested_payments: Dict[Optional[bytes32], List[NotarizedPayment]] = {} leftover_coin_spends: List[CoinSpend] = [] for coin_spend in bundle.coin_spends: if coin_spend.coin.parent_coin_info == ZERO_32: matched, curried_args = match_cat_puzzle( coin_spend.puzzle_reveal.to_program()) if matched: _, tail_hash_program, _ = curried_args tail_hash: Optional[bytes32] = bytes32( tail_hash_program.as_python()) else: tail_hash = None notarized_payments: List[NotarizedPayment] = [] for payment_group in coin_spend.solution.to_program().as_iter( ): nonce = bytes32(payment_group.first().as_python()) payment_args_list: List[Program] = payment_group.rest( ).as_iter() notarized_payments.extend([ NotarizedPayment.from_condition_and_nonce( condition, nonce) for condition in payment_args_list ]) requested_payments[tail_hash] = notarized_payments else: leftover_coin_spends.append(coin_spend) return cls( requested_payments, SpendBundle(leftover_coin_spends, bundle.aggregated_signature))
async def get_block_records_close_to_peak( self, blocks_n: int ) -> Tuple[Dict[bytes32, BlockRecord], Optional[bytes32]]: """ Returns a dictionary with all blocks that have height >= peak height - blocks_n, as well as the peak header hash. """ peak = await self.get_peak() if peak is None: return {}, None ret: Dict[bytes32, BlockRecord] = {} if self.db_wrapper.db_version == 2: async with self.db.execute( "SELECT header_hash, block_record FROM full_blocks WHERE height >= ?", (peak[1] - blocks_n,), ) as cursor: for row in await cursor.fetchall(): header_hash = bytes32(row[0]) ret[header_hash] = BlockRecord.from_bytes(row[1]) else: formatted_str = f"SELECT header_hash, block from block_records WHERE height >= {peak[1] - blocks_n}" async with self.db.execute(formatted_str) as cursor: for row in await cursor.fetchall(): header_hash = bytes32(self.maybe_from_hex(row[0])) ret[header_hash] = BlockRecord.from_bytes(row[1]) return ret, peak[0]
async def get_block_records_in_range( self, start: int, stop: int, ) -> Dict[bytes32, BlockRecord]: """ Returns a dictionary with all blocks in range between start and stop if present. """ ret: Dict[bytes32, BlockRecord] = {} if self.db_wrapper.db_version == 2: async with self.db.execute( "SELECT header_hash, block_record FROM full_blocks WHERE height >= ? AND height <= ?", (start, stop), ) as cursor: for row in await cursor.fetchall(): header_hash = bytes32(row[0]) ret[header_hash] = BlockRecord.from_bytes(row[1]) else: formatted_str = f"SELECT header_hash, block from block_records WHERE height >= {start} and height <= {stop}" async with await self.db.execute(formatted_str) as cursor: for row in await cursor.fetchall(): header_hash = bytes32(self.maybe_from_hex(row[0])) ret[header_hash] = BlockRecord.from_bytes(row[1]) return ret
async def get_unspent_coins_for_wallet( self, wallet_id: int) -> Set[WalletCoinRecord]: """ Returns set of CoinRecords that have not been spent yet for a wallet. """ async with self.wallet_cache_lock: if wallet_id in self.coin_wallet_record_cache: wallet_coins: Dict[ bytes32, WalletCoinRecord] = self.coin_wallet_record_cache[ wallet_id] return set(wallet_coins.values()) coin_set = set() cursor = await self.db_connection.execute( "SELECT * from coin_record WHERE spent=0 and wallet_id=?", (wallet_id, ), ) rows = await cursor.fetchall() await cursor.close() cache_dict = {} for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coin_record = WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]) coin_set.add(coin_record) cache_dict[coin.name()] = coin_record self.coin_wallet_record_cache[wallet_id] = cache_dict return coin_set
async def get_coin_records_by_parent_ids( self, include_spent_coins: bool, parent_ids: List[bytes32], start_height: uint32 = uint32(0), end_height: uint32 = uint32((2 ** 32) - 1), ) -> List[CoinRecord]: if len(parent_ids) == 0: return [] coins = set() parent_ids_db = tuple([pid.hex() for pid in parent_ids]) cursor = await self.coin_record_db.execute( f'SELECT * from coin_record WHERE coin_parent in ({"?," * (len(parent_ids_db) - 1)}?) ' f"AND confirmed_index>=? AND confirmed_index<? " f"{'' if include_spent_coins else 'AND spent=0'}", parent_ids_db + (start_height, end_height), ) rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])) return list(coins)
def compress_root(mystr: bytes) -> bytes32: assert len(mystr) == 33 if mystr[0:1] == MIDDLE: return bytes32(mystr[1:]) if mystr[0:1] == EMPTY: assert mystr[1:] == BLANK return BLANK return bytes32(sha256(mystr).digest()[:32])
async def get_coins_added_at_height(self, height: uint32) -> List[CoinRecord]: cursor = await self.coin_record_db.execute("SELECT * from coin_record WHERE confirmed_index=?", (height,)) rows = await cursor.fetchall() await cursor.close() coins = [] for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.append(CoinRecord(coin, row[1], row[2], row[3], row[4], row[8])) return coins
async def get_coin_record(self, coin_name: bytes32) -> Optional[CoinRecord]: if coin_name.hex() in self.coin_record_cache: return self.coin_record_cache[coin_name.hex()] cursor = await self.coin_record_db.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),)) row = await cursor.fetchone() await cursor.close() if row is not None: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) return CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]) return None
async def get_coin_records_by_puzzle_hash(self, puzzle_hash: bytes32) -> List[WalletCoinRecord]: """Returns a list of all coin records with the given puzzle hash""" coins = set() cursor = await self.db_connection.execute("SELECT * from coin_record WHERE puzzle_hash=?", (puzzle_hash.hex(),)) rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add(WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])) return list(coins)
async def get_coin_record_by_coin_id(self, coin_id: bytes32) -> Optional[WalletCoinRecord]: """Returns a coin records with the given name, if it exists""" cursor = await self.db_connection.execute("SELECT * from coin_record WHERE coin_name=?", (coin_id.hex(),)) row = await cursor.fetchone() await cursor.close() if row is None: return None coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coin_record = WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]) return coin_record
async def get_coin_record(self, coin_name: bytes32) -> Optional[WalletCoinRecord]: """ Returns CoinRecord with specified coin id. """ if coin_name in self.coin_record_cache: return self.coin_record_cache[coin_name] cursor = await self.db_connection.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),)) row = await cursor.fetchone() await cursor.close() if row is not None: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) return WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9]) return None
async def get_all_coins(self) -> Set[WalletCoinRecord]: """ Returns set of all CoinRecords.""" coins = set() cursor = await self.db_connection.execute("SELECT * from coin_record") rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add(WalletCoinRecord(coin, row[1], row[2], row[3], row[4], WalletType(row[8]), row[9])) return coins
async def all_non_reward_coins(self) -> List[Coin]: coins = set() cursor = await self.mempool_manager.coin_store.coin_record_db.execute( "SELECT * from coin_record WHERE coinbase=0 AND spent=0 ", ) rows = await cursor.fetchall() await cursor.close() for row in rows: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) coins.add(coin) return list(coins)
async def get_coin_record(self, coin_name: bytes32) -> Optional[CoinRecord]: cached = self.coin_record_cache.get(coin_name) if cached is not None: return cached cursor = await self.coin_record_db.execute("SELECT * from coin_record WHERE coin_name=?", (coin_name.hex(),)) row = await cursor.fetchone() await cursor.close() if row is not None: coin = Coin(bytes32(bytes.fromhex(row[6])), bytes32(bytes.fromhex(row[5])), uint64.from_bytes(row[7])) record = CoinRecord(coin, row[1], row[2], row[3], row[4], row[8]) self.coin_record_cache.put(record.coin.name(), record) return record return None
def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: """ Hash values in `precalculated` are presumed to have been hashed already. """ if node.listp(): left = _tree_hash(node.first(), precalculated) right = _tree_hash(node.rest(), precalculated) s = b"\2" + left + right else: atom = node.as_atom() if atom in precalculated: return bytes32(atom) s = b"\1" + atom return bytes32(std_hash(s))
def get_offered_coins(self) -> Dict[Optional[bytes32], List[Coin]]: offered_coins: Dict[Optional[bytes32], List[Coin]] = {} for addition in self.bundle.additions(): # Get the parent puzzle parent_puzzle: Program = list( filter(lambda cs: cs.coin.name() == addition.parent_coin_info, self.bundle.coin_spends))[0].puzzle_reveal.to_program() # Determine it's TAIL (or lack of) matched, curried_args = match_cat_puzzle(parent_puzzle) tail_hash: Optional[bytes32] = None if matched: _, tail_hash_program, _ = curried_args tail_hash = bytes32(tail_hash_program.as_python()) offer_ph: bytes32 = construct_cat_puzzle( CAT_MOD, tail_hash, OFFER_MOD).get_tree_hash() else: tail_hash = None offer_ph = OFFER_MOD.get_tree_hash() # Check if the puzzle_hash matches the hypothetical `settlement_payments` puzzle hash if addition.puzzle_hash == offer_ph: if tail_hash in offered_coins: offered_coins[tail_hash].append(addition) else: offered_coins[tail_hash] = [addition] return offered_coins
async def get_block_records_close_to_peak( self, blocks_n: int ) -> Tuple[Dict[bytes32, BlockRecord], Optional[bytes32]]: """ Returns a dictionary with all blocks, as well as the header hash of the peak, if present. """ res = await self.db.execute( "SELECT header_hash, height from block_records WHERE is_peak = 1") row = await res.fetchone() await res.close() if row is None: return {}, None header_hash_bytes, peak_height = row peak: bytes32 = bytes32(bytes.fromhex(header_hash_bytes)) formatted_str = f"SELECT header_hash, block from block_records WHERE height >= {peak_height - blocks_n}" cursor = await self.db.execute(formatted_str) rows = await cursor.fetchall() await cursor.close() ret: Dict[bytes32, BlockRecord] = {} for row in rows: header_hash_bytes, block_record_bytes = row header_hash = bytes.fromhex(header_hash_bytes) ret[header_hash] = BlockRecord.from_bytes(block_record_bytes) return ret, peak
async def get_block_records_by_hash(self, header_hashes: List[bytes32]): """ Returns a list of Block Records, ordered by the same order in which header_hashes are passed in. Throws an exception if the blocks are not present """ if len(header_hashes) == 0: return [] all_blocks: Dict[bytes32, BlockRecord] = {} if self.db_wrapper.db_version == 2: async with self.db.execute( "SELECT header_hash,block_record FROM full_blocks " f'WHERE header_hash in ({"?," * (len(header_hashes) - 1)}?)', tuple(header_hashes), ) as cursor: for row in await cursor.fetchall(): header_hash = bytes32(row[0]) all_blocks[header_hash] = BlockRecord.from_bytes(row[1]) else: formatted_str = f'SELECT block from block_records WHERE header_hash in ({"?," * (len(header_hashes) - 1)}?)' async with self.db.execute(formatted_str, tuple([hh.hex() for hh in header_hashes])) as cursor: for row in await cursor.fetchall(): block_rec: BlockRecord = BlockRecord.from_bytes(row[0]) all_blocks[block_rec.header_hash] = block_rec ret: List[BlockRecord] = [] for hh in header_hashes: if hh not in all_blocks: raise ValueError(f"Header hash {hh} not in the blockchain") ret.append(all_blocks[hh]) return ret
async def create_wallet_for_cat(wallet_state_manager: Any, wallet: Wallet, limitations_program_hash_hex: str, name="CAT WALLET") -> CATWallet: self = CATWallet() self.cost_of_single_tx = None self.standard_wallet = wallet self.log = logging.getLogger(__name__) for id, wallet in wallet_state_manager.wallets.items(): if wallet.type() == CATWallet.type(): if wallet.get_asset_id( ) == limitations_program_hash_hex: # type: ignore self.log.warning( "Not creating wallet for already existing CAT wallet") raise ValueError("Wallet already exists") self.wallet_state_manager = wallet_state_manager if limitations_program_hash_hex in DEFAULT_CATS: cat_info = DEFAULT_CATS[limitations_program_hash_hex] name = cat_info["name"] limitations_program_hash = bytes32( hexstr_to_bytes(limitations_program_hash_hex)) self.cat_info = CATInfo(limitations_program_hash, None, []) info_as_string = bytes(self.cat_info).hex() self.wallet_info = await wallet_state_manager.user_store.create_wallet( name, WalletType.CAT, info_as_string) if self.wallet_info is None: raise Exception("wallet_info is None") await self.wallet_state_manager.add_new_wallet(self, self.id()) return self
def get_quality_string(self, plot_id: bytes32) -> Optional[bytes32]: quality_str = Verifier().validate_proof(plot_id, self.size, self.challenge, bytes(self.proof)) if not quality_str: return None return bytes32(quality_str)
def decode_puzzle_hash(address: str) -> bytes32: hrpgot, data = bech32_decode(address) if data is None: raise ValueError("Invalid Address") decoded = convertbits(data, 5, 8, False) decoded_bytes = bytes32(decoded) return decoded_bytes
def tx(info): j = json.dumps(info) m: Dict = eval(j) inputs: List = m.get("inputs") outputs: List = m.get("outputs") primaries = [] for o in outputs: output: Dict = o address: str = output.get("address") value: float = output.get("value") primaries.append({ "puzzlehash": decode_puzzle_hash(address), "amount": value }) spends: List[CoinSolution] = [] pks: List[str] = [] first_spend = True for i in inputs: input: Dict = i pk: str = input.get("pk") pks.append(pk) txid: Dict = eval(input.get("txId")) parentCoinInfo = txid.get("parentCoinInfo") puzzleHash = txid.get("puzzleHash") amount = txid.get("amount") pa = bytes32(bytes.fromhex(parentCoinInfo[2:])) pu = bytes32(bytes.fromhex(puzzleHash[2:])) a = uint64(amount) coin: Coin = Coin(pa, pu, a) child_sk: PrivateKey = PrivateKey.from_bytes(bytes.fromhex(pk)) child_public_key = child_sk.get_g1() puzzle = puzzle_for_pk(child_public_key) if first_spend: solution: Program = Wallet().make_solution(primaries=primaries) first_spend = False else: solution = Wallet().make_solution() spends.append(CoinSolution(coin, puzzle, solution)) spend_bundle: SpendBundle = SpendBundle(spends, G2Element()) # return json.dumps(spend_bundle.to_json_dict()) return sign_tx(pks, spend_bundle)
async def get_pay_to_singleton_phs(self) -> Set[bytes32]: cursor = await self.connection.execute("SELECT p2_singleton_puzzle_hash from farmer") rows = await cursor.fetchall() all_phs: Set[bytes32] = set() for row in rows: all_phs.add(bytes32(bytes.fromhex(row[0]))) return all_phs
async def get_pool_login_link(self, request: Dict) -> Dict: launcher_id: bytes32 = bytes32(hexstr_to_bytes(request["launcher_id"])) login_link: Optional[str] = await self.service.generate_login_link( launcher_id) if login_link is None: raise ValueError( f"Failed to generate login link for {launcher_id.hex()}") return {"login_link": login_link}
def from_condition(cls, condition: Program) -> "Payment": python_condition: List = condition.as_python() puzzle_hash, amount = python_condition[1:3] memos: List[bytes] = [] if len(python_condition) > 3: memos = python_condition[3] return cls(bytes32(puzzle_hash), uint64(int.from_bytes(amount, "big")), memos)
def coin_serialize(amount: uint64, clvm_serialize: bytes, full_serialize: bytes): c = Coin(bytes32(b"a" * 32), bytes32(b"b" * 32), amount) expected_hash = (b"a" * 32) + (b"b" * 32) + clvm_serialize expected_serialization = (b"a" * 32) + (b"b" * 32) + full_serialize assert c.get_hash() == std_hash(expected_hash) assert c.name() == std_hash(expected_hash) f = io.BytesIO() c.stream(f) assert bytes(f.getvalue()) == expected_serialization # make sure the serialization round-trips f = io.BytesIO(expected_serialization) c2 = Coin.parse(f) assert c2 == c
def mempool_assert_announcement(condition: ConditionWithArgs, announcements: Set[bytes32]) -> Optional[Err]: """ Check if an announcement is included in the list of announcements """ announcement_hash = bytes32(condition.vars[0]) if announcement_hash not in announcements: return Err.ASSERT_ANNOUNCE_CONSUMED_FAILED return None
async def get_peak(self) -> Optional[Tuple[bytes32, uint32]]: if self.db_wrapper.db_version == 2: async with self.db.execute("SELECT hash FROM current_peak WHERE key = 0") as cursor: peak_row = await cursor.fetchone() if peak_row is None: return None async with self.db.execute("SELECT height FROM full_blocks WHERE header_hash=?", (peak_row[0],)) as cursor: peak_height = await cursor.fetchone() if peak_height is None: return None return bytes32(peak_row[0]), uint32(peak_height[0]) else: async with self.db.execute("SELECT header_hash, height from block_records WHERE is_peak = 1") as cursor: peak_row = await cursor.fetchone() if peak_row is None: return None return bytes32(bytes.fromhex(peak_row[0])), uint32(peak_row[1])
def my_id(self) -> bytes32: """If node has public cert use that one for id, if not use private.""" if self.p2p_crt_path is not None: pem_cert = x509.load_pem_x509_certificate(self.p2p_crt_path.read_bytes(), default_backend()) else: pem_cert = x509.load_pem_x509_certificate(self._private_cert_path.read_bytes(), default_backend()) der_cert_bytes = pem_cert.public_bytes(encoding=serialization.Encoding.DER) der_cert = x509.load_der_x509_certificate(der_cert_bytes, default_backend()) return bytes32(der_cert.fingerprint(hashes.SHA256()))
def created_outputs_for_conditions_dict( conditions_dict: Dict[ConditionOpcode, List[ConditionWithArgs]], input_coin_name: bytes32, ) -> List[Coin]: output_coins = [] for cvp in conditions_dict.get(ConditionOpcode.CREATE_COIN, []): puzzle_hash, amount_bin = cvp.vars[0], cvp.vars[1] amount = int_from_bytes(amount_bin) coin = Coin(input_coin_name, bytes32(puzzle_hash), uint64(amount)) output_coins.append(coin) return output_coins