diff --git a/benchmarks/address_manager_store.py b/benchmarks/address_manager_store.py index 13b64d5314..7f2b5e38c7 100644 --- a/benchmarks/address_manager_store.py +++ b/benchmarks/address_manager_store.py @@ -22,7 +22,7 @@ from chia.util.files import write_file_async def generate_random_ip(rand: random.Random) -> str: - return str(IPv4Address(rand.getrandbits(32))) + return str(IPv4Address(rand.randbytes(4))) def populate_address_manager(num_new: int = 500000, num_tried: int = 200000) -> AddressManager: diff --git a/benchmarks/block_store.py b/benchmarks/block_store.py index 7b37800046..e036b2e6f8 100644 --- a/benchmarks/block_store.py +++ b/benchmarks/block_store.py @@ -25,7 +25,6 @@ from chia_rs.sized_ints import uint8, uint32, uint64, uint128 from benchmarks.utils import setup_db from chia._tests.util.benchmarks import ( clvm_generator, - rand_bytes, rand_class_group_element, rand_g1, rand_g2, @@ -110,7 +109,7 @@ async def run_add_block_benchmark(version: int) -> None: rand_hash() if not has_pool_pk else None, rand_g1(), # plot_public_key uint8(32), - rand_bytes(8 * 32), + random.randbytes(8 * 32), ) reward_chain_block = RewardChainBlock( diff --git a/benchmarks/streamable.py b/benchmarks/streamable.py index 5024e1efdd..d7d8a4a8f0 100644 --- a/benchmarks/streamable.py +++ b/benchmarks/streamable.py @@ -1,6 +1,7 @@ from __future__ import annotations import json +import random import sys from dataclasses import dataclass from enum import Enum @@ -14,7 +15,7 @@ from chia_rs.sized_bytes import bytes32 from chia_rs.sized_ints import uint8, uint64 from benchmarks.utils import EnumType, get_commit_hash -from chia._tests.util.benchmarks import rand_bytes, rand_full_block, rand_hash +from chia._tests.util.benchmarks import rand_full_block, rand_hash from chia.util.streamable import Streamable, streamable # to run this benchmark: @@ -50,13 +51,13 @@ class BenchmarkClass(Streamable): def get_random_inner() -> BenchmarkInner: - return BenchmarkInner(rand_bytes(20).hex()) + return BenchmarkInner(random.randbytes(20).hex()) def get_random_middle() -> BenchmarkMiddle: a: uint64 = uint64(10) b: list[bytes32] = [rand_hash() for _ in range(a)] - c: tuple[str, bool, uint8, list[bytes]] = ("benchmark", False, uint8(1), [rand_bytes(a) for _ in range(a)]) + c: tuple[str, bool, uint8, list[bytes]] = ("benchmark", False, uint8(1), [random.randbytes(a) for _ in range(a)]) d: tuple[BenchmarkInner, BenchmarkInner] = (get_random_inner(), get_random_inner()) e: BenchmarkInner = get_random_inner() return BenchmarkMiddle(a, b, c, d, e) diff --git a/build_scripts/check_dependency_artifacts.py b/build_scripts/check_dependency_artifacts.py index 408970b649..5f59e2a3e2 100644 --- a/build_scripts/check_dependency_artifacts.py +++ b/build_scripts/check_dependency_artifacts.py @@ -13,6 +13,7 @@ excepted_packages = { "chialisp_loader", "chialisp_puzzles", "chia_base", + "keyrings.cryptfile", } @@ -36,7 +37,7 @@ def main() -> int: artifact_directory_path = directory_path.joinpath("artifacts") artifact_directory_path.mkdir() - extras = ["upnp"] + extras = ["dev", "legacy-keyring", "upnp"] print("Downloading packages for Python version:") lines = [ diff --git a/chia/_tests/core/consensus/test_pot_iterations.py b/chia/_tests/core/consensus/test_pot_iterations.py index 6dcf1ecea0..68c5d77c8e 100644 --- a/chia/_tests/core/consensus/test_pot_iterations.py +++ b/chia/_tests/core/consensus/test_pot_iterations.py @@ -7,7 +7,6 @@ from pytest import raises from chia.consensus.default_constants import DEFAULT_CONSTANTS from chia.consensus.pos_quality import _expected_plot_size from chia.consensus.pot_iterations import ( - PHASE_OUT_PERIOD, calculate_ip_iters, calculate_iterations_quality, calculate_phase_out, @@ -135,14 +134,16 @@ class TestPotIterations: # after HARD_FORK2_HEIGHT, should return value = delta/phase_out_period * sp_interval assert ( calculate_phase_out(constants, sub_slot_iters, constants.HARD_FORK2_HEIGHT + 1) - == sp_interval // PHASE_OUT_PERIOD + == sp_interval // constants.PLOT_V1_PHASE_OUT ) assert ( - calculate_phase_out(constants, sub_slot_iters, constants.HARD_FORK2_HEIGHT + PHASE_OUT_PERIOD // 2) + calculate_phase_out( + constants, sub_slot_iters, constants.HARD_FORK2_HEIGHT + constants.PLOT_V1_PHASE_OUT // 2 + ) == sp_interval // 2 ) assert ( - calculate_phase_out(constants, sub_slot_iters, constants.HARD_FORK2_HEIGHT + PHASE_OUT_PERIOD) + calculate_phase_out(constants, sub_slot_iters, constants.HARD_FORK2_HEIGHT + constants.PLOT_V1_PHASE_OUT) == sp_interval ) diff --git a/chia/_tests/core/custom_types/test_spend_bundle.py b/chia/_tests/core/custom_types/test_spend_bundle.py index d8e4a26ece..8b68bb541b 100644 --- a/chia/_tests/core/custom_types/test_spend_bundle.py +++ b/chia/_tests/core/custom_types/test_spend_bundle.py @@ -28,10 +28,7 @@ class TestStructStream(unittest.TestCase): def rand_hash(rng: random.Random) -> bytes32: - ret = bytearray(32) - for i in range(32): - ret[i] = rng.getrandbits(8) - return bytes32(ret) + return bytes32.random(r=rng) def create_spends(num: int) -> tuple[list[CoinSpend], list[Coin]]: diff --git a/chia/_tests/core/data_layer/test_data_layer_util.py b/chia/_tests/core/data_layer/test_data_layer_util.py index 194f66357f..dd40ab33cc 100644 --- a/chia/_tests/core/data_layer/test_data_layer_util.py +++ b/chia/_tests/core/data_layer/test_data_layer_util.py @@ -158,13 +158,6 @@ def test_internal_hash(seeded_random: Random) -> None: assert definition(left_hash=left_hash, right_hash=right_hash) == reference -def get_random_bytes(length: int, r: Random) -> bytes: - if length == 0: - return b"" - - return r.getrandbits(length * 8).to_bytes(length, "big") - - def test_leaf_hash(seeded_random: Random) -> None: def definition(key: bytes, value: bytes) -> bytes32: return SerializedProgram.to((key, value)).get_tree_hash() @@ -176,13 +169,13 @@ def test_leaf_hash(seeded_random: Random) -> None: else: length = seeded_random.randrange(100) - key = get_random_bytes(length=length, r=seeded_random) + key = seeded_random.randbytes(length) if cycle in {1, 2}: length = 0 else: length = seeded_random.randrange(100) - value = get_random_bytes(length=length, r=seeded_random) + value = seeded_random.randbytes(length) reference = definition(key=key, value=value) data.append((key, value, reference)) @@ -205,7 +198,7 @@ def test_key_hash(seeded_random: Random) -> None: length = 0 else: length = seeded_random.randrange(100) - key = get_random_bytes(length=length, r=seeded_random) + key = seeded_random.randbytes(length) reference = definition(key=key) data.append((key, reference)) diff --git a/chia/_tests/core/data_layer/test_data_store.py b/chia/_tests/core/data_layer/test_data_store.py index 8f65ae76c3..35777e8a7b 100644 --- a/chia/_tests/core/data_layer/test_data_store.py +++ b/chia/_tests/core/data_layer/test_data_store.py @@ -1589,11 +1589,7 @@ async def test_benchmark_batch_insert_speed( r.seed("shadowlands", version=2) changelist = [ - { - "action": "insert", - "key": x.to_bytes(32, byteorder="big", signed=False), - "value": bytes(r.getrandbits(8) for _ in range(1200)), - } + {"action": "insert", "key": x.to_bytes(32, byteorder="big", signed=False), "value": r.randbytes(1200)} for x in range(case.pre + case.count) ] @@ -1637,7 +1633,7 @@ async def test_benchmark_batch_insert_speed_multiple_batches( { "action": "insert", "key": x.to_bytes(32, byteorder="big", signed=False), - "value": bytes(r.getrandbits(8) for _ in range(10000)), + "value": r.randbytes(10000), } for x in range(batch * case.count, (batch + 1) * case.count) ] diff --git a/chia/_tests/core/full_node/stores/test_block_store.py b/chia/_tests/core/full_node/stores/test_block_store.py index a7e8e07f1c..0bf2ba048f 100644 --- a/chia/_tests/core/full_node/stores/test_block_store.py +++ b/chia/_tests/core/full_node/stores/test_block_store.py @@ -369,16 +369,10 @@ async def test_count_uncompactified_blocks(bt: BlockTools, tmp_dir: Path, db_ver async def test_replace_proof(bt: BlockTools, tmp_dir: Path, db_version: int, use_cache: bool) -> None: blocks = bt.get_consecutive_blocks(10) - def rand_bytes(num: int) -> bytes: - ret = bytearray(num) - for i in range(num): - ret[i] = random.getrandbits(8) - return bytes(ret) - def rand_vdf_proof() -> VDFProof: return VDFProof( uint8(1), # witness_type - rand_bytes(32), # witness + random.randbytes(32), # witness bool(random.randint(0, 1)), # normalized_to_identity ) diff --git a/chia/_tests/core/mempool/test_mempool.py b/chia/_tests/core/mempool/test_mempool.py index c770a8140d..92ab029b5f 100644 --- a/chia/_tests/core/mempool/test_mempool.py +++ b/chia/_tests/core/mempool/test_mempool.py @@ -2955,11 +2955,8 @@ def test_timeout(old: bool) -> None: def rand_hash() -> bytes32: - rng = random.Random() - ret = bytearray(32) - for i in range(32): - ret[i] = rng.getrandbits(8) - return bytes32(ret) + # TODO: does this need to be creating a new rng? + return bytes32.random(r=random.Random()) def item_cost(cost: int, fee_rate: float) -> MempoolItem: diff --git a/chia/_tests/core/test_db_conversion.py b/chia/_tests/core/test_db_conversion.py index 539236e45e..d65d9a215e 100644 --- a/chia/_tests/core/test_db_conversion.py +++ b/chia/_tests/core/test_db_conversion.py @@ -20,13 +20,6 @@ from chia.simulator.block_tools import test_constants from chia.util.db_wrapper import DBWrapper2 -def rand_bytes(num) -> bytes: - ret = bytearray(num) - for i in range(num): - ret[i] = random.getrandbits(8) - return bytes(ret) - - @pytest.mark.anyio @pytest.mark.parametrize("with_hints", [True, False]) @pytest.mark.skip("we no longer support DB v1") @@ -35,21 +28,21 @@ async def test_blocks(default_1000_blocks, with_hints: bool): hints: list[tuple[bytes32, bytes]] = [] for i in range(351): - hints.append((bytes32(rand_bytes(32)), rand_bytes(20))) + hints.append((bytes32.random(), random.randbytes(20))) # the v1 schema allows duplicates in the hints table for i in range(10): - coin_id = bytes32(rand_bytes(32)) - hint = rand_bytes(20) + coin_id = bytes32.random() + hint = random.randbytes(20) hints.append((coin_id, hint)) hints.append((coin_id, hint)) for i in range(2000): - hints.append((bytes32(rand_bytes(32)), rand_bytes(20))) + hints.append((bytes32.random(), random.randbytes(20))) for i in range(5): - coin_id = bytes32(rand_bytes(32)) - hint = rand_bytes(20) + coin_id = bytes32.random() + hint = random.randbytes(20) hints.append((coin_id, hint)) hints.append((coin_id, hint)) diff --git a/chia/_tests/core/test_db_validation.py b/chia/_tests/core/test_db_validation.py index 799fc0ca3d..fef9eb86de 100644 --- a/chia/_tests/core/test_db_validation.py +++ b/chia/_tests/core/test_db_validation.py @@ -1,6 +1,5 @@ from __future__ import annotations -import random import sqlite3 from contextlib import closing from pathlib import Path @@ -25,10 +24,7 @@ from chia.util.db_wrapper import DBWrapper2 def rand_hash() -> bytes32: - ret = bytearray(32) - for i in range(32): - ret[i] = random.getrandbits(8) - return bytes32(ret) + return bytes32.random() def make_version(conn: sqlite3.Connection, version: int) -> None: diff --git a/chia/_tests/core/test_full_node_rpc.py b/chia/_tests/core/test_full_node_rpc.py index 38e7badc27..4df0ef30b2 100644 --- a/chia/_tests/core/test_full_node_rpc.py +++ b/chia/_tests/core/test_full_node_rpc.py @@ -88,8 +88,8 @@ async def test1( peak_block = await client.get_block(state["peak"].header_hash) assert peak_block == blocks[-1] - assert (await client.get_block(bytes32([1] * 32))) is None - + with pytest.raises(ValueError, match="not found"): + await client.get_block(bytes32([1] * 32)) block_record = await client.get_block_record_by_height(2) assert block_record is not None assert block_record.header_hash == blocks[2].header_hash @@ -150,8 +150,10 @@ async def test1( assert len(await client.get_all_mempool_items()) == 0 assert len(await client.get_all_mempool_tx_ids()) == 0 - assert (await client.get_mempool_item_by_tx_id(spend_bundle.name())) is None - assert (await client.get_mempool_item_by_tx_id(spend_bundle.name(), False)) is None + with pytest.raises(ValueError, match="not in the mempool"): + await client.get_mempool_item_by_tx_id(spend_bundle.name()) + with pytest.raises(ValueError, match="not in the mempool"): + await client.get_mempool_item_by_tx_id(spend_bundle.name(), False) await client.push_tx(spend_bundle) coin = spend_bundle.additions()[0] @@ -168,7 +170,8 @@ async def test1( mempool_item = await client.get_mempool_item_by_tx_id(spend_bundle.name()) assert mempool_item is not None assert WalletSpendBundle.from_json_dict(mempool_item["spend_bundle"]) == spend_bundle - assert (await client.get_coin_record_by_name(coin.name())) is None + with pytest.raises(ValueError, match="not found"): + await client.get_coin_record_by_name(coin.name()) # Verify that the include_pending arg to get_mempool_item_by_tx_id works coin_to_spend_pending = included_reward_coins[1] @@ -181,11 +184,11 @@ async def test1( condition_dic=condition_dic, ) await client.push_tx(spend_bundle_pending) - # not strictly in the mempool - assert (await client.get_mempool_item_by_tx_id(spend_bundle_pending.name(), False)) is None + with pytest.raises(ValueError, match="not in the mempool"): + # not strictly in the mempool + await client.get_mempool_item_by_tx_id(spend_bundle_pending.name(), False) # pending entry into mempool, so include_pending fetches mempool_item = await client.get_mempool_item_by_tx_id(spend_bundle_pending.name(), True) - assert mempool_item is not None assert WalletSpendBundle.from_json_dict(mempool_item["spend_bundle"]) == spend_bundle_pending await full_node_api_1.farm_new_transaction_block(FarmNewBlockProtocol(ph_2)) @@ -454,17 +457,15 @@ async def test_signage_points( full_node_service_1.config, ) as client: # Only provide one - res = await client.get_recent_signage_point_or_eos(None, None) - assert res is None - res = await client.get_recent_signage_point_or_eos(std_hash(b"0"), std_hash(b"1")) - assert res is None - + with pytest.raises(ValueError, match="sp_hash or challenge_hash must be provided."): + await client.get_recent_signage_point_or_eos(None, None) + with pytest.raises(ValueError, match="Either sp_hash or challenge_hash must be provided, not both."): + await client.get_recent_signage_point_or_eos(std_hash(b"0"), std_hash(b"1")) # Not found - res = await client.get_recent_signage_point_or_eos(std_hash(b"0"), None) - assert res is None - res = await client.get_recent_signage_point_or_eos(None, std_hash(b"0")) - assert res is None - + with pytest.raises(ValueError, match="in cache"): + await client.get_recent_signage_point_or_eos(std_hash(b"0"), None) + with pytest.raises(ValueError, match="in cache"): + await client.get_recent_signage_point_or_eos(None, std_hash(b"0")) blocks = bt.get_consecutive_blocks(5) for block in blocks: await full_node_api_1.full_node.add_block(block) @@ -494,8 +495,8 @@ async def test_signage_points( assert sp.rc_proof is not None assert sp.rc_vdf is not None # Don't have SP yet - res = await client.get_recent_signage_point_or_eos(sp.cc_vdf.output.get_hash(), None) - assert res is None + with pytest.raises(ValueError, match="Did not find sp"): + await client.get_recent_signage_point_or_eos(sp.cc_vdf.output.get_hash(), None) # Add the last block await full_node_api_1.full_node.add_block(blocks[-1]) @@ -517,9 +518,8 @@ async def test_signage_points( selected_eos = blocks[-1].finished_sub_slots[0] # Don't have EOS yet - res = await client.get_recent_signage_point_or_eos(None, selected_eos.challenge_chain.get_hash()) - assert res is None - + with pytest.raises(ValueError, match="Did not find eos"): + await client.get_recent_signage_point_or_eos(None, selected_eos.challenge_chain.get_hash()) # Properly fetch an EOS for eos in blocks[-1].finished_sub_slots: await full_node_api_1.full_node.add_end_of_sub_slot(eos, peer) diff --git a/chia/_tests/core/test_merkle_set.py b/chia/_tests/core/test_merkle_set.py index 9bb0d12c7b..c8f87e866d 100644 --- a/chia/_tests/core/test_merkle_set.py +++ b/chia/_tests/core/test_merkle_set.py @@ -279,10 +279,7 @@ async def test_merkle_right_edge() -> None: def rand_hash(rng: random.Random) -> bytes32: - ret = bytearray(32) - for i in range(32): - ret[i] = rng.getrandbits(8) - return bytes32(ret) + return bytes32.random(r=rng) @pytest.mark.anyio diff --git a/chia/_tests/core/util/test_streamable.py b/chia/_tests/core/util/test_streamable.py index 809f945779..b75aaddfe8 100644 --- a/chia/_tests/core/util/test_streamable.py +++ b/chia/_tests/core/util/test_streamable.py @@ -372,7 +372,7 @@ def test_not_lists() -> None: def test_basic_optional() -> None: assert is_type_SpecificOptional(Optional[int]) - assert is_type_SpecificOptional(Optional[Optional[int]]) + assert is_type_SpecificOptional(Optional[int]) assert not is_type_SpecificOptional(list[int]) @@ -398,8 +398,8 @@ class PostInitTestClassBad(Streamable): class PostInitTestClassOptional(Streamable): a: Optional[uint8] b: Optional[uint8] - c: Optional[Optional[uint8]] - d: Optional[Optional[uint8]] + c: Optional[uint8] + d: Optional[uint8] @streamable diff --git a/chia/_tests/util/benchmarks.py b/chia/_tests/util/benchmarks.py index 8ba48cf743..7cfd765898 100644 --- a/chia/_tests/util/benchmarks.py +++ b/chia/_tests/util/benchmarks.py @@ -40,29 +40,22 @@ def rewards(height: uint32) -> tuple[Coin, Coin]: return farmer_coin, pool_coin -def rand_bytes(num: int) -> bytes: - ret = bytearray(num) - for i in range(num): - ret[i] = random.getrandbits(8) - return bytes(ret) - - def rand_hash() -> bytes32: - return bytes32(rand_bytes(32)) + return bytes32.random() def rand_g1() -> G1Element: - sk = AugSchemeMPL.key_gen(rand_bytes(96)) + sk = AugSchemeMPL.key_gen(random.randbytes(96)) return sk.get_g1() def rand_g2() -> G2Element: - sk = AugSchemeMPL.key_gen(rand_bytes(96)) + sk = AugSchemeMPL.key_gen(random.randbytes(96)) return AugSchemeMPL.sign(sk, b"foobar") def rand_class_group_element() -> ClassgroupElement: - return ClassgroupElement(bytes100(rand_bytes(100))) + return ClassgroupElement(bytes100.random()) def rand_vdf() -> VDFInfo: @@ -84,7 +77,7 @@ def rand_full_block() -> FullBlock: None, rand_g1(), uint8(0), - rand_bytes(8 * 32), + random.randbytes(8 * 32), ) reward_chain_block = RewardChainBlock( diff --git a/chia/_tests/util/test_full_block_utils.py b/chia/_tests/util/test_full_block_utils.py index 026ef6f5d6..7dcfb91683 100644 --- a/chia/_tests/util/test_full_block_utils.py +++ b/chia/_tests/util/test_full_block_utils.py @@ -26,7 +26,7 @@ from chia_rs import ( from chia_rs.sized_bytes import bytes32 from chia_rs.sized_ints import uint8, uint32, uint64, uint128 -from chia._tests.util.benchmarks import rand_bytes, rand_g1, rand_g2, rand_hash, rand_vdf, rand_vdf_proof, rewards +from chia._tests.util.benchmarks import rand_g1, rand_g2, rand_hash, rand_vdf, rand_vdf_proof, rewards from chia.consensus.generator_tools import get_block_header from chia.full_node.full_block_utils import ( block_info_from_block, @@ -73,7 +73,7 @@ def get_proof_of_space() -> Generator[ProofOfSpace, None, None]: plot_hash, g1(), # plot_public_key uint8(32), - rand_bytes(8 * 32), + random.randbytes(8 * 32), ) diff --git a/chia/_tests/wallet/did_wallet/test_did.py b/chia/_tests/wallet/did_wallet/test_did.py index cf36960abb..0fe6677d79 100644 --- a/chia/_tests/wallet/did_wallet/test_did.py +++ b/chia/_tests/wallet/did_wallet/test_did.py @@ -2,7 +2,7 @@ from __future__ import annotations import dataclasses import json -from typing import Any, Optional, Union +from typing import Any import pytest from chia_rs import AugSchemeMPL, G1Element, G2Element @@ -24,12 +24,7 @@ from chia.types.peer_info import PeerInfo from chia.types.signing_mode import CHIP_0002_SIGN_MESSAGE_PREFIX from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash from chia.wallet.did_wallet.did_wallet import DIDWallet -from chia.wallet.did_wallet.did_wallet_puzzles import ( - DID_INNERPUZ_MOD, -) from chia.wallet.singleton import ( - SINGLETON_LAUNCHER_PUZZLE_HASH, - SINGLETON_TOP_LAYER_MOD_HASH, create_singleton_puzzle, ) from chia.wallet.util.address_type import AddressType @@ -38,9 +33,8 @@ from chia.wallet.util.wallet_types import WalletType from chia.wallet.wallet import Wallet from chia.wallet.wallet_action_scope import WalletActionScope from chia.wallet.wallet_node import WalletNode -from chia.wallet.wallet_request_types import DIDFindLostDID, DIDGetCurrentCoinInfo, DIDGetInfo, DIDGetRecoveryInfo +from chia.wallet.wallet_request_types import DIDFindLostDID, DIDGetCurrentCoinInfo, DIDGetInfo from chia.wallet.wallet_rpc_api import WalletRpcApi -from chia.wallet.wallet_spend_bundle import WalletSpendBundle async def get_wallet_num(wallet_manager): @@ -56,34 +50,12 @@ async def make_did_wallet( wallet: Wallet, amount: uint64, action_scope: WalletActionScope, - recovery_list: list[bytes32] = [], metadata: dict[str, str] = {}, fee: uint64 = uint64(0), - use_alternate_recovery: bool = False, ) -> DIDWallet: - def alt_create_innerpuz( - p2_puzzle_or_hash: Union[Program, bytes32], - recovery_list: list[bytes32], - num_of_backup_ids_needed: uint64, - launcher_id: bytes32, - metadata: Program = Program.to([]), - recovery_list_hash: Optional[Program] = None, - ) -> Program: - # override the default of NIL_TREEHASH with NIL to match other wallet implementations - nil_recovery = Program.to(None) - singleton_struct = Program.to((SINGLETON_TOP_LAYER_MOD_HASH, (launcher_id, SINGLETON_LAUNCHER_PUZZLE_HASH))) - return DID_INNERPUZ_MOD.curry(p2_puzzle_or_hash, nil_recovery, 0, singleton_struct, metadata) - - if use_alternate_recovery: - with pytest.MonkeyPatch.context() as m: - m.setattr("chia.wallet.did_wallet.did_wallet_puzzles.create_innerpuz", alt_create_innerpuz) - did_wallet = await DIDWallet.create_new_did_wallet( - wallet_state_manager, wallet, uint64(101), action_scope, metadata=metadata, fee=fee - ) - else: - did_wallet = await DIDWallet.create_new_did_wallet( - wallet_state_manager, wallet, amount, action_scope, backups_ids=recovery_list, metadata=metadata, fee=fee - ) + did_wallet = await DIDWallet.create_new_did_wallet( + wallet_state_manager, wallet, amount, action_scope, metadata=metadata, fee=fee + ) return did_wallet @@ -94,16 +66,11 @@ async def make_did_wallet( "trusted", [True, False], ) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio async def test_creation_from_coin_spend( self_hostname: str, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted: bool, - use_alternate_recovery: bool, ) -> None: """ Verify that DIDWallet.create_new_did_wallet_from_coin_spend() is called after Singleton creation on @@ -151,12 +118,10 @@ async def test_creation_from_coin_spend( wallet_0, uint64(101), action_scope, - use_alternate_recovery=use_alternate_recovery, ) with pytest.raises(RuntimeError): assert await did_wallet_0.get_coin() == set() - assert await did_wallet_0.get_info_for_recovery() is None await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1]) @@ -187,15 +152,9 @@ async def test_creation_from_coin_spend( ], indirect=True, ) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio @pytest.mark.limit_consensus_modes(reason="irrelevant") -async def test_creation_from_backup_file( - wallet_environments: WalletTestFramework, use_alternate_recovery: bool -) -> None: +async def test_creation_from_backup_file(wallet_environments: WalletTestFramework) -> None: env_0 = wallet_environments.environments[0] env_1 = wallet_environments.environments[1] env_2 = wallet_environments.environments[2] @@ -220,7 +179,6 @@ async def test_creation_from_backup_file( env_0.xch_wallet, uint64(101), action_scope, - use_alternate_recovery=use_alternate_recovery, ) await wallet_environments.process_pending_states( @@ -270,12 +228,9 @@ async def test_creation_from_backup_file( ] ) - # Wallet1 sets up DIDWallet_1 with DIDWallet_0 as backup - backup_ids = [bytes32.from_hexstr(did_wallet_0.get_my_DID())] - async with env_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( - env_1.wallet_state_manager, env_1.xch_wallet, uint64(201), action_scope, backup_ids + env_1.wallet_state_manager, env_1.xch_wallet, uint64(201), action_scope ) await wallet_environments.process_pending_states( @@ -335,539 +290,19 @@ async def test_creation_from_backup_file( backup_data=backup_data, ) did_wallet_2 = env_2.wallet_state_manager.get_wallet(id=uint32(2), required_type=DIDWallet) - recovery_info = await env_2.rpc_client.did_get_recovery_info( - DIDGetRecoveryInfo(uint32(env_2.wallet_aliases["did"])) - ) - assert recovery_info.wallet_id == env_2.wallet_aliases["did"] - assert recovery_info.backup_dids == backup_ids current_coin_info_response = await env_0.rpc_client.did_get_current_coin_info( DIDGetCurrentCoinInfo(uint32(env_0.wallet_aliases["did"])) ) - # TODO: this check is kind of weak, we should research when this endpoint might actually be useful assert current_coin_info_response.wallet_id == env_0.wallet_aliases["did"] - async with env_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - assert recovery_info.pubkey is not None - assert recovery_info.newpuzhash is not None - message_spend_bundle, attest_data = await did_wallet_0.create_attestment( - recovery_info.coin_name, recovery_info.newpuzhash, recovery_info.pubkey, action_scope - ) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "spendable_balance": -101, - "pending_change": 101, - "pending_coin_removal_count": 1, - "max_send_amount": -101, - } - }, - post_block_balance_updates={ - "did": { - "spendable_balance": 101, - "pending_change": -101, - "pending_coin_removal_count": -1, - "max_send_amount": 101, - } - }, - ), - WalletStateTransition( - pre_block_balance_updates={}, - post_block_balance_updates={}, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "init": True, - } - }, - post_block_balance_updates={}, - ), - ] - ) - - ( - test_info_list, - test_message_spend_bundle, - ) = await did_wallet_2.load_attest_files_for_recovery_spend([attest_data]) - assert message_spend_bundle == test_message_spend_bundle - - async with env_2.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - assert did_wallet_2.did_info.temp_coin is not None - await did_wallet_2.recovery_spend( - did_wallet_2.did_info.temp_coin, - recovery_info.newpuzhash, - test_info_list, - recovery_info.pubkey, - test_message_spend_bundle, - action_scope, - ) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={}, - post_block_balance_updates={}, - ), - WalletStateTransition( - pre_block_balance_updates={}, - post_block_balance_updates={ - "did": { - "confirmed_wallet_balance": -201, - "unconfirmed_wallet_balance": -201, - "spendable_balance": -201, - "max_send_amount": -201, - "unspent_coin_count": -1, - } - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "unconfirmed_wallet_balance": 201, - "pending_coin_removal_count": 2, - } - }, - post_block_balance_updates={ - "did": { - "confirmed_wallet_balance": 201, - "spendable_balance": 201, - "max_send_amount": 201, - "unspent_coin_count": 1, - "pending_coin_removal_count": -2, - } - }, - ), - ] - ) for wallet in [did_wallet_0, did_wallet_1, did_wallet_2]: assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet - some_ph = bytes32(32 * b"\2") - async with env_2.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - await did_wallet_2.create_exit_spend(some_ph, action_scope) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={}, - post_block_balance_updates={}, - ), - WalletStateTransition( - pre_block_balance_updates={}, - post_block_balance_updates={}, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "unconfirmed_wallet_balance": -201, - "spendable_balance": -201, - "max_send_amount": -201, - "pending_coin_removal_count": 1, - } - }, - post_block_balance_updates={ - "did": { - "confirmed_wallet_balance": -201, - "unspent_coin_count": -1, - "pending_coin_removal_count": -1, - } - }, - ), - ] - ) - - async def get_coins_with_ph() -> bool: - coins = await wallet_environments.full_node.full_node.coin_store.get_coin_records_by_puzzle_hash(True, some_ph) - return len(coins) == 1 - - await time_out_assert(15, get_coins_with_ph, True) - - for wallet in [did_wallet_0, did_wallet_1]: - assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet - - -@pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") -@pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) -@pytest.mark.anyio -async def test_did_recovery_with_multiple_backup_dids( - wallet_environments: WalletTestFramework, use_alternate_recovery: bool -) -> None: - env_0 = wallet_environments.environments[0] - env_1 = wallet_environments.environments[1] - wallet_node_0 = env_0.node - wallet_node_1 = env_1.node - wallet_0 = env_0.xch_wallet - wallet_1 = env_1.xch_wallet - - env_0.wallet_aliases = { - "xch": 1, - "did": 2, - } - env_1.wallet_aliases = { - "xch": 1, - "did": 2, - } - - async with wallet_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - did_wallet: DIDWallet = await make_did_wallet( - wallet_node_0.wallet_state_manager, - wallet_0, - uint64(101), - action_scope, - use_alternate_recovery=use_alternate_recovery, - ) - assert did_wallet.get_name() == "Profile 1" - recovery_list = [bytes32.from_hexstr(did_wallet.get_my_DID())] - - async with wallet_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet( - wallet_node_1.wallet_state_manager, wallet_1, uint64(101), action_scope, recovery_list - ) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "init": True, - "unconfirmed_wallet_balance": 101, - "pending_change": 101, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "confirmed_wallet_balance": 101, - "spendable_balance": 101, - "max_send_amount": 101, - "unspent_coin_count": 1, - "pending_change": -101, - "pending_coin_removal_count": -1, - }, - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "init": True, - "unconfirmed_wallet_balance": 101, - "pending_change": 101, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "confirmed_wallet_balance": 101, - "spendable_balance": 101, - "max_send_amount": 101, - "unspent_coin_count": 1, - "pending_change": -101, - "pending_coin_removal_count": -1, - }, - }, - ), - ] - ) - assert did_wallet_2.did_info.backup_ids == recovery_list - - recovery_list.append(bytes32.from_hexstr(did_wallet_2.get_my_DID())) - - async with wallet_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - did_wallet_3: DIDWallet = await DIDWallet.create_new_did_wallet( - wallet_node_1.wallet_state_manager, wallet_1, uint64(201), action_scope, recovery_list - ) - - env_1.wallet_aliases["did_2"] = 3 - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={}, - post_block_balance_updates={}, - ), - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "set_remainder": True, - }, - "did_2": { - "init": True, - "unconfirmed_wallet_balance": 201, - "pending_change": 201, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "set_remainder": True, - }, - "did_2": { - "confirmed_wallet_balance": 201, - "spendable_balance": 201, - "max_send_amount": 201, - "unspent_coin_count": 1, - "pending_change": -201, - "pending_coin_removal_count": -1, - }, - }, - ), - ] - ) - coin = await did_wallet_3.get_coin() - - backup_data = did_wallet_3.create_backup() - - async with wallet_node_0.wallet_state_manager.lock: - did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery( - wallet_node_0.wallet_state_manager, - wallet_0, - backup_data, - ) - assert did_wallet_4.get_name() == "Profile 2" - env_0.wallet_aliases["did_2"] = 3 - - pubkey = (await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)).pubkey - new_ph = did_wallet_4.did_info.temp_puzhash - async with did_wallet.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - message_spend_bundle, attest1 = await did_wallet.create_attestment(coin.name(), new_ph, pubkey, action_scope) - - async with did_wallet_2.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope_2: - message_spend_bundle2, attest2 = await did_wallet_2.create_attestment( - coin.name(), new_ph, pubkey, action_scope_2 - ) - - message_spend_bundle = message_spend_bundle.aggregate([message_spend_bundle, message_spend_bundle2]) - - ( - test_info_list, - test_message_spend_bundle, - ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1, attest2]) - assert message_spend_bundle == test_message_spend_bundle - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "spendable_balance": -101, - "pending_change": 101, - "max_send_amount": -101, - "pending_coin_removal_count": 1, - "set_remainder": True, - }, - "did_2": { - "init": True, - "unconfirmed_wallet_balance": 0, - "pending_change": 0, - "pending_coin_removal_count": 0, - }, - }, - post_block_balance_updates={ - "did": { - "spendable_balance": 101, - "pending_change": -101, - "max_send_amount": 101, - "pending_coin_removal_count": -1, - }, - "did_2": { - "confirmed_wallet_balance": 0, - "spendable_balance": 0, - "max_send_amount": 0, - "unspent_coin_count": 0, - "pending_change": 0, - "pending_coin_removal_count": 0, - }, - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "spendable_balance": -101, - "pending_change": 101, - "max_send_amount": -101, - "pending_coin_removal_count": 1, - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did": { - "spendable_balance": 101, - "pending_change": -101, - "max_send_amount": 101, - "pending_coin_removal_count": -1, - }, - }, - ), - ] - ) - - async with did_wallet_4.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, message_spend_bundle, action_scope) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did_2": { - "unconfirmed_wallet_balance": 201, - "pending_change": 0, - "pending_coin_removal_count": 3, - }, - }, - post_block_balance_updates={ - "did_2": { - "confirmed_wallet_balance": 201, - "spendable_balance": 201, - "max_send_amount": 201, - "unspent_coin_count": 1, - "pending_change": 0, - "pending_coin_removal_count": -3, - }, - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did_2": { - "unconfirmed_wallet_balance": 0, # TODO: fix pre-block balances for recovery - "spendable_balance": 0, - "pending_change": 0, - "max_send_amount": 0, - "pending_coin_removal_count": 0, - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did_2": { - "confirmed_wallet_balance": -201, - "spendable_balance": -201, - "max_send_amount": -201, - "unspent_coin_count": -1, - "set_remainder": True, - }, - }, - ), - ] - ) - - for wallet in [did_wallet, did_wallet_2, did_wallet_3, did_wallet_4]: - assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet - @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio -async def test_did_recovery_with_empty_set(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): - env_0 = wallet_environments.environments[0] - wallet_node_0 = env_0.node - wallet_0 = env_0.xch_wallet - - env_0.wallet_aliases = { - "xch": 1, - "did": 2, - } - - async with wallet_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet_0.wallet_state_manager) - - async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - did_wallet: DIDWallet = await make_did_wallet( - wallet_node_0.wallet_state_manager, - wallet_0, - uint64(101), - action_scope, - use_alternate_recovery=use_alternate_recovery, - ) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "init": True, - "unconfirmed_wallet_balance": 101, - "pending_change": 101, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "confirmed_wallet_balance": 101, - "spendable_balance": 101, - "max_send_amount": 101, - "unspent_coin_count": 1, - "pending_change": -101, - "pending_coin_removal_count": -1, - }, - }, - ), - ] - ) - coin = await did_wallet.get_coin() - info: list[tuple[bytes, bytes, int]] = [] - pubkey = (await did_wallet.wallet_state_manager.get_unused_derivation_record(did_wallet.wallet_info.id)).pubkey - with pytest.raises(Exception): # We expect a CLVM 80 error for this test - async with did_wallet.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=False - ) as action_scope: - await did_wallet.recovery_spend( - coin, - ph, - info, - pubkey, - WalletSpendBundle([], AugSchemeMPL.aggregate([])), - action_scope, - ) - - -@pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") -@pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) -@pytest.mark.anyio -async def test_did_find_lost_did(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): +async def test_did_find_lost_did(wallet_environments: WalletTestFramework): env_0 = wallet_environments.environments[0] wallet_node_0 = env_0.node wallet_0 = env_0.xch_wallet @@ -883,7 +318,6 @@ async def test_did_find_lost_did(wallet_environments: WalletTestFramework, use_a wallet_0, uint64(101), action_scope, - use_alternate_recovery=use_alternate_recovery, ) await wallet_environments.process_pending_states( @@ -950,9 +384,6 @@ async def test_did_find_lost_did(wallet_environments: WalletTestFramework, use_a await env_0.check_balances() # Spend DID - recovery_list = [bytes32.fromhex(did_wallet.get_my_DID())] - await did_wallet.update_recovery_list(recovery_list, uint64(1)) - assert did_wallet.did_info.backup_ids == recovery_list async with did_wallet.wallet_state_manager.new_action_scope( wallet_environments.tx_config, push=True ) as action_scope: @@ -1000,12 +431,8 @@ async def test_did_find_lost_did(wallet_environments: WalletTestFramework, use_a @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio -async def test_did_attest_after_recovery(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): +async def test_did_transfer(wallet_environments: WalletTestFramework): env_0 = wallet_environments.environments[0] env_1 = wallet_environments.environments[1] wallet_node_0 = env_0.node @@ -1021,330 +448,6 @@ async def test_did_attest_after_recovery(wallet_environments: WalletTestFramewor "xch": 1, "did": 2, } - - async with wallet_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - did_wallet: DIDWallet = await make_did_wallet( - wallet_node_0.wallet_state_manager, - wallet_0, - uint64(101), - action_scope, - use_alternate_recovery=use_alternate_recovery, - ) - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "init": True, - "unconfirmed_wallet_balance": 101, - "pending_change": 101, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "confirmed_wallet_balance": 101, - "spendable_balance": 101, - "max_send_amount": 101, - "unspent_coin_count": 1, - "pending_change": -101, - "pending_coin_removal_count": -1, - }, - }, - ), - WalletStateTransition(), - ] - ) - - await time_out_assert(15, did_wallet.get_confirmed_balance, 101) - await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101) - recovery_list = [bytes32.from_hexstr(did_wallet.get_my_DID())] - - async with wallet_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet( - wallet_node_1.wallet_state_manager, wallet_1, uint64(101), action_scope, recovery_list - ) - await wallet_environments.process_pending_states( - [ - WalletStateTransition(), - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "init": True, - "unconfirmed_wallet_balance": 101, - "pending_change": 101, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "confirmed_wallet_balance": 101, - "spendable_balance": 101, - "max_send_amount": 101, - "unspent_coin_count": 1, - "pending_change": -101, - "pending_coin_removal_count": -1, - }, - }, - ), - ] - ) - - assert did_wallet_2.did_info.backup_ids == recovery_list - - # Update coin with new ID info - recovery_list = [bytes32.from_hexstr(did_wallet_2.get_my_DID())] - await did_wallet.update_recovery_list(recovery_list, uint64(1)) - assert did_wallet.did_info.backup_ids == recovery_list - async with did_wallet.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - await did_wallet.create_update_spend(action_scope) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "set_remainder": True, - } - }, - post_block_balance_updates={ - "did": { - "set_remainder": True, - } - }, - ), - WalletStateTransition(), - ] - ) - - # DID Wallet 2 recovers into DID Wallet 3 with new innerpuz - backup_data = did_wallet_2.create_backup() - - async with wallet_node_0.wallet_state_manager.lock: - did_wallet_3 = await DIDWallet.create_new_did_wallet_from_recovery( - wallet_node_0.wallet_state_manager, - wallet_0, - backup_data, - ) - env_0.wallet_aliases["did_2"] = 3 - with wallet_environments.new_puzzle_hashes_allowed(): - async with did_wallet_3.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - new_ph = ( - await did_wallet_3.get_did_innerpuz(action_scope, override_reuse_puzhash_with=False) - ).get_tree_hash() - coin = await did_wallet_2.get_coin() - pubkey = (await did_wallet_3.wallet_state_manager.get_unused_derivation_record(did_wallet_3.wallet_info.id)).pubkey - - async with did_wallet.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - message_spend_bundle, attest_data = await did_wallet.create_attestment( - coin.name(), new_ph, pubkey, action_scope - ) - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "set_remainder": True, - }, - "did_2": { - "init": True, - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did": { - "set_remainder": True, - }, - "did_2": { - "set_remainder": True, - }, - }, - ), - WalletStateTransition(), - ] - ) - - ( - info, - message_spend_bundle, - ) = await did_wallet_3.load_attest_files_for_recovery_spend([attest_data]) - async with did_wallet_3.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - await did_wallet_3.recovery_spend(coin, new_ph, info, pubkey, message_spend_bundle, action_scope) - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did_2": { - "unconfirmed_wallet_balance": 101, - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did_2": { - "confirmed_wallet_balance": 101, - "set_remainder": True, - }, - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "unconfirmed_wallet_balance": 0, # TODO: fix pre-block balances for recovery - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did": { - "confirmed_wallet_balance": -101, - "set_remainder": True, - }, - }, - ), - ] - ) - - # DID Wallet 1 recovery spends into DID Wallet 4 - backup_data = did_wallet.create_backup() - - async with wallet_node_1.wallet_state_manager.lock: - did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery( - wallet_node_1.wallet_state_manager, - wallet_1, - backup_data, - ) - env_1.wallet_aliases["did_2"] = 3 - coin = await did_wallet.get_coin() - with wallet_environments.new_puzzle_hashes_allowed(): - async with did_wallet_4.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - new_ph = ( - await did_wallet_4.get_did_innerpuz(action_scope, override_reuse_puzhash_with=False) - ).get_tree_hash() - pubkey = (await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_4.wallet_info.id)).pubkey - async with did_wallet_3.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - message_spend_bundle, attest1 = await did_wallet_3.create_attestment(coin.name(), new_ph, pubkey, action_scope) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did_2": { - "unconfirmed_wallet_balance": 0, - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did_2": { - "confirmed_wallet_balance": 0, - "set_remainder": True, - }, - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did_2": { - "init": True, - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did_2": { - "confirmed_wallet_balance": 0, - "set_remainder": True, - }, - }, - ), - ] - ) - - ( - test_info_list, - test_message_spend_bundle, - ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1]) - async with did_wallet_4.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, test_message_spend_bundle, action_scope) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did": { - "confirmed_wallet_balance": -101, - "set_remainder": True, - }, - }, - ), - WalletStateTransition( - pre_block_balance_updates={ - "did_2": { - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did_2": { - "confirmed_wallet_balance": 101, - "set_remainder": True, - }, - }, - ), - ] - ) - - for wallet in [did_wallet, did_wallet_3, did_wallet_4]: - assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet - - -@pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") -@pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True) -@pytest.mark.parametrize( - "with_recovery", - [True, False], -) -@pytest.mark.anyio -async def test_did_transfer(wallet_environments: WalletTestFramework, with_recovery: bool): - env_0 = wallet_environments.environments[0] - env_1 = wallet_environments.environments[1] - wallet_node_0 = env_0.node - wallet_node_1 = env_1.node - wallet_0 = env_0.xch_wallet - wallet_1 = env_1.xch_wallet - - env_0.wallet_aliases = { - "xch": 1, - "did": 2, - } - env_1.wallet_aliases = { - "xch": 1, - "did": 2, - } - async with wallet_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet_0.wallet_state_manager) fee = uint64(1000) async with wallet_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: @@ -1353,8 +456,6 @@ async def test_did_transfer(wallet_environments: WalletTestFramework, with_recov wallet_0, uint64(101), action_scope, - [ph], - uint64(1), {"Twitter": "Test", "GitHub": "测试"}, fee=fee, ) @@ -1398,7 +499,7 @@ async def test_did_transfer(wallet_environments: WalletTestFramework, with_recov async with did_wallet_1.wallet_state_manager.new_action_scope( wallet_environments.tx_config, push=True ) as action_scope: - await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, action_scope) + await did_wallet_1.transfer_did(new_puzhash, fee, action_scope) await wallet_environments.process_pending_states( [ @@ -1442,9 +543,6 @@ async def test_did_transfer(wallet_environments: WalletTestFramework, with_recov assert isinstance(did_wallet_2, DIDWallet) # mypy assert len(wallet_node_0.wallet_state_manager.wallets) == 1 assert did_wallet_1.did_info.origin_coin == did_wallet_2.did_info.origin_coin - if with_recovery: - assert did_wallet_1.did_info.backup_ids[0] == did_wallet_2.did_info.backup_ids[0] - assert did_wallet_1.did_info.num_of_backup_ids_needed == did_wallet_2.did_info.num_of_backup_ids_needed metadata = json.loads(did_wallet_2.did_info.metadata) assert metadata["Twitter"] == "Test" assert metadata["GitHub"] == "测试" @@ -1475,8 +573,6 @@ async def test_did_auto_transfer_limit( wallet = wallet_node.wallet_state_manager.main_wallet wallet2 = wallet_node_2.wallet_state_manager.main_wallet api_1 = WalletRpcApi(wallet_node_2) - async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet.wallet_state_manager) if trusted: wallet_node.config["trusted_peers"] = { @@ -1501,8 +597,6 @@ async def test_did_auto_transfer_limit( wallet, uint64(101), action_scope, - [bytes32(bytes(ph))], - uint64(1), {"Twitter": "Test", "GitHub": "测试"}, fee=fee, ) @@ -1517,7 +611,7 @@ async def test_did_auto_transfer_limit( async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: new_puzhash = await action_scope.get_puzzle_hash(wallet2.wallet_state_manager) async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - await did_wallet_1.transfer_did(new_puzhash, fee, False, action_scope) + await did_wallet_1.transfer_did(new_puzhash, fee, action_scope) await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2]) # Check if the DID wallet is created in the wallet2 @@ -1587,14 +681,11 @@ async def test_did_auto_transfer_limit( # Check we can still manually add new DIDs while at cap await full_node_api.farm_blocks_to_wallet(1, wallet2) async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet2.wallet_state_manager) did_wallet_11: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node_2.wallet_state_manager, wallet2, uint64(101), action_scope, - [bytes32(bytes(ph))], - uint64(1), {"Twitter": "Test", "GitHub": "测试"}, fee=fee, ) @@ -1612,97 +703,10 @@ async def test_did_auto_transfer_limit( assert len(did_wallets) == 11 -@pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") -@pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) -@pytest.mark.anyio -async def test_update_recovery_list(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): - env = wallet_environments.environments[0] - wallet_node = env.node - wallet = env.xch_wallet - - env.wallet_aliases = { - "xch": 1, - "did": 2, - } - - async with wallet.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet.wallet_state_manager) - did_wallet_1: DIDWallet = await make_did_wallet( - wallet_node.wallet_state_manager, - wallet, - uint64(101), - action_scope, - use_alternate_recovery=use_alternate_recovery, - ) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "init": True, - "unconfirmed_wallet_balance": 101, - "pending_change": 101, - "pending_coin_removal_count": 1, - }, - }, - post_block_balance_updates={ - "xch": { - "set_remainder": True, - }, - "did": { - "confirmed_wallet_balance": 101, - "spendable_balance": 101, - "max_send_amount": 101, - "unspent_coin_count": 1, - "pending_change": -101, - "pending_coin_removal_count": -1, - }, - }, - ), - ] - ) - await did_wallet_1.update_recovery_list([ph], uint64(1)) - async with did_wallet_1.wallet_state_manager.new_action_scope( - wallet_environments.tx_config, push=True - ) as action_scope: - await did_wallet_1.create_update_spend(action_scope) - - await wallet_environments.process_pending_states( - [ - WalletStateTransition( - pre_block_balance_updates={ - "did": { - "set_remainder": True, - }, - }, - post_block_balance_updates={ - "did": { - "set_remainder": True, - }, - }, - ), - ] - ) - assert did_wallet_1.did_info.backup_ids[0] == bytes(ph) - assert did_wallet_1.did_info.num_of_backup_ids_needed == 1 - - @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio -async def test_get_info(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): +async def test_get_info(wallet_environments: WalletTestFramework): env_0 = wallet_environments.environments[0] env_1 = wallet_environments.environments[1] wallet_node_0 = env_0.node @@ -1730,10 +734,8 @@ async def test_get_info(wallet_environments: WalletTestFramework, use_alternate_ wallet_0, did_amount, action_scope, - [], metadata={"twitter": "twitter"}, fee=fee, - use_alternate_recovery=use_alternate_recovery, ) await wallet_environments.process_pending_states( @@ -1781,10 +783,7 @@ async def test_get_info(wallet_environments: WalletTestFramework, use_alternate_ assert response.metadata["twitter"] == "twitter" assert response.latest_coin == (await did_wallet_1.get_coin()).name() assert response.num_verification == 0 - if use_alternate_recovery: - assert response.recovery_list_hash is None - else: - assert response.recovery_list_hash == Program(Program.to([])).get_tree_hash() + assert response.recovery_list_hash == Program(Program.to([])).get_tree_hash() assert decode_puzzle_hash(response.p2_address) == response.hints[0] # Test non-singleton coin @@ -1852,12 +851,8 @@ async def test_get_info(wallet_environments: WalletTestFramework, use_alternate_ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio -async def test_message_spend(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): +async def test_message_spend(wallet_environments: WalletTestFramework): env = wallet_environments.environments[0] wallet_node = env.node wallet = env.xch_wallet @@ -1876,9 +871,7 @@ async def test_message_spend(wallet_environments: WalletTestFramework, use_alter wallet, uint64(101), action_scope, - [], fee=fee, - use_alternate_recovery=use_alternate_recovery, ) await wallet_environments.process_pending_states( [ @@ -1926,12 +919,8 @@ async def test_message_spend(wallet_environments: WalletTestFramework, use_alter @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant") @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio -async def test_update_metadata(wallet_environments: WalletTestFramework, use_alternate_recovery: bool): +async def test_update_metadata(wallet_environments: WalletTestFramework): env = wallet_environments.environments[0] wallet_node = env.node wallet = env.xch_wallet @@ -1950,9 +939,7 @@ async def test_update_metadata(wallet_environments: WalletTestFramework, use_alt wallet, did_amount, action_scope, - [], fee=fee, - use_alternate_recovery=use_alternate_recovery, ) await wallet_environments.process_pending_states( @@ -2052,14 +1039,11 @@ async def test_did_sign_message(wallet_environments: WalletTestFramework): fee = uint64(1000) async with wallet.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet.wallet_state_manager) did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet( wallet_node.wallet_state_manager, wallet, uint64(101), action_scope, - [ph], - uint64(1), {"Twitter": "Test", "GitHub": "测试"}, fee=fee, ) @@ -2164,93 +1148,6 @@ async def test_did_sign_message(wallet_environments: WalletTestFramework): ) -@pytest.mark.parametrize( - "trusted", - [True, False], -) -@pytest.mark.anyio -async def test_create_did_with_recovery_list( - self_hostname: str, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted: bool -) -> None: - """ - A DID is created on-chain in client0, causing a DID Wallet to be created in client1, which shares the same key. - This can happen if someone uses the same key on multiple computers, or is syncing a wallet from scratch. - - For this test, we assign a recovery list hash at DID creation time, but the recovery list is not yet available - to the wallet_node that the DID Wallet is being created in (client1). - - """ - full_nodes, wallets, _ = two_nodes_two_wallets_with_same_keys - full_node_api = full_nodes[0] - full_node_server = full_node_api.server - wallet_node_0, server_0 = wallets[0] - wallet_node_1, server_1 = wallets[1] - - wallet_0 = wallet_node_0.wallet_state_manager.main_wallet - wallet_1 = wallet_node_1.wallet_state_manager.main_wallet - - async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - ph0 = await action_scope.get_puzzle_hash(wallet_0.wallet_state_manager) - async with wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - ph1 = await action_scope.get_puzzle_hash(wallet_1.wallet_state_manager) - - sk0 = await wallet_node_0.wallet_state_manager.get_private_key(ph0) - sk1 = await wallet_node_1.wallet_state_manager.get_private_key(ph1) - assert sk0 == sk1 - - if trusted: - wallet_node_0.config["trusted_peers"] = { - full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex() - } - wallet_node_1.config["trusted_peers"] = { - full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex() - } - - else: - wallet_node_0.config["trusted_peers"] = {} - wallet_node_1.config["trusted_peers"] = {} - await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None) - await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) - await full_node_api.farm_blocks_to_wallet(1, wallet_1) - - # Node 0 sets up a DID Wallet with a backup set, but num_of_backup_ids_needed=0 - # (a malformed solution, but legal for the clvm puzzle) - recovery_list = [bytes32(bytes.fromhex("00" * 32))] - async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet( - wallet_node_0.wallet_state_manager, - wallet_0, - uint64(101), - action_scope, - backups_ids=recovery_list, - num_of_backup_ids_needed=uint64(0), - ) - - await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) - await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0]) - - await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101) - await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101) - await time_out_assert(15, did_wallet_0.get_pending_change_balance, 0) - - await full_node_api.farm_blocks_to_wallet(1, wallet_0) - - ####################### - all_node_0_wallets = await wallet_node_0.wallet_state_manager.user_store.get_all_wallet_info_entries() - all_node_1_wallets = await wallet_node_1.wallet_state_manager.user_store.get_all_wallet_info_entries() - assert len(all_node_0_wallets) == len(all_node_1_wallets) - - # Note that the inner program we expect is different than the on-chain inner. - # This means that we have more work to do in the checks for the two different spend cases of - # the DID wallet Singleton - # assert ( - # json.loads(all_node_0_wallets[1].data)["current_inner"] - # == json.loads(all_node_1_wallets[1].data)["current_inner"] - # ) - - # TODO: See Issue CHIA-1544 # This test should be ported to WalletTestFramework once we can replace keys in the wallet node @pytest.mark.parametrize( @@ -2273,8 +1170,6 @@ async def test_did_resync( fee = uint64(0) wallet_api_1 = WalletRpcApi(wallet_node_1) wallet_api_2 = WalletRpcApi(wallet_node_2) - async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - ph = await action_scope.get_puzzle_hash(wallet.wallet_state_manager) if trusted: wallet_node_1.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()} wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()} @@ -2292,8 +1187,6 @@ async def test_did_resync( wallet, uint64(101), action_scope, - [bytes32(ph)], - uint64(1), {"Twitter": "Test", "GitHub": "测试"}, fee=fee, ) @@ -2306,7 +1199,7 @@ async def test_did_resync( async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: new_puzhash = await action_scope.get_puzzle_hash(wallet2.wallet_state_manager) async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope: - await did_wallet_1.transfer_did(new_puzhash, fee, True, action_scope=action_scope) + await did_wallet_1.transfer_did(new_puzhash, fee, action_scope=action_scope) await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions) await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_1, wallet_node_2]) # Check if the DID wallet is created in the wallet2 @@ -2354,12 +1247,8 @@ async def test_did_resync( ], indirect=True, ) -@pytest.mark.parametrize( - "use_alternate_recovery", - [True, False], -) @pytest.mark.anyio -async def test_did_coin_records(wallet_environments: WalletTestFramework, use_alternate_recovery: bool) -> None: +async def test_did_coin_records(wallet_environments: WalletTestFramework) -> None: # Setup wallet_node = wallet_environments.environments[0].node wallet = wallet_environments.environments[0].xch_wallet @@ -2371,7 +1260,6 @@ async def test_did_coin_records(wallet_environments: WalletTestFramework, use_al wallet, uint64(1), action_scope, - use_alternate_recovery=use_alternate_recovery, ) await wallet_environments.process_pending_states( @@ -2395,7 +1283,7 @@ async def test_did_coin_records(wallet_environments: WalletTestFramework, use_al wallet_environments.tx_config, push=True ) as action_scope: await did_wallet.transfer_did( - await action_scope.get_puzzle_hash(did_wallet.wallet_state_manager), uint64(0), True, action_scope + await action_scope.get_puzzle_hash(did_wallet.wallet_state_manager), uint64(0), action_scope ) await wallet_environments.process_pending_states( [ diff --git a/chia/_tests/wallet/nft_wallet/test_nft_wallet.py b/chia/_tests/wallet/nft_wallet/test_nft_wallet.py index 3ae5800115..87d793bd52 100644 --- a/chia/_tests/wallet/nft_wallet/test_nft_wallet.py +++ b/chia/_tests/wallet/nft_wallet/test_nft_wallet.py @@ -1284,7 +1284,7 @@ async def test_nft_transfer_nft_with_did(wallet_environments: WalletTestFramewor async with did_wallet.wallet_state_manager.new_action_scope( wallet_environments.tx_config, push=True ) as action_scope: - await did_wallet.transfer_did(wallet_1_ph, uint64(0), True, action_scope) + await did_wallet.transfer_did(wallet_1_ph, uint64(0), action_scope) await wallet_environments.process_pending_states( [ diff --git a/chia/_tests/wallet/rpc/test_wallet_rpc.py b/chia/_tests/wallet/rpc/test_wallet_rpc.py index 661e4a5b09..7dd19c19e8 100644 --- a/chia/_tests/wallet/rpc/test_wallet_rpc.py +++ b/chia/_tests/wallet/rpc/test_wallet_rpc.py @@ -111,13 +111,11 @@ from chia.wallet.wallet_request_types import ( DIDGetDID, DIDGetMetadata, DIDGetPubkey, - DIDGetRecoveryList, DIDGetWalletName, DIDMessageSpend, DIDSetWalletName, DIDTransferDID, DIDUpdateMetadata, - DIDUpdateRecoveryIDs, FungibleAsset, GetNotifications, GetPrivateKey, @@ -1538,20 +1536,6 @@ async def test_did_endpoints(wallet_rpc_environment: WalletRpcTestEnvironment) - # Create backup file await wallet_1_rpc.create_did_backup_file(DIDCreateBackupFile(did_wallet_id_0)) - await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1) - await farm_transaction_block(full_node_api, wallet_1_node) - # Update recovery list - update_res = await wallet_1_rpc.update_did_recovery_list( - DIDUpdateRecoveryIDs( - wallet_id=uint32(did_wallet_id_0), new_list=[did_id_0], num_verifications_required=uint64(1), push=True - ), - DEFAULT_TX_CONFIG, - ) - assert len(update_res.transactions) > 0 - recovery_list_res = await wallet_1_rpc.get_did_recovery_list(DIDGetRecoveryList(did_wallet_id_0)) - assert recovery_list_res.num_required == 1 - assert recovery_list_res.recovery_list[0] == did_id_0 - await time_out_assert(5, check_mempool_spend_count, True, full_node_api, 1) await farm_transaction_block(full_node_api, wallet_1_node) diff --git a/chia/_tests/wallet/sync/test_wallet_sync.py b/chia/_tests/wallet/sync/test_wallet_sync.py index 69d86f811a..1371e4f1b0 100644 --- a/chia/_tests/wallet/sync/test_wallet_sync.py +++ b/chia/_tests/wallet/sync/test_wallet_sync.py @@ -25,6 +25,7 @@ from chia_rs.sized_ints import uint32, uint64, uint128 from chiabip158 import PyBIP158 from colorlog import getLogger +from chia._tests.conftest import ConsensusMode from chia._tests.connection_utils import connect_and_get_peer, disconnect_all, disconnect_all_and_reconnect from chia._tests.util.blockchain_mock import BlockchainMock from chia._tests.util.misc import patch_request_handler, wallet_height_at_least @@ -1702,6 +1703,11 @@ async def test_long_sync_untrusted_break( @pytest.mark.anyio @pytest.mark.parametrize("chain_length", [0, 100]) @pytest.mark.parametrize("fork_point", [500, 1500]) +# TODO: todo_v2_plots once we have new test chains, we can probably re-enable this +@pytest.mark.limit_consensus_modes( + allows=[ConsensusMode.PLAIN, ConsensusMode.HARD_FORK_2_0], + reason="after plot-v1 phase-out, the chains aren't valid anymore", +) async def test_long_reorg_nodes_and_wallet( chain_length: int, fork_point: int, diff --git a/chia/_tests/wallet/vc_wallet/test_vc_wallet.py b/chia/_tests/wallet/vc_wallet/test_vc_wallet.py index ccd47079c3..2776f4951d 100644 --- a/chia/_tests/wallet/vc_wallet/test_vc_wallet.py +++ b/chia/_tests/wallet/vc_wallet/test_vc_wallet.py @@ -753,7 +753,7 @@ async def test_self_revoke(wallet_environments: WalletTestFramework) -> None: async with did_wallet.wallet_state_manager.new_action_scope( wallet_environments.tx_config, push=True ) as action_scope: - await did_wallet.transfer_did(bytes32.zeros, uint64(0), False, action_scope) + await did_wallet.transfer_did(bytes32.zeros, uint64(0), action_scope) await wallet_environments.process_pending_states( [ diff --git a/chia/consensus/pot_iterations.py b/chia/consensus/pot_iterations.py index b02d2ca13b..b1dbba146e 100644 --- a/chia/consensus/pot_iterations.py +++ b/chia/consensus/pot_iterations.py @@ -10,9 +10,6 @@ from chia.consensus.pos_quality import _expected_plot_size from chia.types.blockchain_format.proof_of_space import verify_and_get_quality_string from chia.util.hash import std_hash -# TODO: todo_v2_plots add to chia_rs and get from constants -PHASE_OUT_PERIOD = uint32(10000000) - def is_overflow_block(constants: ConsensusConstants, signage_point_index: uint8) -> bool: if signage_point_index >= constants.NUM_SPS_SUB_SLOT: @@ -38,7 +35,7 @@ def calculate_phase_out( ) -> uint64: if prev_transaction_block_height <= constants.HARD_FORK2_HEIGHT: return uint64(0) - elif uint32(prev_transaction_block_height - constants.HARD_FORK2_HEIGHT) >= PHASE_OUT_PERIOD: + elif uint32(prev_transaction_block_height - constants.HARD_FORK2_HEIGHT) >= constants.PLOT_V1_PHASE_OUT: return uint64(calculate_sp_interval_iters(constants, sub_slot_iters)) return uint64( @@ -46,7 +43,7 @@ def calculate_phase_out( uint32(prev_transaction_block_height - constants.HARD_FORK2_HEIGHT) * calculate_sp_interval_iters(constants, sub_slot_iters) ) - // PHASE_OUT_PERIOD + // constants.PLOT_V1_PHASE_OUT ) diff --git a/chia/farmer/farmer_rpc_client.py b/chia/farmer/farmer_rpc_client.py index 0094d1f5f2..94483444c7 100644 --- a/chia/farmer/farmer_rpc_client.py +++ b/chia/farmer/farmer_rpc_client.py @@ -21,7 +21,7 @@ class FarmerRpcClient(RpcClient): async def get_signage_point(self, sp_hash: bytes32) -> Optional[dict[str, Any]]: try: return await self.fetch("get_signage_point", {"sp_hash": sp_hash.hex()}) - except ValueError: + except ValueError: # not synced return None async def get_signage_points(self) -> list[dict[str, Any]]: @@ -83,5 +83,5 @@ class FarmerRpcClient(RpcClient): try: result = await self.fetch("get_pool_login_link", {"launcher_id": launcher_id.hex()}) return cast(Optional[str], result["login_link"]) - except ValueError: + except ValueError: # not connected to pool. return None diff --git a/chia/full_node/full_node.py b/chia/full_node/full_node.py index fe8ea89985..eba2874c19 100644 --- a/chia/full_node/full_node.py +++ b/chia/full_node/full_node.py @@ -1623,6 +1623,7 @@ class FullNode: for i, block in enumerate(blocks_to_validate): header_hash = block.header_hash assert vs.prev_ses_block is None or vs.prev_ses_block.height < block.height + assert pre_validation_results[i].error is None assert pre_validation_results[i].required_iters is not None state_change_summary: Optional[StateChangeSummary] # when adding blocks in batches, we won't have any overlapping diff --git a/chia/full_node/full_node_rpc_client.py b/chia/full_node/full_node_rpc_client.py index 6bb6026e89..ead3bdfa3c 100644 --- a/chia/full_node/full_node_rpc_client.py +++ b/chia/full_node/full_node_rpc_client.py @@ -7,7 +7,7 @@ from chia_rs.sized_bytes import bytes32 from chia_rs.sized_ints import uint32 from chia.consensus.signage_point import SignagePoint -from chia.rpc.rpc_client import RpcClient +from chia.rpc.rpc_client import ResponseFailureError, RpcClient from chia.types.coin_record import CoinRecord from chia.types.coin_spend import CoinSpendWithConditions from chia.types.condition_opcodes import ConditionOpcode @@ -36,11 +36,8 @@ class FullNodeRpcClient(RpcClient): response["blockchain_state"]["peak"] = BlockRecord.from_json_dict(response["blockchain_state"]["peak"]) return cast(dict[str, Any], response["blockchain_state"]) - async def get_block(self, header_hash: bytes32) -> Optional[FullBlock]: - try: - response = await self.fetch("get_block", {"header_hash": header_hash.hex()}) - except Exception: - return None + async def get_block(self, header_hash: bytes32) -> FullBlock: + response = await self.fetch("get_block", {"header_hash": header_hash.hex()}) return FullBlock.from_json_dict(response["block"]) async def get_blocks(self, start: int, end: int, exclude_reorged: bool = False) -> list[FullBlock]: @@ -52,16 +49,15 @@ class FullNodeRpcClient(RpcClient): async def get_block_record_by_height(self, height: int) -> Optional[BlockRecord]: try: response = await self.fetch("get_block_record_by_height", {"height": height}) - except Exception: - return None + except ResponseFailureError as e: # Block Height not found + if e.response["error"] == f"Block height {height} not found in chain": + return None + raise e return BlockRecord.from_json_dict(response["block_record"]) async def get_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]: - try: - response = await self.fetch("get_block_record", {"header_hash": header_hash.hex()}) - if response["block_record"] is None: - return None - except Exception: + response = await self.fetch("get_block_record", {"header_hash": header_hash.hex()}) + if response["block_record"] is None: return None return BlockRecord.from_json_dict(response["block_record"]) @@ -84,12 +80,8 @@ class FullNodeRpcClient(RpcClient): return cast(int, network_space_bytes_estimate["space"]) - async def get_coin_record_by_name(self, coin_id: bytes32) -> Optional[CoinRecord]: - try: - response = await self.fetch("get_coin_record_by_name", {"name": coin_id.hex()}) - except Exception: - return None - + async def get_coin_record_by_name(self, coin_id: bytes32) -> CoinRecord: + response = await self.fetch("get_coin_record_by_name", {"name": coin_id.hex()}) return CoinRecord.from_json_dict(coin_record_dict_backwards_compat(response["coin_record"])) async def get_coin_records_by_names( @@ -180,10 +172,7 @@ class FullNodeRpcClient(RpcClient): return [CoinRecord.from_json_dict(coin_record_dict_backwards_compat(coin)) for coin in response["coin_records"]] async def get_additions_and_removals(self, header_hash: bytes32) -> tuple[list[CoinRecord], list[CoinRecord]]: - try: - response = await self.fetch("get_additions_and_removals", {"header_hash": header_hash.hex()}) - except Exception: - return [], [] + response = await self.fetch("get_additions_and_removals", {"header_hash": header_hash.hex()}) removals = [] additions = [] for coin_record in response["removals"]: @@ -195,51 +184,43 @@ class FullNodeRpcClient(RpcClient): async def get_block_records(self, start: int, end: int) -> list[dict[str, Any]]: try: response = await self.fetch("get_block_records", {"start": start, "end": end}) - if response["block_records"] is None: + except ResponseFailureError as e: # No Peak Yet + if e.response["error"] == "Peak is None": return [] - except Exception: + raise e + if response["block_records"] is None: return [] # TODO: return block records return cast(list[dict[str, Any]], response["block_records"]) - async def get_block_spends(self, header_hash: bytes32) -> Optional[list[CoinSpend]]: - try: - response = await self.fetch("get_block_spends", {"header_hash": header_hash.hex()}) - output = [] - for block_spend in response["block_spends"]: - output.append(CoinSpend.from_json_dict(block_spend)) - return output - except Exception: - return None + async def get_block_spends(self, header_hash: bytes32) -> list[CoinSpend]: + response = await self.fetch("get_block_spends", {"header_hash": header_hash.hex()}) + output = [] + for block_spend in response["block_spends"]: + output.append(CoinSpend.from_json_dict(block_spend)) + return output - async def get_block_spends_with_conditions(self, header_hash: bytes32) -> Optional[list[CoinSpendWithConditions]]: - try: - response = await self.fetch("get_block_spends_with_conditions", {"header_hash": header_hash.hex()}) - block_spends: list[CoinSpendWithConditions] = [] - for block_spend in response["block_spends_with_conditions"]: - coin_spend = CoinSpend.from_json_dict(block_spend["coin_spend"]) - cond_tuples = block_spend["conditions"] - conditions = [] - for condition in cond_tuples: - cwa = ConditionWithArgs( - opcode=ConditionOpcode(bytes([condition[0]])), vars=[hexstr_to_bytes(b) for b in condition[1]] - ) - conditions.append(cwa) - block_spends.append(CoinSpendWithConditions(coin_spend=coin_spend, conditions=conditions)) - return block_spends - - except Exception: - return None + async def get_block_spends_with_conditions(self, header_hash: bytes32) -> list[CoinSpendWithConditions]: + response = await self.fetch("get_block_spends_with_conditions", {"header_hash": header_hash.hex()}) + block_spends: list[CoinSpendWithConditions] = [] + for block_spend in response["block_spends_with_conditions"]: + coin_spend = CoinSpend.from_json_dict(block_spend["coin_spend"]) + cond_tuples = block_spend["conditions"] + conditions = [] + for condition in cond_tuples: + cwa = ConditionWithArgs( + opcode=ConditionOpcode(bytes([condition[0]])), vars=[hexstr_to_bytes(b) for b in condition[1]] + ) + conditions.append(cwa) + block_spends.append(CoinSpendWithConditions(coin_spend=coin_spend, conditions=conditions)) + return block_spends async def push_tx(self, spend_bundle: SpendBundle) -> dict[str, Any]: return await self.fetch("push_tx", {"spend_bundle": spend_bundle.to_json_dict()}) - async def get_puzzle_and_solution(self, coin_id: bytes32, height: uint32) -> Optional[CoinSpend]: - try: - response = await self.fetch("get_puzzle_and_solution", {"coin_id": coin_id.hex(), "height": height}) - return CoinSpend.from_json_dict(response["coin_solution"]) - except Exception: - return None + async def get_puzzle_and_solution(self, coin_id: bytes32, height: uint32) -> CoinSpend: + response = await self.fetch("get_puzzle_and_solution", {"coin_id": coin_id.hex(), "height": height}) + return CoinSpend.from_json_dict(response["coin_solution"]) async def get_all_mempool_tx_ids(self) -> list[bytes32]: response = await self.fetch("get_all_mempool_tx_ids", {}) @@ -256,14 +237,11 @@ class FullNodeRpcClient(RpcClient): self, tx_id: bytes32, include_pending: bool = False, - ) -> Optional[dict[str, Any]]: - try: - response = await self.fetch( - "get_mempool_item_by_tx_id", {"tx_id": tx_id.hex(), "include_pending": include_pending} - ) - return cast(dict[str, Any], response["mempool_item"]) - except Exception: - return None + ) -> dict[str, Any]: + response = await self.fetch( + "get_mempool_item_by_tx_id", {"tx_id": tx_id.hex(), "include_pending": include_pending} + ) + return cast(dict[str, Any], response["mempool_item"]) async def get_mempool_items_by_coin_name(self, coin_name: bytes32) -> dict[str, Any]: response = await self.fetch("get_mempool_items_by_coin_name", {"coin_name": coin_name.hex()}) @@ -275,26 +253,25 @@ class FullNodeRpcClient(RpcClient): async def get_recent_signage_point_or_eos( self, sp_hash: Optional[bytes32], challenge_hash: Optional[bytes32] - ) -> Optional[Any]: - try: - if sp_hash is not None: - assert challenge_hash is None - response = await self.fetch("get_recent_signage_point_or_eos", {"sp_hash": sp_hash.hex()}) - return { - "signage_point": SignagePoint.from_json_dict(response["signage_point"]), - "time_received": response["time_received"], - "reverted": response["reverted"], - } - else: - assert challenge_hash is not None - response = await self.fetch("get_recent_signage_point_or_eos", {"challenge_hash": challenge_hash.hex()}) - return { - "eos": EndOfSubSlotBundle.from_json_dict(response["eos"]), - "time_received": response["time_received"], - "reverted": response["reverted"], - } - except Exception: - return None + ) -> dict[str, Any]: + if sp_hash is not None and challenge_hash is not None: + raise ValueError("Either sp_hash or challenge_hash must be provided, not both.") + elif sp_hash is not None: + response = await self.fetch("get_recent_signage_point_or_eos", {"sp_hash": sp_hash.hex()}) + return { + "signage_point": SignagePoint.from_json_dict(response["signage_point"]), + "time_received": response["time_received"], + "reverted": response["reverted"], + } + elif challenge_hash is not None: + response = await self.fetch("get_recent_signage_point_or_eos", {"challenge_hash": challenge_hash.hex()}) + return { + "eos": EndOfSubSlotBundle.from_json_dict(response["eos"]), + "time_received": response["time_received"], + "reverted": response["reverted"], + } + else: + raise ValueError("sp_hash or challenge_hash must be provided.") async def get_fee_estimate( self, diff --git a/chia/types/mempool_submission_status.py b/chia/types/mempool_submission_status.py index 93a1a6d624..ac86bf4215 100644 --- a/chia/types/mempool_submission_status.py +++ b/chia/types/mempool_submission_status.py @@ -22,7 +22,7 @@ class MempoolSubmissionStatus(Streamable): inclusion_status: uint8 # MempoolInclusionStatus error_msg: Optional[str] - def to_json_dict_convenience(self) -> dict[str, Union[str, MempoolInclusionStatus, Optional[str]]]: + def to_json_dict_convenience(self) -> dict[str, Union[str, MempoolInclusionStatus, None]]: formatted = self.to_json_dict() formatted["inclusion_status"] = MempoolInclusionStatus(self.inclusion_status).name return formatted diff --git a/chia/wallet/did_wallet/did_wallet.py b/chia/wallet/did_wallet/did_wallet.py index 13b6b79b24..219bfb1770 100644 --- a/chia/wallet/did_wallet/did_wallet.py +++ b/chia/wallet/did_wallet/did_wallet.py @@ -78,8 +78,6 @@ class DIDWallet: wallet: Wallet, amount: uint64, action_scope: WalletActionScope, - backups_ids: list[bytes32] = [], - num_of_backup_ids_needed: uint64 = None, metadata: dict[str, str] = {}, name: Optional[str] = None, fee: uint64 = uint64(0), @@ -114,14 +112,10 @@ class DIDWallet: if amount & 1 == 0: raise ValueError("DID amount must be odd number") - if num_of_backup_ids_needed is None: - num_of_backup_ids_needed = uint64(len(backups_ids)) - if num_of_backup_ids_needed > len(backups_ids): - raise ValueError("Cannot require more IDs than are known.") self.did_info = DIDInfo( origin_coin=None, - backup_ids=backups_ids, - num_of_backup_ids_needed=num_of_backup_ids_needed, + backup_ids=[], + num_of_backup_ids_needed=uint64(0), parent_info=[], current_inner=None, temp_coin=None, @@ -229,6 +223,7 @@ class DIDWallet: recovery_list: list[bytes32] = [] backup_required: int = num_verification.as_int() if not did_recovery_is_nil(recovery_list_hash): + self.log.warning(f"DID {launch_coin.name().hex()} has a recovery list hash which has been deprecated.") try: for did in inner_solution.rest().rest().rest().rest().rest().as_python(): recovery_list.append(bytes32(did[0])) @@ -682,7 +677,6 @@ class DIDWallet: self, new_puzhash: bytes32, fee: uint64, - with_recovery: bool, action_scope: WalletActionScope, extra_conditions: tuple[Condition, ...] = tuple(), ) -> None: @@ -690,7 +684,6 @@ class DIDWallet: Transfer the current DID to another owner :param new_puzhash: New owner's p2_puzzle :param fee: Transaction fee - :param with_recovery: A boolean indicates if the recovery info will be sent through the blockchain :return: Spend bundle """ assert self.did_info.current_inner is not None @@ -698,9 +691,8 @@ class DIDWallet: coin = await self.get_coin() backup_ids = [] backup_required = uint64(0) - if with_recovery: - backup_ids = self.did_info.backup_ids - backup_required = self.did_info.num_of_backup_ids_needed + backup_ids = self.did_info.backup_ids + backup_required = self.did_info.num_of_backup_ids_needed new_did_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2( p2_puzhash=new_puzhash, recovery_list=backup_ids, @@ -713,12 +705,7 @@ class DIDWallet: primaries=[CreateCoin(new_did_puzhash, uint64(coin.amount), [new_puzhash])], conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())), ) - # Need to include backup list reveal here, even we are don't recover - # innerpuz solution is - # (mode, p2_solution) - innersol: Program = Program.to([2, p2_solution]) - if with_recovery: - innersol = Program.to([2, p2_solution, [], [], [], self.did_info.backup_ids]) + innersol = Program.to([2, p2_solution, [], [], [], self.did_info.backup_ids]) # full solution is (corehash parent_info my_amount innerpuz_reveal solution) full_puzzle: Program = create_singleton_puzzle( @@ -850,280 +837,6 @@ class DIDWallet: async with action_scope.use() as interface: interface.side_effects.transactions.append(tx) - # This is used to cash out, or update the id_list - async def create_exit_spend(self, puzhash: bytes32, action_scope: WalletActionScope) -> None: - 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]])) - - # innerpuz solution is (mode p2_solution) - innersol: Program = Program.to([1, [[], message_puz, []]]) - # full solution is (corehash parent_info my_amount innerpuz_reveal solution) - innerpuz: Program = self.did_info.current_inner - - full_puzzle: Program = create_singleton_puzzle( - innerpuz, - self.did_info.origin_coin.name(), - ) - parent_info = self.get_parent_for_coin(coin) - assert parent_info is not None - fullsol = Program.to( - [ - [ - parent_info.parent_name, - parent_info.inner_puzzle_hash, - parent_info.amount, - ], - coin.amount, - innersol, - ] - ) - list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)] - spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element()) - - async with action_scope.use() as interface: - interface.side_effects.transactions.append( - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=await action_scope.get_puzzle_hash( - self.wallet_state_manager, override_reuse_puzhash_with=True - ), - amount=uint64(coin.amount), - fee_amount=uint64(0), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=spend_bundle.additions(), - removals=spend_bundle.removals(), - wallet_id=self.wallet_info.id, - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=bytes32.secret(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=ConditionValidTimes(), - ) - ) - - # Pushes a spend bundle to create a message coin on the blockchain - # Returns a spend bundle for the recoverer to spend the message coin - async def create_attestment( - self, - recovering_coin_name: bytes32, - newpuz: bytes32, - pubkey: G1Element, - action_scope: WalletActionScope, - extra_conditions: tuple[Condition, ...] = tuple(), - ) -> tuple[WalletSpendBundle, str]: - """ - Create an attestment - TODO: - 1. We should use/respect `action_scope.config.tx_config` (reuse_puzhash and co) - 2. We should take a fee as it's a requirement for every transaction function to do so - :param recovering_coin_name: Coin ID of the DID - :param newpuz: New puzzle hash - :param pubkey: New wallet pubkey - :return: (Spend bundle, attest string) - """ - assert self.did_info.current_inner is not None - assert self.did_info.origin_coin is not None - coin = await self.get_coin() - message = did_wallet_puzzles.create_recovery_message_puzzle(recovering_coin_name, newpuz, pubkey) - innermessage = message.get_tree_hash() - innerpuz: Program = self.did_info.current_inner - uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz) - assert uncurried is not None - p2_puzzle = uncurried[0] - # innerpuz solution is (mode, p2_solution) - p2_solution = self.standard_wallet.make_solution( - primaries=[ - CreateCoin(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()]), - CreateCoin(innermessage, uint64(0)), - ], - conditions=extra_conditions, - ) - innersol = Program.to([1, p2_solution]) - - # full solution is (corehash parent_info my_amount innerpuz_reveal solution) - full_puzzle: Program = create_singleton_puzzle( - innerpuz, - self.did_info.origin_coin.name(), - ) - parent_info = self.get_parent_for_coin(coin) - assert parent_info is not None - - fullsol = Program.to( - [ - [ - parent_info.parent_name, - parent_info.inner_puzzle_hash, - parent_info.amount, - ], - coin.amount, - innersol, - ] - ) - list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)] - message_spend = did_wallet_puzzles.create_spend_for_message(coin.name(), recovering_coin_name, newpuz, pubkey) - message_spend_bundle = WalletSpendBundle([message_spend], AugSchemeMPL.aggregate([])) - spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element()) - did_record = TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=await action_scope.get_puzzle_hash( - self.wallet_state_manager, override_reuse_puzhash_with=True - ), - amount=uint64(coin.amount), - fee_amount=uint64(0), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=spend_bundle.additions(), - removals=spend_bundle.removals(), - wallet_id=self.wallet_info.id, - sent_to=[], - trade_id=None, - type=uint32(TransactionType.INCOMING_TX.value), - name=bytes32.secret(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=parse_timelock_info(extra_conditions), - ) - async with action_scope.use() as interface: - interface.side_effects.transactions.append(did_record) - attest_str: str = f"{self.get_my_DID()}:{bytes(message_spend_bundle).hex()}:{coin.parent_coin_info.hex()}:" - attest_str += f"{self.did_info.current_inner.get_tree_hash().hex()}:{coin.amount}" - return message_spend_bundle, attest_str - - async def get_info_for_recovery(self) -> Optional[tuple[bytes32, bytes32, uint64]]: - assert self.did_info.current_inner is not None - assert self.did_info.origin_coin is not None - try: - coin = await self.get_coin() - except RuntimeError: - return None - parent = coin.parent_coin_info - innerpuzhash = self.did_info.current_inner.get_tree_hash() - amount = uint64(coin.amount) - return (parent, innerpuzhash, amount) - - async def load_attest_files_for_recovery_spend(self, attest_data: list[str]) -> tuple[list, WalletSpendBundle]: - spend_bundle_list = [] - info_dict = {} - for attest in attest_data: - info = attest.split(":") - info_dict[info[0]] = [ - bytes.fromhex(info[2]), - bytes.fromhex(info[3]), - uint64(info[4]), - ] - new_sb = WalletSpendBundle.from_bytes(bytes.fromhex(info[1])) - spend_bundle_list.append(new_sb) - # info_dict {0xidentity: "(0xparent_info 0xinnerpuz amount)"} - my_recovery_list: list[bytes32] = self.did_info.backup_ids - - # convert info dict into recovery list - same order as wallet - info_list = [] - for entry in my_recovery_list: - if entry.hex() in info_dict: - info_list.append( - [ - info_dict[entry.hex()][0], - info_dict[entry.hex()][1], - info_dict[entry.hex()][2], - ] - ) - else: - info_list.append([]) - message_spend_bundle = WalletSpendBundle.aggregate(spend_bundle_list) - return info_list, message_spend_bundle - - async def recovery_spend( - self, - coin: Coin, - puzhash: bytes32, - parent_innerpuzhash_amounts_for_recovery_ids: list[tuple[bytes, bytes, int]], - pubkey: G1Element, - spend_bundle: WalletSpendBundle, - action_scope: WalletActionScope, - ) -> None: - assert self.did_info.origin_coin is not None - - # innersol is mode new_amount_or_p2_solution new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey recovery_list_reveal my_id) # noqa - innersol: Program = Program.to( - [ - 0, - coin.amount, - puzhash, - parent_innerpuzhash_amounts_for_recovery_ids, - bytes(pubkey), - self.did_info.backup_ids, - coin.name(), - ] - ) - # full solution is (parent_info my_amount solution) - assert self.did_info.current_inner is not None - innerpuz: Program = self.did_info.current_inner - full_puzzle: Program = create_singleton_puzzle( - innerpuz, - self.did_info.origin_coin.name(), - ) - parent_info = self.get_parent_for_coin(coin) - assert parent_info is not None - fullsol = Program.to( - [ - [ - parent_info.parent_name, - parent_info.inner_puzzle_hash, - parent_info.amount, - ], - coin.amount, - innersol, - ] - ) - list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)] - - spend_bundle = spend_bundle.aggregate([spend_bundle, WalletSpendBundle(list_of_coinspends, G2Element())]) - - async with action_scope.use() as interface: - interface.side_effects.transactions.append( - TransactionRecord( - confirmed_at_height=uint32(0), - created_at_time=uint64(int(time.time())), - to_puzzle_hash=await action_scope.get_puzzle_hash( - self.wallet_state_manager, override_reuse_puzhash_with=True - ), - amount=uint64(coin.amount), - fee_amount=uint64(0), - confirmed=False, - sent=uint32(0), - spend_bundle=spend_bundle, - additions=spend_bundle.additions(), - removals=spend_bundle.removals(), - wallet_id=self.wallet_info.id, - sent_to=[], - trade_id=None, - type=uint32(TransactionType.OUTGOING_TX.value), - name=bytes32.secret(), - memos=list(compute_memos(spend_bundle).items()), - valid_times=ConditionValidTimes(), - ) - ) - new_did_info = DIDInfo( - origin_coin=self.did_info.origin_coin, - backup_ids=self.did_info.backup_ids, - num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed, - parent_info=self.did_info.parent_info, - current_inner=self.did_info.current_inner, - temp_coin=self.did_info.temp_coin, - temp_puzhash=self.did_info.temp_puzhash, - temp_pubkey=self.did_info.temp_pubkey, - sent_recovery_transaction=True, - metadata=self.did_info.metadata, - ) - await self.save_info(new_did_info) - async def get_did_innerpuz( self, action_scope: WalletActionScope, @@ -1395,25 +1108,6 @@ class DIDWallet: ) await self.save_info(did_info) - async def update_recovery_list(self, recover_list: list[bytes32], num_of_backup_ids_needed: uint64) -> bool: - if num_of_backup_ids_needed > len(recover_list): - return False - did_info = DIDInfo( - origin_coin=self.did_info.origin_coin, - backup_ids=recover_list, - num_of_backup_ids_needed=num_of_backup_ids_needed, - parent_info=self.did_info.parent_info, - current_inner=self.did_info.current_inner, - temp_coin=self.did_info.temp_coin, - temp_puzhash=self.did_info.temp_puzhash, - temp_pubkey=self.did_info.temp_pubkey, - sent_recovery_transaction=self.did_info.sent_recovery_transaction, - metadata=self.did_info.metadata, - ) - await self.save_info(did_info) - await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id) - return True - async def update_metadata(self, metadata: dict[str, str]) -> bool: # validate metadata if not all(isinstance(k, str) and isinstance(v, str) for k, v in metadata.items()): diff --git a/chia/wallet/vc_wallet/vc_wallet.py b/chia/wallet/vc_wallet/vc_wallet.py index c03ea76fc7..b386f4e9b6 100644 --- a/chia/wallet/vc_wallet/vc_wallet.py +++ b/chia/wallet/vc_wallet/vc_wallet.py @@ -400,11 +400,6 @@ class VCWallet: ) return - recovery_info: Optional[tuple[bytes32, bytes32, uint64]] = await did_wallet.get_info_for_recovery() - if recovery_info is None: - raise RuntimeError("DID could not currently be accessed while trying to revoke VC") # pragma: no cover - _, provider_inner_puzhash, _ = recovery_info - # Generate spend specific nonce coins = {await did_wallet.get_coin()} coins.add(vc.coin) @@ -421,7 +416,10 @@ class VCWallet: ) # Assemble final bundle - expected_did_announcement, vc_spend = vc.activate_backdoor(provider_inner_puzhash, announcement_nonce=nonce) + assert did_wallet.did_info.current_inner is not None + expected_did_announcement, vc_spend = vc.activate_backdoor( + did_wallet.did_info.current_inner.get_tree_hash(), announcement_nonce=nonce + ) await did_wallet.create_message_spend( action_scope, extra_conditions=(*extra_conditions, expected_did_announcement, vc_announcement), diff --git a/chia/wallet/wallet_request_types.py b/chia/wallet/wallet_request_types.py index e8df53c606..7a3d18e4b9 100644 --- a/chia/wallet/wallet_request_types.py +++ b/chia/wallet/wallet_request_types.py @@ -389,23 +389,6 @@ class DIDGetPubkeyResponse(Streamable): pubkey: G1Element -@streamable -@dataclass(frozen=True) -class DIDGetRecoveryInfo(Streamable): - wallet_id: uint32 - - -@streamable -@dataclass(frozen=True) -class DIDGetRecoveryInfoResponse(Streamable): - wallet_id: uint32 - my_did: str - coin_name: bytes32 - newpuzhash: Optional[bytes32] - pubkey: Optional[G1Element] - backup_dids: list[bytes32] - - @streamable @dataclass(frozen=True) class DIDGetCurrentCoinInfo(Streamable): @@ -449,20 +432,6 @@ class DIDGetDIDResponse(Streamable): coin_id: Optional[bytes32] = None -@streamable -@dataclass(frozen=True) -class DIDGetRecoveryList(Streamable): - wallet_id: uint32 - - -@streamable -@dataclass(frozen=True) -class DIDGetRecoveryListResponse(Streamable): - wallet_id: uint32 - recovery_list: list[str] - num_required: uint16 - - @streamable @dataclass(frozen=True) class DIDGetMetadata(Streamable): @@ -999,20 +968,6 @@ class CombineCoinsResponse(TransactionEndpointResponse): pass -@streamable -@kw_only_dataclass -class DIDUpdateRecoveryIDs(TransactionEndpointRequest): - wallet_id: uint32 = field(default_factory=default_raise) - new_list: list[str] = field(default_factory=default_raise) - num_verifications_required: Optional[uint64] = None - - -@streamable -@dataclass(frozen=True) -class DIDUpdateRecoveryIDsResponse(TransactionEndpointResponse): - pass - - @streamable @kw_only_dataclass class DIDMessageSpend(TransactionEndpointRequest): @@ -1048,6 +1003,11 @@ class DIDTransferDID(TransactionEndpointRequest): inner_address: str = field(default_factory=default_raise) with_recovery_info: bool = True + def __post_init__(self) -> None: + if self.with_recovery_info is False: + raise ValueError("Recovery related options are no longer supported. `with_recovery` must always be true.") + return super().__post_init__() + @streamable @dataclass(frozen=True) diff --git a/chia/wallet/wallet_rpc_api.py b/chia/wallet/wallet_rpc_api.py index a37f5bc157..6cac029b90 100644 --- a/chia/wallet/wallet_rpc_api.py +++ b/chia/wallet/wallet_rpc_api.py @@ -132,10 +132,6 @@ from chia.wallet.wallet_request_types import ( DIDGetMetadataResponse, DIDGetPubkey, DIDGetPubkeyResponse, - DIDGetRecoveryInfo, - DIDGetRecoveryInfoResponse, - DIDGetRecoveryList, - DIDGetRecoveryListResponse, DIDGetWalletName, DIDGetWalletNameResponse, DIDMessageSpend, @@ -146,8 +142,6 @@ from chia.wallet.wallet_request_types import ( DIDTransferDIDResponse, DIDUpdateMetadata, DIDUpdateMetadataResponse, - DIDUpdateRecoveryIDs, - DIDUpdateRecoveryIDsResponse, DLDeleteMirror, DLDeleteMirrorResponse, DLGetMirrors, @@ -556,15 +550,10 @@ class WalletRpcApi: # DID Wallet "/did_set_wallet_name": self.did_set_wallet_name, "/did_get_wallet_name": self.did_get_wallet_name, - "/did_update_recovery_ids": self.did_update_recovery_ids, "/did_update_metadata": self.did_update_metadata, "/did_get_pubkey": self.did_get_pubkey, "/did_get_did": self.did_get_did, - "/did_recovery_spend": self.did_recovery_spend, - "/did_get_recovery_list": self.did_get_recovery_list, "/did_get_metadata": self.did_get_metadata, - "/did_create_attest": self.did_create_attest, - "/did_get_information_needed_for_recovery": self.did_get_information_needed_for_recovery, "/did_get_current_coin_info": self.did_get_current_coin_info, "/did_create_backup_file": self.did_create_backup_file, "/did_transfer_did": self.did_transfer_did, @@ -1112,12 +1101,8 @@ class WalletRpcApi: elif request["wallet_type"] == "did_wallet": if request["did_type"] == "new": - backup_dids = [] - num_needed = 0 - for d in request["backup_dids"]: - backup_dids.append(decode_puzzle_hash(d)) - if len(backup_dids) > 0: - num_needed = uint64(request["num_of_backup_ids_needed"]) + if "backup_dids" in request and request["backup_dids"] != []: + raise ValueError("Recovery options are no longer supported. `backup_dids` cannot be set.") metadata: dict[str, str] = {} if "metadata" in request: if type(request["metadata"]) is dict: @@ -1132,8 +1117,6 @@ class WalletRpcApi: main_wallet, uint64(request["amount"]), action_scope, - backup_dids, - uint64(num_needed), metadata, did_wallet_name, uint64(request.get("fee", 0)), @@ -2591,31 +2574,6 @@ class WalletRpcApi: wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) return DIDGetWalletNameResponse(request.wallet_id, wallet.get_name()) - @tx_endpoint(push=True) - @marshal - async def did_update_recovery_ids( - self, - request: DIDUpdateRecoveryIDs, - action_scope: WalletActionScope, - extra_conditions: tuple[Condition, ...] = tuple(), - ) -> DIDUpdateRecoveryIDsResponse: - wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) - recovery_list = [decode_puzzle_hash(puzzle_hash) for puzzle_hash in request.new_list] - new_amount_verifications_required = ( - request.num_verifications_required - if request.num_verifications_required is not None - else uint64(len(recovery_list)) - ) - async with self.service.wallet_state_manager.lock: - update_success = await wallet.update_recovery_list(recovery_list, new_amount_verifications_required) - # Update coin with new ID info - if update_success: - await wallet.create_update_spend(action_scope, fee=request.fee, extra_conditions=extra_conditions) - # tx_endpoint will take care of default values here - return DIDUpdateRecoveryIDsResponse([], []) - else: - raise RuntimeError("updating recovery list failed") - @tx_endpoint(push=False) @marshal async def did_message_spend( @@ -2910,68 +2868,14 @@ class WalletRpcApi: except RuntimeError: return DIDGetDIDResponse(wallet_id=request.wallet_id, my_did=my_did) - @marshal - async def did_get_recovery_list(self, request: DIDGetRecoveryList) -> DIDGetRecoveryListResponse: - wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) - recovery_list = wallet.did_info.backup_ids - recovery_dids = [] - for backup_id in recovery_list: - recovery_dids.append(encode_puzzle_hash(backup_id, AddressType.DID.hrp(self.service.config))) - return DIDGetRecoveryListResponse( - wallet_id=request.wallet_id, - recovery_list=recovery_dids, - num_required=uint16(wallet.did_info.num_of_backup_ids_needed), - ) - @marshal async def did_get_metadata(self, request: DIDGetMetadata) -> DIDGetMetadataResponse: wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) metadata = json.loads(wallet.did_info.metadata) - return DIDGetMetadataResponse(wallet_id=request.wallet_id, metadata=metadata) - - # TODO: this needs a test - # Don't need full @tx_endpoint decorator here, but "push" is still a valid option - async def did_recovery_spend(self, request: dict[str, Any]) -> EndpointResult: # pragma: no cover - wallet_id = uint32(request["wallet_id"]) - wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=DIDWallet) - if len(request["attest_data"]) < wallet.did_info.num_of_backup_ids_needed: - return {"success": False, "reason": "insufficient messages"} - async with self.service.wallet_state_manager.lock: - ( - info_list, - message_spend_bundle, - ) = await wallet.load_attest_files_for_recovery_spend(request["attest_data"]) - - if "pubkey" in request: - pubkey = G1Element.from_bytes(hexstr_to_bytes(request["pubkey"])) - else: - assert wallet.did_info.temp_pubkey is not None - pubkey = G1Element.from_bytes(wallet.did_info.temp_pubkey) - - if "puzhash" in request: - puzhash = bytes32.from_hexstr(request["puzhash"]) - else: - assert wallet.did_info.temp_puzhash is not None - puzhash = wallet.did_info.temp_puzhash - - assert wallet.did_info.temp_coin is not None - async with self.service.wallet_state_manager.new_action_scope( - DEFAULT_TX_CONFIG, push=request.get("push", True) - ) as action_scope: - await wallet.recovery_spend( - wallet.did_info.temp_coin, - puzhash, - info_list, - pubkey, - message_spend_bundle, - action_scope, - ) - [tx] = action_scope.side_effects.transactions - return { - "success": True, - "spend_bundle": tx.spend_bundle, - "transactions": [tx.to_json_dict_convenience(self.service.config)], - } + return DIDGetMetadataResponse( + wallet_id=request.wallet_id, + metadata=metadata, + ) @marshal async def did_get_pubkey(self, request: DIDGetPubkey) -> DIDGetPubkeyResponse: @@ -2980,57 +2884,6 @@ class WalletRpcApi: (await wallet.wallet_state_manager.get_unused_derivation_record(request.wallet_id)).pubkey ) - # TODO: this needs a test - @tx_endpoint(push=True) - async def did_create_attest( - self, - request: dict[str, Any], - action_scope: WalletActionScope, - extra_conditions: tuple[Condition, ...] = tuple(), - ) -> EndpointResult: # pragma: no cover - wallet_id = uint32(request["wallet_id"]) - wallet = self.service.wallet_state_manager.get_wallet(id=wallet_id, required_type=DIDWallet) - async with self.service.wallet_state_manager.lock: - info = await wallet.get_info_for_recovery() - coin = bytes32.from_hexstr(request["coin_name"]) - pubkey = G1Element.from_bytes(hexstr_to_bytes(request["pubkey"])) - message_spend_bundle, attest_data = await wallet.create_attestment( - coin, - bytes32.from_hexstr(request["puzhash"]), - pubkey, - action_scope, - extra_conditions=extra_conditions, - ) - if info is not None: - return { - "success": True, - "message_spend_bundle": bytes(message_spend_bundle).hex(), - "info": [info[0].hex(), info[1].hex(), info[2]], - "attest_data": attest_data, - "transactions": None, # tx_endpoint wrapper will take care of this - } - else: - return {"success": False} - - @marshal - async def did_get_information_needed_for_recovery(self, request: DIDGetRecoveryInfo) -> DIDGetRecoveryInfoResponse: - did_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) - my_did = encode_puzzle_hash( - bytes32.from_hexstr(did_wallet.get_my_DID()), AddressType.DID.hrp(self.service.config) - ) - assert did_wallet.did_info.temp_coin is not None - coin_name = did_wallet.did_info.temp_coin.name() - return DIDGetRecoveryInfoResponse( - wallet_id=request.wallet_id, - my_did=my_did, - coin_name=coin_name, - newpuzhash=did_wallet.did_info.temp_puzhash, - pubkey=G1Element.from_bytes(did_wallet.did_info.temp_pubkey) - if did_wallet.did_info.temp_pubkey is not None - else None, - backup_dids=did_wallet.did_info.backup_ids, - ) - @marshal async def did_get_current_coin_info(self, request: DIDGetCurrentCoinInfo) -> DIDGetCurrentCoinInfoResponse: did_wallet = self.service.wallet_state_manager.get_wallet(id=request.wallet_id, required_type=DIDWallet) @@ -3038,15 +2891,15 @@ class WalletRpcApi: bytes32.from_hexstr(did_wallet.get_my_DID()), AddressType.DID.hrp(self.service.config) ) - did_coin_threeple = await did_wallet.get_info_for_recovery() + assert did_wallet.did_info.current_inner is not None + parent_coin = await did_wallet.get_coin() assert my_did is not None - assert did_coin_threeple is not None return DIDGetCurrentCoinInfoResponse( wallet_id=request.wallet_id, my_did=my_did, - did_parent=did_coin_threeple[0], - did_innerpuz=did_coin_threeple[1], - did_amount=did_coin_threeple[2], + did_parent=parent_coin.parent_coin_info, + did_innerpuz=did_wallet.did_info.current_inner.get_tree_hash(), + did_amount=parent_coin.amount, ) @marshal @@ -3070,7 +2923,6 @@ class WalletRpcApi: await did_wallet.transfer_did( puzzle_hash, request.fee, - request.with_recovery_info, action_scope, extra_conditions=extra_conditions, ) diff --git a/chia/wallet/wallet_rpc_client.py b/chia/wallet/wallet_rpc_client.py index d06d97abce..57d5eaa77d 100644 --- a/chia/wallet/wallet_rpc_client.py +++ b/chia/wallet/wallet_rpc_client.py @@ -52,10 +52,6 @@ from chia.wallet.wallet_request_types import ( DIDGetMetadataResponse, DIDGetPubkey, DIDGetPubkeyResponse, - DIDGetRecoveryInfo, - DIDGetRecoveryInfoResponse, - DIDGetRecoveryList, - DIDGetRecoveryListResponse, DIDGetWalletName, DIDGetWalletNameResponse, DIDMessageSpend, @@ -66,8 +62,6 @@ from chia.wallet.wallet_request_types import ( DIDTransferDIDResponse, DIDUpdateMetadata, DIDUpdateMetadataResponse, - DIDUpdateRecoveryIDs, - DIDUpdateRecoveryIDsResponse, DLDeleteMirror, DLDeleteMirrorResponse, DLGetMirrors, @@ -543,25 +537,6 @@ class WalletRpcClient(RpcClient): await self.fetch("did_create_backup_file", request.to_json_dict()) ) - async def update_did_recovery_list( - self, - request: DIDUpdateRecoveryIDs, - tx_config: TXConfig, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> DIDUpdateRecoveryIDsResponse: - return DIDUpdateRecoveryIDsResponse.from_json_dict( - await self.fetch( - "did_update_recovery_ids", - request.json_serialize_for_transport(tx_config, extra_conditions, timelock_info), - ) - ) - - async def get_did_recovery_list(self, request: DIDGetRecoveryList) -> DIDGetRecoveryListResponse: - return DIDGetRecoveryListResponse.from_json_dict( - await self.fetch("did_get_recovery_list", request.to_json_dict()) - ) - async def did_message_spend( self, request: DIDMessageSpend, @@ -604,43 +579,11 @@ class WalletRpcClient(RpcClient): response = await self.fetch("create_new_wallet", request) return response - async def did_create_attest( - self, - wallet_id: int, - coin_name: str, - pubkey: str, - puzhash: str, - file_name: str, - extra_conditions: tuple[Condition, ...] = tuple(), - timelock_info: ConditionValidTimes = ConditionValidTimes(), - ) -> dict[str, Any]: - request = { - "wallet_id": wallet_id, - "coin_name": coin_name, - "pubkey": pubkey, - "puzhash": puzhash, - "filename": file_name, - "extra_conditions": conditions_to_json_dicts(extra_conditions), - **timelock_info.to_json_dict(), - } - response = await self.fetch("did_create_attest", request) - return response - - async def did_get_recovery_info(self, request: DIDGetRecoveryInfo) -> DIDGetRecoveryInfoResponse: - return DIDGetRecoveryInfoResponse.from_json_dict( - await self.fetch("did_get_information_needed_for_recovery", request.to_json_dict()) - ) - async def did_get_current_coin_info(self, request: DIDGetCurrentCoinInfo) -> DIDGetCurrentCoinInfoResponse: return DIDGetCurrentCoinInfoResponse.from_json_dict( await self.fetch("did_get_current_coin_info", request.to_json_dict()) ) - async def did_recovery_spend(self, wallet_id: int, attest_filenames: str) -> dict[str, Any]: - request = {"wallet_id": wallet_id, "attest_filenames": attest_filenames} - response = await self.fetch("did_recovery_spend", request) - return response - async def did_transfer_did( self, request: DIDTransferDID, @@ -762,7 +705,7 @@ class WalletRpcClient(RpcClient): request = {"asset_id": asset_id.hex()} try: res = await self.fetch("cat_asset_id_to_name", request) - except ValueError: + except ValueError: # This happens if the asset_id is unknown return None wallet_id: Optional[uint32] = None if res["wallet_id"] is None else uint32(int(res["wallet_id"])) diff --git a/poetry-check.py b/poetry-check.py index aa46893805..1f44fe9d48 100644 --- a/poetry-check.py +++ b/poetry-check.py @@ -9,6 +9,7 @@ def main() -> int: [ "poetry", "check", + "--strict", ], check=True, ) diff --git a/poetry.lock b/poetry.lock index 6f9bc09707..db5ba2f730 100644 --- a/poetry.lock +++ b/poetry.lock @@ -140,7 +140,6 @@ description = "CORS support for aiohttp" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "aiohttp_cors-0.8.1-py3-none-any.whl", hash = "sha256:3180cf304c5c712d626b9162b195b1db7ddf976a2a25172b35bb2448b890a80d"}, {file = "aiohttp_cors-0.8.1.tar.gz", hash = "sha256:ccacf9cb84b64939ea15f859a146af1f662a6b1d68175754a07315e305fb1403"}, @@ -190,7 +189,7 @@ description = "Python graph (network) package" optional = true python-versions = "*" groups = ["main"] -markers = "python_version <= \"3.12\" and extra == \"dev\"" +markers = "extra == \"dev\" and python_version <= \"3.12\"" files = [ {file = "altgraph-0.17.4-py2.py3-none-any.whl", hash = "sha256:642743b4750de17e655e6711601b077bc6598dbfa3ba5fa2b2a35ce12b508dff"}, {file = "altgraph-0.17.4.tar.gz", hash = "sha256:1b5afbb98f6c4dcadb2e2ae6ab9fa994bbb8c1d75f4fa96d340f9437ae454406"}, @@ -226,7 +225,6 @@ description = "Argon2 for Python" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"legacy-keyring\"" files = [ {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, @@ -248,7 +246,6 @@ description = "Low-level CFFI bindings for Argon2" optional = true python-versions = ">=3.6" groups = ["main"] -markers = "extra == \"legacy-keyring\"" files = [ {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, @@ -336,7 +333,6 @@ description = "Simple bencode parser (for Python 2, Python 3 and PyPy)" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "bencode.py-4.0.0-py2.py3-none-any.whl", hash = "sha256:99c06a55764e85ffe81622fdf9ee78bd737bad3ea61d119784a54bb28860d962"}, {file = "bencode.py-4.0.0.tar.gz", hash = "sha256:2a24ccda1725a51a650893d0b63260138359eaa299bb6e7a09961350a2a6e05c"}, @@ -506,18 +502,18 @@ bitarray = ">=3.0.0,<4.0" [[package]] name = "boto3" -version = "1.39.1" +version = "1.39.4" description = "The AWS SDK for Python" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "boto3-1.39.1-py3-none-any.whl", hash = "sha256:beb945ec1ab4bb48d39640ce7d3054b7e4ab2020ef3259034c039195ae04b2f7"}, - {file = "boto3-1.39.1.tar.gz", hash = "sha256:3f89d6f05ab7d3a6f6807b45e9456a1a0db53bb47b1758cf5e0a3479cdd6d734"}, + {file = "boto3-1.39.4-py3-none-any.whl", hash = "sha256:f8e9534b429121aa5c5b7c685c6a94dd33edf14f87926e9a182d5b50220ba284"}, + {file = "boto3-1.39.4.tar.gz", hash = "sha256:6c955729a1d70181bc8368e02a7d3f350884290def63815ebca8408ee6d47571"}, ] [package.dependencies] -botocore = ">=1.39.1,<1.40.0" +botocore = ">=1.39.4,<1.40.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.13.0,<0.14.0" @@ -526,14 +522,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.39.1" +version = "1.39.4" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "botocore-1.39.1-py3-none-any.whl", hash = "sha256:912d518ac3096460e54d2cf80899943a521a586fd5c075568e807f3c35623318"}, - {file = "botocore-1.39.1.tar.gz", hash = "sha256:ac829b46b30bd837392c9792cdf63b44d290a4691c028b5e66ab471ced1b8305"}, + {file = "botocore-1.39.4-py3-none-any.whl", hash = "sha256:c41e167ce01cfd1973c3fa9856ef5244a51ddf9c82cb131120d8617913b6812a"}, + {file = "botocore-1.39.4.tar.gz", hash = "sha256:e662ac35c681f7942a93f2ec7b4cde8f8b56dd399da47a79fa3e370338521a56"}, ] [package.dependencies] @@ -554,7 +550,6 @@ description = "A simple, correct Python build frontend" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "build-1.2.2.post1-py3-none-any.whl", hash = "sha256:1d61c0887fa860c01971625baae8bdd338e517b836a2f70dd1f7aa3a6b2fc5b5"}, {file = "build-1.2.2.post1.tar.gz", hash = "sha256:b36993e92ca9375a219c99e606a122ff365a760a2d4bba0caa09bd5278b608b7"}, @@ -581,7 +576,7 @@ description = "Python package for providing Mozilla's CA Bundle." optional = true python-versions = ">=3.6" groups = ["main"] -markers = "sys_platform == \"linux\" and extra == \"dev\"" +markers = "extra == \"dev\" and sys_platform == \"linux\"" files = [ {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, @@ -594,7 +589,6 @@ description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" groups = ["main"] -markers = "platform_python_implementation != \"PyPy\" or extra == \"legacy-keyring\"" files = [ {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, @@ -660,7 +654,6 @@ description = "Validate configuration and produce human readable error messages. optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -673,7 +666,6 @@ description = "Universal encoding detector for Python 3" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, @@ -686,7 +678,7 @@ description = "The Real First Universal Charset Detector. Open, modern and activ optional = true python-versions = ">=3.7.0" groups = ["main"] -markers = "sys_platform == \"linux\" and extra == \"dev\"" +markers = "extra == \"dev\" and sys_platform == \"linux\"" files = [ {file = "charset-normalizer-3.3.0.tar.gz", hash = "sha256:63563193aec44bce707e0c5ca64ff69fa72ed7cf34ce6e11d5127555756fd2f6"}, {file = "charset_normalizer-3.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:effe5406c9bd748a871dbcaf3ac69167c38d72db8c9baf3ff954c344f31c4cbe"}, @@ -877,6 +869,7 @@ files = [ {file = "chiabip158-1.5.2-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b7b36a529ee5685294fe55cedfa0788cb1baac03c310b1533cd23481357efd10"}, {file = "chiabip158-1.5.2-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad40df68317d39f33272e25fd9651f05a27b85d524e9ed694ac7549cde44918c"}, {file = "chiabip158-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:07b298cfb0621dba1027c710e9669970f4e089c118db8732bd456101c727db65"}, + {file = "chiabip158-1.5.2.tar.gz", hash = "sha256:86c225f5a566cca3199607f6ea646799da9e406df6fb0ae7323d57e5ac8e2f2c"}, ] [[package]] @@ -1118,7 +1111,6 @@ description = "Code coverage measurement for Python" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "coverage-7.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:66283a192a14a3854b2e7f3418d7db05cdf411012ab7ff5db98ff3b181e1f912"}, {file = "coverage-7.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4e01d138540ef34fcf35c1aa24d06c3de2a4cffa349e29a10056544f35cca15f"}, @@ -1252,7 +1244,6 @@ description = "Run coverage and linting reports on diffs" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "diff_cover-9.4.1-py3-none-any.whl", hash = "sha256:84d5bd402f566d04212126988a2c352b8ec801fa7e43b8856bd8dc146baec5a9"}, {file = "diff_cover-9.4.1.tar.gz", hash = "sha256:7ded89e5fb3a61161be9b98d025f2ad4f5aa95de593c3fbeb65419ddb6667610"}, @@ -1274,7 +1265,6 @@ description = "Distribution utilities" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, @@ -1336,7 +1326,6 @@ description = "execnet: rapid multi-Python deployment" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, @@ -1456,7 +1445,6 @@ description = "Git Object Database" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, @@ -1472,7 +1460,6 @@ description = "GitPython is a Python library used to interact with Git repositor optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, @@ -1512,7 +1499,6 @@ description = "File identification library for Python" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "identify-2.5.30-py2.py3-none-any.whl", hash = "sha256:afe67f26ae29bab007ec21b03d4114f41316ab9dd15aa8736a167481e108da54"}, {file = "identify-2.5.30.tar.gz", hash = "sha256:f302a4256a15c849b91cfcdcec052a8ce914634b2f77ae87dad29cd749f2d88d"}, @@ -1669,7 +1655,6 @@ description = "A very fast and expressive template engine." optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -1730,7 +1715,6 @@ description = "Encrypted file keyring backend" optional = true python-versions = ">=3.5" groups = ["main"] -markers = "extra == \"legacy-keyring\"" files = [ {file = "keyrings.cryptfile-1.3.9.tar.gz", hash = "sha256:7c2a453cab9985426b8c21f7ad54a57e49ff8e819ba18e08340bd8801acf0091"}, ] @@ -1748,7 +1732,6 @@ description = "Powerful and Pythonic XML processing library combining libxml2/li optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "lxml-6.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:35bc626eec405f745199200ccb5c6b36f202675d204aa29bb52e27ba2b71dea8"}, {file = "lxml-6.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:246b40f8a4aec341cbbf52617cad8ab7c888d944bfe12a6abd2b1f6cfb6f6082"}, @@ -1875,7 +1858,6 @@ description = "Python port of markdown-it. Markdown parsing, done right!" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, @@ -1901,7 +1883,6 @@ description = "Safely add untrusted strings to HTML/XML markup." optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, @@ -1972,7 +1953,6 @@ description = "Markdown URL utilities" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, @@ -1985,7 +1965,7 @@ description = "A module for monitoring memory usage of a python program" optional = true python-versions = ">=3.5" groups = ["main"] -markers = "sys_platform == \"linux\" and extra == \"dev\"" +markers = "extra == \"dev\" and sys_platform == \"linux\"" files = [ {file = "memory_profiler-0.61.0-py3-none-any.whl", hash = "sha256:400348e61031e3942ad4d4109d18753b2fb08c2f6fb8290671c5513a34182d84"}, {file = "memory_profiler-0.61.0.tar.gz", hash = "sha256:4e5b73d7864a1d1292fb76a03e82a3e78ef934d06828a698d9dada76da2067b0"}, @@ -2001,7 +1981,6 @@ description = "MiniUPnP IGD client" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"upnp\"" files = [ {file = "miniupnpc-2.3.3-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:0424940059620f7b2a753876d40719324f32d2d2d6684a8851ae512b22b978ec"}, {file = "miniupnpc-2.3.3-cp310-cp310-macosx_13_0_x86_64.whl", hash = "sha256:6a86e1d7387954f5a1ab43ef1ddbf35cd7a0cdcf7f1d02b632fd79e473fedd64"}, @@ -2149,7 +2128,6 @@ description = "Optional static typing for Python" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "mypy-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:979e4e1a006511dacf628e36fadfecbcc0160a8af6ca7dad2f5025529e082c13"}, {file = "mypy-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c4bb0e1bd29f7d34efcccd71cf733580191e9a264a2202b0239da95984c5b559"}, @@ -2204,7 +2182,6 @@ description = "Type system extensions for programs checked with the mypy type ch optional = true python-versions = ">=3.5" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, @@ -2217,7 +2194,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "python_version < \"3.10\" and extra == \"dev\"" +markers = "python_version < \"3.10\"" files = [ {file = "networkx-3.2.1-py3-none-any.whl", hash = "sha256:f18c69adc97877c42332c170849c96cefa91881c99a7cb3e95b7c659ebdc1ec2"}, {file = "networkx-3.2.1.tar.gz", hash = "sha256:9f1bb5cf3409bf324e0a722c20bdb4c20ee39bf1c30ce8ae499c8502b0b5e0c6"}, @@ -2237,7 +2214,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = true python-versions = ">=3.10" groups = ["main"] -markers = "python_version >= \"3.10\" and extra == \"dev\" and python_version < \"3.12\"" +markers = "python_version < \"3.12\" and python_version >= \"3.10\"" files = [ {file = "networkx-3.4.2-py3-none-any.whl", hash = "sha256:df5d4365b724cf81b8c6a7312509d0c22386097011ad1abe274afd5e9d3bbc5f"}, {file = "networkx-3.4.2.tar.gz", hash = "sha256:307c3669428c5362aab27c8a1260aa8f47c4e91d3891f48be0141738d8d053e1"}, @@ -2258,7 +2235,7 @@ description = "Python package for creating and manipulating graphs and networks" optional = true python-versions = ">=3.11" groups = ["main"] -markers = "python_version >= \"3.12\" and extra == \"dev\"" +markers = "python_version >= \"3.12\"" files = [ {file = "networkx-3.5-py3-none-any.whl", hash = "sha256:0030d386a9a06dee3565298b4a734b68589749a544acbb6c412dc9e2489ec6ec"}, {file = "networkx-3.5.tar.gz", hash = "sha256:d4c6f9cf81f52d69230866796b82afbccdec3db7ae4fbd1b65ea750feed50037"}, @@ -2280,7 +2257,6 @@ description = "Node.js virtual environment builder" optional = true python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, @@ -2333,7 +2309,6 @@ description = "A small Python package for determining appropriate platform-speci optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, @@ -2386,7 +2361,6 @@ description = "A framework for managing and maintaining multi-language pre-commi optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"}, {file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"}, @@ -2406,7 +2380,6 @@ description = "Library for building powerful interactive command lines in Python optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, @@ -2538,7 +2511,6 @@ description = "Create torrents via command line!" optional = true python-versions = "<4,>=3.5" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "py3createtorrent-1.2.1-py3-none-any.whl", hash = "sha256:dede7e87d869d2b013a633486f5f1fcedd6f057ff9f12d9ba9a370acfc496311"}, {file = "py3createtorrent-1.2.1.tar.gz", hash = "sha256:04d801adbbe8beb37547104935bd1fb81e02459341b524f85852629fa7dd326d"}, @@ -2554,7 +2526,6 @@ description = "C parser in Python" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" groups = ["main"] -markers = "platform_python_implementation != \"PyPy\" or extra == \"legacy-keyring\"" files = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, @@ -2567,7 +2538,6 @@ description = "Cryptographic library for Python" optional = true python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" groups = ["main"] -markers = "extra == \"legacy-keyring\"" files = [ {file = "pycryptodome-3.20.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:f0e6d631bae3f231d3634f91ae4da7a960f7ff87f2865b2d2b831af1dfb04e9a"}, {file = "pycryptodome-3.20.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:baee115a9ba6c5d2709a1e88ffe62b73ecc044852a925dcb67713a288c4ec70f"}, @@ -2610,7 +2580,6 @@ description = "Python interface to Graphviz's Dot" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pydot-3.0.4-py3-none-any.whl", hash = "sha256:bfa9c3fc0c44ba1d132adce131802d7df00429d1a79cc0346b0a5cd374dbe9c6"}, {file = "pydot-3.0.4.tar.gz", hash = "sha256:3ce88b2558f3808b0376f22bfa6c263909e1c3981e2a7b629b65b451eee4a25d"}, @@ -2646,7 +2615,7 @@ description = "PyInstaller bundles a Python application and all its dependencies optional = true python-versions = "<3.14,>=3.8" groups = ["main"] -markers = "python_version <= \"3.12\" and extra == \"dev\"" +markers = "extra == \"dev\" and python_version <= \"3.12\"" files = [ {file = "pyinstaller-6.14.1-py3-none-macosx_10_13_universal2.whl", hash = "sha256:da559cfe4f7a20a7ebdafdf12ea2a03ea94d3caa49736ef53ee2c155d78422c9"}, {file = "pyinstaller-6.14.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:f040d1e3d42af3730104078d10d4a8ca3350bd1c78de48f12e1b26f761e0cbc3"}, @@ -2683,7 +2652,7 @@ description = "Community maintained hooks for PyInstaller" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "python_version <= \"3.12\" and extra == \"dev\"" +markers = "extra == \"dev\" and python_version <= \"3.12\"" files = [ {file = "pyinstaller_hooks_contrib-2025.5-py3-none-any.whl", hash = "sha256:ebfae1ba341cb0002fb2770fad0edf2b3e913c2728d92df7ad562260988ca373"}, {file = "pyinstaller_hooks_contrib-2025.5.tar.gz", hash = "sha256:707386770b8fe066c04aad18a71bc483c7b25e18b4750a756999f7da2ab31982"}, @@ -2701,7 +2670,6 @@ description = "pyparsing module - Classes and methods to define and execute pars optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pyparsing-3.2.3-py3-none-any.whl", hash = "sha256:a749938e02d6fd0b59b356ca504a24982314bb090c383e3cf201c95ef7e2bfcf"}, {file = "pyparsing-3.2.3.tar.gz", hash = "sha256:b9c13f1ab8b3b542f72e28f634bad4de758ab3ce4546e4301970ad6fa77c38be"}, @@ -2717,7 +2685,6 @@ description = "Wrappers to call pyproject.toml-based build backend hooks." optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pyproject_hooks-1.0.0-py3-none-any.whl", hash = "sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8"}, {file = "pyproject_hooks-1.0.0.tar.gz", hash = "sha256:f271b298b97f5955d53fb12b72c1fb1948c22c1a6b70b315c54cedaca0264ef5"}, @@ -2757,7 +2724,6 @@ description = "Pytest plugin for measuring coverage." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, @@ -2778,7 +2744,6 @@ description = "Thin-wrapper around the mock package for easier use with pytest" optional = true python-versions = ">=3.8" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pytest_mock-3.14.1-py3-none-any.whl", hash = "sha256:178aefcd11307d874b4cd3100344e7e2d888d9791a6a1d9bfe90fbc1b74fd1d0"}, {file = "pytest_mock-3.14.1.tar.gz", hash = "sha256:159e9edac4c451ce77a5cdb9fc5d1100708d2dd4ba3c3df572f14097351af80e"}, @@ -2797,7 +2762,7 @@ description = "Pytest plugin for analyzing resource usage." optional = true python-versions = ">=3.5" groups = ["main"] -markers = "sys_platform == \"linux\" and extra == \"dev\"" +markers = "extra == \"dev\" and sys_platform == \"linux\"" files = [ {file = "pytest-monitor-1.6.6.tar.gz", hash = "sha256:b0c44dc44a2d6cdd19f84caa18fafeb1227e2b33bcbd11a2071dacd3763e1b6f"}, {file = "pytest_monitor-1.6.6-py3-none-any.whl", hash = "sha256:5be37d14aa423fe97af94bd44e3a47a551bd5d94d64921974580bbaadc1c1c94"}, @@ -2817,7 +2782,6 @@ description = "pytest xdist plugin for distributed testing, most importantly acr optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "pytest_xdist-3.8.0-py3-none-any.whl", hash = "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88"}, {file = "pytest_xdist-3.8.0.tar.gz", hash = "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1"}, @@ -2955,7 +2919,7 @@ description = "Python HTTP for Humans." optional = true python-versions = ">=3.8" groups = ["main"] -markers = "sys_platform == \"linux\" and extra == \"dev\"" +markers = "extra == \"dev\" and sys_platform == \"linux\"" files = [ {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, @@ -2978,7 +2942,6 @@ description = "Render rich text, tables, progress bars, syntax highlighting, mar optional = true python-versions = ">=3.8.0" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90"}, {file = "rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098"}, @@ -2994,31 +2957,30 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "ruff" -version = "0.11.11" +version = "0.12.4" description = "An extremely fast Python linter and code formatter, written in Rust." optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ - {file = "ruff-0.11.11-py3-none-linux_armv6l.whl", hash = "sha256:9924e5ae54125ed8958a4f7de320dab7380f6e9fa3195e3dc3b137c6842a0092"}, - {file = "ruff-0.11.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c8a93276393d91e952f790148eb226658dd275cddfde96c6ca304873f11d2ae4"}, - {file = "ruff-0.11.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d6e333dbe2e6ae84cdedefa943dfd6434753ad321764fd937eef9d6b62022bcd"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7885d9a5e4c77b24e8c88aba8c80be9255fa22ab326019dac2356cff42089fc6"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1b5ab797fcc09121ed82e9b12b6f27e34859e4227080a42d090881be888755d4"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e231ff3132c1119ece836487a02785f099a43992b95c2f62847d29bace3c75ac"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:a97c9babe1d4081037a90289986925726b802d180cca784ac8da2bbbc335f709"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8c4ddcbe8a19f59f57fd814b8b117d4fcea9bee7c0492e6cf5fdc22cfa563c8"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6224076c344a7694c6fbbb70d4f2a7b730f6d47d2a9dc1e7f9d9bb583faf390b"}, - {file = "ruff-0.11.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:882821fcdf7ae8db7a951df1903d9cb032bbe838852e5fc3c2b6c3ab54e39875"}, - {file = "ruff-0.11.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:dcec2d50756463d9df075a26a85a6affbc1b0148873da3997286caf1ce03cae1"}, - {file = "ruff-0.11.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:99c28505ecbaeb6594701a74e395b187ee083ee26478c1a795d35084d53ebd81"}, - {file = "ruff-0.11.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:9263f9e5aa4ff1dec765e99810f1cc53f0c868c5329b69f13845f699fe74f639"}, - {file = "ruff-0.11.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:64ac6f885e3ecb2fdbb71de2701d4e34526651f1e8503af8fb30d4915a3fe345"}, - {file = "ruff-0.11.11-py3-none-win32.whl", hash = "sha256:1adcb9a18802268aaa891ffb67b1c94cd70578f126637118e8099b8e4adcf112"}, - {file = "ruff-0.11.11-py3-none-win_amd64.whl", hash = "sha256:748b4bb245f11e91a04a4ff0f96e386711df0a30412b9fe0c74d5bdc0e4a531f"}, - {file = "ruff-0.11.11-py3-none-win_arm64.whl", hash = "sha256:6c51f136c0364ab1b774767aa8b86331bd8e9d414e2d107db7a2189f35ea1f7b"}, - {file = "ruff-0.11.11.tar.gz", hash = "sha256:7774173cc7c1980e6bf67569ebb7085989a78a103922fb83ef3dfe230cd0687d"}, + {file = "ruff-0.12.4-py3-none-linux_armv6l.whl", hash = "sha256:cb0d261dac457ab939aeb247e804125a5d521b21adf27e721895b0d3f83a0d0a"}, + {file = "ruff-0.12.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:55c0f4ca9769408d9b9bac530c30d3e66490bd2beb2d3dae3e4128a1f05c7442"}, + {file = "ruff-0.12.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a8224cc3722c9ad9044da7f89c4c1ec452aef2cfe3904365025dd2f51daeae0e"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9949d01d64fa3672449a51ddb5d7548b33e130240ad418884ee6efa7a229586"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:be0593c69df9ad1465e8a2d10e3defd111fdb62dcd5be23ae2c06da77e8fcffb"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7dea966bcb55d4ecc4cc3270bccb6f87a337326c9dcd3c07d5b97000dbff41c"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:afcfa3ab5ab5dd0e1c39bf286d829e042a15e966b3726eea79528e2e24d8371a"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c057ce464b1413c926cdb203a0f858cd52f3e73dcb3270a3318d1630f6395bb3"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e64b90d1122dc2713330350626b10d60818930819623abbb56535c6466cce045"}, + {file = "ruff-0.12.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2abc48f3d9667fdc74022380b5c745873499ff827393a636f7a59da1515e7c57"}, + {file = "ruff-0.12.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2b2449dc0c138d877d629bea151bee8c0ae3b8e9c43f5fcaafcd0c0d0726b184"}, + {file = "ruff-0.12.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:56e45bb11f625db55f9b70477062e6a1a04d53628eda7784dce6e0f55fd549eb"}, + {file = "ruff-0.12.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:478fccdb82ca148a98a9ff43658944f7ab5ec41c3c49d77cd99d44da019371a1"}, + {file = "ruff-0.12.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0fc426bec2e4e5f4c4f182b9d2ce6a75c85ba9bcdbe5c6f2a74fcb8df437df4b"}, + {file = "ruff-0.12.4-py3-none-win32.whl", hash = "sha256:4de27977827893cdfb1211d42d84bc180fceb7b72471104671c59be37041cf93"}, + {file = "ruff-0.12.4-py3-none-win_amd64.whl", hash = "sha256:fe0b9e9eb23736b453143d72d2ceca5db323963330d5b7859d60d101147d461a"}, + {file = "ruff-0.12.4-py3-none-win_arm64.whl", hash = "sha256:0618ec4442a83ab545e5b71202a5c0ed7791e8471435b94e655b570a5031a98e"}, + {file = "ruff-0.12.4.tar.gz", hash = "sha256:13efa16df6c6eeb7d0f091abae50f58e9522f3843edb40d56ad52a5a4a4b6873"}, ] [[package]] @@ -3180,14 +3142,14 @@ test = ["pytest"] [[package]] name = "setuptools" -version = "80.8.0" +version = "80.9.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" groups = ["main"] files = [ - {file = "setuptools-80.8.0-py3-none-any.whl", hash = "sha256:95a60484590d24103af13b686121328cc2736bee85de8936383111e421b9edc0"}, - {file = "setuptools-80.8.0.tar.gz", hash = "sha256:49f7af965996f26d43c8ae34539c8d99c5042fbff34302ea151eaa9c207cd257"}, + {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, + {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, ] [package.extras] @@ -3218,7 +3180,6 @@ description = "A pure Python implementation of a sliding window memory map manag optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, @@ -3255,7 +3216,7 @@ description = "A list of Python Standard Libraries (2.7 through 3.13)." optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\" and python_version < \"3.10\"" +markers = "python_version < \"3.10\"" files = [ {file = "stdlib_list-0.11.1-py3-none-any.whl", hash = "sha256:9029ea5e3dfde8cd4294cfd4d1797be56a67fc4693c606181730148c3fd1da29"}, {file = "stdlib_list-0.11.1.tar.gz", hash = "sha256:95ebd1d73da9333bba03ccc097f5bac05e3aa03e6822a0c0290f87e1047f1857"}, @@ -3275,7 +3236,6 @@ description = "A Python tool to maintain a modular package architecture." optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "tach-0.29.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:517f33d18d381326a775d101650e576c6922db53b2c336192db7db88b9a3521d"}, {file = "tach-0.29.0-cp37-abi3-macosx_11_0_arm64.whl", hash = "sha256:d984f54bebba0e4c981d2a08c3e4cdf76c3b5f3126e2f593a0faaed9d218552a"}, @@ -3311,7 +3271,6 @@ description = "A lil' TOML parser" optional = false python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\" or python_version < \"3.11\"" files = [ {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, @@ -3324,7 +3283,6 @@ description = "A lil' TOML writer" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90"}, {file = "tomli_w-1.2.0.tar.gz", hash = "sha256:2dd14fac5a47c27be9cd4c976af5a12d87fb1f0b4512f81d69cce3b35ae25021"}, @@ -3332,15 +3290,14 @@ files = [ [[package]] name = "types-aiofiles" -version = "24.1.0.20250606" +version = "24.1.0.20250708" description = "Typing stubs for aiofiles" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ - {file = "types_aiofiles-24.1.0.20250606-py3-none-any.whl", hash = "sha256:e568c53fb9017c80897a9aa15c74bf43b7ee90e412286ec1e0912b6e79301aee"}, - {file = "types_aiofiles-24.1.0.20250606.tar.gz", hash = "sha256:48f9e26d2738a21e0b0f19381f713dcdb852a36727da8414b1ada145d40a18fe"}, + {file = "types_aiofiles-24.1.0.20250708-py3-none-any.whl", hash = "sha256:07f8f06465fd415d9293467d1c66cd074b2c3b62b679e26e353e560a8cf63720"}, + {file = "types_aiofiles-24.1.0.20250708.tar.gz", hash = "sha256:c8207ed7385491ce5ba94da02658164ebd66b69a44e892288c9f20cbbf5284ff"}, ] [[package]] @@ -3350,7 +3307,6 @@ description = "Typing stubs for cryptography" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "types-cryptography-3.3.23.2.tar.gz", hash = "sha256:09cc53f273dd4d8c29fa7ad11fefd9b734126d467960162397bc5e3e604dea75"}, {file = "types_cryptography-3.3.23.2-py3-none-any.whl", hash = "sha256:b965d548f148f8e87f353ccf2b7bd92719fdf6c845ff7cedf2abb393a0643e4f"}, @@ -3363,7 +3319,6 @@ description = "Typing stubs for PyYAML" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "types_pyyaml-6.0.12.20250516-py3-none-any.whl", hash = "sha256:8478208feaeb53a34cb5d970c56a7cd76b72659442e733e268a94dc72b2d0530"}, {file = "types_pyyaml-6.0.12.20250516.tar.gz", hash = "sha256:9f21a70216fc0fa1b216a8176db5f9e0af6eb35d2f2932acb87689d03a5bf6ba"}, @@ -3376,7 +3331,6 @@ description = "Typing stubs for setuptools" optional = true python-versions = ">=3.9" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "types_setuptools-80.9.0.20250529-py3-none-any.whl", hash = "sha256:00dfcedd73e333a430e10db096e4d46af93faf9314f832f13b6bbe3d6757e95f"}, {file = "types_setuptools-80.9.0.20250529.tar.gz", hash = "sha256:79e088ba0cba2186c8d6499cbd3e143abb142d28a44b042c28d3148b1e353c91"}, @@ -3438,7 +3392,6 @@ description = "Virtual Python Environment builder" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "virtualenv-20.26.6-py3-none-any.whl", hash = "sha256:7345cc5b25405607a624d8418154577459c3e0277f5466dd79c49d5e492995f2"}, {file = "virtualenv-20.26.6.tar.gz", hash = "sha256:280aede09a2a5c317e409a00102e7077c6432c5a38f0ef938e643805a7ad2c48"}, @@ -3503,7 +3456,6 @@ description = "Measures the displayed width of unicode strings in a terminal" optional = true python-versions = "*" groups = ["main"] -markers = "extra == \"dev\"" files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -3516,7 +3468,7 @@ description = "A built-package format for Python" optional = true python-versions = ">=3.7" groups = ["main"] -markers = "sys_platform == \"linux\" and extra == \"dev\"" +markers = "extra == \"dev\" and sys_platform == \"linux\"" files = [ {file = "wheel-0.41.2-py3-none-any.whl", hash = "sha256:75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8"}, {file = "wheel-0.41.2.tar.gz", hash = "sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985"}, @@ -3785,4 +3737,4 @@ upnp = ["miniupnpc"] [metadata] lock-version = "2.1" python-versions = ">=3.9, <4" -content-hash = "a0b086bb169964bc3c677ffeceb8d2d8a3e5c13d0eb245f685ea49538cab48a5" +content-hash = "1ae7dc9d5aaaee0970c3ef5752cd29841350d65b788486a107dde51a801b2f8b" diff --git a/pyproject.toml b/pyproject.toml index ba314d0aab..85180fac74 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -109,7 +109,7 @@ miniupnpc = {version = ">=2.3.2, <3", source = "chia", optional = true} # {version=">=1.26.4", python = ">=3.9", optional = true}] ruff = { version = ">=0.8.1", optional = true } -[tool.poetry.extras] +[project.optional-dependencies] dev = ["aiohttp_cors", "build", "coverage", "diff-cover", "mypy", "pre-commit", "py3createtorrent", "pyinstaller", "pytest", "pytest-cov", "pytest-mock", "pytest-monitor", "pytest-xdist", "ruff", "tach", "types-aiofiles", "types-cryptography", "types-pyyaml", "types-setuptools", "lxml"] upnp = ["miniupnpc"] legacy_keyring = ["keyrings.cryptfile"] diff --git a/tools/validate_rpcs.py b/tools/validate_rpcs.py index c375fd891c..aa77347f45 100755 --- a/tools/validate_rpcs.py +++ b/tools/validate_rpcs.py @@ -153,9 +153,11 @@ async def node_spends_with_conditions( block_hash: bytes32, height: int, ) -> None: - result = await node_client.get_block_spends_with_conditions(block_hash) - if result is None: + try: + await node_client.get_block_spends_with_conditions(block_hash) + except Exception as e: print(f"ERROR: [{height}] get_block_spends_with_conditions returned invalid result") + raise e async def node_block_spends( @@ -163,9 +165,11 @@ async def node_block_spends( block_hash: bytes32, height: int, ) -> None: - result = await node_client.get_block_spends(block_hash) - if result is None: + try: + await node_client.get_block_spends(block_hash) + except Exception as e: print(f"ERROR: [{height}] get_block_spends returned invalid result") + raise e async def node_additions_removals( @@ -173,9 +177,11 @@ async def node_additions_removals( block_hash: bytes32, height: int, ) -> None: - response = await node_client.get_additions_and_removals(block_hash) - if response is None: + try: + await node_client.get_additions_and_removals(block_hash) + except Exception as e: print(f"ERROR: [{height}] get_additions_and_removals returned invalid result") + raise e async def cli_async(