From 1166b50b622d2e41b3934cc0d24e4248bd6fd99e Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Mon, 20 Nov 2023 20:49:59 -0500 Subject: [PATCH 01/34] clvm mypie --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9583edab2ea3..e6db2db5d60d 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ "chiavdf==1.1.0", # timelord and vdf verification "chiabip158==1.3", # bip158-style wallet filters "chiapos==2.0.3", # proof of space - "clvm==0.9.8", + "clvm @ git+https://github.com/chia-network/clvm@mypie", "clvm_tools==0.4.7", # Currying, Program.to, other conveniences "chia_rs==0.2.13", "clvm-tools-rs==0.1.38", # Rust implementation of clvm_tools' compiler From 1ee16331e6aced93a5e81721f7e1068d8677bb2b Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Mon, 18 Dec 2023 20:08:31 -0500 Subject: [PATCH 02/34] update exclusions --- mypy-exclusions.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/mypy-exclusions.txt b/mypy-exclusions.txt index 3fb3d99dedd6..68f91e36379a 100644 --- a/mypy-exclusions.txt +++ b/mypy-exclusions.txt @@ -24,16 +24,13 @@ chia.wallet.chialisp chia.wallet.did_wallet.did_wallet chia.wallet.did_wallet.did_wallet_puzzles chia.wallet.key_val_store -chia.wallet.lineage_proof chia.wallet.nft_wallet.nft_puzzles chia.wallet.payment chia.wallet.puzzles.load_clvm chia.wallet.puzzles.p2_conditions -chia.wallet.puzzles.p2_delegated_conditions chia.wallet.puzzles.p2_delegated_puzzle chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle chia.wallet.puzzles.p2_m_of_n_delegate_direct -chia.wallet.puzzles.p2_puzzle_hash chia.wallet.puzzles.singleton_top_layer chia.wallet.puzzles.tails chia.wallet.trading.trade_store From 767cc27402680a9ddbba9d912b482bae108c8f67 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Tue, 19 Dec 2023 23:56:06 -0500 Subject: [PATCH 03/34] wip --- chia/data_layer/data_layer_wallet.py | 23 ++++++++++--------- chia/rpc/wallet_rpc_api.py | 11 ++++++--- chia/types/blockchain_format/tree_hash.py | 20 ++++++++-------- chia/wallet/cat_wallet/cat_wallet.py | 6 +++-- chia/wallet/dao_wallet/dao_wallet.py | 6 ++--- chia/wallet/did_wallet/did_wallet.py | 19 +++++++++++---- chia/wallet/nft_wallet/nft_puzzles.py | 20 ++++++++++++---- chia/wallet/nft_wallet/nft_wallet.py | 1 + chia/wallet/puzzles/clawback/drivers.py | 5 ++-- chia/wallet/trading/offer.py | 2 +- chia/wallet/wallet.py | 2 +- chia/wallet/wallet_state_manager.py | 7 +++++- tests/core/mempool/test_mempool_manager.py | 18 +++++++-------- tests/core/test_cost_calculation.py | 1 + tests/generator/test_compression.py | 2 +- tests/wallet/cat_wallet/test_cat_lifecycle.py | 2 +- tests/wallet/nft_wallet/test_nft_lifecycle.py | 8 +++---- tests/wallet/nft_wallet/test_nft_puzzles.py | 6 +++-- 18 files changed, 99 insertions(+), 60 deletions(-) diff --git a/chia/data_layer/data_layer_wallet.py b/chia/data_layer/data_layer_wallet.py index d8bbe6093512..b32a1e976d9d 100644 --- a/chia/data_layer/data_layer_wallet.py +++ b/chia/data_layer/data_layer_wallet.py @@ -8,6 +8,7 @@ from chia_rs import G1Element, G2Element from clvm.EvalError import EvalError +from clvm.SExp import CastableType from typing_extensions import Unpack, final from chia.consensus.block_record import BlockRecord @@ -466,20 +467,20 @@ async def create_update_state_spend( # Optionally add an ephemeral spend to announce if announce_new_state: - announce_only: Program = Program.to( - ( - 1, + announce_only_python: Tuple[int, List[List[CastableType]]] = ( + 1, + [ [ - [ - 51, - new_puz_hash, - singleton_record.lineage_proof.amount, - [launcher_id, root_hash, new_puz_hash], - ], - [62, b"$"], + 51, + new_puz_hash, + singleton_record.lineage_proof.amount, + [launcher_id, root_hash, new_puz_hash], ], - ) + [62, b"$"], + ], ) + + announce_only: Program = Program.to(announce_only_python) second_full_puz: Program = create_host_fullpuz( announce_only, root_hash, diff --git a/chia/rpc/wallet_rpc_api.py b/chia/rpc/wallet_rpc_api.py index 9e44b4ed162f..4a504e5a1eb0 100644 --- a/chia/rpc/wallet_rpc_api.py +++ b/chia/rpc/wallet_rpc_api.py @@ -2179,10 +2179,14 @@ async def did_get_info(self, request: Dict[str, Any]) -> EndpointResult: if coin_state.coin.name() in memos: for memo in memos[coin_state.coin.name()]: hints.append(memo.hex()) + assert recovery_list_hash.atom is not None + launcher_id = singleton_struct.rest().first().atom + assert launcher_id is not None + assert public_key.atom is not None return { "success": True, "did_id": encode_puzzle_hash( - bytes32.from_hexstr(singleton_struct.rest().first().atom.hex()), + bytes32.from_hexstr(launcher_id.hex()), AddressType.DID.hrp(self.service.config), ), "latest_coin": coin_state.coin.name().hex(), @@ -2191,7 +2195,7 @@ async def did_get_info(self, request: Dict[str, Any]) -> EndpointResult: "recovery_list_hash": recovery_list_hash.atom.hex(), "num_verification": num_verification.as_int(), "metadata": did_program_to_metadata(metadata), - "launcher_id": singleton_struct.rest().first().atom.hex(), + "launcher_id": launcher_id.hex(), "full_puzzle": full_puzzle, "solution": Program.from_bytes(bytes(coin_spend.solution)).as_python(), "hints": hints, @@ -2221,6 +2225,7 @@ async def did_find_lost_did(self, request: Dict[str, Any]) -> EndpointResult: if curried_args is None: return {"success": False, "error": "The coin is not a DID."} p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = curried_args + assert recovery_list_hash.atom is not None did_data: DIDCoinData = DIDCoinData( p2_puzzle, bytes32(recovery_list_hash.atom), @@ -3411,7 +3416,7 @@ async def nft_get_info(self, request: Dict[str, Any]) -> EndpointResult: full_puzzle = nft_puzzles.create_full_puzzle( uncurried_nft.singleton_launcher_id, metadata, - uncurried_nft.metadata_updater_hash, + bytes32(uncurried_nft.metadata_updater_hash), inner_puzzle, ) diff --git a/chia/types/blockchain_format/tree_hash.py b/chia/types/blockchain_format/tree_hash.py index 1e59e9b7c23e..6a12c7a67dc0 100644 --- a/chia/types/blockchain_format/tree_hash.py +++ b/chia/types/blockchain_format/tree_hash.py @@ -10,15 +10,15 @@ from typing import Callable, List, Optional, Set -from clvm import CLVMObject +from clvm.CLVMObject import CLVMStorage from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.hash import std_hash -Op = Callable[[List["CLVMObject"], List["Op"], Set[bytes32]], None] +Op = Callable[[List[CLVMStorage], List["Op"], Set[bytes32]], None] -def sha256_treehash(sexp: CLVMObject, precalculated: Optional[Set[bytes32]] = None) -> bytes32: +def sha256_treehash(sexp: CLVMStorage, precalculated: Optional[Set[bytes32]] = None) -> bytes32: """ Hash values in `precalculated` are presumed to have been hashed already. """ @@ -26,7 +26,7 @@ def sha256_treehash(sexp: CLVMObject, precalculated: Optional[Set[bytes32]] = No if precalculated is None: precalculated = set() - def handle_sexp(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + def handle_sexp(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated: Set[bytes32]) -> None: sexp = sexp_stack.pop() if sexp.pair: p0, p1 = sexp.pair @@ -37,18 +37,20 @@ def handle_sexp(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: op_stack.append(roll) op_stack.append(handle_sexp) else: - if sexp.atom in precalculated: - r = sexp.atom + # not a pair, so an atom + atom: bytes = sexp.atom # type: ignore[assignment] + if atom in precalculated: + r = atom else: - r = std_hash(b"\1" + sexp.atom) + r = std_hash(b"\1" + atom) sexp_stack.append(r) - def handle_pair(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + def handle_pair(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated: Set[bytes32]) -> None: p0 = sexp_stack.pop() p1 = sexp_stack.pop() sexp_stack.append(std_hash(b"\2" + p0 + p1)) - def roll(sexp_stack: List[CLVMObject], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + def roll(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated: Set[bytes32]) -> None: p0 = sexp_stack.pop() p1 = sexp_stack.pop() sexp_stack.append(p0) diff --git a/chia/wallet/cat_wallet/cat_wallet.py b/chia/wallet/cat_wallet/cat_wallet.py index 9e3be1456ba3..913c6ed3e67f 100644 --- a/chia/wallet/cat_wallet/cat_wallet.py +++ b/chia/wallet/cat_wallet/cat_wallet.py @@ -395,9 +395,11 @@ async def coin_added( cat_curried_args = match_cat_puzzle(uncurry_puzzle(coin_spend.puzzle_reveal.to_program())) if cat_curried_args is not None: cat_mod_hash, tail_program_hash, cat_inner_puzzle = cat_curried_args + assert cat_mod_hash.atom is not None + assert tail_program_hash.atom is not None parent_coin_data = CATCoinData( - cat_mod_hash.atom, - tail_program_hash.atom, + bytes32(cat_mod_hash.atom), + bytes32(tail_program_hash.atom), cat_inner_puzzle, coin_state[0].coin.parent_coin_info, uint64(coin_state[0].coin.amount), diff --git a/chia/wallet/dao_wallet/dao_wallet.py b/chia/wallet/dao_wallet/dao_wallet.py index 864149584cdd..81739aa40392 100644 --- a/chia/wallet/dao_wallet/dao_wallet.py +++ b/chia/wallet/dao_wallet/dao_wallet.py @@ -1273,8 +1273,8 @@ async def create_proposal_close_spend( sum = 0 coin_spends = [] - xch_parent_amount_list = [] - tailhash_parent_amount_list = [] + xch_parent_amount_list: List[List[Union[bytes32, int]]] = [] + tailhash_parent_amount_list: List[List[Union[bytes32, List[List[Union[bytes32, int]]]]]] = [] treasury_inner_puzhash = self.dao_info.current_treasury_innerpuz.get_tree_hash() p2_singleton_puzzle = get_p2_singleton_puzzle(self.dao_info.treasury_id) cat_launcher = create_cat_launcher_for_singleton_id(self.dao_info.treasury_id) @@ -1358,7 +1358,7 @@ async def create_proposal_close_spend( if condition.first().as_int() == 51: sum_of_conditions += condition.rest().rest().first().as_int() cat_coins = await self.select_coins_for_asset_type(uint64(sum_of_conditions), tail_hash) - parent_amount_list = [] + parent_amount_list: List[List[Union[bytes32, int]]] = [] for cat_coin in cat_coins: sum_of_coins += cat_coin.amount parent_amount_list.append([cat_coin.parent_coin_info, cat_coin.amount]) diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 436c60547132..fcdcc39e9c90 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -7,6 +7,7 @@ import time from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Set, Tuple, cast +from clvm.SExp import CastableType from chia_rs import AugSchemeMPL, G1Element, G2Element from chia.protocols.wallet_protocol import CoinState @@ -359,9 +360,10 @@ async def coin_added(self, coin: Coin, _: uint32, peer: WSChiaConnection, parent did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args) assert did_curried_args is not None p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args + assert recovery_list_hash.atom is not None did_data = DIDCoinData( p2_puzzle, - recovery_list_hash.atom, + bytes32(recovery_list_hash.atom), uint16(num_verification.as_int()), singleton_struct, metadata, @@ -830,7 +832,8 @@ async def create_exit_spend(self, puzhash: bytes32, tx_config: TXConfig): assert self.did_info.current_inner is not None assert self.did_info.origin_coin is not None coin = await self.get_coin() - message_puz = Program.to((1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]])) + message_puz_python: Tuple[int, List[CastableType]] = (1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]]) + message_puz = Program.to(message_puz_python) # innerpuz solution is (mode p2_solution) innersol: Program = Program.to([1, [[], message_puz, []]]) @@ -1159,15 +1162,21 @@ async def inner_puzzle_for_did_puzzle(self, did_hash: bytes32) -> Program: assert self.did_info.current_inner is not None uncurried_args = uncurry_innerpuz(self.did_info.current_inner) assert uncurried_args is not None - old_recovery_list_hash: Optional[Program] = None - p2_puzzle, old_recovery_list_hash, _, _, _ = uncurried_args + old_recovery_list: Optional[Program] + p2_puzzle, old_recovery_list, _, _, _ = uncurried_args if record is None: record = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash( p2_puzzle.get_tree_hash() ) if not (self.did_info.num_of_backup_ids_needed > 0 and len(self.did_info.backup_ids) == 0): # We have the recovery list, don't reset it - old_recovery_list_hash = None + old_recovery_list = None + + old_recovery_list_hash: Optional[bytes32] + if old_recovery_list is not None: + old_recovery_list_hash = bytes32(old_recovery_list) + else: + old_recovery_list_hash = old_recovery_list inner_puzzle: Program = did_wallet_puzzles.create_innerpuz( puzzle_for_pk(record.pubkey), diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 85a9fad8e190..778483ac1f2e 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -281,11 +281,13 @@ def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tup continue condition_code = condition.first().as_int() log.debug("Checking condition code: %r", condition_code) + atom = condition.rest().rest().first().atom + assert atom is not None if condition_code == -24: # metadata update metadata = update_metadata(metadata, condition) metadata = Program.to(metadata) - elif condition_code == 51 and int_from_bytes(condition.rest().rest().first().atom) == 1: + elif condition_code == 51 and int_from_bytes(atom) == 1: # destination puzhash if puzhash_for_derivation is not None: # ignore duplicated create coin conditions @@ -305,11 +307,15 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - new_did_id = condition.at("rf").atom + atom = condition.at("rf").atom + if atom is None: + new_did_id = atom + else: + new_did_id = bytes32(atom) elif condition.first().as_int() == 51: new_puzhash = condition.at("rf").atom # assert new_puzhash and new_did_id - log.debug(f"Found NFT puzzle details: {new_did_id} {new_puzhash}") + log.debug(f"Found NFT puzzle details: {new_did_id!r} {new_puzhash!r}") assert unft.transfer_program new_ownership_puzzle = construct_ownership_layer(new_did_id, unft.transfer_program, new_inner_puzzle) @@ -318,9 +324,13 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Optional[bytes32]: conditions = unft.p2_puzzle.run(unft.get_innermost_solution(solution)) - new_did_id = None + new_did_id: Optional[bytes32] = None for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - new_did_id = condition.at("rf").atom + atom = condition.at("rf").atom + if atom is None: + new_did_id = atom + else: + new_did_id = bytes32(atom) return new_did_id diff --git a/chia/wallet/nft_wallet/nft_wallet.py b/chia/wallet/nft_wallet/nft_wallet.py index a4576fbd1b6f..459b538deb1d 100644 --- a/chia/wallet/nft_wallet/nft_wallet.py +++ b/chia/wallet/nft_wallet/nft_wallet.py @@ -210,6 +210,7 @@ async def puzzle_solution_received(self, coin: Coin, data: NFTCoinData, peer: WS minter_did = await self.wallet_state_manager.get_minter_did(launcher_coin_states[0].coin, peer) else: inner_puzzle = p2_puzzle + assert uncurried_nft.metadata_updater_hash.atom is not None child_puzzle: Program = nft_puzzles.create_full_puzzle( singleton_id, Program.to(metadata), diff --git a/chia/wallet/puzzles/clawback/drivers.py b/chia/wallet/puzzles/clawback/drivers.py index 70460485d065..e4804367b2ca 100644 --- a/chia/wallet/puzzles/clawback/drivers.py +++ b/chia/wallet/puzzles/clawback/drivers.py @@ -3,6 +3,7 @@ import logging from typing import Any, List, Optional, Set, Union +from chia.types.blockchain_format.serialized_program import SerializedProgram from chia.consensus.default_constants import DEFAULT_CONSTANTS from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -128,8 +129,8 @@ def match_clawback_puzzle( return None # Fetch Remark condition conditions = conditions_for_solution( - inner_puzzle, - inner_solution, + SerializedProgram.from_program(inner_puzzle), + SerializedProgram.from_program(inner_solution), DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM // 8, ) metadata: Optional[ClawbackMetadata] = None diff --git a/chia/wallet/trading/offer.py b/chia/wallet/trading/offer.py index 3db1d38ff82a..fa568e5d30f1 100644 --- a/chia/wallet/trading/offer.py +++ b/chia/wallet/trading/offer.py @@ -619,7 +619,7 @@ def from_spend_bundle(cls, bundle: SpendBundle) -> Offer: 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() + payment_args_list = payment_group.rest().as_iter() notarized_payments.extend( [NotarizedPayment.from_condition_and_nonce(condition, nonce) for condition in payment_args_list] ) diff --git a/chia/wallet/wallet.py b/chia/wallet/wallet.py index a1b5da9cd41b..7cad5ebc138e 100644 --- a/chia/wallet/wallet.py +++ b/chia/wallet/wallet.py @@ -230,7 +230,7 @@ def make_solution( def add_condition_to_solution(self, condition: Program, solution: Program) -> Program: python_program = solution.as_python() python_program[1].append(condition) - return cast(Program, Program.to(python_program)) + return Program.to(python_program) async def select_coins( self, diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index 6029b36b6feb..5d256f23929d 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -795,6 +795,8 @@ async def determine_coin_type( cat_curried_args = match_cat_puzzle(uncurried) if cat_curried_args is not None: cat_mod_hash, tail_program_hash, cat_inner_puzzle = cat_curried_args + assert cat_mod_hash.atom is not None + assert tail_program_hash.atom is not None cat_data: CATCoinData = CATCoinData( bytes32(cat_mod_hash.atom), bytes32(tail_program_hash.atom), @@ -826,6 +828,7 @@ async def determine_coin_type( did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args) if did_curried_args is not None and coin_state.coin.amount % 2 == 1: p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args + assert recovery_list_hash.atom is not None did_data: DIDCoinData = DIDCoinData( p2_puzzle, bytes32(recovery_list_hash.atom), @@ -1177,7 +1180,9 @@ async def handle_did( assert hinted_coin.hint is not None, f"hint missing for coin {hinted_coin.coin}" derivation_record = await self.puzzle_store.get_derivation_record_for_puzzle_hash(hinted_coin.hint) - launch_id: bytes32 = bytes32(parent_data.singleton_struct.rest().first().atom) + launcher_id_atom = parent_data.singleton_struct.rest().first().atom + assert launcher_id_atom is not None + launch_id: bytes32 = bytes32(launcher_id_atom) if derivation_record is None: self.log.info(f"Received state for the coin that doesn't belong to us {coin_state}") # Check if it was owned by us diff --git a/tests/core/mempool/test_mempool_manager.py b/tests/core/mempool/test_mempool_manager.py index 189e2caffda4..b08f86455fae 100644 --- a/tests/core/mempool/test_mempool_manager.py +++ b/tests/core/mempool/test_mempool_manager.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple +from typing import Any, Awaitable, Callable, Dict, List, Optional, Set, Tuple, Union import pytest from chia_rs import ELIGIBLE_FOR_DEDUP, G1Element, G2Element @@ -1194,14 +1194,14 @@ async def test_replacing_one_with_an_eligible_coin() -> None: @pytest.mark.parametrize("amount", [0, 1]) def test_run_for_cost(amount: int) -> None: - conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, amount]] + conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, amount]] solution = SerializedProgram.to(conditions) cost = run_for_cost(IDENTITY_PUZZLE, solution, additions_count=1, max_cost=uint64(10000000)) assert cost == uint64(1800044) def test_run_for_cost_max_cost() -> None: - conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1]] + conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1]] solution = SerializedProgram.to(conditions) with pytest.raises(ValueError, match="cost exceeded"): run_for_cost(IDENTITY_PUZZLE, solution, additions_count=1, max_cost=uint64(43)) @@ -1227,7 +1227,7 @@ def test_dedup_info_nothing_to_do() -> None: def test_dedup_info_eligible_1st_time() -> None: # Eligible coin encountered for the first time - conditions = [ + conditions: List[List[Union[bytes, int]]] = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] @@ -1249,7 +1249,7 @@ def test_dedup_info_eligible_1st_time() -> None: def test_dedup_info_eligible_but_different_solution() -> None: # Eligible coin but different solution from the one we encountered - initial_conditions = [ + initial_conditions: List[List[Union[bytes, int]]] = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] @@ -1266,14 +1266,14 @@ def test_dedup_info_eligible_but_different_solution() -> None: def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None: # Eligible coin encountered a second time, and another for the first time - initial_conditions = [ + initial_conditions: List[List[Union[bytes, int]]] = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] initial_solution = SerializedProgram.to(initial_conditions) eligible_coin_spends = EligibleCoinSpends({TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=None)}) sb1 = spend_bundle_from_conditions(initial_conditions, TEST_COIN) - second_conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] + second_conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] second_solution = SerializedProgram.to(second_conditions) sb2 = spend_bundle_from_conditions(second_conditions, TEST_COIN2) sb = SpendBundle.aggregate([sb1, sb2]) @@ -1299,12 +1299,12 @@ def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None: def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() -> None: # Eligible coin encountered a third time, another for the second time and one non eligible - initial_conditions = [ + initial_conditions: List[List[Union[bytes, int]]] = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] initial_solution = SerializedProgram.to(initial_conditions) - second_conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] + second_conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] second_solution = SerializedProgram.to(second_conditions) saved_cost = uint64(3600044) eligible_coin_spends = EligibleCoinSpends( diff --git a/tests/core/test_cost_calculation.py b/tests/core/test_cost_calculation.py index f50a369e7fa2..8637f4127385 100644 --- a/tests/core/test_cost_calculation.py +++ b/tests/core/test_cost_calculation.py @@ -302,6 +302,7 @@ async def test_get_puzzle_and_solution_for_coin_performance(benchmark_runner: Be coin_spends = result.first() for spend in coin_spends.as_iter(): parent, puzzle, amount, solution = spend.as_iter() + assert parent.atom is not None and amount.atom is not None spends.append(Coin(bytes32(parent.atom), Program.to(puzzle).get_tree_hash(), int_from_bytes(amount.atom))) print(f"found {len(spends)} spent coins in block") diff --git a/tests/generator/test_compression.py b/tests/generator/test_compression.py index f69115c92cee..bbef493903f9 100644 --- a/tests/generator/test_compression.py +++ b/tests/generator/test_compression.py @@ -7,7 +7,7 @@ import pytest from chia_rs import ALLOW_BACKREFS -from clvm import SExp +from clvm.SExp import SExp from clvm.serialize import sexp_from_stream from clvm_tools import binutils diff --git a/tests/wallet/cat_wallet/test_cat_lifecycle.py b/tests/wallet/cat_wallet/test_cat_lifecycle.py index f126ea4484f6..ef3cf7e45cd0 100644 --- a/tests/wallet/cat_wallet/test_cat_lifecycle.py +++ b/tests/wallet/cat_wallet/test_cat_lifecycle.py @@ -37,7 +37,7 @@ async def do_spend( sim_client: SimClient, tail: Program, coins: List[Coin], - lineage_proofs: List[Program], + lineage_proofs: List[LineageProof], inner_solutions: List[Program], expected_result: Tuple[MempoolInclusionStatus, Err], reveal_limitations_program: bool = True, diff --git a/tests/wallet/nft_wallet/test_nft_lifecycle.py b/tests/wallet/nft_wallet/test_nft_lifecycle.py index f0c26092f7bc..b16f9ad65693 100644 --- a/tests/wallet/nft_wallet/test_nft_lifecycle.py +++ b/tests/wallet/nft_wallet/test_nft_lifecycle.py @@ -1,10 +1,11 @@ from __future__ import annotations import itertools -from typing import List +from typing import List, Tuple import pytest from chia_rs import G2Element +from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.types.announcement import Announcement @@ -317,9 +318,8 @@ async def test_default_transfer_program(cost_logger: CostLogger) -> None: Program.to([[[62, FAKE_LAUNCHER_ID]]]), ) - expected_announcement_data = Program.to( - (FAKE_LAUNCHER_ID, [[ROYALTY_ADDRESS, 50, [ROYALTY_ADDRESS]]]) - ).get_tree_hash() + expected_announcement_python: Tuple[bytes32, List[List[CastableType]]] = (FAKE_LAUNCHER_ID, [[ROYALTY_ADDRESS, 50, [ROYALTY_ADDRESS]]]) + expected_announcement_data = Program.to(expected_announcement_python).get_tree_hash() xch_announcement_spend = make_spend( xch_coin, ACS, diff --git a/tests/wallet/nft_wallet/test_nft_puzzles.py b/tests/wallet/nft_wallet/test_nft_puzzles.py index 8c710d6cfb59..d965efdb4df3 100644 --- a/tests/wallet/nft_wallet/test_nft_puzzles.py +++ b/tests/wallet/nft_wallet/test_nft_puzzles.py @@ -1,7 +1,9 @@ from __future__ import annotations import random -from typing import Tuple +from typing import List, Tuple + +from clvm.SExp import CastableType from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -177,7 +179,7 @@ def get_updated_nft_puzzle(puzzle: Program, solution: Program) -> bytes32: def test_transfer_puzzle_builder() -> None: - metadata = [ + metadata: List[Tuple[str, CastableType]] = [ ("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", 0xD4584AD463139FA8C0D9F68F4B59F185), ] From 11b5595db8c21a9ae866689218952b52515ee7d5 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Dec 2023 17:06:16 -0500 Subject: [PATCH 04/34] some --- chia/data_layer/data_store.py | 5 +-- chia/types/blockchain_format/program.py | 40 +++++++++++++------ .../blockchain_format/serialized_program.py | 11 +++-- chia/wallet/conditions.py | 3 +- chia/wallet/nft_wallet/uncurry_nft.py | 6 +-- chia/wallet/util/debug_spend_bundle.py | 2 +- 6 files changed, 39 insertions(+), 28 deletions(-) diff --git a/chia/data_layer/data_store.py b/chia/data_layer/data_store.py index 123aaafce417..1d12593eb1c9 100644 --- a/chia/data_layer/data_store.py +++ b/chia/data_layer/data_store.py @@ -1418,10 +1418,7 @@ async def get_tree_as_program(self, tree_id: bytes32) -> Program: hash_to_node[node.hash] = node root_node = hash_to_node[root_node.hash] - # TODO: Remove ignore when done. - # https://github.com/Chia-Network/clvm/pull/102 - # https://github.com/Chia-Network/clvm/pull/106 - program: Program = Program.to(root_node) + program = Program.to(root_node) return program diff --git a/chia/types/blockchain_format/program.py b/chia/types/blockchain_format/program.py index 904654eb38f4..de254bf7321d 100644 --- a/chia/types/blockchain_format/program.py +++ b/chia/types/blockchain_format/program.py @@ -1,13 +1,14 @@ from __future__ import annotations import io -from typing import Any, Callable, Dict, Optional, Set, Tuple +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar, Union from chia_rs import ALLOW_BACKREFS, run_chia_program, tree_hash -from clvm import SExp from clvm.casts import int_from_bytes +from clvm.CLVMObject import CLVMStorage from clvm.EvalError import EvalError from clvm.serialize import sexp_from_stream, sexp_to_stream +from clvm.SExp import CastableType, SExp from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.byte_types import hexstr_to_bytes @@ -18,20 +19,24 @@ INFINITE_COST = 11000000000 +T_CLVMStorage = TypeVar("T_CLVMStorage", bound=CLVMStorage) +T_Program = TypeVar("T_Program", bound="Program") + + class Program(SExp): """ A thin wrapper around s-expression data intended to be invoked with "eval". """ @classmethod - def parse(cls, f) -> Program: + def parse(cls: Type[T_Program], f) -> T_Program: return sexp_from_stream(f, cls.to) def stream(self, f): sexp_to_stream(self, f) @classmethod - def from_bytes(cls, blob: bytes) -> Program: + def from_bytes(cls: Type[T_Program], blob: bytes) -> T_Program: # this runs the program "1", which just returns the first argument. # the first argument is the buffer we want to parse. This effectively # leverages the rust parser and LazyNode, making it a lot faster to @@ -42,10 +47,10 @@ def from_bytes(cls, blob: bytes) -> Program: 50, ALLOW_BACKREFS, ) - return Program.to(ret) + return cls.to(ret) @classmethod - def fromhex(cls, hexstr: str) -> Program: + def fromhex(cls: Type[T_Program], hexstr: str) -> T_Program: return cls.from_bytes(hexstr_to_bytes(hexstr)) def __bytes__(self) -> bytes: @@ -75,7 +80,7 @@ def at(self, position: str) -> Program: raise ValueError(f"`at` got illegal character `{c}`. Only `f` & `r` allowed") return v - def replace(self, **kwargs) -> Program: + def replace(self: T_Program, **kwargs) -> T_Program: """ Create a new program replacing the given paths (using `at` syntax). Example: @@ -108,15 +113,15 @@ def get_tree_hash_precalc(self, *args: bytes32) -> bytes32: def get_tree_hash(self) -> bytes32: return bytes32(tree_hash(bytes(self))) - def _run(self, max_cost: int, flags: int, args: object) -> Tuple[int, Program]: + def _run(self, max_cost: int, flags: int, args: CastableType) -> Tuple[int, Program]: prog_args = Program.to(args) cost, r = run_chia_program(self.as_bin(), prog_args.as_bin(), max_cost, flags) return cost, Program.to(r) - def run_with_cost(self, max_cost: int, args: object) -> Tuple[int, Program]: + def run_with_cost(self, max_cost: int, args: CastableType) -> Tuple[int, Program]: return self._run(max_cost, 0, args) - def run(self, args: object) -> Program: + def run(self, args: CastableType) -> Program: cost, r = self.run_with_cost(INFINITE_COST, args) return r @@ -143,7 +148,7 @@ def curry(self, *args) -> Program: return Program.to([2, (1, self), fixed_args]) def uncurry(self) -> Tuple[Program, Program]: - def match(o: SExp, expected: bytes) -> None: + def match(o: CLVMStorage, expected: bytes) -> None: if o.atom != expected: raise ValueError(f"expected: {expected.hex()}") @@ -151,6 +156,9 @@ def match(o: SExp, expected: bytes) -> None: # (2 (1 . ) ) ev, quoted_inner, args_list = self.as_iter() match(ev, b"\x02") + if TYPE_CHECKING: + # this being False is presently handled in the TypeError exception handler below + assert quoted_inner.pair is not None match(quoted_inner.pair[0], b"\x01") mod = quoted_inner.pair[1] args = [] @@ -158,6 +166,9 @@ def match(o: SExp, expected: bytes) -> None: # (4 (1 . ) ) cons, quoted_arg, rest = args_list.as_iter() match(cons, b"\x04") + if TYPE_CHECKING: + # this being False is presently handled in the TypeError exception handler below + assert quoted_arg.pair is not None match(quoted_arg.pair[0], b"\x01") args.append(quoted_arg.pair[1]) args_list = rest @@ -198,7 +209,8 @@ def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: right = _tree_hash(node.rest(), precalculated) s = b"\2" + left + right else: - atom = node.as_atom() + # node.listp() is False so must be an atom + atom: bytes = node.as_atom() # type: ignore[assignment] if atom in precalculated: return bytes32(atom) s = b"\1" + atom @@ -208,7 +220,9 @@ def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: NIL = Program.from_bytes(b"\x80") -def _sexp_replace(sexp: SExp, to_sexp: Callable[[Any], SExp], **kwargs) -> SExp: +def _sexp_replace( + sexp: T_CLVMStorage, to_sexp: Callable[[CastableType], T_Program], **kwargs +) -> Union[T_Program, T_CLVMStorage]: # if `kwargs == {}` then `return sexp` unchanged if len(kwargs) == 0: return sexp diff --git a/chia/types/blockchain_format/serialized_program.py b/chia/types/blockchain_format/serialized_program.py index f2cacdea8a56..ec7ea8946f95 100644 --- a/chia/types/blockchain_format/serialized_program.py +++ b/chia/types/blockchain_format/serialized_program.py @@ -4,15 +4,14 @@ from typing import Tuple from chia_rs import MEMPOOL_MODE, run_chia_program, serialized_length, tree_hash -from clvm import SExp -from clvm.SExp import CastableType +from clvm.SExp import CastableType, SExp from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.byte_types import hexstr_to_bytes -def _serialize(node: object) -> bytes: +def _serialize(node: CastableType) -> bytes: if isinstance(node, list): serialized_list = bytearray() for a in node: @@ -93,13 +92,13 @@ def __ne__(self, other: object) -> bool: def get_tree_hash(self) -> bytes32: return bytes32(tree_hash(self._buf)) - def run_mempool_with_cost(self, max_cost: int, arg: object) -> Tuple[int, Program]: + def run_mempool_with_cost(self, max_cost: int, arg: CastableType) -> Tuple[int, Program]: return self._run(max_cost, MEMPOOL_MODE, arg) - def run_with_cost(self, max_cost: int, arg: object) -> Tuple[int, Program]: + def run_with_cost(self, max_cost: int, arg: CastableType) -> Tuple[int, Program]: return self._run(max_cost, 0, arg) - def _run(self, max_cost: int, flags: int, arg: object) -> Tuple[int, Program]: + def _run(self, max_cost: int, flags: int, arg: CastableType) -> Tuple[int, Program]: # when multiple arguments are passed, concatenate them into a serialized # buffer. Some arguments may already be in serialized form (e.g. # SerializedProgram) so we don't want to de-serialize those just to diff --git a/chia/wallet/conditions.py b/chia/wallet/conditions.py index 3b11d76ff8c4..0ade82b9eb03 100644 --- a/chia/wallet/conditions.py +++ b/chia/wallet/conditions.py @@ -6,6 +6,7 @@ from chia_rs import G1Element from clvm.casts import int_from_bytes, int_to_bytes +from clvm.SExp import CastableType from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -231,7 +232,7 @@ class CreateCoin(Condition): memos: Optional[List[bytes]] = None def to_program(self) -> Program: - condition_args = [ConditionOpcode.CREATE_COIN, self.puzzle_hash, self.amount] + condition_args: List[CastableType] = [ConditionOpcode.CREATE_COIN, self.puzzle_hash, self.amount] if self.memos is not None: condition_args.append(self.memos) condition: Program = Program.to(condition_args) diff --git a/chia/wallet/nft_wallet/uncurry_nft.py b/chia/wallet/nft_wallet/uncurry_nft.py index 3c74fa56284c..01722393aab3 100644 --- a/chia/wallet/nft_wallet/uncurry_nft.py +++ b/chia/wallet/nft_wallet/uncurry_nft.py @@ -148,7 +148,7 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> transfer_program = None transfer_program_args = None royalty_address = None - royalty_percentage = None + royalty_percentage: Optional[uint16] = None nft_inner_puzzle_mod = None mod, ol_args = inner_puzzle.uncurry() supports_did = False @@ -157,8 +157,8 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> log.debug("Parsing ownership layer") _, current_did, transfer_program, p2_puzzle = ol_args.as_iter() transfer_program_mod, transfer_program_args = transfer_program.uncurry() - _, royalty_address_p, royalty_percentage = transfer_program_args.as_iter() - royalty_percentage = uint16(royalty_percentage.as_int()) + _, royalty_address_p, royalty_percentage_program = transfer_program_args.as_iter() + royalty_percentage = uint16(royalty_percentage_program.as_int()) royalty_address = royalty_address_p.atom current_did = current_did.atom if current_did == b"": diff --git a/chia/wallet/util/debug_spend_bundle.py b/chia/wallet/util/debug_spend_bundle.py index 4165f50c8db1..34451755e562 100644 --- a/chia/wallet/util/debug_spend_bundle.py +++ b/chia/wallet/util/debug_spend_bundle.py @@ -3,7 +3,7 @@ from typing import List from chia_rs import AugSchemeMPL, G1Element -from clvm import KEYWORD_FROM_ATOM +from clvm.operators import KEYWORD_FROM_ATOM from clvm_tools.binutils import disassemble as bu_disassemble from chia.consensus.default_constants import DEFAULT_CONSTANTS From 8b09ee9a4126d9b372e783f7a1c964a5d2b475c8 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Dec 2023 21:12:41 -0500 Subject: [PATCH 05/34] undo for now --- chia/rpc/wallet_rpc_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chia/rpc/wallet_rpc_api.py b/chia/rpc/wallet_rpc_api.py index 4a504e5a1eb0..29d5797d69be 100644 --- a/chia/rpc/wallet_rpc_api.py +++ b/chia/rpc/wallet_rpc_api.py @@ -3416,7 +3416,7 @@ async def nft_get_info(self, request: Dict[str, Any]) -> EndpointResult: full_puzzle = nft_puzzles.create_full_puzzle( uncurried_nft.singleton_launcher_id, metadata, - bytes32(uncurried_nft.metadata_updater_hash), + uncurried_nft.metadata_updater_hash, inner_puzzle, ) From 2fe2498ff90c728071ce3773c57cfeb3412f0043 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Dec 2023 22:16:56 -0500 Subject: [PATCH 06/34] more --- benchmarks/mempool-long-lived.py | 6 +++--- chia/data_layer/data_layer_util.py | 3 ++- chia/pools/pool_puzzles.py | 6 +++--- chia/wallet/nft_wallet/singleton_outer_puzzle.py | 11 ++++++++--- chia/wallet/nft_wallet/uncurry_nft.py | 4 ++-- chia/wallet/wallet_singleton_store.py | 6 +++--- tests/generator/test_rom.py | 3 ++- tests/wallet/dao_wallet/test_dao_clvm.py | 10 +++++----- 8 files changed, 28 insertions(+), 21 deletions(-) diff --git a/benchmarks/mempool-long-lived.py b/benchmarks/mempool-long-lived.py index 38db69ecdd30..c02528a409ae 100644 --- a/benchmarks/mempool-long-lived.py +++ b/benchmarks/mempool-long-lived.py @@ -11,7 +11,7 @@ from chia.consensus.default_constants import DEFAULT_CONSTANTS from chia.full_node.mempool_manager import MempoolManager from chia.types.blockchain_format.coin import Coin -from chia.types.blockchain_format.program import Program +from chia.types.blockchain_format.serialized_program import SerializedProgram from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.coin_record import CoinRecord from chia.types.coin_spend import CoinSpend @@ -44,7 +44,7 @@ def is_transaction_block(self) -> bool: return self.timestamp is not None -IDENTITY_PUZZLE = Program.to(1) +IDENTITY_PUZZLE = SerializedProgram.to(1) IDENTITY_PUZZLE_HASH = IDENTITY_PUZZLE.get_tree_hash() @@ -62,7 +62,7 @@ def make_spend_bundle(coin: Coin, height: int) -> SpendBundle: int_to_bytes(coin.amount // 2 - height * 10), ], ] - spend = CoinSpend(coin, IDENTITY_PUZZLE, Program.to(conditions)) + spend = CoinSpend(coin, IDENTITY_PUZZLE, SerializedProgram.to(conditions)) return SpendBundle([spend], G2Element()) diff --git a/chia/data_layer/data_layer_util.py b/chia/data_layer/data_layer_util.py index 4f88bf700908..cb61b279c611 100644 --- a/chia/data_layer/data_layer_util.py +++ b/chia/data_layer/data_layer_util.py @@ -7,6 +7,7 @@ # TODO: remove or formalize this import aiosqlite as aiosqlite +from clvm.CLVMObject import CLVMStorage from typing_extensions import final from chia.types.blockchain_format.program import Program @@ -144,7 +145,7 @@ class TerminalNode: atom: None = field(init=False, default=None) @property - def pair(self) -> Tuple[bytes32, bytes32]: + def pair(self) -> Tuple[CLVMStorage, CLVMStorage]: return Program.to(self.key), Program.to(self.value) @classmethod diff --git a/chia/pools/pool_puzzles.py b/chia/pools/pool_puzzles.py index a6a0f4f04cd2..ad70072d45d6 100644 --- a/chia/pools/pool_puzzles.py +++ b/chia/pools/pool_puzzles.py @@ -105,7 +105,7 @@ def get_delayed_puz_info_from_launcher_spend(coinsol: CoinSpend) -> Tuple[uint64 delayed_puzzle_hash: Optional[bytes32] = None for key, value in extra_data.as_python(): if key == b"t": - seconds = int_from_bytes(value) + seconds = uint64(int_from_bytes(value)) if key == b"h": delayed_puzzle_hash = bytes32(value) assert seconds is not None @@ -130,8 +130,8 @@ def get_seconds_and_delayed_puzhash_from_p2_singleton_puzzle(puzzle: Program) -> return False inner_f, args = r singleton_mod_hash, launcher_id, launcher_puzzle_hash, seconds_delay, delayed_puzzle_hash = list(args.as_iter()) - seconds_delay = uint64(seconds_delay.as_int()) - return seconds_delay, delayed_puzzle_hash.as_atom() + seconds_delay_uint = uint64(seconds_delay.as_int()) + return seconds_delay_uint, delayed_puzzle_hash.as_atom() # Verify that a puzzle is a Pool Wallet Singleton diff --git a/chia/wallet/nft_wallet/singleton_outer_puzzle.py b/chia/wallet/nft_wallet/singleton_outer_puzzle.py index dd20083e3db1..1188caba9f18 100644 --- a/chia/wallet/nft_wallet/singleton_outer_puzzle.py +++ b/chia/wallet/nft_wallet/singleton_outer_puzzle.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Callable, Optional +from typing import Any, Callable, Dict, Optional from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -31,10 +31,15 @@ def match(self, puzzle: UncurriedPuzzle) -> Optional[PuzzleInfo]: matched, curried_args = match_singleton_puzzle(puzzle) if matched: singleton_struct, inner_puzzle = curried_args - launcher_struct = singleton_struct.pair[1].pair + pair = singleton_struct.pair + assert pair is not None + launcher_struct = pair[1].pair + assert launcher_struct is not None launcher_id = launcher_struct[0].atom + assert launcher_id is not None launcher_ph = launcher_struct[1].atom - constructor_dict = { + assert launcher_ph is not None + constructor_dict: Dict[str, Any] = { "type": "singleton", "launcher_id": "0x" + launcher_id.hex(), "launcher_ph": "0x" + launcher_ph.hex(), diff --git a/chia/wallet/nft_wallet/uncurry_nft.py b/chia/wallet/nft_wallet/uncurry_nft.py index 01722393aab3..891f88242353 100644 --- a/chia/wallet/nft_wallet/uncurry_nft.py +++ b/chia/wallet/nft_wallet/uncurry_nft.py @@ -155,12 +155,12 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> if mod == NFT_OWNERSHIP_LAYER: supports_did = True log.debug("Parsing ownership layer") - _, current_did, transfer_program, p2_puzzle = ol_args.as_iter() + _, current_did_program, transfer_program, p2_puzzle = ol_args.as_iter() transfer_program_mod, transfer_program_args = transfer_program.uncurry() _, royalty_address_p, royalty_percentage_program = transfer_program_args.as_iter() royalty_percentage = uint16(royalty_percentage_program.as_int()) royalty_address = royalty_address_p.atom - current_did = current_did.atom + current_did = current_did_program.atom if current_did == b"": # For unassigned NFT, set owner DID to None current_did = None diff --git a/chia/wallet/wallet_singleton_store.py b/chia/wallet/wallet_singleton_store.py index 56f9d457f2c7..06ca22250785 100644 --- a/chia/wallet/wallet_singleton_store.py +++ b/chia/wallet/wallet_singleton_store.py @@ -14,7 +14,7 @@ from chia.types.condition_opcodes import ConditionOpcode from chia.util.condition_tools import conditions_dict_for_solution from chia.util.db_wrapper import DBWrapper2, execute_fetchone -from chia.util.ints import uint32 +from chia.util.ints import uint32, uint64 from chia.wallet import singleton from chia.wallet.lineage_proof import LineageProof from chia.wallet.singleton import get_inner_puzzle_from_singleton, get_singleton_id_from_puzzle @@ -113,10 +113,10 @@ async def add_spend( lineage_bytes = [x.as_atom() for x in coin_state.solution.to_program().first().as_iter()] if len(lineage_bytes) == 2: - lineage_proof = LineageProof(bytes32(lineage_bytes[0]), None, int_from_bytes(lineage_bytes[1])) + lineage_proof = LineageProof(bytes32(lineage_bytes[0]), None, uint64(int_from_bytes(lineage_bytes[1]))) else: lineage_proof = LineageProof( - bytes32(lineage_bytes[0]), bytes32(lineage_bytes[1]), int_from_bytes(lineage_bytes[2]) + bytes32(lineage_bytes[0]), bytes32(lineage_bytes[1]), uint64(int_from_bytes(lineage_bytes[2])) ) # Create and save the new singleton record new_record = SingletonRecord( diff --git a/tests/generator/test_rom.py b/tests/generator/test_rom.py index 65cd29cca065..29a9f1576a72 100644 --- a/tests/generator/test_rom.py +++ b/tests/generator/test_rom.py @@ -2,6 +2,7 @@ from typing import List, Tuple +from clvm.CLVMObject import CLVMStorage from clvm_tools import binutils from clvm_tools.clvmc import compile_clvm_text @@ -84,7 +85,7 @@ def run_generator(self: BlockGenerator) -> Tuple[int, Program]: return GENERATOR_MOD.run_with_cost(MAX_COST, [self.program, args]) -def as_atom_list(prg: Program) -> List[bytes]: +def as_atom_list(prg: CLVMStorage) -> List[bytes]: """ Pretend `prg` is a list of atoms. Return the corresponding python list of atoms. diff --git a/tests/wallet/dao_wallet/test_dao_clvm.py b/tests/wallet/dao_wallet/test_dao_clvm.py index f0facfcbc004..f08c5b049ed6 100644 --- a/tests/wallet/dao_wallet/test_dao_clvm.py +++ b/tests/wallet/dao_wallet/test_dao_clvm.py @@ -316,11 +316,11 @@ def test_proposal() -> None: treasury_inner, ) treasury_puzhash = treasury.get_tree_hash() - apa_msg = singleton_id + apa_msg_bytes = singleton_id timer_apa = std_hash(timer_puzhash + singleton_id) assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == timer_apa - assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][1].vars[0] == std_hash(treasury_puzhash + apa_msg) + assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][1].vars[0] == std_hash(treasury_puzhash + apa_msg_bytes) # close a failed proposal full_proposal = proposal_curry_one.curry( @@ -347,8 +347,8 @@ def test_proposal() -> None: ] ) conds = conditions_dict_for_solution(full_proposal, solution, INFINITE_COST) - apa_msg = int_to_bytes(0) - assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][1].vars[0] == std_hash(treasury_puzhash + apa_msg) + apa_msg_int = int_to_bytes(0) + assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][1].vars[0] == std_hash(treasury_puzhash + apa_msg_int) assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == timer_apa finished_puz = DAO_FINISHED_STATE.curry(singleton_struct, DAO_FINISHED_STATE_HASH) @@ -373,7 +373,7 @@ def test_proposal() -> None: ] ) conds = conditions_dict_for_solution(full_proposal, solution, INFINITE_COST) - assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == std_hash(treasury_puzhash + apa_msg) + assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == std_hash(treasury_puzhash + apa_msg_int) assert conds[ConditionOpcode.CREATE_COIN][0].vars[0] == finished_puz.get_tree_hash() From 14362a89616dedb10b49a089793ce9e93eb41a74 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Sun, 24 Dec 2023 16:31:37 -0500 Subject: [PATCH 07/34] more --- chia/pools/pool_puzzles.py | 2 +- chia/wallet/cat_wallet/cat_outer_puzzle.py | 5 +- chia/wallet/cat_wallet/cat_utils.py | 3 +- chia/wallet/dao_wallet/dao_utils.py | 3 +- chia/wallet/nft_wallet/uncurry_nft.py | 27 +++++++--- chia/wallet/util/compute_hints.py | 5 +- chia/wallet/vc_wallet/cr_cat_drivers.py | 53 +++++++++----------- chia/wallet/vc_wallet/vc_drivers.py | 18 +++---- tests/core/custom_types/test_spend_bundle.py | 3 +- tests/core/mempool/test_mempool_manager.py | 3 +- tests/wallet/dao_wallet/test_dao_clvm.py | 34 +++++++------ tests/wallet/db_wallet/test_db_graftroot.py | 5 +- tests/wallet/vc_wallet/test_vc_lifecycle.py | 21 ++++---- 13 files changed, 101 insertions(+), 81 deletions(-) diff --git a/chia/pools/pool_puzzles.py b/chia/pools/pool_puzzles.py index ad70072d45d6..e22fdebad661 100644 --- a/chia/pools/pool_puzzles.py +++ b/chia/pools/pool_puzzles.py @@ -131,7 +131,7 @@ def get_seconds_and_delayed_puzhash_from_p2_singleton_puzzle(puzzle: Program) -> inner_f, args = r singleton_mod_hash, launcher_id, launcher_puzzle_hash, seconds_delay, delayed_puzzle_hash = list(args.as_iter()) seconds_delay_uint = uint64(seconds_delay.as_int()) - return seconds_delay_uint, delayed_puzzle_hash.as_atom() + return seconds_delay_uint, bytes32(delayed_puzzle_hash.as_atom()) # Verify that a puzzle is a Pool Wallet Singleton diff --git a/chia/wallet/cat_wallet/cat_outer_puzzle.py b/chia/wallet/cat_wallet/cat_outer_puzzle.py index d90161a02546..18d5e7bd01f5 100644 --- a/chia/wallet/cat_wallet/cat_outer_puzzle.py +++ b/chia/wallet/cat_wallet/cat_outer_puzzle.py @@ -1,7 +1,7 @@ from __future__ import annotations from dataclasses import dataclass -from typing import Callable, List, Optional +from typing import Any, Callable, Dict, List, Optional from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -33,7 +33,8 @@ def match(self, puzzle: UncurriedPuzzle) -> Optional[PuzzleInfo]: if args is None: return None _, tail_hash, inner_puzzle = args - constructor_dict = { + assert tail_hash.atom is not None + constructor_dict: Dict[str, Any] = { "type": "CAT", "tail": "0x" + tail_hash.atom.hex(), } diff --git a/chia/wallet/cat_wallet/cat_utils.py b/chia/wallet/cat_wallet/cat_utils.py index 484dd3289437..4ae9e30a456a 100644 --- a/chia/wallet/cat_wallet/cat_utils.py +++ b/chia/wallet/cat_wallet/cat_utils.py @@ -4,6 +4,7 @@ from typing import Iterator, List, Optional, Union from chia_rs import G2Element +from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin, coin_as_list from chia.types.blockchain_format.program import INFINITE_COST, Program @@ -98,7 +99,7 @@ def subtotals_for_deltas(deltas: List[int]) -> List[int]: def next_info_for_spendable_cat(spendable_cat: SpendableCAT) -> Program: c = spendable_cat.coin - list = [c.parent_coin_info, spendable_cat.inner_puzzle.get_tree_hash(), c.amount] + list: CastableType = [c.parent_coin_info, spendable_cat.inner_puzzle.get_tree_hash(), c.amount] return Program.to(list) diff --git a/chia/wallet/dao_wallet/dao_utils.py b/chia/wallet/dao_wallet/dao_utils.py index 214a0c5180ed..ac974004e726 100644 --- a/chia/wallet/dao_wallet/dao_utils.py +++ b/chia/wallet/dao_wallet/dao_utils.py @@ -5,6 +5,7 @@ from typing import Any, Iterator, List, Optional, Tuple, Union from clvm.EvalError import EvalError +from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -794,7 +795,7 @@ async def generate_mint_proposal_innerpuz( # cat_tail_hash = cat_wallet.cat_info.limitations_program_hash eve_puz_hash = curry_cat_eve(cats_new_innerpuzhash) full_puz = construct_cat_puzzle(CAT_MOD, cat_tail_hash, eve_puz_hash) - xch_conditions = [ + xch_conditions: List[List[CastableType]] = [ [ 51, cat_launcher.get_tree_hash(), diff --git a/chia/wallet/nft_wallet/uncurry_nft.py b/chia/wallet/nft_wallet/uncurry_nft.py index 891f88242353..17b78d248a3d 100644 --- a/chia/wallet/nft_wallet/uncurry_nft.py +++ b/chia/wallet/nft_wallet/uncurry_nft.py @@ -105,6 +105,12 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> try: (singleton_struct, nft_state_layer) = curried_args.as_iter() singleton_mod_hash = singleton_struct.first() + + # singleton_mod_hash: Optional[bytes32] + # if atom is None: + # singleton_mod_hash = None + # else: + # singleton_mod_hash = bytes32(atom) singleton_launcher_id = singleton_struct.rest().first() launcher_puzhash = singleton_struct.rest().rest() except ValueError as e: @@ -118,6 +124,7 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> try: # Set nft parameters nft_mod_hash, metadata, metadata_updater_hash, inner_puzzle = curried_args.as_iter() + assert nft_mod_hash.atom is not None data_uris = Program.to([]) data_hash = Program.to(0) meta_uris = Program.to([]) @@ -144,10 +151,10 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> edition_number = kv_pair.rest() if kv_pair.first().as_atom() == b"st": edition_total = kv_pair.rest() - current_did = None + current_did: Optional[bytes32] = None transfer_program = None transfer_program_args = None - royalty_address = None + royalty_address: Optional[bytes32] = None royalty_percentage: Optional[uint16] = None nft_inner_puzzle_mod = None mod, ol_args = inner_puzzle.uncurry() @@ -159,11 +166,14 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> transfer_program_mod, transfer_program_args = transfer_program.uncurry() _, royalty_address_p, royalty_percentage_program = transfer_program_args.as_iter() royalty_percentage = uint16(royalty_percentage_program.as_int()) - royalty_address = royalty_address_p.atom - current_did = current_did_program.atom - if current_did == b"": + assert royalty_address_p.atom is not None + royalty_address = bytes32(royalty_address_p.atom) + atom = current_did_program.atom + if atom == b"": # For unassigned NFT, set owner DID to None - current_did = None + atom = None + if atom is not None: + current_did = bytes32(atom) else: log.debug("Creating a standard NFT puzzle") p2_puzzle = inner_puzzle @@ -171,12 +181,15 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> log.debug("Cannot uncurry NFT state layer: Args %s Error: %s", curried_args, e) return None + assert singleton_launcher_id.atom is not None + singleton_launcher_id_bytes32 = bytes32(singleton_launcher_id.atom) + return cls( nft_mod_hash=bytes32(nft_mod_hash.atom), nft_state_layer=nft_state_layer, singleton_struct=singleton_struct, singleton_mod_hash=singleton_mod_hash, - singleton_launcher_id=singleton_launcher_id.atom, + singleton_launcher_id=singleton_launcher_id_bytes32, launcher_puzhash=launcher_puzhash, metadata=metadata, data_uris=data_uris, diff --git a/chia/wallet/util/compute_hints.py b/chia/wallet/util/compute_hints.py index 6962c60589b7..de982e8aac57 100644 --- a/chia/wallet/util/compute_hints.py +++ b/chia/wallet/util/compute_hints.py @@ -49,7 +49,10 @@ def compute_spend_hints_and_additions( continue cost += ConditionCost.CREATE_COIN.value - coin: Coin = Coin(cs.coin.name(), bytes32(condition.at("rf").atom), uint64(condition.at("rrf").as_int())) + rf = condition.at("rf").atom + assert rf is not None + + coin: Coin = Coin(cs.coin.name(), bytes32(rf), uint64(condition.at("rrf").as_int())) hint: Optional[bytes32] = None if ( condition.at("rrr") != Program.to(None) # There's more than two arguments diff --git a/chia/wallet/vc_wallet/cr_cat_drivers.py b/chia/wallet/vc_wallet/cr_cat_drivers.py index 23b6d7a89b91..c4a278285ba5 100644 --- a/chia/wallet/vc_wallet/cr_cat_drivers.py +++ b/chia/wallet/vc_wallet/cr_cat_drivers.py @@ -6,6 +6,7 @@ from typing import Iterable, List, Optional, Tuple, Type, TypeVar from clvm.casts import int_to_bytes +from clvm.SExp import CastableType from chia.types.announcement import Announcement from chia.types.blockchain_format.coin import Coin, coin_as_list @@ -50,6 +51,15 @@ package_or_requirement="chia.wallet.vc_wallet.cr_puzzles", include_standard_libraries=True, ) +something_a: CastableType = [ + 4, + (1, create_eml_covenant_morpher(create_did_tp().get_tree_hash())), + [4, (1, create_did_tp()), 1], +] +something_b: CastableType = ( + something_a, + None, +) CREDENTIAL_STRUCT: Program = Program.to( ( ( @@ -75,16 +85,7 @@ Program.to( int_to_bytes(2) + Program.to((1, COVENANT_LAYER_HASH)).get_tree_hash_precalc(COVENANT_LAYER_HASH) ), - Program.to( - ( - [ - 4, - (1, create_eml_covenant_morpher(create_did_tp().get_tree_hash())), - [4, (1, create_did_tp()), 1], - ], - None, - ) - ).get_tree_hash(), + Program.to(something_b).get_tree_hash(), ), ), ), @@ -211,17 +212,13 @@ def launch( new_cr_layer_hash ) - eve_innerpuz: Program = Program.to( - ( - 1, - [ - [51, new_cr_layer_hash, payment.amount, payment.memos], - [51, None, -113, tail, tail_solution], - [60, None], - [1, payment.puzzle_hash, authorized_providers, proofs_checker], - ], - ) - ) + something_a: List[List[CastableType]] = [ + [51, new_cr_layer_hash, payment.amount, payment.memos], + [51, None, -113, tail, tail_solution], + [60, None], + [1, payment.puzzle_hash, authorized_providers, proofs_checker], + ] + eve_innerpuz: Program = Program.to((1, something_a)) eve_cat_puzzle: Program = construct_cat_puzzle( CAT_MOD, tail_hash, @@ -230,15 +227,11 @@ def launch( eve_cat_puzzle_hash: bytes32 = eve_cat_puzzle.get_tree_hash() eve_coin: Coin = Coin(origin_coin.name(), eve_cat_puzzle_hash, payment.amount) - dpuz: Program = Program.to( - ( - 1, - [ - [51, eve_cat_puzzle_hash, payment.amount], - [61, std_hash(eve_coin.name())], - ], - ) - ) + something_b: CastableType = [ + [51, eve_cat_puzzle_hash, payment.amount], + [61, std_hash(eve_coin.name())], + ] + dpuz: Program = Program.to((1, something_b)) eve_proof: LineageProof = LineageProof( eve_coin.parent_coin_info, diff --git a/chia/wallet/vc_wallet/vc_drivers.py b/chia/wallet/vc_wallet/vc_drivers.py index ce10974f652c..a685d17e3f37 100644 --- a/chia/wallet/vc_wallet/vc_drivers.py +++ b/chia/wallet/vc_wallet/vc_drivers.py @@ -3,6 +3,8 @@ from dataclasses import dataclass, replace from typing import List, Optional, Tuple, Type, TypeVar +from clvm.SExp import CastableType + from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -389,16 +391,12 @@ def launch( launcher_coin.name(), metadata_layer_hash, # type: ignore ).get_tree_hash_precalc(metadata_layer_hash) - launch_dpuz: Program = Program.to( - ( - 1, - [ - [51, wrapped_inner_puzzle_hash, uint64(1), memos], - [1, new_inner_puzzle_hash], - [-10, provider_id, transfer_program.get_tree_hash()], - ], - ) - ) + something: List[List[CastableType]] = [ + [51, wrapped_inner_puzzle_hash, uint64(1), memos], + [1, new_inner_puzzle_hash], + [-10, provider_id, transfer_program.get_tree_hash()], + ] + launch_dpuz: Program = Program.to((1, something)) second_launcher_solution = Program.to([launch_dpuz, None]) second_launcher_coin: Coin = Coin( launcher_coin.name(), diff --git a/tests/core/custom_types/test_spend_bundle.py b/tests/core/custom_types/test_spend_bundle.py index 78c61e2a2a3d..bdea795b5e43 100644 --- a/tests/core/custom_types/test_spend_bundle.py +++ b/tests/core/custom_types/test_spend_bundle.py @@ -7,6 +7,7 @@ import pytest from chia_rs import G2Element +from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -103,7 +104,7 @@ def create_spends(num: int) -> Tuple[List[CoinSpend], List[Coin]]: for i in range(num): target_ph = rand_hash(rng) - conditions = [[ConditionOpcode.CREATE_COIN, target_ph, 1]] + conditions: List[CastableType] = [[ConditionOpcode.CREATE_COIN, target_ph, 1]] coin = Coin(rand_hash(rng), puzzle_hash, 1000) new_coin = Coin(coin.name(), target_ph, 1) create_coin.append(new_coin) diff --git a/tests/core/mempool/test_mempool_manager.py b/tests/core/mempool/test_mempool_manager.py index 2612f4a9332d..7ccca90c1389 100644 --- a/tests/core/mempool/test_mempool_manager.py +++ b/tests/core/mempool/test_mempool_manager.py @@ -6,6 +6,7 @@ import pytest from chia_rs import ELIGIBLE_FOR_DEDUP, G1Element, G2Element from chiabip158 import PyBIP158 +from clvm.SExp import CastableType from chia.consensus.constants import ConsensusConstants from chia.consensus.cost_calculator import NPCResult @@ -1718,7 +1719,7 @@ async def make_setup_and_coins( ), ], ) -async def test_mempool_timelocks(cond1: List[object], cond2: List[object], expected: Optional[Err]) -> None: +async def test_mempool_timelocks(cond1: List[CastableType], cond2: List[CastableType], expected: Optional[Err]) -> None: coins = [] test_coin_records = {} diff --git a/tests/wallet/dao_wallet/test_dao_clvm.py b/tests/wallet/dao_wallet/test_dao_clvm.py index f08c5b049ed6..43f605d851d2 100644 --- a/tests/wallet/dao_wallet/test_dao_clvm.py +++ b/tests/wallet/dao_wallet/test_dao_clvm.py @@ -5,6 +5,7 @@ import pytest from chia_rs import AugSchemeMPL from clvm.casts import int_to_bytes +from clvm.SExp import CastableType from chia.clvm.spend_sim import SimClient, SpendSim, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -541,8 +542,8 @@ def test_validator() -> None: ) spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() - parent_amt_list = [[parent_id, locked_amount]] - cat_parent_amt_list: List[Optional[Any]] = [] + parent_amt_list: CastableType = [[parent_id, locked_amount]] + cat_parent_amt_list: CastableType = [] spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()]) output_conds = spend_p2_singleton.run(spend_p2_singleton_solution) @@ -609,8 +610,8 @@ def test_spend_p2_singleton() -> None: ] # Solution Values - xch_parent_amt_list = [[b"x" * 32, 10], [b"y" * 32, 100]] - cat_parent_amt_list = [ + xch_parent_amt_list: CastableType = [[b"x" * 32, 10], [b"y" * 32, 100]] + cat_parent_amt_list: CastableType = [ [cat_tail_1, [["b" * 32, 100], [b"c" * 32, 400]]], [cat_tail_2, [[b"e" * 32, 100], [b"f" * 32, 400]]], ] @@ -720,13 +721,13 @@ def test_merge_p2_singleton() -> None: Program.to("fake_parent_3").get_tree_hash(), ] amounts = [1000, 2000, 3000] - parent_puzhash_amounts = [] + parent_puzhash_amounts: List[List[CastableType]] = [] merge_coin_ids: List[bytes32] = [] for pid, amt in zip(parent_ids, amounts): parent_puzhash_amounts.append([pid, my_puzhash, amt]) merge_coin_ids.append(Coin(pid, my_puzhash, amt).name()) - output_parent_amount = [output_parent_id, output_coin_amount] + output_parent_amount: List[CastableType] = [output_parent_id, output_coin_amount] output_coin_id = Coin(output_parent_id, my_puzhash, output_coin_amount).name() agg_sol = Program.to([[output_coin_id, my_puzhash, output_coin_amount, parent_puzhash_amounts, 0]]) @@ -737,7 +738,8 @@ def test_merge_p2_singleton() -> None: agg_acas = [x.vars[0] for x in agg_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT]] for coin_id, ppa in zip(merge_coin_ids, parent_puzhash_amounts): - sol = Program.to([[coin_id, ppa[1], ppa[2], 0, output_parent_amount]]) + something: CastableType = [[coin_id, ppa[1], ppa[2], 0, output_parent_amount]] + sol = Program.to(something) merge_conds = conditions_dict_for_solution(p2_singleton, sol, INFINITE_COST) # merge coin announces 0 cca = std_hash(coin_id + merge_conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0]) @@ -824,9 +826,10 @@ def test_treasury() -> None: ) spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() - parent_amt_list = [[parent_id, locked_amount]] + parent_amt_list: List[List[CastableType]] = [[parent_id, locked_amount]] cat_parent_amt_list: List[Optional[Any]] = [] - spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()]) + something: CastableType = [parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()] + spend_p2_singleton_solution = Program.to(something) proposal: Program = proposal_curry_one.curry( proposal_curry_one.get_tree_hash(), @@ -895,7 +898,7 @@ def test_lockup() -> None: INNERPUZ, ).get_tree_hash() message = Program.to([new_proposal, lockup_coin_amount, 1, my_id]).get_tree_hash() - generated_conditions = [[51, child_puzhash, lockup_coin_amount], [62, message]] + generated_conditions: List[List[CastableType]] = [[51, child_puzhash, lockup_coin_amount], [62, message]] solution: Program = Program.to( [ my_id, @@ -964,7 +967,7 @@ def test_lockup() -> None: new_innerpuz, ).get_tree_hash() message = Program.to([0, 0, 0, my_id]).get_tree_hash() - spend_conds = [[51, child_lockup, lockup_coin_amount], [62, message]] + spend_conds: List[List[CastableType]] = [[51, child_lockup, lockup_coin_amount], [62, message]] transfer_sol = Program.to( [ my_id, @@ -1071,9 +1074,10 @@ def test_proposal_lifecycle() -> None: ) spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() - parent_amt_list = [[parent_id, locked_amount]] - cat_parent_amt_list: List[Optional[Any]] = [] - spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash]) + parent_amt_list: CastableType = [[parent_id, locked_amount]] + cat_parent_amt_list: CastableType = [] + something: List[CastableType] = [parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash] + spend_p2_singleton_solution = Program.to(something) # Setup Proposal proposal_id = Program.to("proposal_id").get_tree_hash() @@ -1119,7 +1123,7 @@ def test_proposal_lifecycle() -> None: ) # lineage_proof my_amount inner_solution - lineage_proof = [treasury_id, treasury_inner_puzhash, treasury_amount] + lineage_proof: CastableType = [treasury_id, treasury_inner_puzhash, treasury_amount] full_treasury_solution = Program.to([lineage_proof, treasury_amount, treasury_solution]) full_proposal_solution = Program.to([lineage_proof, proposal_amt, proposal_solution]) diff --git a/tests/wallet/db_wallet/test_db_graftroot.py b/tests/wallet/db_wallet/test_db_graftroot.py index e1958679965c..eef11286e24c 100644 --- a/tests/wallet/db_wallet/test_db_graftroot.py +++ b/tests/wallet/db_wallet/test_db_graftroot.py @@ -4,6 +4,7 @@ import pytest from chia_rs import G2Element +from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -44,7 +45,9 @@ async def test_graftroot(cost_logger: CostLogger) -> None: # Create the coin we're testing all_values: List[bytes32] = [bytes32([x] * 32) for x in range(0, 100)] root, proofs = build_merkle_tree(all_values) - p2_conditions = Program.to((1, [[51, ACS_PH, 0]])) # An coin to create to make sure this hits the blockchain + something_a: CastableType = [51, ACS_PH, 0] + something_b: CastableType = (1, [something_a]) + p2_conditions = Program.to(something_b) # An coin to create to make sure this hits the blockchain desired_key_values = ((bytes32([0] * 32), bytes32([1] * 32)), (bytes32([7] * 32), bytes32([8] * 32))) desired_row_hashes: List[bytes32] = [build_merkle_tree_from_binary_tree(kv)[0] for kv in desired_key_values] fake_struct: Program = Program.to((ACS_PH, NIL_PH)) diff --git a/tests/wallet/vc_wallet/test_vc_lifecycle.py b/tests/wallet/vc_wallet/test_vc_lifecycle.py index 63e79257bb93..7e2028d6e4d5 100644 --- a/tests/wallet/vc_wallet/test_vc_lifecycle.py +++ b/tests/wallet/vc_wallet/test_vc_lifecycle.py @@ -5,6 +5,7 @@ import pytest from chia_rs import G2Element +from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -665,6 +666,15 @@ async def test_vc_lifecycle(test_syncing: bool, cost_logger: CostLogger) -> None "attempt_honest_cat_piggyback", None, ): + something_a: List[CastableType] = [[60, b"\xcd" + bytes(32)]] if error == "make_banned_announcement" else [] + something_b: CastableType = [ + [ + 51, + ACS_PH, + cr_1.coin.amount if error != "use_malicious_cats" else malicious_cr_1.coin.amount, + ], + *something_a, + ] # The CR-CAT coin spends expected_announcements, cr_cat_spends, new_crcats = CRCAT.spend_many( [ @@ -672,16 +682,7 @@ async def test_vc_lifecycle(test_syncing: bool, cost_logger: CostLogger) -> None cr_1 if error != "use_malicious_cats" else malicious_cr_1, 0, ACS, - Program.to( - [ - [ - 51, - ACS_PH, - cr_1.coin.amount if error != "use_malicious_cats" else malicious_cr_1.coin.amount, - ], - *([[60, b"\xcd" + bytes(32)]] if error == "make_banned_announcement" else []), - ] - ), + Program.to(something_b), ), ( cr_2 if error != "use_malicious_cats" else malicious_cr_2, From b19325aff019613df55f37cb6858e26f40043218 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 27 Dec 2023 15:03:30 -0500 Subject: [PATCH 08/34] drop the program usage in datalayer tests --- chia/data_layer/data_layer_util.py | 31 ++++-- chia/data_layer/data_store.py | 7 +- tests/core/data_layer/test_data_store.py | 126 +++++++++++------------ tests/core/data_layer/util.py | 60 +++++------ 4 files changed, 112 insertions(+), 112 deletions(-) diff --git a/chia/data_layer/data_layer_util.py b/chia/data_layer/data_layer_util.py index cb61b279c611..760326a8cf9c 100644 --- a/chia/data_layer/data_layer_util.py +++ b/chia/data_layer/data_layer_util.py @@ -1,13 +1,12 @@ from __future__ import annotations import dataclasses -from dataclasses import dataclass, field +from dataclasses import dataclass from enum import IntEnum from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union # TODO: remove or formalize this import aiosqlite as aiosqlite -from clvm.CLVMObject import CLVMStorage from typing_extensions import final from chia.types.blockchain_format.program import Program @@ -135,6 +134,7 @@ class CommitState(IntEnum): Node = Union["TerminalNode", "InternalNode"] +@final @dataclass(frozen=True) class TerminalNode: hash: bytes32 @@ -142,11 +142,13 @@ class TerminalNode: key: bytes value: bytes - atom: None = field(init=False, default=None) - - @property - def pair(self) -> Tuple[CLVMStorage, CLVMStorage]: - return Program.to(self.key), Program.to(self.value) + @classmethod + def from_key_value(cls, key: bytes, value: bytes) -> TerminalNode: + return cls( + hash=leaf_hash(key=key, value=value), + key=key, + value=value, + ) @classmethod def from_row(cls, row: aiosqlite.Row) -> TerminalNode: @@ -232,6 +234,7 @@ def valid(self) -> bool: return True +@final @dataclass(frozen=True) class InternalNode: hash: bytes32 @@ -239,8 +242,18 @@ class InternalNode: left_hash: bytes32 right_hash: bytes32 - pair: Optional[Tuple[Node, Node]] = None - atom: None = None + left: Optional[Node] = None + right: Optional[Node] = None + + @classmethod + def from_child_nodes(cls, left: Node, right: Node) -> InternalNode: + return cls( + hash=internal_hash(left_hash=left.hash, right_hash=right.hash), + left_hash=left.hash, + right_hash=right.hash, + left=left, + right=right, + ) @classmethod def from_row(cls, row: aiosqlite.Row) -> InternalNode: diff --git a/chia/data_layer/data_store.py b/chia/data_layer/data_store.py index 1d12593eb1c9..874b08c58fbb 100644 --- a/chia/data_layer/data_store.py +++ b/chia/data_layer/data_store.py @@ -1390,7 +1390,7 @@ async def get_node(self, node_hash: bytes32) -> Node: node = row_to_node(row=row) return node - async def get_tree_as_program(self, tree_id: bytes32) -> Program: + async def get_tree_as_nodes(self, tree_id: bytes32) -> Node: async with self.db_wrapper.reader() as reader: root = await self.get_tree_root(tree_id=tree_id) # TODO: consider actual proper behavior @@ -1414,13 +1414,12 @@ async def get_tree_as_program(self, tree_id: bytes32) -> Program: hash_to_node: Dict[bytes32, Node] = {} for node in reversed(nodes): if isinstance(node, InternalNode): - node = replace(node, pair=(hash_to_node[node.left_hash], hash_to_node[node.right_hash])) + node = replace(node, left=hash_to_node[node.left_hash], right=hash_to_node[node.right_hash]) hash_to_node[node.hash] = node root_node = hash_to_node[root_node.hash] - program = Program.to(root_node) - return program + return root_node async def get_proof_of_inclusion_by_hash( self, diff --git a/tests/core/data_layer/test_data_store.py b/tests/core/data_layer/test_data_store.py index 79b67535e548..0b195c0e9e12 100644 --- a/tests/core/data_layer/test_data_store.py +++ b/tests/core/data_layer/test_data_store.py @@ -253,7 +253,7 @@ async def test_build_a_tree( example = await create_example(data_store, tree_id) await _debug_dump(db=data_store.db_wrapper, description="final") - actual = await data_store.get_tree_as_program(tree_id=tree_id) + actual = await data_store.get_tree_as_nodes(tree_id=tree_id) # print("actual ", actual.as_python()) # print("expected", example.expected.as_python()) assert actual == example.expected @@ -751,30 +751,28 @@ async def test_delete_from_left_both_terminal(data_store: DataStore, tree_id: by if use_hint: hint_keys_values = await data_store.get_keys_values_dict(tree_id=tree_id) - expected = Program.to( - ( - ( - ( - (b"\x00", b"\x10\x00"), - (b"\x01", b"\x11\x01"), - ), - ( - (b"\x02", b"\x12\x02"), - (b"\x03", b"\x13\x03"), - ), + expected = InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x00", value=b"\x10\x00"), + right=TerminalNode.from_key_value(key=b"\x01", value=b"\x11\x01"), ), - ( - (b"\x05", b"\x15\x05"), - ( - (b"\x06", b"\x16\x06"), - (b"\x07", b"\x17\x07"), - ), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x02", value=b"\x12\x02"), + right=TerminalNode.from_key_value(key=b"\x03", value=b"\x13\x03"), + ), + ), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x05", value=b"\x15\x05"), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x06", value=b"\x16\x06"), + right=TerminalNode.from_key_value(key=b"\x07", value=b"\x17\x07"), ), ), ) await data_store.delete(key=b"\x04", tree_id=tree_id, hint_keys_values=hint_keys_values, status=Status.COMMITTED) - result = await data_store.get_tree_as_program(tree_id=tree_id) + result = await data_store.get_tree_as_nodes(tree_id=tree_id) assert result == expected @@ -791,28 +789,26 @@ async def test_delete_from_left_other_not_terminal(data_store: DataStore, tree_i if use_hint: hint_keys_values = await data_store.get_keys_values_dict(tree_id=tree_id) - expected = Program.to( - ( - ( - ( - (b"\x00", b"\x10\x00"), - (b"\x01", b"\x11\x01"), - ), - ( - (b"\x02", b"\x12\x02"), - (b"\x03", b"\x13\x03"), - ), + expected = InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x00", value=b"\x10\x00"), + right=TerminalNode.from_key_value(key=b"\x01", value=b"\x11\x01"), ), - ( - (b"\x06", b"\x16\x06"), - (b"\x07", b"\x17\x07"), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x02", value=b"\x12\x02"), + right=TerminalNode.from_key_value(key=b"\x03", value=b"\x13\x03"), ), ), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x06", value=b"\x16\x06"), + right=TerminalNode.from_key_value(key=b"\x07", value=b"\x17\x07"), + ), ) await data_store.delete(key=b"\x04", tree_id=tree_id, hint_keys_values=hint_keys_values, status=Status.COMMITTED) await data_store.delete(key=b"\x05", tree_id=tree_id, hint_keys_values=hint_keys_values, status=Status.COMMITTED) - result = await data_store.get_tree_as_program(tree_id=tree_id) + result = await data_store.get_tree_as_nodes(tree_id=tree_id) assert result == expected @@ -829,30 +825,28 @@ async def test_delete_from_right_both_terminal(data_store: DataStore, tree_id: b if use_hint: hint_keys_values = await data_store.get_keys_values_dict(tree_id=tree_id) - expected = Program.to( - ( - ( - ( - (b"\x00", b"\x10\x00"), - (b"\x01", b"\x11\x01"), - ), - (b"\x02", b"\x12\x02"), + expected = InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x00", value=b"\x10\x00"), + right=TerminalNode.from_key_value(key=b"\x01", value=b"\x11\x01"), ), - ( - ( - (b"\x04", b"\x14\x04"), - (b"\x05", b"\x15\x05"), - ), - ( - (b"\x06", b"\x16\x06"), - (b"\x07", b"\x17\x07"), - ), + right=TerminalNode.from_key_value(key=b"\x02", value=b"\x12\x02"), + ), + right=InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x04", value=b"\x14\x04"), + right=TerminalNode.from_key_value(key=b"\x05", value=b"\x15\x05"), + ), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x06", value=b"\x16\x06"), + right=TerminalNode.from_key_value(key=b"\x07", value=b"\x17\x07"), ), ), ) await data_store.delete(key=b"\x03", tree_id=tree_id, hint_keys_values=hint_keys_values, status=Status.COMMITTED) - result = await data_store.get_tree_as_program(tree_id=tree_id) + result = await data_store.get_tree_as_nodes(tree_id=tree_id) assert result == expected @@ -869,28 +863,26 @@ async def test_delete_from_right_other_not_terminal(data_store: DataStore, tree_ if use_hint: hint_keys_values = await data_store.get_keys_values_dict(tree_id=tree_id) - expected = Program.to( - ( - ( - (b"\x00", b"\x10\x00"), - (b"\x01", b"\x11\x01"), + expected = InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x00", value=b"\x10\x00"), + right=TerminalNode.from_key_value(key=b"\x01", value=b"\x11\x01"), + ), + right=InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x04", value=b"\x14\x04"), + right=TerminalNode.from_key_value(key=b"\x05", value=b"\x15\x05"), ), - ( - ( - (b"\x04", b"\x14\x04"), - (b"\x05", b"\x15\x05"), - ), - ( - (b"\x06", b"\x16\x06"), - (b"\x07", b"\x17\x07"), - ), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x06", value=b"\x16\x06"), + right=TerminalNode.from_key_value(key=b"\x07", value=b"\x17\x07"), ), ), ) await data_store.delete(key=b"\x03", tree_id=tree_id, hint_keys_values=hint_keys_values, status=Status.COMMITTED) await data_store.delete(key=b"\x02", tree_id=tree_id, hint_keys_values=hint_keys_values, status=Status.COMMITTED) - result = await data_store.get_tree_as_program(tree_id=tree_id) + result = await data_store.get_tree_as_nodes(tree_id=tree_id) assert result == expected diff --git a/tests/core/data_layer/util.py b/tests/core/data_layer/util.py index 89da59a0130c..e32dffafa3f2 100644 --- a/tests/core/data_layer/util.py +++ b/tests/core/data_layer/util.py @@ -8,7 +8,7 @@ from dataclasses import dataclass from typing import IO, TYPE_CHECKING, Any, Dict, Iterator, List, Literal, Optional, Union, overload -from chia.data_layer.data_layer_util import NodeType, Side, Status +from chia.data_layer.data_layer_util import InternalNode, Node, NodeType, Side, Status, TerminalNode from chia.data_layer.data_store import DataStore from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -47,21 +47,19 @@ async def general_insert( @dataclass(frozen=True) class Example: - expected: Program + expected: Node terminal_nodes: List[bytes32] async def add_0123_example(data_store: DataStore, tree_id: bytes32) -> Example: - expected = Program.to( - ( - ( - (b"\x00", b"\x10\x00"), - (b"\x01", b"\x11\x01"), - ), - ( - (b"\x02", b"\x12\x02"), - (b"\x03", b"\x13\x03"), - ), + expected = InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x00", value=b"\x10\x00"), + right=TerminalNode.from_key_value(key=b"\x01", value=b"\x11\x01"), + ), + right=InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x02", value=b"\x12\x02"), + right=TerminalNode.from_key_value(key=b"\x03", value=b"\x13\x03"), ), ) @@ -76,27 +74,25 @@ async def add_0123_example(data_store: DataStore, tree_id: bytes32) -> Example: async def add_01234567_example(data_store: DataStore, tree_id: bytes32) -> Example: - expected = Program.to( - ( - ( - ( - (b"\x00", b"\x10\x00"), - (b"\x01", b"\x11\x01"), - ), - ( - (b"\x02", b"\x12\x02"), - (b"\x03", b"\x13\x03"), - ), + expected = InternalNode.from_child_nodes( + left=InternalNode.from_child_nodes( + InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x00", value=b"\x10\x00"), + right=TerminalNode.from_key_value(key=b"\x01", value=b"\x11\x01"), + ), + InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x02", value=b"\x12\x02"), + right=TerminalNode.from_key_value(key=b"\x03", value=b"\x13\x03"), + ), + ), + right=InternalNode.from_child_nodes( + InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x04", value=b"\x14\x04"), + right=TerminalNode.from_key_value(key=b"\x05", value=b"\x15\x05"), ), - ( - ( - (b"\x04", b"\x14\x04"), - (b"\x05", b"\x15\x05"), - ), - ( - (b"\x06", b"\x16\x06"), - (b"\x07", b"\x17\x07"), - ), + InternalNode.from_child_nodes( + left=TerminalNode.from_key_value(key=b"\x06", value=b"\x16\x06"), + right=TerminalNode.from_key_value(key=b"\x07", value=b"\x17\x07"), ), ), ) From f0e88eee13a0016425c07fdf98305507b421851a Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 27 Dec 2023 16:35:53 -0500 Subject: [PATCH 09/34] ignore tree hash errors --- chia/types/blockchain_format/tree_hash.py | 28 +++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/chia/types/blockchain_format/tree_hash.py b/chia/types/blockchain_format/tree_hash.py index 6a12c7a67dc0..120462a6bc9e 100644 --- a/chia/types/blockchain_format/tree_hash.py +++ b/chia/types/blockchain_format/tree_hash.py @@ -8,14 +8,18 @@ from __future__ import annotations -from typing import Callable, List, Optional, Set +from typing import Callable, List, Optional, Set, Union from clvm.CLVMObject import CLVMStorage +from clvm.SExp import SExp from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.hash import std_hash -Op = Callable[[List[CLVMStorage], List["Op"], Set[bytes32]], None] +ValueType = Union[bytes, CLVMStorage] +ValueStackType = List[ValueType] +Op = Callable[[ValueStackType, "OpStackType", Set[bytes32]], None] +OpStackType = List[Op] def sha256_treehash(sexp: CLVMStorage, precalculated: Optional[Set[bytes32]] = None) -> bytes32: @@ -26,8 +30,9 @@ def sha256_treehash(sexp: CLVMStorage, precalculated: Optional[Set[bytes32]] = N if precalculated is None: precalculated = set() - def handle_sexp(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated: Set[bytes32]) -> None: - sexp = sexp_stack.pop() + def handle_sexp(sexp_stack: ValueStackType, op_stack: OpStackType, precalculated: Set[bytes32]) -> None: + # just trusting it is right, otherwise we get an attribute error + sexp: SExp = sexp_stack.pop() # type: ignore[assignment] if sexp.pair: p0, p1 = sexp.pair sexp_stack.append(p0) @@ -45,20 +50,23 @@ def handle_sexp(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated r = std_hash(b"\1" + atom) sexp_stack.append(r) - def handle_pair(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated: Set[bytes32]) -> None: - p0 = sexp_stack.pop() - p1 = sexp_stack.pop() + def handle_pair(sexp_stack: ValueStackType, op_stack: OpStackType, precalculated: Set[bytes32]) -> None: + # just trusting it is right, otherwise we get a type error + p0: bytes = sexp_stack.pop() # type: ignore[assignment] + p1: bytes = sexp_stack.pop() # type: ignore[assignment] sexp_stack.append(std_hash(b"\2" + p0 + p1)) - def roll(sexp_stack: List[CLVMStorage], op_stack: List[Op], precalculated: Set[bytes32]) -> None: + def roll(sexp_stack: ValueStackType, op_stack: OpStackType, precalculated: Set[bytes32]) -> None: p0 = sexp_stack.pop() p1 = sexp_stack.pop() sexp_stack.append(p0) sexp_stack.append(p1) - sexp_stack = [sexp] + sexp_stack: ValueStackType = [sexp] op_stack: List[Op] = [handle_sexp] while len(op_stack) > 0: op = op_stack.pop() op(sexp_stack, op_stack, precalculated) - return bytes32(sexp_stack[0]) + # just trusting it is right, otherwise we get some error, probably + result: bytes = sexp_stack[0] # type: ignore[assignment] + return bytes32(result) From 3d528dbd34a8176f8703714bc385d25d3393a241 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 27 Dec 2023 17:21:58 -0500 Subject: [PATCH 10/34] ignore enough in _sexp_replace... --- chia/types/blockchain_format/program.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/chia/types/blockchain_format/program.py b/chia/types/blockchain_format/program.py index de254bf7321d..8446d83d2667 100644 --- a/chia/types/blockchain_format/program.py +++ b/chia/types/blockchain_format/program.py @@ -1,7 +1,7 @@ from __future__ import annotations import io -from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar from chia_rs import ALLOW_BACKREFS, run_chia_program, tree_hash from clvm.casts import int_from_bytes @@ -80,7 +80,7 @@ def at(self, position: str) -> Program: raise ValueError(f"`at` got illegal character `{c}`. Only `f` & `r` allowed") return v - def replace(self: T_Program, **kwargs) -> T_Program: + def replace(self: T_Program, **kwargs: CastableType) -> T_Program: """ Create a new program replacing the given paths (using `at` syntax). Example: @@ -220,23 +220,26 @@ def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: NIL = Program.from_bytes(b"\x80") +# real return type is more like Union[T_Program, CastableType] when considering corner and terminal cases def _sexp_replace( - sexp: T_CLVMStorage, to_sexp: Callable[[CastableType], T_Program], **kwargs -) -> Union[T_Program, T_CLVMStorage]: + sexp: T_CLVMStorage, to_sexp: Callable[[CastableType], T_Program], **kwargs: CastableType +) -> T_Program: # if `kwargs == {}` then `return sexp` unchanged if len(kwargs) == 0: - return sexp + # yes, the terminal case is hinted incorrectly for now + return sexp # type: ignore[return-value] if "" in kwargs: if len(kwargs) > 1: raise ValueError("conflicting paths") - return kwargs[""] + # yes, the terminal case is hinted incorrectly for now + return kwargs[""] # type: ignore[return-value] # we've confirmed that no `kwargs` is the empty string. # Now split `kwargs` into two groups: those # that start with `f` and those that start with `r` - args_by_prefix: Dict[str, SExp] = {} + args_by_prefix: Dict[str, Dict[str, CastableType]] = {} for k, v in kwargs.items(): c = k[0] if c not in "fr": From 602d89958e108bd1bb57d9050db67d9e3257f1c9 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 11:31:13 -0400 Subject: [PATCH 11/34] again --- chia/_tests/core/test_cost_calculation.py | 2 +- chia/_tests/util/run_block.py | 2 +- .../wallet/cat_wallet/test_offer_lifecycle.py | 8 ++-- .../nft_wallet/test_ownership_outer_puzzle.py | 4 +- .../wallet/test_singleton_lifecycle_fast.py | 42 +++++++------------ chia/data_layer/data_layer_util.py | 2 +- chia/full_node/coin_store.py | 4 +- chia/full_node/mempool_check_conditions.py | 4 +- chia/rpc/wallet_rpc_api.py | 6 +-- chia/simulator/block_tools.py | 2 +- chia/simulator/wallet_tools.py | 2 +- chia/types/coin_spend.py | 3 +- chia/wallet/conditions.py | 5 +-- chia/wallet/dao_wallet/dao_wallet.py | 2 +- chia/wallet/did_wallet/did_wallet_puzzles.py | 11 ++--- chia/wallet/lineage_proof.py | 5 +-- chia/wallet/nft_wallet/nft_puzzles.py | 5 +-- .../wallet/puzzles/p2_delegated_conditions.py | 5 +-- chia/wallet/puzzles/p2_puzzle_hash.py | 5 +-- chia/wallet/puzzles/singleton_top_layer.py | 14 +++---- chia/wallet/util/compute_memos.py | 3 +- chia/wallet/wallet_singleton_store.py | 2 +- 22 files changed, 54 insertions(+), 84 deletions(-) diff --git a/chia/_tests/core/test_cost_calculation.py b/chia/_tests/core/test_cost_calculation.py index 5a0767f02a45..39e665a75555 100644 --- a/chia/_tests/core/test_cost_calculation.py +++ b/chia/_tests/core/test_cost_calculation.py @@ -298,7 +298,7 @@ async def test_get_puzzle_and_solution_for_coin_performance(benchmark_runner: Be parent, puzzle, amount_program, _ = spend.as_iter() parent_coin_info = parent.as_atom() puzzle_hash = puzzle.get_tree_hash() - amount = amount_program.as_int() + amount = uint64(amount_program.as_int()) coin = Coin(parent_coin_info=parent_coin_info, puzzle_hash=puzzle_hash, amount=amount) spent_coins.append(coin) diff --git a/chia/_tests/util/run_block.py b/chia/_tests/util/run_block.py index 4207625d5fdb..be64c6322bb7 100644 --- a/chia/_tests/util/run_block.py +++ b/chia/_tests/util/run_block.py @@ -114,7 +114,7 @@ def run_generator(block_generator: BlockGenerator, constants: ConsensusConstants break puzzle_hash = puzzle.get_tree_hash() - coin = Coin(bytes32(parent.as_atom()), puzzle_hash, amount.as_int()) + coin = Coin(bytes32(parent.as_atom()), puzzle_hash, uint64(amount.as_int())) cat_list.append( CAT( asset_id=bytes(asset_id).hex()[2:], diff --git a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py index 4fbffdf4915c..58b272485879 100644 --- a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +++ b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py @@ -1,9 +1,10 @@ from __future__ import annotations -from typing import Any, Dict, List, Optional, cast +from typing import Dict, List, Optional import pytest from chia_rs import G2Element +from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, SimClient, SpendSim, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -32,8 +33,7 @@ # Some methods mapping strings to CATs def str_to_tail(tail_str: str) -> Program: - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([3, [], [1, tail_str], []])) + return Program.to([3, [], [1, tail_str], []]) def str_to_tail_hash(tail_str: str) -> bytes32: @@ -121,7 +121,7 @@ def generate_secure_bundle( announcement_assertions = [a.to_program() for a in announcements] selected_coin_amount = sum([c.amount for c in selected_coins]) non_primaries = [] if len(selected_coins) < 2 else selected_coins[1:] - inner_solution: List[List[Any]] = [ + inner_solution: List[CastableType] = [ [51, Offer.ph(), offered_amount], # Offered coin [51, acs_ph, uint64(selected_coin_amount - offered_amount)], # Change *announcement_assertions, diff --git a/chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py b/chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py index a4091853aa25..067a0b5cdad1 100644 --- a/chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +++ b/chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py @@ -27,8 +27,8 @@ def test_ownership_outer_puzzle() -> None: """ ) transfer_program_default: Program = puzzle_for_transfer_program(bytes32([1] * 32), bytes32([2] * 32), uint16(5000)) - ownership_puzzle: Program = puzzle_for_ownership_layer(owner, transfer_program, ACS) - ownership_puzzle_empty: Program = puzzle_for_ownership_layer(NIL, transfer_program, ACS) + ownership_puzzle: Program = puzzle_for_ownership_layer(owner, Program.to(transfer_program), ACS) + ownership_puzzle_empty: Program = puzzle_for_ownership_layer(NIL, Program.to(transfer_program), ACS) ownership_puzzle_default: Program = puzzle_for_ownership_layer(owner, transfer_program_default, ACS) ownership_driver: Optional[PuzzleInfo] = match_puzzle(uncurry_puzzle(ownership_puzzle)) ownership_driver_empty: Optional[PuzzleInfo] = match_puzzle(uncurry_puzzle(ownership_puzzle_empty)) diff --git a/chia/_tests/wallet/test_singleton_lifecycle_fast.py b/chia/_tests/wallet/test_singleton_lifecycle_fast.py index 0b0b8dbcd8c0..0b362158b590 100644 --- a/chia/_tests/wallet/test_singleton_lifecycle_fast.py +++ b/chia/_tests/wallet/test_singleton_lifecycle_fast.py @@ -102,8 +102,7 @@ def solve_launcher(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], kwa destination_puzzle_hash = from_kwargs(kwargs, "destination_puzzle_hash", bytes32) metadata = from_kwargs(kwargs, "metadata", List[Tuple[str, str]]) solution = Program.to([destination_puzzle_hash, launcher_amount, metadata]) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def solve_anyone_can_spend(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], kwargs: Dict[str, Any]) -> Program: @@ -113,8 +112,7 @@ def solve_anyone_can_spend(solver: Solver, puzzle_db: PuzzleDB, args: List[Progr """ conditions = from_kwargs(kwargs, "conditions", List[Program]) solution = Program.to(conditions) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def solve_anyone_can_spend_with_padding( @@ -123,8 +121,7 @@ def solve_anyone_can_spend_with_padding( """This is the puzzle `(a (q . 1) 3)`. It's only for testing.""" conditions = from_kwargs(kwargs, "conditions", List[Program]) solution = Program.to((0, conditions)) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def solve_singleton(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], kwargs: Dict[str, Any]) -> Program: @@ -137,8 +134,7 @@ def solve_singleton(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], kw lineage_proof = from_kwargs(kwargs, "lineage_proof", Program) coin_amount = from_kwargs(kwargs, "coin_amount", uint64) solution = inner_solution.to([lineage_proof, coin_amount, inner_solution.rest()]) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def solve_pool_member(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], kwargs: Dict[str, Any]) -> Program: @@ -149,14 +145,12 @@ def solve_pool_member(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], to_waiting_room = pool_member_spend_type == "to-waiting-room" if to_waiting_room: key_value_list = from_kwargs(kwargs, "key_value_list", Program) - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([0, 1, 0, 0, key_value_list])) + return Program.to([0, 1, 0, 0, key_value_list]) # it's an "absorb_pool_reward" type pool_reward_amount = from_kwargs(kwargs, "pool_reward_amount", uint64) pool_reward_height = from_kwargs(kwargs, "pool_reward_height", int) solution = Program.to([0, pool_reward_amount, pool_reward_height]) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def solve_pool_waiting_room( @@ -170,14 +164,12 @@ def solve_pool_waiting_room( if exit_waiting_room: key_value_list = from_kwargs(kwargs, "key_value_list", List[Tuple[str, str]]) destination_puzzle_hash = from_kwargs(kwargs, "destination_puzzle_hash", bytes32) - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([0, 1, key_value_list, destination_puzzle_hash])) + return Program.to([0, 1, key_value_list, destination_puzzle_hash]) # it's an "absorb_pool_reward" type pool_reward_amount = from_kwargs(kwargs, "pool_reward_amount", uint64) pool_reward_height = from_kwargs(kwargs, "pool_reward_height", int) solution = Program.to([0, 0, pool_reward_amount, pool_reward_height]) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def solve_p2_singleton(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], kwargs: Dict[str, Any]) -> Program: @@ -190,8 +182,7 @@ def solve_p2_singleton(solver: Solver, puzzle_db: PuzzleDB, args: List[Program], singleton_inner_puzzle_hash = from_kwargs(kwargs, "singleton_inner_puzzle_hash", bytes32) p2_singleton_coin_name = from_kwargs(kwargs, "p2_singleton_coin_name", bytes) solution = Program.to([singleton_inner_puzzle_hash, p2_singleton_coin_name]) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution raise ValueError("can't solve `delayed-spend` yet") @@ -228,8 +219,7 @@ def inner_puzzle_for_puzzle(self, puzzle: Program) -> Program: template, args = puzzle.uncurry() assert bytes(template) == bytes(SINGLETON_MOD) _, inner_puzzle = list(args.as_iter()) - # TODO: Remove cast when we improve typing - return cast(Program, inner_puzzle) + return inner_puzzle def coin_spend_for_conditions(self, puzzle_db: PuzzleDB, **kwargs: object) -> CoinSpend: coin = self.current_state @@ -274,8 +264,7 @@ def adaptor_for_singleton_inner_puzzle(puzzle: Program) -> Program: """ # this is pretty slow and lame program = binutils.assemble("(a (q . %s) 3)" % binutils.disassemble(puzzle)) - # TODO: Remove cast when we improve typing - return cast(Program, Program.to(program)) + return Program.to(program) def launcher_conditions_and_spend_bundle( @@ -323,8 +312,7 @@ def singleton_puzzle_hash(launcher_id: bytes32, launcher_puzzle_hash: bytes32, i def solution_for_singleton_puzzle(lineage_proof: Program, my_amount: int, inner_solution: Program) -> Program: - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([lineage_proof, my_amount, inner_solution])) + return Program.to([lineage_proof, my_amount, inner_solution]) def p2_singleton_puzzle_for_launcher( @@ -391,16 +379,14 @@ def lineage_proof_for_coin_spend(coin_spend: CoinSpend) -> Program: inner_puzzle_hash = None if coin.puzzle_hash == LAUNCHER_PUZZLE_HASH: - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([parent_name, amount])) + return Program.to([parent_name, amount]) full_puzzle = Program.from_bytes(bytes(coin_spend.puzzle_reveal)) _, args = full_puzzle.uncurry() _, __, ___, inner_puzzle = list(args.as_iter()) inner_puzzle_hash = inner_puzzle.get_tree_hash() - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([parent_name, inner_puzzle_hash, amount])) + return Program.to([parent_name, inner_puzzle_hash, amount]) def create_throwaway_pubkey(seed: bytes) -> G1Element: diff --git a/chia/data_layer/data_layer_util.py b/chia/data_layer/data_layer_util.py index 8734bcdd8a05..3079c7882368 100644 --- a/chia/data_layer/data_layer_util.py +++ b/chia/data_layer/data_layer_util.py @@ -42,7 +42,7 @@ def leaf_hash(key: bytes, value: bytes) -> bytes32: def key_hash(key: bytes) -> bytes32: - return Program.to(key).get_tree_hash() # type: ignore[no-any-return] + return Program.to(key).get_tree_hash() @dataclasses.dataclass(frozen=True) diff --git a/chia/full_node/coin_store.py b/chia/full_node/coin_store.py index 95ae5dc70254..99ce8e7d1845 100644 --- a/chia/full_node/coin_store.py +++ b/chia/full_node/coin_store.py @@ -613,8 +613,8 @@ async def get_unspent_lineage_info_for_puzzle_hash(self, puzzle_hash: bytes32) - coin_id, coin_amount, parent_id, parent_amount, parent_parent_id = rows[0] return UnspentLineageInfo( coin_id=bytes32(coin_id), - coin_amount=int_from_bytes(coin_amount), + coin_amount=uint64(int_from_bytes(coin_amount)), parent_id=bytes32(parent_id), - parent_amount=int_from_bytes(parent_amount), + parent_amount=uint64(int_from_bytes(parent_amount)), parent_parent_id=bytes32(parent_parent_id), ) diff --git a/chia/full_node/mempool_check_conditions.py b/chia/full_node/mempool_check_conditions.py index eb40763ba026..40e915b185ce 100644 --- a/chia/full_node/mempool_check_conditions.py +++ b/chia/full_node/mempool_check_conditions.py @@ -145,7 +145,7 @@ def get_spends_for_block(generator: BlockGenerator, height: int, constants: Cons for spend in Program.to(ret).first().as_iter(): parent, puzzle, amount, solution = spend.as_iter() puzzle_hash = puzzle.get_tree_hash() - coin = Coin(parent.as_atom(), puzzle_hash, amount.as_int()) + coin = Coin(parent.as_atom(), puzzle_hash, uint64(amount.as_int())) spends.append(make_spend(coin, puzzle, solution)) return spends @@ -174,7 +174,7 @@ def get_spends_for_block_with_conditions( for spend in Program.to(ret).first().as_iter(): parent, puzzle, amount, solution = spend.as_iter() puzzle_hash = puzzle.get_tree_hash() - coin = Coin(parent.as_atom(), puzzle_hash, amount.as_int()) + coin = Coin(parent.as_atom(), puzzle_hash, uint64(amount.as_int())) coin_spend = make_spend(coin, puzzle, solution) conditions = conditions_for_solution(puzzle, solution, DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM) spends.append(CoinSpendWithConditions(coin_spend, conditions)) diff --git a/chia/rpc/wallet_rpc_api.py b/chia/rpc/wallet_rpc_api.py index 69ec0d441067..58b021a6e1d0 100644 --- a/chia/rpc/wallet_rpc_api.py +++ b/chia/rpc/wallet_rpc_api.py @@ -2234,7 +2234,7 @@ async def did_get_info(self, request: Dict[str, Any]) -> EndpointResult: if curried_args is None: return {"success": False, "error": "The coin is not a DID."} p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = curried_args - launcher_id = singleton_struct.rest().first().as_atom() + launcher_id = bytes32(singleton_struct.rest().first().as_atom()) uncurried_p2 = uncurry_puzzle(p2_puzzle) (public_key,) = uncurried_p2.args.as_iter() memos = compute_memos(SpendBundle([coin_spend], G2Element())) @@ -2244,12 +2244,10 @@ async def did_get_info(self, request: Dict[str, Any]) -> EndpointResult: for memo in coin_memos: hints.append(memo.hex()) assert recovery_list_hash.atom is not None - launcher_id = singleton_struct.rest().first().atom - assert launcher_id is not None assert public_key.atom is not None return { "success": True, - "did_id": encode_puzzle_hash(bytes32(launcher_id), AddressType.DID.hrp(self.service.config)), + "did_id": encode_puzzle_hash(launcher_id, AddressType.DID.hrp(self.service.config)), "latest_coin": coin_state.coin.name().hex(), "p2_address": encode_puzzle_hash(p2_puzzle.get_tree_hash(), AddressType.XCH.hrp(self.service.config)), "public_key": public_key.as_atom().hex(), diff --git a/chia/simulator/block_tools.py b/chia/simulator/block_tools.py index ec86190f94ed..747c0476727a 100644 --- a/chia/simulator/block_tools.py +++ b/chia/simulator/block_tools.py @@ -169,7 +169,7 @@ def compute_additions_unchecked(sb: SpendBundle) -> List[Coin]: if op != ConditionOpcode.CREATE_COIN.value: continue puzzle_hash = next(atoms).as_atom() - amount = next(atoms).as_int() + amount = uint64(next(atoms).as_int()) ret.append(Coin(parent_id, puzzle_hash, amount)) return ret diff --git a/chia/simulator/wallet_tools.py b/chia/simulator/wallet_tools.py index 7902c0c82ce3..1c6f3c53d4f3 100644 --- a/chia/simulator/wallet_tools.py +++ b/chia/simulator/wallet_tools.py @@ -148,7 +148,7 @@ def generate_unsigned_transaction( coin_to_append = Coin( coin.name(), bytes32(outputs.vars[0]), - int_from_bytes(outputs.vars[1]), + uint64(int_from_bytes(outputs.vars[1])), ) message_list.append(coin_to_append.name()) message = std_hash(b"".join(message_list)) diff --git a/chia/types/coin_spend.py b/chia/types/coin_spend.py index e2d95e36c403..097ecac9ebf9 100644 --- a/chia/types/coin_spend.py +++ b/chia/types/coin_spend.py @@ -13,6 +13,7 @@ from chia.types.condition_opcodes import ConditionOpcode from chia.types.condition_with_args import ConditionWithArgs from chia.util.errors import Err, ValidationError +from chia.util.ints import uint64 from chia.util.streamable import Streamable, streamable CoinSpend = chia_rs.CoinSpend @@ -75,7 +76,7 @@ def compute_additions_with_cost( continue cost += ConditionCost.CREATE_COIN.value puzzle_hash = next(atoms).as_atom() - amount = next(atoms).as_int() + amount = uint64(next(atoms).as_int()) ret.append(Coin(parent_id, puzzle_hash, amount)) return ret, cost diff --git a/chia/wallet/conditions.py b/chia/wallet/conditions.py index def7352b57d2..37467d42a5a7 100644 --- a/chia/wallet/conditions.py +++ b/chia/wallet/conditions.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass, fields, replace -from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, TypeVar, Union, cast, final, get_type_hints +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, TypeVar, Union, final, get_type_hints from chia_rs import G1Element from clvm.casts import int_from_bytes, int_to_bytes @@ -734,8 +734,7 @@ class UnknownCondition(Condition): args: List[Program] def to_program(self) -> Program: - # TODO: Remove cast when we have proper hinting for this - return cast(Program, self.opcode.cons(Program.to(self.args))) + return self.opcode.cons(Program.to(self.args)) @classmethod def from_program(cls, program: Program) -> UnknownCondition: diff --git a/chia/wallet/dao_wallet/dao_wallet.py b/chia/wallet/dao_wallet/dao_wallet.py index b90f99cbd429..4c5647c768c2 100644 --- a/chia/wallet/dao_wallet/dao_wallet.py +++ b/chia/wallet/dao_wallet/dao_wallet.py @@ -1278,7 +1278,7 @@ async def create_proposal_close_spend( if cond.rest().first().as_atom() == cat_launcher.get_tree_hash(): cat_wallet: CATWallet = self.wallet_state_manager.wallets[self.dao_info.cat_wallet_id] cat_tail_hash = cat_wallet.cat_info.limitations_program_hash - mint_amount = cond.rest().rest().first().as_int() + mint_amount = uint64(cond.rest().rest().first().as_int()) new_cat_puzhash = bytes32(cond.rest().rest().rest().first().first().as_atom()) eve_puzzle = curry_cat_eve(new_cat_puzhash) if genesis_id is None: diff --git a/chia/wallet/did_wallet/did_wallet_puzzles.py b/chia/wallet/did_wallet/did_wallet_puzzles.py index a505c8bf1de8..fb1153c2f825 100644 --- a/chia/wallet/did_wallet/did_wallet_puzzles.py +++ b/chia/wallet/did_wallet/did_wallet_puzzles.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Dict, Iterator, List, Optional, Tuple, Union, cast +from typing import Dict, Iterator, List, Optional, Tuple, Union from chia_rs import G1Element @@ -132,8 +132,7 @@ def create_recovery_message_puzzle(recovering_coin_id: bytes32, newpuz: bytes32, ], ) ) - # TODO: Remove cast when we have proper hinting for this - return cast(Program, puzzle) + return puzzle def create_spend_for_message( @@ -163,8 +162,7 @@ def match_did_puzzle(mod: Program, curried_args: Program) -> Optional[Iterator[P if mod == SINGLETON_TOP_LAYER_MOD: mod, curried_args = curried_args.rest().first().uncurry() if mod == DID_INNERPUZ_MOD: - # TODO: Remove cast when we have clvm type hinting for this - return cast(Iterator[Program], curried_args.as_iter()) + return curried_args.as_iter() except Exception: import traceback @@ -194,8 +192,7 @@ def metadata_to_program(metadata: Dict[str, str]) -> Program: kv_list = [] for key, value in metadata.items(): kv_list.append((key, value)) - # TODO: Remove cast when we have proper hinting for this - return cast(Program, Program.to(kv_list)) + return Program.to(kv_list) def did_program_to_metadata(program: Program) -> Dict[str, str]: diff --git a/chia/wallet/lineage_proof.py b/chia/wallet/lineage_proof.py index 95c8a55f4210..59a3477315ec 100644 --- a/chia/wallet/lineage_proof.py +++ b/chia/wallet/lineage_proof.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from enum import Enum -from typing import Any, Dict, List, Optional, cast +from typing import Any, Dict, List, Optional from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -52,8 +52,7 @@ def to_program(self) -> Program: final_list.append(self.inner_puzzle_hash) if self.amount is not None: final_list.append(self.amount) - # TODO: Remove cast when we improve typing - return cast(Program, Program.to(final_list)) + return Program.to(final_list) def is_none(self) -> bool: return all([self.parent_name is None, self.inner_puzzle_hash is None, self.amount is None]) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 77a4881a4322..7889b60cace7 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -1,7 +1,7 @@ from __future__ import annotations import logging -from typing import Any, Dict, List, Optional, Tuple, cast +from typing import Any, Dict, List, Optional, Tuple from clvm.casts import int_from_bytes from clvm_tools.binutils import disassemble @@ -237,8 +237,7 @@ def create_ownership_layer_transfer_solution( log.debug("Condition list raw: %r", condition_list) solution = Program.to([[solution_for_conditions(condition_list)]]) log.debug("Generated transfer solution: %s", solution) - # TODO: Remove cast when we improve typing - return cast(Program, solution) + return solution def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tuple[Program, bytes32]: diff --git a/chia/wallet/puzzles/p2_delegated_conditions.py b/chia/wallet/puzzles/p2_delegated_conditions.py index 7f81903975db..1ef2c50669df 100644 --- a/chia/wallet/puzzles/p2_delegated_conditions.py +++ b/chia/wallet/puzzles/p2_delegated_conditions.py @@ -7,8 +7,6 @@ from __future__ import annotations -from typing import cast - from chia.types.blockchain_format.program import Program from .load_clvm import load_clvm_maybe_recompile @@ -21,5 +19,4 @@ def puzzle_for_pk(public_key: Program) -> Program: def solution_for_conditions(conditions: Program) -> Program: - # TODO: Remove cast when we improve typing - return cast(Program, conditions.to([conditions])) + return conditions.to([conditions]) diff --git a/chia/wallet/puzzles/p2_puzzle_hash.py b/chia/wallet/puzzles/p2_puzzle_hash.py index fa4b08024d94..a540ccaec6d2 100644 --- a/chia/wallet/puzzles/p2_puzzle_hash.py +++ b/chia/wallet/puzzles/p2_puzzle_hash.py @@ -7,8 +7,6 @@ from __future__ import annotations -from typing import cast - from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -27,5 +25,4 @@ def puzzle_for_inner_puzzle(inner_puzzle: Program) -> Program: def solution_for_inner_puzzle_and_inner_solution(inner_puzzle: Program, inner_puzzle_solution: Program) -> Program: - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([inner_puzzle, inner_puzzle_solution])) + return Program.to([inner_puzzle, inner_puzzle_solution]) diff --git a/chia/wallet/puzzles/singleton_top_layer.py b/chia/wallet/puzzles/singleton_top_layer.py index cd08b496543d..596d6fa92284 100644 --- a/chia/wallet/puzzles/singleton_top_layer.py +++ b/chia/wallet/puzzles/singleton_top_layer.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Iterator, List, Optional, Tuple, cast +from typing import Iterator, List, Optional, Tuple from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -175,8 +175,7 @@ def generate_launcher_coin(coin: Coin, amount: uint64) -> Coin: # Wrap inner puzzles that are not singleton specific to strip away "truths" def adapt_inner_to_singleton(inner_puzzle: Program) -> Program: # (a (q . inner_puzzle) (r 1)) - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([2, (1, inner_puzzle), [6, 1]])) + return Program.to([2, (1, inner_puzzle), [6, 1]]) def adapt_inner_puzzle_hash_to_singleton(inner_puzzle_hash: bytes32) -> bytes32: @@ -240,8 +239,7 @@ def solution_for_singleton(lineage_proof: LineageProof, amount: uint64, inner_so parent_info = [lineage_proof.parent_name, lineage_proof.amount] else: parent_info = [lineage_proof.parent_name, lineage_proof.inner_puzzle_hash, lineage_proof.amount] - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([parent_info, amount, inner_solution])) + return Program.to([parent_info, amount, inner_solution]) # Create a coin that a singleton can claim @@ -258,14 +256,12 @@ def pay_to_singleton_or_delay_puzzle(launcher_id: bytes32, delay_time: uint64, d # Solution for EITHER p2_singleton or the claiming spend case for p2_singleton_or_delayed_puzhash def solution_for_p2_singleton(p2_singleton_coin: Coin, singleton_inner_puzhash: bytes32) -> Program: - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([singleton_inner_puzhash, p2_singleton_coin.name()])) + return Program.to([singleton_inner_puzhash, p2_singleton_coin.name()]) # Solution for the delayed spend case for p2_singleton_or_delayed_puzhash def solution_for_p2_delayed_puzzle(output_amount: uint64) -> Program: - # TODO: Remove cast when we improve typing - return cast(Program, Program.to([output_amount, []])) + return Program.to([output_amount, []]) # Get announcement conditions for singleton solution and full CoinSpend for the claimed coin diff --git a/chia/wallet/util/compute_memos.py b/chia/wallet/util/compute_memos.py index 2a27bde8fbaf..f646443b8fbf 100644 --- a/chia/wallet/util/compute_memos.py +++ b/chia/wallet/util/compute_memos.py @@ -10,6 +10,7 @@ from chia.types.coin_spend import CoinSpend from chia.types.condition_opcodes import ConditionOpcode from chia.types.spend_bundle import SpendBundle +from chia.util.ints import uint64 def compute_memos_for_spend(coin_spend: CoinSpend) -> Dict[bytes32, List[bytes]]: @@ -18,7 +19,7 @@ def compute_memos_for_spend(coin_spend: CoinSpend) -> Dict[bytes32, List[bytes]] for condition in result.as_python(): if condition[0] == ConditionOpcode.CREATE_COIN and len(condition) >= 4: # If only 3 elements (opcode + 2 args), there is no memo, this is ph, amount - coin_added = Coin(coin_spend.coin.name(), bytes32(condition[1]), int_from_bytes(condition[2])) + coin_added = Coin(coin_spend.coin.name(), bytes32(condition[1]), uint64(int_from_bytes(condition[2]))) if type(condition[3]) is not list: # If it's not a list, it's not the correct format continue diff --git a/chia/wallet/wallet_singleton_store.py b/chia/wallet/wallet_singleton_store.py index d2d412ea2c1e..f6843a544906 100644 --- a/chia/wallet/wallet_singleton_store.py +++ b/chia/wallet/wallet_singleton_store.py @@ -104,7 +104,7 @@ async def add_spend( cc_cond = [cond for cond in conditions[ConditionOpcode.CREATE_COIN] if int_from_bytes(cond.vars[1]) % 2 == 1][0] - coin = Coin(coin_state.coin.name(), cc_cond.vars[0], int_from_bytes(cc_cond.vars[1])) + coin = Coin(coin_state.coin.name(), cc_cond.vars[0], uint64(int_from_bytes(cc_cond.vars[1]))) inner_puz = get_inner_puzzle_from_singleton(coin_state.puzzle_reveal) if inner_puz is None: # pragma: no cover raise RuntimeError("Could not get inner puzzle from puzzle reveal in coin spend %s", coin_state) From 74eb8b23ef2a2ad710cb2329bad10ac8c6e8b856 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 12:07:27 -0400 Subject: [PATCH 12/34] almost --- chia/wallet/puzzles/clawback/drivers.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/chia/wallet/puzzles/clawback/drivers.py b/chia/wallet/puzzles/clawback/drivers.py index e72c854c7690..d6c234f83a9c 100644 --- a/chia/wallet/puzzles/clawback/drivers.py +++ b/chia/wallet/puzzles/clawback/drivers.py @@ -129,10 +129,14 @@ def match_clawback_puzzle( # Check if the inner puzzle is a P2 puzzle if MOD != uncurried.mod: return None + if not isinstance(inner_puzzle, SerializedProgram): + inner_puzzle = SerializedProgram.from_program(inner_puzzle) + if not isinstance(inner_solution, SerializedProgram): + inner_solution = SerializedProgram.from_program(inner_solution) # Fetch Remark condition conditions = conditions_for_solution( - SerializedProgram.from_program(inner_puzzle), - SerializedProgram.from_program(inner_solution), + inner_puzzle, + inner_solution, DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM // 8, ) metadata: Optional[ClawbackMetadata] = None From 93852d78139a92029cb60d7a34170d9caa1da091 Mon Sep 17 00:00:00 2001 From: Matt Date: Fri, 15 Mar 2024 10:18:47 -0700 Subject: [PATCH 13/34] Fix test_singleton.py --- chia/_tests/wallet/test_singleton.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chia/_tests/wallet/test_singleton.py b/chia/_tests/wallet/test_singleton.py index 74f17df68ff8..af6d65d3eec0 100644 --- a/chia/_tests/wallet/test_singleton.py +++ b/chia/_tests/wallet/test_singleton.py @@ -22,19 +22,19 @@ POOL_REWARD_PREFIX_MAINNET = bytes32.fromhex("ccd5bb71183532bff220ba46c268991a00000000000000000000000000000000") -def singleton_puzzle(launcher_id: Program, launcher_puzzle_hash: bytes32, inner_puzzle: Program) -> Program: +def singleton_puzzle(launcher_id: bytes32, launcher_puzzle_hash: bytes32, inner_puzzle: Program) -> Program: return SINGLETON_MOD.curry((SINGLETON_MOD_HASH, (launcher_id, launcher_puzzle_hash)), inner_puzzle) -def p2_singleton_puzzle(launcher_id: Program, launcher_puzzle_hash: bytes32) -> Program: +def p2_singleton_puzzle(launcher_id: bytes32, launcher_puzzle_hash: bytes32) -> Program: return P2_SINGLETON_MOD.curry(SINGLETON_MOD_HASH, launcher_id, launcher_puzzle_hash) -def singleton_puzzle_hash(launcher_id: Program, launcher_puzzle_hash: bytes32, inner_puzzle: Program) -> bytes32: +def singleton_puzzle_hash(launcher_id: bytes32, launcher_puzzle_hash: bytes32, inner_puzzle: Program) -> bytes32: return singleton_puzzle(launcher_id, launcher_puzzle_hash, inner_puzzle).get_tree_hash() -def p2_singleton_puzzle_hash(launcher_id: Program, launcher_puzzle_hash: bytes32) -> bytes32: +def p2_singleton_puzzle_hash(launcher_id: bytes32, launcher_puzzle_hash: bytes32) -> bytes32: return p2_singleton_puzzle(launcher_id, launcher_puzzle_hash).get_tree_hash() From 533a3ab9839f184d5d0c4a9945c317eeadf623fb Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 15:00:51 -0400 Subject: [PATCH 14/34] dl fixup --- chia/data_layer/data_layer_util.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/chia/data_layer/data_layer_util.py b/chia/data_layer/data_layer_util.py index 3079c7882368..716cfc15e854 100644 --- a/chia/data_layer/data_layer_util.py +++ b/chia/data_layer/data_layer_util.py @@ -1,7 +1,7 @@ from __future__ import annotations import dataclasses -from dataclasses import dataclass +from dataclasses import dataclass, field from enum import IntEnum from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union @@ -180,6 +180,9 @@ class TerminalNode: key: bytes value: bytes + # left for now for interface back-compat even though it is constant + atom: None = field(init=False, default=None) + @classmethod def from_key_value(cls, key: bytes, value: bytes) -> TerminalNode: return cls( From 62c0661e7da3f1df64cfac0e2236ed044878bfb4 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 15:15:55 -0400 Subject: [PATCH 15/34] did fixup --- chia/wallet/did_wallet/did_wallet.py | 12 +++--------- chia/wallet/did_wallet/did_wallet_puzzles.py | 4 ++-- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 93d0131f6fcd..3269e727c74e 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -1170,21 +1170,15 @@ async def inner_puzzle_for_did_puzzle(self, did_hash: bytes32) -> Program: assert self.did_info.current_inner is not None uncurried_args = uncurry_innerpuz(self.did_info.current_inner) assert uncurried_args is not None - old_recovery_list: Optional[Program] - p2_puzzle, old_recovery_list, _, _, _ = uncurried_args + old_recovery_list_hash: Optional[Program] = None + p2_puzzle, old_recovery_list_hash, _, _, _ = uncurried_args if record is None: record = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash( p2_puzzle.get_tree_hash() ) if not (self.did_info.num_of_backup_ids_needed > 0 and len(self.did_info.backup_ids) == 0): # We have the recovery list, don't reset it - old_recovery_list = None - - old_recovery_list_hash: Optional[bytes32] - if old_recovery_list is not None: - old_recovery_list_hash = bytes32(old_recovery_list) - else: - old_recovery_list_hash = old_recovery_list + old_recovery_list_hash = None inner_puzzle: Program = did_wallet_puzzles.create_innerpuz( p2_puzzle_or_hash=puzzle_for_pk(record.pubkey), diff --git a/chia/wallet/did_wallet/did_wallet_puzzles.py b/chia/wallet/did_wallet/did_wallet_puzzles.py index fb1153c2f825..bedacc384ddb 100644 --- a/chia/wallet/did_wallet/did_wallet_puzzles.py +++ b/chia/wallet/did_wallet/did_wallet_puzzles.py @@ -34,7 +34,7 @@ def create_innerpuz( num_of_backup_ids_needed: uint64, launcher_id: bytes32, metadata: Program = Program.to([]), - recovery_list_hash: Optional[bytes32] = None, + recovery_list_hash: Optional[Program] = None, ) -> Program: """ Create DID inner puzzle @@ -48,7 +48,7 @@ def create_innerpuz( Note: Receiving a standard P2 puzzle hash wouldn't calculate a valid puzzle, but that can be useful if calling `.get_tree_hash_precalc()` on it. """ - backup_ids_hash = Program.to(recovery_list).get_tree_hash() + backup_ids_hash: Union[Program, bytes32] = Program.to(recovery_list).get_tree_hash() if recovery_list_hash is not None: backup_ids_hash = recovery_list_hash singleton_struct = Program.to((SINGLETON_TOP_LAYER_MOD_HASH, (launcher_id, SINGLETON_LAUNCHER_PUZZLE_HASH))) From c25780cb796e872d74e08100366766609b4a5014 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 17:20:16 -0400 Subject: [PATCH 16/34] touchup --- chia/wallet/nft_wallet/nft_puzzles.py | 22 ++++++++++++---------- chia/wallet/nft_wallet/uncurry_nft.py | 6 ------ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 7889b60cace7..03f5e396fdca 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -250,20 +250,22 @@ def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tup continue condition_code = condition.first().as_int() log.debug("Checking condition code: %r", condition_code) - atom = condition.rest().rest().first().atom - assert atom is not None if condition_code == -24: # metadata update metadata = update_metadata(metadata, condition) metadata = Program.to(metadata) - elif condition_code == 51 and int_from_bytes(atom) == 1: - # destination puzhash - if puzhash_for_derivation is not None: - # ignore duplicated create coin conditions - continue - memo = bytes32(condition.as_python()[-1][0]) - puzhash_for_derivation = memo - log.debug("Got back puzhash from solution: %s", puzhash_for_derivation) + else: + atom = condition.rest().rest().first().atom + assert atom is not None + + if condition_code == 51 and int_from_bytes(atom) == 1: + # destination puzhash + if puzhash_for_derivation is not None: + # ignore duplicated create coin conditions + continue + memo = bytes32(condition.as_python()[-1][0]) + puzhash_for_derivation = memo + log.debug("Got back puzhash from solution: %s", puzhash_for_derivation) assert puzhash_for_derivation return metadata, puzhash_for_derivation diff --git a/chia/wallet/nft_wallet/uncurry_nft.py b/chia/wallet/nft_wallet/uncurry_nft.py index 17b78d248a3d..278d9ea7a7c6 100644 --- a/chia/wallet/nft_wallet/uncurry_nft.py +++ b/chia/wallet/nft_wallet/uncurry_nft.py @@ -105,12 +105,6 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> try: (singleton_struct, nft_state_layer) = curried_args.as_iter() singleton_mod_hash = singleton_struct.first() - - # singleton_mod_hash: Optional[bytes32] - # if atom is None: - # singleton_mod_hash = None - # else: - # singleton_mod_hash = bytes32(atom) singleton_launcher_id = singleton_struct.rest().first() launcher_puzhash = singleton_struct.rest().rest() except ValueError as e: From 17a7039e56a92e30cc98b9305e8caec16fcb7223 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 18:30:03 -0400 Subject: [PATCH 17/34] nft fixup --- chia/wallet/nft_wallet/nft_puzzles.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 03f5e396fdca..3546173ded70 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -254,11 +254,11 @@ def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tup # metadata update metadata = update_metadata(metadata, condition) metadata = Program.to(metadata) - else: + elif condition_code == 51: atom = condition.rest().rest().first().atom assert atom is not None - if condition_code == 51 and int_from_bytes(atom) == 1: + if int_from_bytes(atom) == 1: # destination puzhash if puzhash_for_derivation is not None: # ignore duplicated create coin conditions From 5df1a705ecbd98545ce11e2c146249748a5aee66 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 19:19:18 -0400 Subject: [PATCH 18/34] fixup tests --- chia/wallet/nft_wallet/nft_puzzles.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 3546173ded70..489212f8f100 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -278,11 +278,7 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - atom = condition.at("rf").atom - if atom is None: - new_did_id = atom - else: - new_did_id = bytes32(atom) + new_did_id = condition.at("rf").atom elif condition.first().as_int() == 51: new_puzhash = condition.at("rf").atom # assert new_puzhash and new_did_id @@ -299,9 +295,5 @@ def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Optional[bytes32 for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - atom = condition.at("rf").atom - if atom is None: - new_did_id = atom - else: - new_did_id = bytes32(atom) + new_did_id = condition.at("rf").atom return new_did_id From f282e6374c795e0a49f29f60ff8f8c04a8a86fd6 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 19:30:43 -0400 Subject: [PATCH 19/34] Revert "fixup tests" This reverts commit 5df1a705ecbd98545ce11e2c146249748a5aee66. --- chia/wallet/nft_wallet/nft_puzzles.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 489212f8f100..3546173ded70 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -278,7 +278,11 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - new_did_id = condition.at("rf").atom + atom = condition.at("rf").atom + if atom is None: + new_did_id = atom + else: + new_did_id = bytes32(atom) elif condition.first().as_int() == 51: new_puzhash = condition.at("rf").atom # assert new_puzhash and new_did_id @@ -295,5 +299,9 @@ def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Optional[bytes32 for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - new_did_id = condition.at("rf").atom + atom = condition.at("rf").atom + if atom is None: + new_did_id = atom + else: + new_did_id = bytes32(atom) return new_did_id From 6049ed39e1c74f0687493b4d77ef8f38b8b772cc Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 19:32:20 -0400 Subject: [PATCH 20/34] or this i guess --- chia/wallet/nft_wallet/nft_puzzles.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 3546173ded70..f38eeb0bf033 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -279,8 +279,8 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: if condition.first().as_int() == -10: # this is the change owner magic condition atom = condition.at("rf").atom - if atom is None: - new_did_id = atom + if atom is None or atom == b"": + new_did_id = None else: new_did_id = bytes32(atom) elif condition.first().as_int() == 51: @@ -300,8 +300,8 @@ def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Optional[bytes32 if condition.first().as_int() == -10: # this is the change owner magic condition atom = condition.at("rf").atom - if atom is None: - new_did_id = atom + if atom is None or atom == b"": + new_did_id = None else: new_did_id = bytes32(atom) return new_did_id From 894f5e4469ad7b70338143674120014e65bbdfb3 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Fri, 15 Mar 2024 20:58:34 -0400 Subject: [PATCH 21/34] blah --- chia/wallet/nft_wallet/nft_puzzles.py | 7 +++++-- chia/wallet/wallet_state_manager.py | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index f38eeb0bf033..78af779b5058 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -280,6 +280,8 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: # this is the change owner magic condition atom = condition.at("rf").atom if atom is None or atom == b"": + # TODO: 0193847 this is a similar case to below where there is + # trouble, review new_did_id = None else: new_did_id = bytes32(atom) @@ -295,13 +297,14 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Optional[bytes32]: conditions = unft.p2_puzzle.run(unft.get_innermost_solution(solution)) - new_did_id: Optional[bytes32] = None + new_did_id = None for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition atom = condition.at("rf").atom if atom is None or atom == b"": - new_did_id = None + # TODO: 0193847 something seems to depend on retaining b"" and not None + new_did_id = atom else: new_did_id = bytes32(atom) return new_did_id diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index ad7e3a271177..18389bb6d3ea 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -1299,6 +1299,7 @@ async def get_minter_did(self, launcher_coin: Coin, peer: WSChiaConnection) -> O if not eve_uncurried_nft.supports_did: return None minter_did = get_new_owner_did(eve_uncurried_nft, eve_coin_spend.solution.to_program()) + # TODO: 0193847 per hinting for above, this shouldn't be needed if minter_did == b"": minter_did = None if minter_did is None: @@ -1438,6 +1439,8 @@ async def handle_nft( if new_did_id is None: new_did_id = old_did_id if new_did_id == b"": + # TODO: 0193847 per hinting for above, this shouldn't be needed and + # shouldn't be reachable but it seems it is new_did_id = None self.log.debug( "Handling NFT: %s, old DID:%s, new DID:%s, old P2:%s, new P2:%s", From 9c3cb36caef6f9289dc3bde94c37bb334600d42a Mon Sep 17 00:00:00 2001 From: Matt Date: Mon, 18 Mar 2024 10:39:40 -0700 Subject: [PATCH 22/34] Fix get_owner_did --- chia/wallet/nft_wallet/nft_puzzles.py | 12 ++++++------ chia/wallet/wallet_state_manager.py | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 78af779b5058..2eed03613251 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -1,7 +1,7 @@ from __future__ import annotations import logging -from typing import Any, Dict, List, Optional, Tuple +from typing import Any, Dict, List, Literal, Optional, Tuple, Union from clvm.casts import int_from_bytes from clvm_tools.binutils import disassemble @@ -295,16 +295,16 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: return new_ownership_puzzle -def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Optional[bytes32]: +def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Union[None, Literal[b""], bytes32]: conditions = unft.p2_puzzle.run(unft.get_innermost_solution(solution)) - new_did_id = None + new_did_id: Union[None, Literal[b""], bytes32] = None for condition in conditions.as_iter(): if condition.first().as_int() == -10: # this is the change owner magic condition - atom = condition.at("rf").atom - if atom is None or atom == b"": + atom = condition.at("rf").as_atom() + if atom == b"": # TODO: 0193847 something seems to depend on retaining b"" and not None - new_did_id = atom + new_did_id = b"" else: new_did_id = bytes32(atom) return new_did_id diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index 18389bb6d3ea..beade47cd99b 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -1424,7 +1424,7 @@ async def handle_nft( """ wallet_identifier = None # DID ID determines which NFT wallet should process the NFT - new_did_id = None + new_did_id: Optional[bytes32] = None old_did_id = None # P2 puzzle hash determines if we should ignore the NFT uncurried_nft: UncurriedNFT = nft_data.uncurried_nft @@ -1434,14 +1434,16 @@ async def handle_nft( nft_data.parent_coin_spend.solution, ) if uncurried_nft.supports_did: - new_did_id = get_new_owner_did(uncurried_nft, nft_data.parent_coin_spend.solution.to_program()) + _new_did_id = get_new_owner_did(uncurried_nft, nft_data.parent_coin_spend.solution.to_program()) old_did_id = uncurried_nft.owner_did - if new_did_id is None: + if _new_did_id is None: new_did_id = old_did_id - if new_did_id == b"": + elif _new_did_id == b"": # TODO: 0193847 per hinting for above, this shouldn't be needed and # shouldn't be reachable but it seems it is new_did_id = None + else: + new_did_id = _new_did_id self.log.debug( "Handling NFT: %s, old DID:%s, new DID:%s, old P2:%s, new P2:%s", nft_data.parent_coin_spend, From 5578369825d513449219c26b3d94811f065249d4 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Mon, 18 Mar 2024 16:44:12 -0400 Subject: [PATCH 23/34] tidy --- chia/types/blockchain_format/program.py | 1 + chia/wallet/nft_wallet/nft_puzzles.py | 3 --- chia/wallet/wallet_state_manager.py | 3 --- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/chia/types/blockchain_format/program.py b/chia/types/blockchain_format/program.py index c6a4badcc90a..25993cbddd1b 100644 --- a/chia/types/blockchain_format/program.py +++ b/chia/types/blockchain_format/program.py @@ -230,6 +230,7 @@ def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: NIL = Program.from_bytes(b"\x80") +# TODO: review # real return type is more like Union[T_Program, CastableType] when considering corner and terminal cases def _sexp_replace( sexp: T_CLVMStorage, to_sexp: Callable[[CastableType], T_Program], **kwargs: CastableType diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 2eed03613251..8fea3998dd14 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -280,8 +280,6 @@ def recurry_nft_puzzle(unft: UncurriedNFT, solution: Program, new_inner_puzzle: # this is the change owner magic condition atom = condition.at("rf").atom if atom is None or atom == b"": - # TODO: 0193847 this is a similar case to below where there is - # trouble, review new_did_id = None else: new_did_id = bytes32(atom) @@ -303,7 +301,6 @@ def get_new_owner_did(unft: UncurriedNFT, solution: Program) -> Union[None, Lite # this is the change owner magic condition atom = condition.at("rf").as_atom() if atom == b"": - # TODO: 0193847 something seems to depend on retaining b"" and not None new_did_id = b"" else: new_did_id = bytes32(atom) diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index beade47cd99b..eb1e0beffd99 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -1299,7 +1299,6 @@ async def get_minter_did(self, launcher_coin: Coin, peer: WSChiaConnection) -> O if not eve_uncurried_nft.supports_did: return None minter_did = get_new_owner_did(eve_uncurried_nft, eve_coin_spend.solution.to_program()) - # TODO: 0193847 per hinting for above, this shouldn't be needed if minter_did == b"": minter_did = None if minter_did is None: @@ -1439,8 +1438,6 @@ async def handle_nft( if _new_did_id is None: new_did_id = old_did_id elif _new_did_id == b"": - # TODO: 0193847 per hinting for above, this shouldn't be needed and - # shouldn't be reachable but it seems it is new_did_id = None else: new_did_id = _new_did_id From e0381a1cbecd41367bb023acba1022d37f7a4e36 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Mon, 18 Mar 2024 18:20:32 -0400 Subject: [PATCH 24/34] blah --- chia/types/blockchain_format/program.py | 1 - 1 file changed, 1 deletion(-) diff --git a/chia/types/blockchain_format/program.py b/chia/types/blockchain_format/program.py index 25993cbddd1b..c6a4badcc90a 100644 --- a/chia/types/blockchain_format/program.py +++ b/chia/types/blockchain_format/program.py @@ -230,7 +230,6 @@ def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: NIL = Program.from_bytes(b"\x80") -# TODO: review # real return type is more like Union[T_Program, CastableType] when considering corner and terminal cases def _sexp_replace( sexp: T_CLVMStorage, to_sexp: Callable[[CastableType], T_Program], **kwargs: CastableType From 9cfc11a398d6ebc46c51e91882fe15d8a9fe6eb1 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 20 Mar 2024 09:50:55 -0400 Subject: [PATCH 25/34] `.as_atom()` --- chia/rpc/wallet_rpc_api.py | 3 --- chia/wallet/cat_wallet/cat_outer_puzzle.py | 3 +-- chia/wallet/cat_wallet/cat_wallet.py | 6 ++---- chia/wallet/did_wallet/did_wallet.py | 3 +-- chia/wallet/nft_wallet/nft_wallet.py | 3 +-- chia/wallet/nft_wallet/uncurry_nft.py | 9 +++------ chia/wallet/wallet_state_manager.py | 9 +++------ 7 files changed, 11 insertions(+), 25 deletions(-) diff --git a/chia/rpc/wallet_rpc_api.py b/chia/rpc/wallet_rpc_api.py index 58b021a6e1d0..5765589750ab 100644 --- a/chia/rpc/wallet_rpc_api.py +++ b/chia/rpc/wallet_rpc_api.py @@ -2243,8 +2243,6 @@ async def did_get_info(self, request: Dict[str, Any]) -> EndpointResult: if coin_memos is not None: for memo in coin_memos: hints.append(memo.hex()) - assert recovery_list_hash.atom is not None - assert public_key.atom is not None return { "success": True, "did_id": encode_puzzle_hash(launcher_id, AddressType.DID.hrp(self.service.config)), @@ -2284,7 +2282,6 @@ async def did_find_lost_did(self, request: Dict[str, Any]) -> EndpointResult: if curried_args is None: return {"success": False, "error": "The coin is not a DID."} p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = curried_args - assert recovery_list_hash.atom is not None did_data: DIDCoinData = DIDCoinData( p2_puzzle, bytes32(recovery_list_hash.as_atom()), diff --git a/chia/wallet/cat_wallet/cat_outer_puzzle.py b/chia/wallet/cat_wallet/cat_outer_puzzle.py index 18d5e7bd01f5..6e111286ae51 100644 --- a/chia/wallet/cat_wallet/cat_outer_puzzle.py +++ b/chia/wallet/cat_wallet/cat_outer_puzzle.py @@ -33,10 +33,9 @@ def match(self, puzzle: UncurriedPuzzle) -> Optional[PuzzleInfo]: if args is None: return None _, tail_hash, inner_puzzle = args - assert tail_hash.atom is not None constructor_dict: Dict[str, Any] = { "type": "CAT", - "tail": "0x" + tail_hash.atom.hex(), + "tail": "0x" + tail_hash.as_atom().hex(), } next_constructor = self._match(uncurry_puzzle(inner_puzzle)) if next_constructor is not None: diff --git a/chia/wallet/cat_wallet/cat_wallet.py b/chia/wallet/cat_wallet/cat_wallet.py index b24e3eaffb9b..a1c0813a39d7 100644 --- a/chia/wallet/cat_wallet/cat_wallet.py +++ b/chia/wallet/cat_wallet/cat_wallet.py @@ -395,11 +395,9 @@ async def coin_added( cat_curried_args = match_cat_puzzle(uncurry_puzzle(coin_spend.puzzle_reveal.to_program())) if cat_curried_args is not None: cat_mod_hash, tail_program_hash, cat_inner_puzzle = cat_curried_args - assert cat_mod_hash.atom is not None - assert tail_program_hash.atom is not None parent_coin_data = CATCoinData( - bytes32(cat_mod_hash.atom), - bytes32(tail_program_hash.atom), + bytes32(cat_mod_hash.as_atom()), + bytes32(tail_program_hash.as_atom()), cat_inner_puzzle, coin_state[0].coin.parent_coin_info, uint64(coin_state[0].coin.amount), diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 3269e727c74e..9db98d646958 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -375,10 +375,9 @@ async def coin_added(self, coin: Coin, _: uint32, peer: WSChiaConnection, parent did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args) assert did_curried_args is not None p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args - assert recovery_list_hash.atom is not None did_data = DIDCoinData( p2_puzzle=p2_puzzle, - recovery_list_hash=bytes32(recovery_list_hash.atom), + recovery_list_hash=bytes32(recovery_list_hash.as_atom()), num_verification=uint16(num_verification.as_int()), singleton_struct=singleton_struct, metadata=metadata, diff --git a/chia/wallet/nft_wallet/nft_wallet.py b/chia/wallet/nft_wallet/nft_wallet.py index 7ae4ca5d7e95..64b972b27868 100644 --- a/chia/wallet/nft_wallet/nft_wallet.py +++ b/chia/wallet/nft_wallet/nft_wallet.py @@ -217,11 +217,10 @@ async def puzzle_solution_received(self, coin: Coin, data: NFTCoinData, peer: WS minter_did = await self.wallet_state_manager.get_minter_did(launcher_coin_states[0].coin, peer) else: inner_puzzle = p2_puzzle - assert uncurried_nft.metadata_updater_hash.atom is not None child_puzzle: Program = nft_puzzles.create_full_puzzle( singleton_id, Program.to(metadata), - bytes32(uncurried_nft.metadata_updater_hash.atom), + bytes32(uncurried_nft.metadata_updater_hash.as_atom()), inner_puzzle, ) self.log.debug( diff --git a/chia/wallet/nft_wallet/uncurry_nft.py b/chia/wallet/nft_wallet/uncurry_nft.py index 278d9ea7a7c6..d2f047f84c94 100644 --- a/chia/wallet/nft_wallet/uncurry_nft.py +++ b/chia/wallet/nft_wallet/uncurry_nft.py @@ -118,7 +118,6 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> try: # Set nft parameters nft_mod_hash, metadata, metadata_updater_hash, inner_puzzle = curried_args.as_iter() - assert nft_mod_hash.atom is not None data_uris = Program.to([]) data_hash = Program.to(0) meta_uris = Program.to([]) @@ -160,8 +159,7 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> transfer_program_mod, transfer_program_args = transfer_program.uncurry() _, royalty_address_p, royalty_percentage_program = transfer_program_args.as_iter() royalty_percentage = uint16(royalty_percentage_program.as_int()) - assert royalty_address_p.atom is not None - royalty_address = bytes32(royalty_address_p.atom) + royalty_address = bytes32(royalty_address_p.as_atom()) atom = current_did_program.atom if atom == b"": # For unassigned NFT, set owner DID to None @@ -175,11 +173,10 @@ def uncurry(cls: Type[_T_UncurriedNFT], mod: Program, curried_args: Program) -> log.debug("Cannot uncurry NFT state layer: Args %s Error: %s", curried_args, e) return None - assert singleton_launcher_id.atom is not None - singleton_launcher_id_bytes32 = bytes32(singleton_launcher_id.atom) + singleton_launcher_id_bytes32 = bytes32(singleton_launcher_id.as_atom()) return cls( - nft_mod_hash=bytes32(nft_mod_hash.atom), + nft_mod_hash=bytes32(nft_mod_hash.as_atom()), nft_state_layer=nft_state_layer, singleton_struct=singleton_struct, singleton_mod_hash=singleton_mod_hash, diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index eb1e0beffd99..99fb7cb0404e 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -803,11 +803,9 @@ async def determine_coin_type( cat_curried_args = match_cat_puzzle(uncurried) if cat_curried_args is not None: cat_mod_hash, tail_program_hash, cat_inner_puzzle = cat_curried_args - assert cat_mod_hash.atom is not None - assert tail_program_hash.atom is not None cat_data: CATCoinData = CATCoinData( - bytes32(cat_mod_hash.atom), - bytes32(tail_program_hash.atom), + bytes32(cat_mod_hash.as_atom()), + bytes32(tail_program_hash.as_atom()), cat_inner_puzzle, parent_coin_state.coin.parent_coin_info, uint64(parent_coin_state.coin.amount), @@ -836,10 +834,9 @@ async def determine_coin_type( did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args) if did_curried_args is not None and coin_state.coin.amount % 2 == 1: p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args - assert recovery_list_hash.atom is not None did_data: DIDCoinData = DIDCoinData( p2_puzzle, - bytes32(recovery_list_hash.atom), + bytes32(recovery_list_hash.as_atom()), uint16(num_verification.as_int()), singleton_struct, metadata, From bbc1e967918ecc1207d75edfcccf2cf0455970f1 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 20 Mar 2024 10:26:16 -0400 Subject: [PATCH 26/34] `.as_int()` --- chia/wallet/nft_wallet/nft_puzzles.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 8fea3998dd14..1373f8eb2997 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -3,7 +3,6 @@ import logging from typing import Any, Dict, List, Literal, Optional, Tuple, Union -from clvm.casts import int_from_bytes from clvm_tools.binutils import disassemble from chia.types.blockchain_format.program import Program @@ -255,10 +254,9 @@ def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tup metadata = update_metadata(metadata, condition) metadata = Program.to(metadata) elif condition_code == 51: - atom = condition.rest().rest().first().atom - assert atom is not None + atom = condition.rest().rest().first().as_int() - if int_from_bytes(atom) == 1: + if atom == 1: # destination puzhash if puzhash_for_derivation is not None: # ignore duplicated create coin conditions From b7f8058d5a53692ece4cfcabd65bc07ca9ea4bd0 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 20 Mar 2024 10:28:52 -0400 Subject: [PATCH 27/34] Update chia/wallet/nft_wallet/nft_puzzles.py --- chia/wallet/nft_wallet/nft_puzzles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 1373f8eb2997..05747b6147aa 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -261,7 +261,7 @@ def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tup if puzhash_for_derivation is not None: # ignore duplicated create coin conditions continue - memo = bytes32(condition.as_python()[-1][0]) + memo = bytes32(condition.at("rrrfrf").as_atom()) puzhash_for_derivation = memo log.debug("Got back puzhash from solution: %s", puzhash_for_derivation) assert puzhash_for_derivation From 4d770493389dbb5e22fe11894ea9a62ed8f2df4e Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Wed, 20 Mar 2024 12:42:05 -0400 Subject: [PATCH 28/34] `rrrff` --- chia/wallet/nft_wallet/nft_puzzles.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chia/wallet/nft_wallet/nft_puzzles.py b/chia/wallet/nft_wallet/nft_puzzles.py index 05747b6147aa..4acdbac52cbf 100644 --- a/chia/wallet/nft_wallet/nft_puzzles.py +++ b/chia/wallet/nft_wallet/nft_puzzles.py @@ -261,7 +261,7 @@ def get_metadata_and_phs(unft: UncurriedNFT, solution: SerializedProgram) -> Tup if puzhash_for_derivation is not None: # ignore duplicated create coin conditions continue - memo = bytes32(condition.at("rrrfrf").as_atom()) + memo = bytes32(condition.at("rrrff").as_atom()) puzhash_for_derivation = memo log.debug("Got back puzhash from solution: %s", puzhash_for_derivation) assert puzhash_for_derivation From b42e703e26c917be91b4709969bd10278bd70558 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Mar 2024 22:19:45 -0400 Subject: [PATCH 29/34] stop using `CastableType` --- .../core/custom_types/test_spend_bundle.py | 3 +- .../core/mempool/test_mempool_manager.py | 21 ++++++------ chia/_tests/core/test_program.py | 7 ++-- .../wallet/cat_wallet/test_offer_lifecycle.py | 3 +- .../_tests/wallet/dao_wallet/test_dao_clvm.py | 33 +++++++++---------- .../wallet/db_wallet/test_db_graftroot.py | 5 ++- .../wallet/nft_wallet/test_nft_lifecycle.py | 5 ++- .../wallet/nft_wallet/test_nft_puzzles.py | 6 ++-- .../wallet/vc_wallet/test_vc_lifecycle.py | 5 ++- chia/data_layer/data_layer_wallet.py | 3 +- chia/types/blockchain_format/program.py | 18 +++++----- chia/wallet/cat_wallet/cat_utils.py | 3 +- chia/wallet/conditions.py | 3 +- chia/wallet/dao_wallet/dao_utils.py | 3 +- chia/wallet/did_wallet/did_wallet.py | 3 +- chia/wallet/vc_wallet/cr_cat_drivers.py | 9 +++-- chia/wallet/vc_wallet/vc_drivers.py | 4 +-- 17 files changed, 57 insertions(+), 77 deletions(-) diff --git a/chia/_tests/core/custom_types/test_spend_bundle.py b/chia/_tests/core/custom_types/test_spend_bundle.py index 2659f80efb03..3821749d5317 100644 --- a/chia/_tests/core/custom_types/test_spend_bundle.py +++ b/chia/_tests/core/custom_types/test_spend_bundle.py @@ -6,7 +6,6 @@ import pytest from chia_rs import G2Element -from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -60,7 +59,7 @@ def create_spends(num: int) -> Tuple[List[CoinSpend], List[Coin]]: for i in range(num): target_ph = rand_hash(rng) - conditions: List[CastableType] = [[ConditionOpcode.CREATE_COIN, target_ph, 1]] + conditions = [[ConditionOpcode.CREATE_COIN, target_ph, 1]] coin = Coin(rand_hash(rng), puzzle_hash, uint64(1000)) new_coin = Coin(coin.name(), target_ph, uint64(1)) create_coin.append(new_coin) diff --git a/chia/_tests/core/mempool/test_mempool_manager.py b/chia/_tests/core/mempool/test_mempool_manager.py index 8f08564dfeec..28e8366eca00 100644 --- a/chia/_tests/core/mempool/test_mempool_manager.py +++ b/chia/_tests/core/mempool/test_mempool_manager.py @@ -2,12 +2,11 @@ import dataclasses import logging -from typing import Any, Awaitable, Callable, Collection, Dict, List, Optional, Set, Tuple, Union +from typing import Any, Awaitable, Callable, Collection, Dict, List, Optional, Set, Tuple import pytest from chia_rs import ELIGIBLE_FOR_DEDUP, ELIGIBLE_FOR_FF, G1Element, G2Element from chiabip158 import PyBIP158 -from clvm.SExp import CastableType from chia._tests.util.misc import invariant_check_mempool from chia._tests.util.setup_nodes import OldSimulatorsAndWallets @@ -1329,14 +1328,14 @@ async def test_replacing_one_with_an_eligible_coin() -> None: @pytest.mark.parametrize("amount", [0, 1]) def test_run_for_cost(amount: int) -> None: - conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, amount]] + conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, amount]] solution = SerializedProgram.to(conditions) cost = run_for_cost(IDENTITY_PUZZLE, solution, additions_count=1, max_cost=uint64(10000000)) assert cost == uint64(1800044) def test_run_for_cost_max_cost() -> None: - conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1]] + conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1]] solution = SerializedProgram.to(conditions) with pytest.raises(ValueError, match="cost exceeded"): run_for_cost(IDENTITY_PUZZLE, solution, additions_count=1, max_cost=uint64(43)) @@ -1363,7 +1362,7 @@ def test_dedup_info_nothing_to_do() -> None: def test_dedup_info_eligible_1st_time() -> None: # Eligible coin encountered for the first time - conditions: List[List[Union[bytes, int]]] = [ + conditions = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] @@ -1386,7 +1385,7 @@ def test_dedup_info_eligible_1st_time() -> None: def test_dedup_info_eligible_but_different_solution() -> None: # Eligible coin but different solution from the one we encountered - initial_conditions: List[List[Union[bytes, int]]] = [ + initial_conditions = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] @@ -1404,14 +1403,14 @@ def test_dedup_info_eligible_but_different_solution() -> None: def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None: # Eligible coin encountered a second time, and another for the first time - initial_conditions: List[List[Union[bytes, int]]] = [ + initial_conditions = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] initial_solution = SerializedProgram.to(initial_conditions) eligible_coin_spends = EligibleCoinSpends({TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=None)}) sb1 = spend_bundle_from_conditions(initial_conditions, TEST_COIN) - second_conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] + second_conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] second_solution = SerializedProgram.to(second_conditions) sb2 = spend_bundle_from_conditions(second_conditions, TEST_COIN2) sb = SpendBundle.aggregate([sb1, sb2]) @@ -1438,12 +1437,12 @@ def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None: def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() -> None: # Eligible coin encountered a third time, another for the second time and one non eligible - initial_conditions: List[List[Union[bytes, int]]] = [ + initial_conditions = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] initial_solution = SerializedProgram.to(initial_conditions) - second_conditions: List[List[Union[bytes, int]]] = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] + second_conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3]] second_solution = SerializedProgram.to(second_conditions) saved_cost = uint64(3600044) eligible_coin_spends = EligibleCoinSpends( @@ -1845,7 +1844,7 @@ async def make_setup_and_coins( ), ], ) -async def test_mempool_timelocks(cond1: List[CastableType], cond2: List[CastableType], expected: Optional[Err]) -> None: +async def test_mempool_timelocks(cond1: List[object], cond2: List[object], expected: Optional[Err]) -> None: coins = [] test_coin_records = {} diff --git a/chia/_tests/core/test_program.py b/chia/_tests/core/test_program.py index cea5e494ec10..70b389c32975 100644 --- a/chia/_tests/core/test_program.py +++ b/chia/_tests/core/test_program.py @@ -1,8 +1,7 @@ from __future__ import annotations -from typing import List +from typing import Any -from clvm.SExp import CastableType from clvm_tools import binutils from chia.types.blockchain_format.program import Program @@ -11,7 +10,7 @@ from chia.util.ints import uint32, uint64 -def program_roundtrip(o: CastableType) -> None: +def program_roundtrip(o: Any) -> None: prg1 = Program.to(o) prg2 = SerializedProgram.to(o) prg3 = SerializedProgram.from_program(prg1) @@ -26,7 +25,7 @@ def program_roundtrip(o: CastableType) -> None: def test_serialized_program_to() -> None: prg = "(q ((0x0101010101010101010101010101010101010101010101010101010101010101 80 123 (() (q . ())))))" # noqa - tests: List[CastableType] = [ + tests = [ 0, 1, (1, 2), diff --git a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py index 58b272485879..4c9a771d1c2b 100644 --- a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +++ b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py @@ -4,7 +4,6 @@ import pytest from chia_rs import G2Element -from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, SimClient, SpendSim, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -121,7 +120,7 @@ def generate_secure_bundle( announcement_assertions = [a.to_program() for a in announcements] selected_coin_amount = sum([c.amount for c in selected_coins]) non_primaries = [] if len(selected_coins) < 2 else selected_coins[1:] - inner_solution: List[CastableType] = [ + inner_solution = [ [51, Offer.ph(), offered_amount], # Offered coin [51, acs_ph, uint64(selected_coin_amount - offered_amount)], # Change *announcement_assertions, diff --git a/chia/_tests/wallet/dao_wallet/test_dao_clvm.py b/chia/_tests/wallet/dao_wallet/test_dao_clvm.py index d975ef2c05a4..d4b78d446807 100644 --- a/chia/_tests/wallet/dao_wallet/test_dao_clvm.py +++ b/chia/_tests/wallet/dao_wallet/test_dao_clvm.py @@ -5,7 +5,6 @@ import pytest from chia_rs import AugSchemeMPL from clvm.casts import int_to_bytes -from clvm.SExp import CastableType from chia.clvm.spend_sim import SimClient, SpendSim, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -542,8 +541,8 @@ def test_validator() -> None: ) spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() - parent_amt_list: CastableType = [[parent_id, locked_amount]] - cat_parent_amt_list: CastableType = [] + parent_amt_list = [[parent_id, locked_amount]] + cat_parent_amt_list: List[Any] = [] spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()]) output_conds = spend_p2_singleton.run(spend_p2_singleton_solution) @@ -610,8 +609,8 @@ def test_spend_p2_singleton() -> None: ] # Solution Values - xch_parent_amt_list: CastableType = [[b"x" * 32, 10], [b"y" * 32, 100]] - cat_parent_amt_list: CastableType = [ + xch_parent_amt_list = [[b"x" * 32, 10], [b"y" * 32, 100]] + cat_parent_amt_list = [ [cat_tail_1, [["b" * 32, 100], [b"c" * 32, 400]]], [cat_tail_2, [[b"e" * 32, 100], [b"f" * 32, 400]]], ] @@ -721,13 +720,13 @@ def test_merge_p2_singleton() -> None: Program.to("fake_parent_3").get_tree_hash(), ] amounts = [uint64(1000), uint64(2000), uint64(3000)] - parent_puzhash_amounts: List[List[CastableType]] = [] + parent_puzhash_amounts = [] merge_coin_ids: List[bytes32] = [] for pid, amt in zip(parent_ids, amounts): parent_puzhash_amounts.append([pid, my_puzhash, amt]) merge_coin_ids.append(Coin(pid, my_puzhash, amt).name()) - output_parent_amount: List[CastableType] = [output_parent_id, output_coin_amount] + output_parent_amount = [output_parent_id, output_coin_amount] output_coin_id = Coin(output_parent_id, my_puzhash, output_coin_amount).name() agg_sol = Program.to([[output_coin_id, my_puzhash, output_coin_amount, parent_puzhash_amounts, 0]]) @@ -738,7 +737,7 @@ def test_merge_p2_singleton() -> None: agg_acas = [x.vars[0] for x in agg_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT]] for coin_id, ppa in zip(merge_coin_ids, parent_puzhash_amounts): - something: CastableType = [[coin_id, ppa[1], ppa[2], 0, output_parent_amount]] + something = [[coin_id, ppa[1], ppa[2], 0, output_parent_amount]] sol = Program.to(something) merge_conds = conditions_dict_for_solution(p2_singleton, sol, INFINITE_COST) # merge coin announces 0 @@ -826,9 +825,9 @@ def test_treasury() -> None: ) spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() - parent_amt_list: List[List[CastableType]] = [[parent_id, locked_amount]] - cat_parent_amt_list: List[Optional[Any]] = [] - something: CastableType = [parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()] + parent_amt_list = [[parent_id, locked_amount]] + cat_parent_amt_list: List[Any] = [] + something = [parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()] spend_p2_singleton_solution = Program.to(something) proposal: Program = proposal_curry_one.curry( @@ -898,7 +897,7 @@ def test_lockup() -> None: INNERPUZ, ).get_tree_hash() message = Program.to([new_proposal, lockup_coin_amount, 1, my_id]).get_tree_hash() - generated_conditions: List[List[CastableType]] = [[51, child_puzhash, lockup_coin_amount], [62, message]] + generated_conditions = [[51, child_puzhash, lockup_coin_amount], [62, message]] solution: Program = Program.to( [ my_id, @@ -967,7 +966,7 @@ def test_lockup() -> None: new_innerpuz, ).get_tree_hash() message = Program.to([0, 0, 0, my_id]).get_tree_hash() - spend_conds: List[List[CastableType]] = [[51, child_lockup, lockup_coin_amount], [62, message]] + spend_conds = [[51, child_lockup, lockup_coin_amount], [62, message]] transfer_sol = Program.to( [ my_id, @@ -1074,9 +1073,9 @@ def test_proposal_lifecycle() -> None: ) spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() - parent_amt_list: CastableType = [[parent_id, locked_amount]] - cat_parent_amt_list: CastableType = [] - something: List[CastableType] = [parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash] + parent_amt_list = [[parent_id, locked_amount]] + cat_parent_amt_list: List[Any] = [] + something = [parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash] spend_p2_singleton_solution = Program.to(something) # Setup Proposal @@ -1123,7 +1122,7 @@ def test_proposal_lifecycle() -> None: ) # lineage_proof my_amount inner_solution - lineage_proof: CastableType = [treasury_id, treasury_inner_puzhash, treasury_amount] + lineage_proof = [treasury_id, treasury_inner_puzhash, treasury_amount] full_treasury_solution = Program.to([lineage_proof, treasury_amount, treasury_solution]) full_proposal_solution = Program.to([lineage_proof, proposal_amt, proposal_solution]) diff --git a/chia/_tests/wallet/db_wallet/test_db_graftroot.py b/chia/_tests/wallet/db_wallet/test_db_graftroot.py index eef11286e24c..12bf664cb6ad 100644 --- a/chia/_tests/wallet/db_wallet/test_db_graftroot.py +++ b/chia/_tests/wallet/db_wallet/test_db_graftroot.py @@ -4,7 +4,6 @@ import pytest from chia_rs import G2Element -from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -45,8 +44,8 @@ async def test_graftroot(cost_logger: CostLogger) -> None: # Create the coin we're testing all_values: List[bytes32] = [bytes32([x] * 32) for x in range(0, 100)] root, proofs = build_merkle_tree(all_values) - something_a: CastableType = [51, ACS_PH, 0] - something_b: CastableType = (1, [something_a]) + something_a = [51, ACS_PH, 0] + something_b = (1, [something_a]) p2_conditions = Program.to(something_b) # An coin to create to make sure this hits the blockchain desired_key_values = ((bytes32([0] * 32), bytes32([1] * 32)), (bytes32([7] * 32), bytes32([8] * 32))) desired_row_hashes: List[bytes32] = [build_merkle_tree_from_binary_tree(kv)[0] for kv in desired_key_values] diff --git a/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py b/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py index 012983c0cd92..d299b508e969 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py @@ -1,11 +1,10 @@ from __future__ import annotations import itertools -from typing import List, Tuple +from typing import List import pytest from chia_rs import G2Element -from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.types.blockchain_format.program import Program @@ -319,7 +318,7 @@ async def test_default_transfer_program(cost_logger: CostLogger) -> None: Program.to([[[62, FAKE_LAUNCHER_ID]]]), ) - expected_announcement_python: Tuple[bytes32, List[List[CastableType]]] = ( + expected_announcement_python = ( FAKE_LAUNCHER_ID, [[ROYALTY_ADDRESS, 50, [ROYALTY_ADDRESS]]], ) diff --git a/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py b/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py index 2e2a36fd0891..49f0c2e60d37 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py @@ -1,9 +1,7 @@ from __future__ import annotations import random -from typing import List, Tuple - -from clvm.SExp import CastableType +from typing import Tuple from chia._tests.core.make_block_generator import int_to_public_key from chia.types.blockchain_format.program import Program @@ -146,7 +144,7 @@ def get_updated_nft_puzzle(puzzle: Program, solution: Program) -> bytes32: def test_transfer_puzzle_builder() -> None: - metadata: List[Tuple[str, CastableType]] = [ + metadata = [ ("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", 0xD4584AD463139FA8C0D9F68F4B59F185), ] diff --git a/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py b/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py index 0fed774939db..d5ac7f135850 100644 --- a/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +++ b/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py @@ -5,7 +5,6 @@ import pytest from chia_rs import G2Element -from clvm.SExp import CastableType from chia.clvm.spend_sim import CostLogger, sim_and_client from chia.types.blockchain_format.coin import Coin @@ -667,8 +666,8 @@ async def test_vc_lifecycle(test_syncing: bool, cost_logger: CostLogger) -> None "attempt_honest_cat_piggyback", None, ): - something_a: List[CastableType] = [[60, b"\xcd" + bytes(32)]] if error == "make_banned_announcement" else [] - something_b: CastableType = [ + something_a = [[60, b"\xcd" + bytes(32)]] if error == "make_banned_announcement" else [] + something_b = [ [ 51, ACS_PH, diff --git a/chia/data_layer/data_layer_wallet.py b/chia/data_layer/data_layer_wallet.py index dfb02cc30f98..a1d7215ba6d8 100644 --- a/chia/data_layer/data_layer_wallet.py +++ b/chia/data_layer/data_layer_wallet.py @@ -8,7 +8,6 @@ from chia_rs import G1Element, G2Element from clvm.EvalError import EvalError -from clvm.SExp import CastableType from typing_extensions import Unpack, final from chia.consensus.block_record import BlockRecord @@ -468,7 +467,7 @@ async def create_update_state_spend( # Optionally add an ephemeral spend to announce if announce_new_state: - announce_only_python: Tuple[int, List[List[CastableType]]] = ( + announce_only_python = ( 1, [ [ diff --git a/chia/types/blockchain_format/program.py b/chia/types/blockchain_format/program.py index c6a4badcc90a..6e90fc736911 100644 --- a/chia/types/blockchain_format/program.py +++ b/chia/types/blockchain_format/program.py @@ -8,7 +8,7 @@ from clvm.CLVMObject import CLVMStorage from clvm.EvalError import EvalError from clvm.serialize import sexp_from_stream, sexp_to_stream -from clvm.SExp import CastableType, SExp +from clvm.SExp import SExp from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.byte_types import hexstr_to_bytes @@ -90,7 +90,7 @@ def at(self, position: str) -> Program: raise ValueError(f"`at` got illegal character `{c}`. Only `f` & `r` allowed") return v - def replace(self: T_Program, **kwargs: CastableType) -> T_Program: + def replace(self: T_Program, **kwargs: Any) -> T_Program: """ Create a new program replacing the given paths (using `at` syntax). Example: @@ -123,15 +123,15 @@ def get_tree_hash_precalc(self, *args: bytes32) -> bytes32: def get_tree_hash(self) -> bytes32: return bytes32(tree_hash(bytes(self))) - def _run(self, max_cost: int, flags: int, args: CastableType) -> Tuple[int, Program]: + def _run(self, max_cost: int, flags: int, args: Any) -> Tuple[int, Program]: prog_args = Program.to(args) cost, r = run_chia_program(self.as_bin(), prog_args.as_bin(), max_cost, flags) return cost, Program.to(r) - def run_with_cost(self, max_cost: int, args: CastableType) -> Tuple[int, Program]: + def run_with_cost(self, max_cost: int, args: Any) -> Tuple[int, Program]: return self._run(max_cost, 0, args) - def run(self, args: CastableType) -> Program: + def run(self, args: Any) -> Program: cost, r = self.run_with_cost(INFINITE_COST, args) return r @@ -231,9 +231,7 @@ def _tree_hash(node: SExp, precalculated: Set[bytes32]) -> bytes32: # real return type is more like Union[T_Program, CastableType] when considering corner and terminal cases -def _sexp_replace( - sexp: T_CLVMStorage, to_sexp: Callable[[CastableType], T_Program], **kwargs: CastableType -) -> T_Program: +def _sexp_replace(sexp: T_CLVMStorage, to_sexp: Callable[[Any], T_Program], **kwargs: Any) -> T_Program: # if `kwargs == {}` then `return sexp` unchanged if len(kwargs) == 0: # yes, the terminal case is hinted incorrectly for now @@ -243,13 +241,13 @@ def _sexp_replace( if len(kwargs) > 1: raise ValueError("conflicting paths") # yes, the terminal case is hinted incorrectly for now - return kwargs[""] # type: ignore[return-value] + return kwargs[""] # we've confirmed that no `kwargs` is the empty string. # Now split `kwargs` into two groups: those # that start with `f` and those that start with `r` - args_by_prefix: Dict[str, Dict[str, CastableType]] = {} + args_by_prefix: Dict[str, Dict[str, Any]] = {} for k, v in kwargs.items(): c = k[0] if c not in "fr": diff --git a/chia/wallet/cat_wallet/cat_utils.py b/chia/wallet/cat_wallet/cat_utils.py index 4ae9e30a456a..484dd3289437 100644 --- a/chia/wallet/cat_wallet/cat_utils.py +++ b/chia/wallet/cat_wallet/cat_utils.py @@ -4,7 +4,6 @@ from typing import Iterator, List, Optional, Union from chia_rs import G2Element -from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin, coin_as_list from chia.types.blockchain_format.program import INFINITE_COST, Program @@ -99,7 +98,7 @@ def subtotals_for_deltas(deltas: List[int]) -> List[int]: def next_info_for_spendable_cat(spendable_cat: SpendableCAT) -> Program: c = spendable_cat.coin - list: CastableType = [c.parent_coin_info, spendable_cat.inner_puzzle.get_tree_hash(), c.amount] + list = [c.parent_coin_info, spendable_cat.inner_puzzle.get_tree_hash(), c.amount] return Program.to(list) diff --git a/chia/wallet/conditions.py b/chia/wallet/conditions.py index 37467d42a5a7..66b424e8173f 100644 --- a/chia/wallet/conditions.py +++ b/chia/wallet/conditions.py @@ -6,7 +6,6 @@ from chia_rs import G1Element from clvm.casts import int_from_bytes, int_to_bytes -from clvm.SExp import CastableType from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -230,7 +229,7 @@ class CreateCoin(Condition): memos: Optional[List[bytes]] = None def to_program(self) -> Program: - condition_args: List[CastableType] = [ConditionOpcode.CREATE_COIN, self.puzzle_hash, self.amount] + condition_args = [ConditionOpcode.CREATE_COIN, self.puzzle_hash, self.amount] if self.memos is not None: condition_args.append(self.memos) condition: Program = Program.to(condition_args) diff --git a/chia/wallet/dao_wallet/dao_utils.py b/chia/wallet/dao_wallet/dao_utils.py index ac974004e726..214a0c5180ed 100644 --- a/chia/wallet/dao_wallet/dao_utils.py +++ b/chia/wallet/dao_wallet/dao_utils.py @@ -5,7 +5,6 @@ from typing import Any, Iterator, List, Optional, Tuple, Union from clvm.EvalError import EvalError -from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program @@ -795,7 +794,7 @@ async def generate_mint_proposal_innerpuz( # cat_tail_hash = cat_wallet.cat_info.limitations_program_hash eve_puz_hash = curry_cat_eve(cats_new_innerpuzhash) full_puz = construct_cat_puzzle(CAT_MOD, cat_tail_hash, eve_puz_hash) - xch_conditions: List[List[CastableType]] = [ + xch_conditions = [ [ 51, cat_launcher.get_tree_hash(), diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 9db98d646958..9a315735af16 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -8,7 +8,6 @@ from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Optional, Set, Tuple, cast from chia_rs import AugSchemeMPL, G1Element, G2Element -from clvm.SExp import CastableType from chia.protocols.wallet_protocol import CoinState from chia.server.ws_connection import WSChiaConnection @@ -843,7 +842,7 @@ async def create_exit_spend(self, puzhash: bytes32, tx_config: TXConfig) -> List assert self.did_info.current_inner is not None assert self.did_info.origin_coin is not None coin = await self.get_coin() - message_puz_python: Tuple[int, List[CastableType]] = ( + message_puz_python = ( 1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]], ) diff --git a/chia/wallet/vc_wallet/cr_cat_drivers.py b/chia/wallet/vc_wallet/cr_cat_drivers.py index 1619821583be..aa3d9fbb33e0 100644 --- a/chia/wallet/vc_wallet/cr_cat_drivers.py +++ b/chia/wallet/vc_wallet/cr_cat_drivers.py @@ -6,7 +6,6 @@ from typing import Iterable, List, Optional, Tuple, Type, TypeVar from clvm.casts import int_to_bytes -from clvm.SExp import CastableType from chia.types.blockchain_format.coin import Coin, coin_as_list from chia.types.blockchain_format.program import Program @@ -51,12 +50,12 @@ package_or_requirement="chia.wallet.vc_wallet.cr_puzzles", include_standard_libraries=True, ) -something_a: CastableType = [ +something_a = [ 4, (1, create_eml_covenant_morpher(create_did_tp().get_tree_hash())), [4, (1, create_did_tp()), 1], ] -something_b: CastableType = ( +something_b = ( something_a, None, ) @@ -212,7 +211,7 @@ def launch( new_cr_layer_hash ) - something_a: List[List[CastableType]] = [ + something_a = [ [51, new_cr_layer_hash, payment.amount, payment.memos], [51, None, -113, tail, tail_solution], [60, None], @@ -227,7 +226,7 @@ def launch( eve_cat_puzzle_hash: bytes32 = eve_cat_puzzle.get_tree_hash() eve_coin: Coin = Coin(origin_coin.name(), eve_cat_puzzle_hash, payment.amount) - something_b: CastableType = [ + something_b = [ [51, eve_cat_puzzle_hash, payment.amount], [61, std_hash(eve_coin.name())], ] diff --git a/chia/wallet/vc_wallet/vc_drivers.py b/chia/wallet/vc_wallet/vc_drivers.py index 5923f2c10374..457a32d4ea4b 100644 --- a/chia/wallet/vc_wallet/vc_drivers.py +++ b/chia/wallet/vc_wallet/vc_drivers.py @@ -3,8 +3,6 @@ from dataclasses import dataclass, replace from typing import List, Optional, Tuple, Type, TypeVar -from clvm.SExp import CastableType - from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.sized_bytes import bytes32 @@ -385,7 +383,7 @@ def launch( launcher_coin.name(), metadata_layer_hash, # type: ignore ).get_tree_hash_precalc(metadata_layer_hash) - something: List[List[CastableType]] = [ + something = [ [51, wrapped_inner_puzzle_hash, uint64(1), memos], [1, new_inner_puzzle_hash], [-10, provider_id, transfer_program.get_tree_hash()], From 46a7a77e844f36f5e85fa4344989b0ebf1de1735 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Thu, 21 Mar 2024 22:46:17 -0400 Subject: [PATCH 30/34] undo stuff around using `CastableType` --- chia/_tests/core/test_program.py | 7 +-- .../wallet/cat_wallet/test_offer_lifecycle.py | 6 +-- .../_tests/wallet/dao_wallet/test_dao_clvm.py | 15 +++--- .../wallet/db_wallet/test_db_graftroot.py | 4 +- .../wallet/nft_wallet/test_nft_lifecycle.py | 8 ++- .../wallet/nft_wallet/test_nft_puzzles.py | 5 +- .../wallet/vc_wallet/test_vc_lifecycle.py | 20 +++---- chia/data_layer/data_layer_wallet.py | 22 ++++---- chia/wallet/dao_wallet/dao_wallet.py | 6 +-- chia/wallet/did_wallet/did_wallet.py | 6 +-- chia/wallet/vc_wallet/cr_cat_drivers.py | 52 +++++++++++-------- chia/wallet/vc_wallet/vc_drivers.py | 16 +++--- 12 files changed, 83 insertions(+), 84 deletions(-) diff --git a/chia/_tests/core/test_program.py b/chia/_tests/core/test_program.py index 70b389c32975..cea5e494ec10 100644 --- a/chia/_tests/core/test_program.py +++ b/chia/_tests/core/test_program.py @@ -1,7 +1,8 @@ from __future__ import annotations -from typing import Any +from typing import List +from clvm.SExp import CastableType from clvm_tools import binutils from chia.types.blockchain_format.program import Program @@ -10,7 +11,7 @@ from chia.util.ints import uint32, uint64 -def program_roundtrip(o: Any) -> None: +def program_roundtrip(o: CastableType) -> None: prg1 = Program.to(o) prg2 = SerializedProgram.to(o) prg3 = SerializedProgram.from_program(prg1) @@ -25,7 +26,7 @@ def program_roundtrip(o: Any) -> None: def test_serialized_program_to() -> None: prg = "(q ((0x0101010101010101010101010101010101010101010101010101010101010101 80 123 (() (q . ())))))" # noqa - tests = [ + tests: List[CastableType] = [ 0, 1, (1, 2), diff --git a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py index 4c9a771d1c2b..63ec88e1c922 100644 --- a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +++ b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Dict, List, Optional +from typing import Any, Dict, List, Optional import pytest from chia_rs import G2Element @@ -117,10 +117,10 @@ def generate_secure_bundle( offered_amount: uint64, tail_str: Optional[str] = None, ) -> SpendBundle: - announcement_assertions = [a.to_program() for a in announcements] + announcement_assertions: List[Any] = [a.to_program() for a in announcements] selected_coin_amount = sum([c.amount for c in selected_coins]) non_primaries = [] if len(selected_coins) < 2 else selected_coins[1:] - inner_solution = [ + inner_solution: List[List[Any]] = [ [51, Offer.ph(), offered_amount], # Offered coin [51, acs_ph, uint64(selected_coin_amount - offered_amount)], # Change *announcement_assertions, diff --git a/chia/_tests/wallet/dao_wallet/test_dao_clvm.py b/chia/_tests/wallet/dao_wallet/test_dao_clvm.py index d4b78d446807..7840d143681c 100644 --- a/chia/_tests/wallet/dao_wallet/test_dao_clvm.py +++ b/chia/_tests/wallet/dao_wallet/test_dao_clvm.py @@ -542,7 +542,7 @@ def test_validator() -> None: spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() parent_amt_list = [[parent_id, locked_amount]] - cat_parent_amt_list: List[Any] = [] + cat_parent_amt_list: List[Optional[Any]] = [] spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()]) output_conds = spend_p2_singleton.run(spend_p2_singleton_solution) @@ -737,8 +737,7 @@ def test_merge_p2_singleton() -> None: agg_acas = [x.vars[0] for x in agg_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT]] for coin_id, ppa in zip(merge_coin_ids, parent_puzhash_amounts): - something = [[coin_id, ppa[1], ppa[2], 0, output_parent_amount]] - sol = Program.to(something) + sol = Program.to([[coin_id, ppa[1], ppa[2], 0, output_parent_amount]]) merge_conds = conditions_dict_for_solution(p2_singleton, sol, INFINITE_COST) # merge coin announces 0 cca = std_hash(coin_id + merge_conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0]) @@ -826,9 +825,8 @@ def test_treasury() -> None: spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() parent_amt_list = [[parent_id, locked_amount]] - cat_parent_amt_list: List[Any] = [] - something = [parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()] - spend_p2_singleton_solution = Program.to(something) + cat_parent_amt_list: List[Optional[Any]] = [] + spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()]) proposal: Program = proposal_curry_one.curry( proposal_curry_one.get_tree_hash(), @@ -1074,9 +1072,8 @@ def test_proposal_lifecycle() -> None: spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash() parent_amt_list = [[parent_id, locked_amount]] - cat_parent_amt_list: List[Any] = [] - something = [parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash] - spend_p2_singleton_solution = Program.to(something) + cat_parent_amt_list: List[Optional[Any]] = [] + spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash]) # Setup Proposal proposal_id = Program.to("proposal_id").get_tree_hash() diff --git a/chia/_tests/wallet/db_wallet/test_db_graftroot.py b/chia/_tests/wallet/db_wallet/test_db_graftroot.py index 12bf664cb6ad..e1958679965c 100644 --- a/chia/_tests/wallet/db_wallet/test_db_graftroot.py +++ b/chia/_tests/wallet/db_wallet/test_db_graftroot.py @@ -44,9 +44,7 @@ async def test_graftroot(cost_logger: CostLogger) -> None: # Create the coin we're testing all_values: List[bytes32] = [bytes32([x] * 32) for x in range(0, 100)] root, proofs = build_merkle_tree(all_values) - something_a = [51, ACS_PH, 0] - something_b = (1, [something_a]) - p2_conditions = Program.to(something_b) # An coin to create to make sure this hits the blockchain + p2_conditions = Program.to((1, [[51, ACS_PH, 0]])) # An coin to create to make sure this hits the blockchain desired_key_values = ((bytes32([0] * 32), bytes32([1] * 32)), (bytes32([7] * 32), bytes32([8] * 32))) desired_row_hashes: List[bytes32] = [build_merkle_tree_from_binary_tree(kv)[0] for kv in desired_key_values] fake_struct: Program = Program.to((ACS_PH, NIL_PH)) diff --git a/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py b/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py index d299b508e969..2b83281617d4 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py @@ -318,11 +318,9 @@ async def test_default_transfer_program(cost_logger: CostLogger) -> None: Program.to([[[62, FAKE_LAUNCHER_ID]]]), ) - expected_announcement_python = ( - FAKE_LAUNCHER_ID, - [[ROYALTY_ADDRESS, 50, [ROYALTY_ADDRESS]]], - ) - expected_announcement_data = Program.to(expected_announcement_python).get_tree_hash() + expected_announcement_data = Program.to( + (FAKE_LAUNCHER_ID, [[ROYALTY_ADDRESS, 50, [ROYALTY_ADDRESS]]]) + ).get_tree_hash() xch_announcement_spend = make_spend( xch_coin, ACS, diff --git a/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py b/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py index 49f0c2e60d37..602e733dad56 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_puzzles.py @@ -144,10 +144,7 @@ def get_updated_nft_puzzle(puzzle: Program, solution: Program) -> bytes32: def test_transfer_puzzle_builder() -> None: - metadata = [ - ("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), - ("h", 0xD4584AD463139FA8C0D9F68F4B59F185), - ] + metadata = [("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", 0xD4584AD463139FA8C0D9F68F4B59F185)] sp2_puzzle, solution = make_a_new_solution() p2_puzzle, ownership_puzzle = make_a_new_ownership_layer_puzzle() clvm_nft_puzzle = create_nft_layer_puzzle_with_curry_params( diff --git a/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py b/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py index d5ac7f135850..9b57a46dd84c 100644 --- a/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +++ b/chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py @@ -666,15 +666,6 @@ async def test_vc_lifecycle(test_syncing: bool, cost_logger: CostLogger) -> None "attempt_honest_cat_piggyback", None, ): - something_a = [[60, b"\xcd" + bytes(32)]] if error == "make_banned_announcement" else [] - something_b = [ - [ - 51, - ACS_PH, - cr_1.coin.amount if error != "use_malicious_cats" else malicious_cr_1.coin.amount, - ], - *something_a, - ] # The CR-CAT coin spends expected_announcements, cr_cat_spends, new_crcats = CRCAT.spend_many( [ @@ -682,7 +673,16 @@ async def test_vc_lifecycle(test_syncing: bool, cost_logger: CostLogger) -> None cr_1 if error != "use_malicious_cats" else malicious_cr_1, 0, ACS, - Program.to(something_b), + Program.to( + [ + [ + 51, + ACS_PH, + cr_1.coin.amount if error != "use_malicious_cats" else malicious_cr_1.coin.amount, + ], + *([[60, b"\xcd" + bytes(32)]] if error == "make_banned_announcement" else []), + ] + ), ), ( cr_2 if error != "use_malicious_cats" else malicious_cr_2, diff --git a/chia/data_layer/data_layer_wallet.py b/chia/data_layer/data_layer_wallet.py index a1d7215ba6d8..8322bc046752 100644 --- a/chia/data_layer/data_layer_wallet.py +++ b/chia/data_layer/data_layer_wallet.py @@ -467,20 +467,20 @@ async def create_update_state_spend( # Optionally add an ephemeral spend to announce if announce_new_state: - announce_only_python = ( - 1, - [ + announce_only: Program = Program.to( + ( + 1, [ - 51, - new_puz_hash, - singleton_record.lineage_proof.amount, - [launcher_id, root_hash, new_puz_hash], + [ + 51, + new_puz_hash, + singleton_record.lineage_proof.amount, + [launcher_id, root_hash, new_puz_hash], + ], + [62, b"$"], ], - [62, b"$"], - ], + ) ) - - announce_only: Program = Program.to(announce_only_python) second_full_puz: Program = create_host_fullpuz( announce_only, root_hash, diff --git a/chia/wallet/dao_wallet/dao_wallet.py b/chia/wallet/dao_wallet/dao_wallet.py index 4c5647c768c2..3fae7515ee23 100644 --- a/chia/wallet/dao_wallet/dao_wallet.py +++ b/chia/wallet/dao_wallet/dao_wallet.py @@ -1266,8 +1266,8 @@ async def create_proposal_close_spend( sum = 0 coin_spends = [] - xch_parent_amount_list: List[List[Union[bytes32, int]]] = [] - tailhash_parent_amount_list: List[List[Union[bytes32, List[List[Union[bytes32, int]]]]]] = [] + xch_parent_amount_list = [] + tailhash_parent_amount_list = [] treasury_inner_puzhash = self.dao_info.current_treasury_innerpuz.get_tree_hash() p2_singleton_puzzle = get_p2_singleton_puzzle(self.dao_info.treasury_id) cat_launcher = create_cat_launcher_for_singleton_id(self.dao_info.treasury_id) @@ -1351,7 +1351,7 @@ async def create_proposal_close_spend( if condition.first().as_int() == 51: sum_of_conditions += condition.rest().rest().first().as_int() cat_coins = await self.select_coins_for_asset_type(uint64(sum_of_conditions), tail_hash) - parent_amount_list: List[List[Union[bytes32, int]]] = [] + parent_amount_list = [] for cat_coin in cat_coins: sum_of_coins += cat_coin.amount parent_amount_list.append([cat_coin.parent_coin_info, cat_coin.amount]) diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 9a315735af16..8d90c202ca19 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -842,11 +842,7 @@ async def create_exit_spend(self, puzhash: bytes32, tx_config: TXConfig) -> List assert self.did_info.current_inner is not None assert self.did_info.origin_coin is not None coin = await self.get_coin() - message_puz_python = ( - 1, - [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]], - ) - message_puz = Program.to(message_puz_python) + message_puz = Program.to((1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]])) # innerpuz solution is (mode p2_solution) innersol: Program = Program.to([1, [[], message_puz, []]]) diff --git a/chia/wallet/vc_wallet/cr_cat_drivers.py b/chia/wallet/vc_wallet/cr_cat_drivers.py index aa3d9fbb33e0..7a5f9ab53266 100644 --- a/chia/wallet/vc_wallet/cr_cat_drivers.py +++ b/chia/wallet/vc_wallet/cr_cat_drivers.py @@ -50,15 +50,6 @@ package_or_requirement="chia.wallet.vc_wallet.cr_puzzles", include_standard_libraries=True, ) -something_a = [ - 4, - (1, create_eml_covenant_morpher(create_did_tp().get_tree_hash())), - [4, (1, create_did_tp()), 1], -] -something_b = ( - something_a, - None, -) CREDENTIAL_STRUCT: Program = Program.to( ( ( @@ -84,7 +75,16 @@ Program.to( int_to_bytes(2) + Program.to((1, COVENANT_LAYER_HASH)).get_tree_hash_precalc(COVENANT_LAYER_HASH) ), - Program.to(something_b).get_tree_hash(), + Program.to( + ( + [ + 4, + (1, create_eml_covenant_morpher(create_did_tp().get_tree_hash())), + [4, (1, create_did_tp()), 1], + ], + None, + ) + ).get_tree_hash(), ), ), ), @@ -211,13 +211,17 @@ def launch( new_cr_layer_hash ) - something_a = [ - [51, new_cr_layer_hash, payment.amount, payment.memos], - [51, None, -113, tail, tail_solution], - [60, None], - [1, payment.puzzle_hash, authorized_providers, proofs_checker], - ] - eve_innerpuz: Program = Program.to((1, something_a)) + eve_innerpuz: Program = Program.to( + ( + 1, + [ + [51, new_cr_layer_hash, payment.amount, payment.memos], + [51, None, -113, tail, tail_solution], + [60, None], + [1, payment.puzzle_hash, authorized_providers, proofs_checker], + ], + ) + ) eve_cat_puzzle: Program = construct_cat_puzzle( CAT_MOD, tail_hash, @@ -226,11 +230,15 @@ def launch( eve_cat_puzzle_hash: bytes32 = eve_cat_puzzle.get_tree_hash() eve_coin: Coin = Coin(origin_coin.name(), eve_cat_puzzle_hash, payment.amount) - something_b = [ - [51, eve_cat_puzzle_hash, payment.amount], - [61, std_hash(eve_coin.name())], - ] - dpuz: Program = Program.to((1, something_b)) + dpuz: Program = Program.to( + ( + 1, + [ + [51, eve_cat_puzzle_hash, payment.amount], + [61, std_hash(eve_coin.name())], + ], + ) + ) eve_proof: LineageProof = LineageProof( eve_coin.parent_coin_info, diff --git a/chia/wallet/vc_wallet/vc_drivers.py b/chia/wallet/vc_wallet/vc_drivers.py index 457a32d4ea4b..72c5addebf57 100644 --- a/chia/wallet/vc_wallet/vc_drivers.py +++ b/chia/wallet/vc_wallet/vc_drivers.py @@ -383,12 +383,16 @@ def launch( launcher_coin.name(), metadata_layer_hash, # type: ignore ).get_tree_hash_precalc(metadata_layer_hash) - something = [ - [51, wrapped_inner_puzzle_hash, uint64(1), memos], - [1, new_inner_puzzle_hash], - [-10, provider_id, transfer_program.get_tree_hash()], - ] - launch_dpuz: Program = Program.to((1, something)) + launch_dpuz: Program = Program.to( + ( + 1, + [ + [51, wrapped_inner_puzzle_hash, uint64(1), memos], + [1, new_inner_puzzle_hash], + [-10, provider_id, transfer_program.get_tree_hash()], + ], + ) + ) second_launcher_solution = Program.to([launch_dpuz, None]) second_launcher_coin: Coin = Coin( launcher_coin.name(), From d79ac98c017af255c54e9e2af85e0d979bde3f19 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Mon, 25 Mar 2024 15:01:14 -0400 Subject: [PATCH 31/34] `announcement_assertions: List[Program]` --- chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py index 63ec88e1c922..8e8f26204c89 100644 --- a/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +++ b/chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py @@ -117,10 +117,10 @@ def generate_secure_bundle( offered_amount: uint64, tail_str: Optional[str] = None, ) -> SpendBundle: - announcement_assertions: List[Any] = [a.to_program() for a in announcements] + announcement_assertions: List[Program] = [a.to_program() for a in announcements] selected_coin_amount = sum([c.amount for c in selected_coins]) non_primaries = [] if len(selected_coins) < 2 else selected_coins[1:] - inner_solution: List[List[Any]] = [ + inner_solution: List[Any] = [ [51, Offer.ph(), offered_amount], # Offered coin [51, acs_ph, uint64(selected_coin_amount - offered_amount)], # Change *announcement_assertions, From 061eaa10451fabfb3bdbbb99b51c74d06f49d183 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Tue, 2 Apr 2024 13:41:39 -0400 Subject: [PATCH 32/34] Update chia/types/blockchain_format/program.py --- chia/types/blockchain_format/program.py | 1 - 1 file changed, 1 deletion(-) diff --git a/chia/types/blockchain_format/program.py b/chia/types/blockchain_format/program.py index 6e90fc736911..864936a16fc1 100644 --- a/chia/types/blockchain_format/program.py +++ b/chia/types/blockchain_format/program.py @@ -240,7 +240,6 @@ def _sexp_replace(sexp: T_CLVMStorage, to_sexp: Callable[[Any], T_Program], **kw if "" in kwargs: if len(kwargs) > 1: raise ValueError("conflicting paths") - # yes, the terminal case is hinted incorrectly for now return kwargs[""] # we've confirmed that no `kwargs` is the empty string. From 63858f197ddc0c205f4eaaa3d5c2dbbbc7cc70b8 Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Tue, 7 May 2024 09:37:07 -0400 Subject: [PATCH 33/34] more --- chia/pools/pool_puzzles.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chia/pools/pool_puzzles.py b/chia/pools/pool_puzzles.py index aeee2c59a5ab..8283194d0a46 100644 --- a/chia/pools/pool_puzzles.py +++ b/chia/pools/pool_puzzles.py @@ -110,7 +110,8 @@ def get_delayed_puz_info_from_launcher_spend(coinsol: CoinSpend) -> Tuple[uint64 if key.atom == b"t": seconds = uint64(value.as_int()) if key.atom == b"h": - delayed_puzzle_hash = bytes32(value.as_atom()) + assert value.atom is not None + delayed_puzzle_hash = bytes32(value.atom) assert seconds is not None assert delayed_puzzle_hash is not None return seconds, delayed_puzzle_hash From e265924f32e323e455d5c3f7ff7e01f01be4ae7f Mon Sep 17 00:00:00 2001 From: Kyle Altendorf Date: Tue, 7 May 2024 14:31:24 -0400 Subject: [PATCH 34/34] clvm==0.9.10 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ede3b31f0eab..9b28691131d3 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ "chiavdf==1.1.4", # timelord and vdf verification "chiabip158==1.5.1", # bip158-style wallet filters "chiapos==2.0.4", # proof of space - "clvm @ git+https://github.com/chia-network/clvm@mypie", + "clvm==0.9.10", "clvm_tools==0.4.9", # Currying, Program.to, other conveniences "chia_rs==0.7.0", "clvm-tools-rs==0.1.40", # Rust implementation of clvm_tools' compiler