chia-blockchain 2.5.0rc1__py3-none-any.whl → 2.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chia/_tests/README.md +1 -1
- chia/_tests/blockchain/blockchain_test_utils.py +24 -26
- chia/_tests/blockchain/test_augmented_chain.py +6 -8
- chia/_tests/blockchain/test_blockchain.py +409 -307
- chia/_tests/blockchain/test_blockchain_transactions.py +56 -75
- chia/_tests/blockchain/test_build_chains.py +11 -13
- chia/_tests/blockchain/test_get_block_generator.py +8 -8
- chia/_tests/blockchain/test_lookup_fork_chain.py +3 -4
- chia/_tests/build-init-files.py +3 -4
- chia/_tests/build-job-matrix.py +9 -9
- chia/_tests/check_sql_statements.py +2 -3
- chia/_tests/clvm/benchmark_costs.py +1 -1
- chia/_tests/clvm/coin_store.py +7 -5
- chia/_tests/clvm/test_chialisp_deserialization.py +8 -8
- chia/_tests/clvm/test_condition_codes.py +2 -2
- chia/_tests/clvm/test_curry_and_treehash.py +2 -4
- chia/_tests/clvm/test_message_conditions.py +184 -0
- chia/_tests/clvm/test_puzzle_compression.py +1 -2
- chia/_tests/clvm/test_puzzle_drivers.py +3 -3
- chia/_tests/clvm/test_puzzles.py +13 -18
- chia/_tests/clvm/test_singletons.py +17 -17
- chia/_tests/clvm/test_spend_sim.py +7 -7
- chia/_tests/cmds/cmd_test_utils.py +42 -45
- chia/_tests/cmds/conftest.py +2 -2
- chia/_tests/cmds/test_click_types.py +21 -16
- chia/_tests/cmds/test_cmd_framework.py +255 -35
- chia/_tests/cmds/test_cmds_util.py +2 -2
- chia/_tests/cmds/test_daemon.py +3 -3
- chia/_tests/cmds/test_dev_gh.py +131 -0
- chia/_tests/cmds/test_farm_cmd.py +1 -2
- chia/_tests/cmds/test_show.py +6 -6
- chia/_tests/cmds/test_tx_config_args.py +2 -1
- chia/_tests/cmds/wallet/test_dao.py +23 -23
- chia/_tests/cmds/wallet/test_did.py +29 -29
- chia/_tests/cmds/wallet/test_nft.py +24 -23
- chia/_tests/cmds/wallet/test_notifications.py +8 -8
- chia/_tests/cmds/wallet/test_tx_decorators.py +3 -3
- chia/_tests/cmds/wallet/test_vcs.py +97 -73
- chia/_tests/cmds/wallet/test_wallet.py +74 -75
- chia/_tests/cmds/wallet/test_wallet_check.py +5 -7
- chia/_tests/conftest.py +153 -38
- chia/_tests/connection_utils.py +7 -6
- chia/_tests/core/cmds/test_beta.py +3 -3
- chia/_tests/core/cmds/test_keys.py +6 -6
- chia/_tests/core/cmds/test_wallet.py +3 -3
- chia/_tests/core/consensus/test_block_creation.py +3 -5
- chia/_tests/core/custom_types/test_coin.py +1 -3
- chia/_tests/core/custom_types/test_spend_bundle.py +3 -4
- chia/_tests/core/daemon/test_daemon.py +58 -58
- chia/_tests/core/daemon/test_keychain_proxy.py +2 -1
- chia/_tests/core/data_layer/conftest.py +4 -3
- chia/_tests/core/data_layer/test_data_cli.py +1 -2
- chia/_tests/core/data_layer/test_data_layer.py +5 -5
- chia/_tests/core/data_layer/test_data_layer_util.py +8 -9
- chia/_tests/core/data_layer/test_data_rpc.py +75 -93
- chia/_tests/core/data_layer/test_data_store.py +38 -37
- chia/_tests/core/data_layer/test_data_store_schema.py +11 -11
- chia/_tests/core/data_layer/util.py +11 -10
- chia/_tests/core/farmer/test_farmer_api.py +6 -4
- chia/_tests/core/full_node/full_sync/test_full_sync.py +5 -10
- chia/_tests/core/full_node/ram_db.py +2 -2
- chia/_tests/core/full_node/stores/test_block_store.py +113 -11
- chia/_tests/core/full_node/stores/test_coin_store.py +37 -28
- chia/_tests/core/full_node/stores/test_full_node_store.py +34 -30
- chia/_tests/core/full_node/stores/test_hint_store.py +3 -4
- chia/_tests/core/full_node/test_address_manager.py +2 -2
- chia/_tests/core/full_node/test_block_height_map.py +1 -1
- chia/_tests/core/full_node/test_conditions.py +10 -12
- chia/_tests/core/full_node/test_full_node.py +2077 -1822
- chia/_tests/core/full_node/test_generator_tools.py +4 -4
- chia/_tests/core/full_node/test_hint_management.py +2 -2
- chia/_tests/core/full_node/test_performance.py +2 -5
- chia/_tests/core/full_node/test_subscriptions.py +4 -4
- chia/_tests/core/full_node/test_tx_processing_queue.py +5 -4
- chia/_tests/core/make_block_generator.py +5 -7
- chia/_tests/core/mempool/test_mempool.py +205 -208
- chia/_tests/core/mempool/test_mempool_fee_protocol.py +5 -5
- chia/_tests/core/mempool/test_mempool_item_queries.py +2 -4
- chia/_tests/core/mempool/test_mempool_manager.py +109 -80
- chia/_tests/core/mempool/test_mempool_performance.py +3 -4
- chia/_tests/core/mempool/test_singleton_fast_forward.py +12 -12
- chia/_tests/core/server/flood.py +6 -4
- chia/_tests/core/server/serve.py +10 -7
- chia/_tests/core/server/test_api_protocol.py +21 -0
- chia/_tests/core/server/test_capabilities.py +3 -5
- chia/_tests/core/server/test_dos.py +15 -16
- chia/_tests/core/server/test_loop.py +14 -10
- chia/_tests/core/server/test_node_discovery.py +1 -2
- chia/_tests/core/server/test_rate_limits.py +156 -44
- chia/_tests/core/server/test_server.py +8 -7
- chia/_tests/core/services/test_services.py +59 -37
- chia/_tests/core/ssl/test_ssl.py +5 -3
- chia/_tests/core/test_cost_calculation.py +5 -6
- chia/_tests/core/test_crawler.py +2 -2
- chia/_tests/core/test_db_conversion.py +5 -4
- chia/_tests/core/test_db_validation.py +6 -5
- chia/_tests/core/test_farmer_harvester_rpc.py +8 -7
- chia/_tests/core/test_filter.py +3 -5
- chia/_tests/core/test_full_node_rpc.py +64 -90
- chia/_tests/core/test_merkle_set.py +10 -10
- chia/_tests/core/test_program.py +2 -4
- chia/_tests/core/test_rpc_util.py +1 -2
- chia/_tests/core/test_seeder.py +124 -12
- chia/_tests/core/util/test_block_cache.py +5 -5
- chia/_tests/core/util/test_cached_bls.py +3 -3
- chia/_tests/core/util/test_config.py +13 -13
- chia/_tests/core/util/test_files.py +2 -2
- chia/_tests/core/util/test_jsonify.py +9 -9
- chia/_tests/core/util/test_keychain.py +13 -5
- chia/_tests/core/util/test_keyring_wrapper.py +6 -5
- chia/_tests/core/util/test_log_exceptions.py +3 -3
- chia/_tests/core/util/test_streamable.py +38 -38
- chia/_tests/db/test_db_wrapper.py +13 -12
- chia/_tests/environments/common.py +2 -2
- chia/_tests/environments/full_node.py +2 -2
- chia/_tests/environments/wallet.py +109 -48
- chia/_tests/farmer_harvester/test_farmer.py +35 -35
- chia/_tests/farmer_harvester/test_farmer_harvester.py +17 -17
- chia/_tests/farmer_harvester/test_filter_prefix_bits.py +6 -5
- chia/_tests/farmer_harvester/test_third_party_harvesters.py +73 -46
- chia/_tests/fee_estimation/test_fee_estimation_integration.py +8 -8
- chia/_tests/fee_estimation/test_fee_estimation_rpc.py +47 -47
- chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +6 -7
- chia/_tests/fee_estimation/test_mempoolitem_height_added.py +11 -11
- chia/_tests/generator/test_compression.py +13 -30
- chia/_tests/generator/test_generator_types.py +3 -3
- chia/_tests/generator/test_rom.py +7 -9
- chia/_tests/plot_sync/test_delta.py +2 -3
- chia/_tests/plot_sync/test_plot_sync.py +25 -24
- chia/_tests/plot_sync/test_receiver.py +9 -9
- chia/_tests/plot_sync/test_sender.py +1 -1
- chia/_tests/plot_sync/test_sync_simulated.py +27 -26
- chia/_tests/plot_sync/util.py +2 -1
- chia/_tests/plotting/test_plot_manager.py +54 -11
- chia/_tests/plotting/util.py +2 -3
- chia/_tests/pools/test_pool_cli_parsing.py +128 -0
- chia/_tests/pools/test_pool_cmdline.py +993 -15
- chia/_tests/pools/test_pool_config.py +3 -5
- chia/_tests/pools/test_pool_puzzles_lifecycle.py +10 -11
- chia/_tests/pools/test_pool_rpc.py +203 -90
- chia/_tests/pools/test_pool_wallet.py +12 -8
- chia/_tests/pools/test_wallet_pool_store.py +3 -3
- chia/_tests/process_junit.py +16 -17
- chia/_tests/rpc/test_rpc_client.py +59 -2
- chia/_tests/rpc/test_rpc_server.py +183 -0
- chia/_tests/simulation/test_simulation.py +5 -5
- chia/_tests/simulation/test_simulator.py +8 -10
- chia/_tests/simulation/test_start_simulator.py +5 -4
- chia/_tests/timelord/test_new_peak.py +19 -19
- chia/_tests/tools/test_run_block.py +1 -2
- chia/_tests/tools/test_virtual_project.py +591 -0
- chia/_tests/util/benchmark_cost.py +9 -9
- chia/_tests/util/benchmarks.py +1 -2
- chia/_tests/util/blockchain.py +12 -11
- chia/_tests/util/blockchain_mock.py +15 -15
- chia/_tests/util/build_network_protocol_files.py +12 -12
- chia/_tests/util/db_connection.py +3 -2
- chia/_tests/util/full_sync.py +14 -6
- chia/_tests/util/gen_ssl_certs.py +4 -5
- chia/_tests/util/generator_tools_testing.py +5 -7
- chia/_tests/util/get_name_puzzle_conditions.py +52 -0
- chia/_tests/util/key_tool.py +2 -3
- chia/_tests/util/misc.py +59 -106
- chia/_tests/util/network_protocol_data.py +7 -9
- chia/_tests/util/protocol_messages_json.py +112 -111
- chia/_tests/util/rpc.py +3 -0
- chia/_tests/util/run_block.py +16 -16
- chia/_tests/util/setup_nodes.py +25 -23
- chia/{clvm → _tests/util}/spend_sim.py +59 -55
- chia/_tests/util/split_managers.py +12 -9
- chia/_tests/util/temp_file.py +1 -1
- chia/_tests/util/test_action_scope.py +2 -1
- chia/_tests/util/test_async_pool.py +8 -8
- chia/_tests/util/test_build_job_matrix.py +2 -3
- chia/_tests/util/test_condition_tools.py +4 -6
- chia/_tests/util/test_config.py +5 -5
- chia/_tests/util/test_dump_keyring.py +1 -1
- chia/_tests/util/test_full_block_utils.py +19 -11
- chia/_tests/util/test_limited_semaphore.py +4 -3
- chia/_tests/util/test_logging_filter.py +2 -3
- chia/_tests/util/test_misc.py +29 -28
- chia/_tests/util/test_network.py +32 -31
- chia/_tests/util/test_network_protocol_files.py +2 -3
- chia/_tests/util/test_network_protocol_json.py +1 -0
- chia/_tests/util/test_network_protocol_test.py +18 -19
- chia/_tests/util/test_paginator.py +3 -4
- chia/_tests/util/test_pprint.py +1 -1
- chia/_tests/util/test_priority_mutex.py +18 -17
- chia/_tests/util/test_recursive_replace.py +2 -2
- chia/_tests/util/test_testnet_overrides.py +3 -3
- chia/_tests/util/test_timing.py +1 -1
- chia/_tests/util/test_trusted_peer.py +2 -2
- chia/_tests/util/time_out_assert.py +43 -6
- chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +13 -13
- chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +1 -1
- chia/_tests/wallet/cat_wallet/test_cat_wallet.py +117 -29
- chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +15 -15
- chia/_tests/wallet/cat_wallet/test_trades.py +50 -28
- chia/_tests/wallet/clawback/test_clawback_decorator.py +3 -5
- chia/_tests/wallet/clawback/test_clawback_lifecycle.py +6 -6
- chia/_tests/wallet/clawback/test_clawback_metadata.py +1 -2
- chia/_tests/wallet/conftest.py +135 -74
- chia/_tests/wallet/dao_wallet/test_dao_clvm.py +25 -17
- chia/_tests/wallet/dao_wallet/test_dao_wallets.py +75 -75
- chia/_tests/wallet/db_wallet/test_db_graftroot.py +10 -12
- chia/_tests/wallet/db_wallet/test_dl_offers.py +6 -6
- chia/_tests/wallet/db_wallet/test_dl_wallet.py +18 -18
- chia/_tests/wallet/did_wallet/test_did.py +1277 -474
- chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +12 -11
- chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +115 -105
- chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +6 -7
- chia/_tests/wallet/nft_wallet/test_nft_offers.py +16 -16
- chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +3 -3
- chia/_tests/wallet/nft_wallet/test_nft_wallet.py +38 -12
- chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +1 -1
- chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +31 -33
- chia/_tests/wallet/rpc/test_wallet_rpc.py +218 -171
- chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +36 -37
- chia/_tests/wallet/sync/test_wallet_sync.py +241 -78
- chia/_tests/wallet/test_address_type.py +20 -20
- chia/_tests/wallet/test_clvm_streamable.py +5 -5
- chia/_tests/wallet/test_coin_management.py +354 -0
- chia/_tests/wallet/test_coin_selection.py +34 -35
- chia/_tests/wallet/test_conditions.py +28 -16
- chia/_tests/wallet/test_debug_spend_bundle.py +156 -14
- chia/_tests/wallet/test_new_wallet_protocol.py +29 -31
- chia/_tests/wallet/test_nft_store.py +1 -2
- chia/_tests/wallet/test_notifications.py +2 -2
- chia/_tests/wallet/test_offer_parsing_performance.py +1 -1
- chia/_tests/wallet/test_puzzle_store.py +2 -3
- chia/_tests/wallet/test_sign_coin_spends.py +3 -3
- chia/_tests/wallet/test_signer_protocol.py +33 -34
- chia/_tests/wallet/test_singleton_lifecycle_fast.py +29 -29
- chia/_tests/wallet/test_taproot.py +1 -1
- chia/_tests/wallet/test_transaction_store.py +23 -19
- chia/_tests/wallet/test_util.py +36 -32
- chia/_tests/wallet/test_wallet.py +37 -37
- chia/_tests/wallet/test_wallet_action_scope.py +8 -8
- chia/_tests/wallet/test_wallet_blockchain.py +4 -6
- chia/_tests/wallet/test_wallet_coin_store.py +34 -34
- chia/_tests/wallet/test_wallet_node.py +69 -72
- chia/_tests/wallet/test_wallet_retry.py +3 -3
- chia/_tests/wallet/test_wallet_state_manager.py +12 -5
- chia/_tests/wallet/test_wallet_trade_store.py +2 -2
- chia/_tests/wallet/test_wallet_utils.py +5 -4
- chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +3 -3
- chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +18 -18
- chia/_tests/wallet/vc_wallet/test_vc_wallet.py +69 -40
- chia/_tests/wallet/wallet_block_tools.py +27 -27
- chia/_tests/weight_proof/test_weight_proof.py +30 -30
- chia/apis.py +19 -0
- chia/cmds/beta.py +8 -7
- chia/cmds/beta_funcs.py +15 -11
- chia/cmds/check_wallet_db.py +29 -27
- chia/cmds/chia.py +17 -9
- chia/cmds/cmd_classes.py +87 -79
- chia/cmds/cmd_helpers.py +242 -0
- chia/cmds/cmds_util.py +56 -66
- chia/cmds/coin_funcs.py +168 -153
- chia/cmds/coins.py +156 -194
- chia/cmds/configure.py +4 -3
- chia/cmds/dao.py +89 -33
- chia/cmds/dao_funcs.py +55 -33
- chia/cmds/data.py +7 -6
- chia/cmds/data_funcs.py +26 -21
- chia/cmds/db.py +4 -3
- chia/cmds/db_backup_func.py +2 -2
- chia/cmds/db_upgrade_func.py +3 -3
- chia/cmds/db_validate_func.py +2 -2
- chia/cmds/dev.py +2 -0
- chia/cmds/farm.py +18 -5
- chia/cmds/farm_funcs.py +17 -24
- chia/cmds/gh.py +275 -0
- chia/cmds/init.py +4 -11
- chia/cmds/init_funcs.py +9 -9
- chia/cmds/installers.py +5 -3
- chia/cmds/keys.py +56 -39
- chia/cmds/keys_funcs.py +30 -31
- chia/cmds/netspace.py +6 -3
- chia/cmds/netspace_funcs.py +3 -2
- chia/cmds/param_types.py +16 -6
- chia/cmds/passphrase.py +8 -7
- chia/cmds/passphrase_funcs.py +7 -61
- chia/cmds/peer.py +2 -1
- chia/cmds/peer_funcs.py +5 -5
- chia/cmds/plotnft.py +207 -153
- chia/cmds/plotnft_funcs.py +205 -174
- chia/cmds/plots.py +14 -6
- chia/cmds/plotters.py +2 -1
- chia/cmds/rpc.py +48 -28
- chia/cmds/show.py +2 -1
- chia/cmds/show_funcs.py +7 -6
- chia/cmds/signer.py +50 -58
- chia/cmds/sim.py +22 -14
- chia/cmds/sim_funcs.py +11 -11
- chia/cmds/start.py +3 -3
- chia/cmds/start_funcs.py +9 -12
- chia/cmds/stop.py +4 -3
- chia/cmds/units.py +1 -3
- chia/cmds/wallet.py +252 -96
- chia/cmds/wallet_funcs.py +217 -143
- chia/consensus/block_body_validation.py +133 -86
- chia/consensus/block_creation.py +42 -21
- chia/consensus/block_header_validation.py +32 -37
- chia/consensus/block_record.py +1 -2
- chia/consensus/blockchain.py +167 -180
- chia/consensus/blockchain_interface.py +10 -10
- chia/consensus/constants.py +2 -2
- chia/consensus/default_constants.py +3 -4
- chia/consensus/difficulty_adjustment.py +5 -5
- chia/consensus/find_fork_point.py +5 -5
- chia/consensus/full_block_to_block_record.py +4 -4
- chia/consensus/get_block_challenge.py +2 -2
- chia/consensus/get_block_generator.py +4 -3
- chia/consensus/multiprocess_validation.py +207 -304
- chia/consensus/vdf_info_computation.py +3 -3
- chia/daemon/client.py +46 -27
- chia/daemon/keychain_proxy.py +10 -9
- chia/daemon/keychain_server.py +18 -18
- chia/daemon/server.py +103 -113
- chia/daemon/windows_signal.py +2 -2
- chia/data_layer/data_layer.py +64 -76
- chia/data_layer/data_layer_api.py +8 -0
- chia/data_layer/data_layer_errors.py +3 -3
- chia/data_layer/data_layer_server.py +2 -2
- chia/data_layer/data_layer_util.py +71 -71
- chia/data_layer/data_layer_wallet.py +63 -67
- chia/data_layer/data_store.py +72 -72
- chia/data_layer/dl_wallet_store.py +10 -10
- chia/data_layer/download_data.py +5 -5
- chia/data_layer/s3_plugin_service.py +9 -9
- chia/data_layer/util/benchmark.py +0 -1
- chia/data_layer/util/plugin.py +2 -3
- chia/farmer/farmer.py +46 -43
- chia/farmer/farmer_api.py +27 -21
- chia/full_node/block_height_map.py +6 -6
- chia/full_node/block_store.py +41 -35
- chia/full_node/coin_store.py +42 -41
- chia/full_node/fee_estimate.py +2 -2
- chia/full_node/fee_estimation.py +1 -2
- chia/full_node/fee_history.py +5 -6
- chia/full_node/fee_tracker.py +24 -24
- chia/full_node/full_node.py +574 -300
- chia/full_node/full_node_api.py +181 -130
- chia/full_node/full_node_store.py +43 -43
- chia/full_node/hint_management.py +4 -4
- chia/full_node/hint_store.py +9 -10
- chia/full_node/mempool.py +25 -19
- chia/full_node/mempool_check_conditions.py +11 -42
- chia/full_node/mempool_manager.py +48 -53
- chia/full_node/pending_tx_cache.py +9 -9
- chia/full_node/subscriptions.py +23 -24
- chia/full_node/sync_store.py +8 -7
- chia/full_node/tx_processing_queue.py +3 -3
- chia/full_node/util/__init__.py +0 -0
- chia/full_node/weight_proof.py +79 -78
- chia/harvester/harvester.py +9 -8
- chia/harvester/harvester_api.py +19 -13
- chia/introducer/introducer.py +7 -5
- chia/introducer/introducer_api.py +9 -3
- chia/legacy/keyring.py +6 -5
- chia/plot_sync/delta.py +8 -8
- chia/plot_sync/receiver.py +12 -11
- chia/plot_sync/sender.py +15 -12
- chia/plotters/bladebit.py +12 -12
- chia/plotters/chiapos.py +2 -2
- chia/plotters/madmax.py +8 -8
- chia/plotters/plotters.py +6 -6
- chia/plotters/plotters_util.py +6 -4
- chia/plotting/cache.py +8 -7
- chia/plotting/check_plots.py +8 -8
- chia/plotting/create_plots.py +6 -6
- chia/plotting/manager.py +22 -22
- chia/plotting/util.py +31 -19
- chia/pools/pool_config.py +7 -7
- chia/pools/pool_puzzles.py +16 -16
- chia/pools/pool_wallet.py +64 -57
- chia/pools/pool_wallet_info.py +3 -3
- chia/protocols/full_node_protocol.py +3 -3
- chia/protocols/harvester_protocol.py +12 -12
- chia/protocols/introducer_protocol.py +1 -2
- chia/protocols/protocol_message_types.py +4 -4
- chia/protocols/protocol_state_machine.py +2 -2
- chia/protocols/protocol_timing.py +1 -0
- chia/protocols/shared_protocol.py +3 -3
- chia/protocols/timelord_protocol.py +2 -2
- chia/protocols/wallet_protocol.py +33 -33
- chia/rpc/crawler_rpc_api.py +12 -7
- chia/rpc/data_layer_rpc_api.py +49 -44
- chia/rpc/data_layer_rpc_client.py +41 -41
- chia/rpc/data_layer_rpc_util.py +7 -11
- chia/rpc/farmer_rpc_api.py +32 -27
- chia/rpc/farmer_rpc_client.py +14 -14
- chia/rpc/full_node_rpc_api.py +53 -48
- chia/rpc/full_node_rpc_client.py +30 -30
- chia/rpc/harvester_rpc_api.py +16 -11
- chia/rpc/harvester_rpc_client.py +6 -6
- chia/rpc/rpc_client.py +34 -14
- chia/rpc/rpc_server.py +117 -43
- chia/rpc/timelord_rpc_api.py +9 -4
- chia/rpc/util.py +11 -211
- chia/rpc/wallet_request_types.py +276 -60
- chia/rpc/wallet_rpc_api.py +563 -399
- chia/rpc/wallet_rpc_client.py +220 -250
- chia/seeder/crawl_store.py +6 -8
- chia/seeder/crawler.py +23 -36
- chia/seeder/crawler_api.py +28 -22
- chia/seeder/dns_server.py +99 -50
- chia/seeder/start_crawler.py +13 -9
- chia/server/address_manager.py +19 -19
- chia/server/address_manager_store.py +17 -17
- chia/server/api_protocol.py +106 -1
- chia/server/capabilities.py +3 -3
- chia/server/chia_policy.py +17 -16
- chia/server/introducer_peers.py +3 -3
- chia/server/node_discovery.py +34 -38
- chia/server/rate_limit_numbers.py +26 -16
- chia/server/rate_limits.py +67 -27
- chia/server/server.py +52 -31
- chia/server/signal_handlers.py +6 -3
- chia/server/ssl_context.py +5 -5
- chia/server/start_data_layer.py +37 -23
- chia/server/start_farmer.py +28 -16
- chia/server/start_full_node.py +29 -23
- chia/server/start_harvester.py +28 -15
- chia/server/start_introducer.py +27 -15
- chia/server/start_service.py +17 -29
- chia/server/start_timelord.py +25 -18
- chia/server/start_wallet.py +22 -18
- chia/server/upnp.py +4 -3
- chia/server/ws_connection.py +68 -54
- chia/simulator/add_blocks_in_batches.py +54 -0
- chia/simulator/block_tools.py +65 -64
- chia/simulator/full_node_simulator.py +66 -74
- chia/simulator/setup_services.py +10 -9
- chia/simulator/simulator_full_node_rpc_api.py +12 -14
- chia/simulator/simulator_full_node_rpc_client.py +3 -5
- chia/simulator/simulator_test_tools.py +8 -7
- chia/simulator/socket.py +1 -4
- chia/simulator/ssl_certs.py +5 -5
- chia/simulator/ssl_certs_1.py +2 -4
- chia/simulator/ssl_certs_10.py +2 -4
- chia/simulator/ssl_certs_2.py +2 -4
- chia/simulator/ssl_certs_3.py +2 -4
- chia/simulator/ssl_certs_4.py +2 -4
- chia/simulator/ssl_certs_5.py +2 -4
- chia/simulator/ssl_certs_6.py +2 -4
- chia/simulator/ssl_certs_7.py +2 -4
- chia/simulator/ssl_certs_8.py +2 -4
- chia/simulator/ssl_certs_9.py +2 -4
- chia/simulator/start_simulator.py +14 -6
- chia/simulator/wallet_tools.py +21 -20
- chia/ssl/create_ssl.py +11 -11
- chia/timelord/iters_from_block.py +2 -2
- chia/timelord/timelord.py +57 -33
- chia/timelord/timelord_api.py +12 -6
- chia/timelord/timelord_launcher.py +10 -8
- chia/timelord/timelord_state.py +5 -5
- chia/types/block_protocol.py +2 -2
- chia/types/blockchain_format/coin.py +3 -3
- chia/types/blockchain_format/program.py +17 -18
- chia/types/blockchain_format/tree_hash.py +9 -9
- chia/types/coin_spend.py +8 -8
- chia/types/condition_with_args.py +1 -2
- chia/types/eligible_coin_spends.py +16 -15
- chia/types/generator_types.py +1 -2
- chia/types/internal_mempool_item.py +1 -2
- chia/types/mempool_item.py +7 -7
- chia/types/mempool_submission_status.py +2 -2
- chia/types/peer_info.py +1 -1
- chia/types/spend_bundle.py +1 -2
- chia/types/transaction_queue_entry.py +2 -2
- chia/types/unfinished_header_block.py +2 -2
- chia/types/validation_state.py +14 -0
- chia/types/weight_proof.py +5 -6
- chia/util/action_scope.py +8 -8
- chia/util/async_pool.py +6 -4
- chia/util/augmented_chain.py +13 -9
- chia/util/batches.py +5 -2
- chia/util/bech32m.py +14 -11
- chia/util/beta_metrics.py +5 -4
- chia/util/block_cache.py +5 -5
- chia/util/byte_types.py +2 -0
- chia/util/check_fork_next_block.py +3 -2
- chia/util/chia_logging.py +41 -21
- chia/util/collection.py +3 -3
- chia/util/condition_tools.py +18 -18
- chia/util/config.py +26 -25
- chia/util/cpu.py +2 -0
- chia/util/db_synchronous.py +2 -0
- chia/util/db_version.py +2 -0
- chia/util/db_wrapper.py +13 -10
- chia/util/default_root.py +17 -0
- chia/util/dump_keyring.py +6 -6
- chia/util/errors.py +5 -3
- chia/util/file_keyring.py +22 -33
- chia/util/files.py +2 -0
- chia/util/full_block_utils.py +31 -7
- chia/util/generator_tools.py +18 -8
- chia/util/hash.py +3 -1
- chia/util/initial-config.yaml +19 -0
- chia/util/inline_executor.py +2 -0
- chia/util/ip_address.py +39 -0
- chia/util/json_util.py +0 -4
- chia/util/keychain.py +27 -24
- chia/util/keyring_wrapper.py +65 -4
- chia/util/limited_semaphore.py +3 -1
- chia/util/lock.py +4 -2
- chia/util/log_exceptions.py +5 -2
- chia/util/logging.py +3 -1
- chia/util/lru_cache.py +2 -0
- chia/util/math.py +4 -4
- chia/util/network.py +15 -73
- chia/util/paginator.py +3 -1
- chia/util/path.py +2 -0
- chia/util/permissions.py +3 -2
- chia/util/prev_transaction_block.py +1 -3
- chia/util/priority_mutex.py +6 -3
- chia/util/profiler.py +7 -4
- chia/util/recursive_replace.py +2 -0
- chia/util/safe_cancel_task.py +2 -0
- chia/util/service_groups.py +2 -2
- chia/util/setproctitle.py +2 -0
- chia/util/significant_bits.py +2 -0
- chia/util/ssl_check.py +11 -11
- chia/util/streamable.py +44 -56
- chia/util/task_referencer.py +59 -0
- chia/util/task_timing.py +22 -18
- chia/util/timing.py +4 -1
- chia/util/vdf_prover.py +2 -3
- chia/util/virtual_project_analysis.py +540 -0
- chia/util/ws_message.py +6 -6
- chia/wallet/cat_wallet/cat_info.py +3 -3
- chia/wallet/cat_wallet/cat_outer_puzzle.py +3 -3
- chia/wallet/cat_wallet/cat_utils.py +5 -4
- chia/wallet/cat_wallet/cat_wallet.py +56 -70
- chia/wallet/cat_wallet/dao_cat_info.py +3 -3
- chia/wallet/cat_wallet/dao_cat_wallet.py +18 -18
- chia/wallet/cat_wallet/lineage_store.py +2 -2
- chia/wallet/coin_selection.py +15 -15
- chia/wallet/conditions.py +257 -71
- chia/wallet/dao_wallet/dao_info.py +4 -4
- chia/wallet/dao_wallet/dao_utils.py +43 -42
- chia/wallet/dao_wallet/dao_wallet.py +66 -68
- chia/wallet/db_wallet/db_wallet_puzzles.py +12 -8
- chia/wallet/derive_keys.py +11 -11
- chia/wallet/did_wallet/did_info.py +3 -3
- chia/wallet/did_wallet/did_wallet.py +56 -47
- chia/wallet/did_wallet/did_wallet_puzzles.py +7 -6
- chia/wallet/lineage_proof.py +4 -4
- chia/wallet/nft_wallet/metadata_outer_puzzle.py +2 -2
- chia/wallet/nft_wallet/nft_info.py +4 -4
- chia/wallet/nft_wallet/nft_puzzles.py +16 -16
- chia/wallet/nft_wallet/nft_wallet.py +90 -89
- chia/wallet/nft_wallet/ownership_outer_puzzle.py +2 -2
- chia/wallet/nft_wallet/singleton_outer_puzzle.py +2 -2
- chia/wallet/nft_wallet/transfer_program_puzzle.py +2 -2
- chia/wallet/nft_wallet/uncurry_nft.py +2 -2
- chia/wallet/notification_manager.py +5 -5
- chia/wallet/notification_store.py +6 -6
- chia/wallet/outer_puzzles.py +2 -2
- chia/wallet/payment.py +4 -5
- chia/wallet/puzzle_drivers.py +4 -4
- chia/wallet/puzzles/clawback/drivers.py +5 -5
- chia/wallet/puzzles/clawback/puzzle_decorator.py +7 -7
- chia/wallet/puzzles/load_clvm.py +2 -3
- chia/wallet/puzzles/p2_conditions.py +1 -2
- chia/wallet/puzzles/p2_delegated_conditions.py +1 -2
- chia/wallet/puzzles/p2_delegated_puzzle.py +2 -3
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +3 -4
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +1 -2
- chia/wallet/puzzles/p2_puzzle_hash.py +1 -2
- chia/wallet/puzzles/puzzle_utils.py +7 -7
- chia/wallet/puzzles/singleton_top_layer.py +6 -5
- chia/wallet/puzzles/singleton_top_layer_v1_1.py +6 -5
- chia/wallet/puzzles/tails.py +34 -30
- chia/wallet/signer_protocol.py +7 -8
- chia/wallet/singleton.py +4 -4
- chia/wallet/trade_manager.py +155 -141
- chia/wallet/trade_record.py +5 -5
- chia/wallet/trading/offer.py +100 -101
- chia/wallet/trading/trade_store.py +14 -14
- chia/wallet/transaction_record.py +31 -16
- chia/wallet/util/address_type.py +4 -4
- chia/wallet/util/blind_signer_tl.py +8 -12
- chia/wallet/util/clvm_streamable.py +15 -15
- chia/wallet/util/compute_hints.py +5 -5
- chia/wallet/util/compute_memos.py +4 -6
- chia/wallet/util/curry_and_treehash.py +3 -2
- chia/wallet/util/debug_spend_bundle.py +6 -8
- chia/wallet/util/merkle_tree.py +10 -10
- chia/wallet/util/merkle_utils.py +10 -10
- chia/wallet/util/new_peak_queue.py +3 -3
- chia/wallet/util/peer_request_cache.py +8 -8
- chia/{util → wallet/util}/pprint.py +2 -3
- chia/wallet/util/puzzle_compression.py +3 -4
- chia/wallet/util/puzzle_decorator.py +10 -10
- chia/wallet/util/query_filter.py +9 -10
- chia/wallet/util/tx_config.py +12 -12
- chia/wallet/util/wallet_sync_utils.py +24 -21
- chia/wallet/util/wallet_types.py +9 -2
- chia/wallet/vc_wallet/cr_cat_drivers.py +28 -27
- chia/wallet/vc_wallet/cr_cat_wallet.py +42 -40
- chia/wallet/vc_wallet/cr_outer_puzzle.py +4 -4
- chia/wallet/vc_wallet/vc_drivers.py +16 -16
- chia/wallet/vc_wallet/vc_store.py +9 -9
- chia/wallet/vc_wallet/vc_wallet.py +35 -35
- chia/wallet/wallet.py +54 -54
- chia/wallet/wallet_action_scope.py +14 -13
- chia/wallet/wallet_blockchain.py +10 -10
- chia/wallet/wallet_coin_record.py +2 -2
- chia/wallet/wallet_coin_store.py +10 -10
- chia/wallet/wallet_info.py +1 -2
- chia/wallet/wallet_interested_store.py +5 -5
- chia/wallet/wallet_nft_store.py +6 -6
- chia/wallet/wallet_node.py +72 -76
- chia/wallet/wallet_node_api.py +33 -27
- chia/wallet/wallet_pool_store.py +1 -2
- chia/wallet/wallet_protocol.py +15 -15
- chia/wallet/wallet_puzzle_store.py +35 -4
- chia/wallet/wallet_retry_store.py +2 -2
- chia/wallet/wallet_singleton_store.py +10 -9
- chia/wallet/wallet_spend_bundle.py +4 -20
- chia/wallet/wallet_state_manager.py +223 -224
- chia/wallet/wallet_transaction_store.py +44 -18
- chia/wallet/wallet_user_store.py +2 -2
- chia/wallet/wallet_weight_proof_handler.py +2 -2
- {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/LICENSE +1 -1
- {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/METADATA +67 -72
- chia_blockchain-2.5.1.dist-info/RECORD +1042 -0
- {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/WHEEL +1 -1
- mozilla-ca/cacert.pem +32 -87
- chia/_tests/cmds/wallet/test_coins.py +0 -195
- chia/consensus/block_root_validation.py +0 -46
- chia/util/api_decorators.py +0 -89
- chia_blockchain-2.5.0rc1.dist-info/RECORD +0 -1028
- {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/entry_points.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from dataclasses import dataclass
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any,
|
|
5
|
+
from typing import Any, Optional, cast
|
|
6
6
|
from unittest.mock import MagicMock
|
|
7
7
|
|
|
8
8
|
import pytest
|
|
@@ -20,10 +20,14 @@ class MockStandardWallet:
|
|
|
20
20
|
async def get_new_puzzlehash(self) -> bytes32:
|
|
21
21
|
return self.canned_puzzlehash
|
|
22
22
|
|
|
23
|
+
async def get_puzzle_hash(self, new: bool) -> bytes32:
|
|
24
|
+
return self.canned_puzzlehash
|
|
25
|
+
|
|
23
26
|
|
|
24
27
|
@dataclass
|
|
25
28
|
class MockWalletStateManager:
|
|
26
29
|
root_path: Optional[Path] = None
|
|
30
|
+
config: dict[str, Any] = field(default_factory=dict)
|
|
27
31
|
|
|
28
32
|
|
|
29
33
|
@dataclass
|
|
@@ -56,7 +60,7 @@ async def test_update_pool_config_new_config(monkeypatch: Any) -> None:
|
|
|
56
60
|
Test that PoolWallet can create a new pool config
|
|
57
61
|
"""
|
|
58
62
|
|
|
59
|
-
updated_configs:
|
|
63
|
+
updated_configs: list[MockPoolWalletConfig] = []
|
|
60
64
|
payout_instructions_ph = rand_hash()
|
|
61
65
|
launcher_id: bytes32 = rand_hash()
|
|
62
66
|
p2_singleton_puzzle_hash: bytes32 = rand_hash()
|
|
@@ -75,14 +79,14 @@ async def test_update_pool_config_new_config(monkeypatch: Any) -> None:
|
|
|
75
79
|
)
|
|
76
80
|
|
|
77
81
|
# No config data
|
|
78
|
-
def mock_load_pool_config(root_path: Path) ->
|
|
82
|
+
def mock_load_pool_config(root_path: Path) -> list[MockPoolWalletConfig]:
|
|
79
83
|
return []
|
|
80
84
|
|
|
81
85
|
monkeypatch.setattr("chia.pools.pool_wallet.load_pool_config", mock_load_pool_config)
|
|
82
86
|
|
|
83
87
|
# Mock pool_config.update_pool_config to capture the updated configs
|
|
84
88
|
async def mock_pool_config_update_pool_config(
|
|
85
|
-
root_path: Path, pool_config_list:
|
|
89
|
+
root_path: Path, pool_config_list: list[MockPoolWalletConfig]
|
|
86
90
|
) -> None:
|
|
87
91
|
nonlocal updated_configs
|
|
88
92
|
updated_configs = pool_config_list
|
|
@@ -121,7 +125,7 @@ async def test_update_pool_config_existing_payout_instructions(monkeypatch: Any)
|
|
|
121
125
|
Test that PoolWallet will retain existing payout_instructions when updating the pool config.
|
|
122
126
|
"""
|
|
123
127
|
|
|
124
|
-
updated_configs:
|
|
128
|
+
updated_configs: list[MockPoolWalletConfig] = []
|
|
125
129
|
payout_instructions_ph = rand_hash()
|
|
126
130
|
launcher_id: bytes32 = rand_hash()
|
|
127
131
|
p2_singleton_puzzle_hash: bytes32 = rand_hash()
|
|
@@ -157,7 +161,7 @@ async def test_update_pool_config_existing_payout_instructions(monkeypatch: Any)
|
|
|
157
161
|
)
|
|
158
162
|
|
|
159
163
|
# No config data
|
|
160
|
-
def mock_load_pool_config(root_path: Path) ->
|
|
164
|
+
def mock_load_pool_config(root_path: Path) -> list[MockPoolWalletConfig]:
|
|
161
165
|
nonlocal existing_config
|
|
162
166
|
return [existing_config]
|
|
163
167
|
|
|
@@ -165,7 +169,7 @@ async def test_update_pool_config_existing_payout_instructions(monkeypatch: Any)
|
|
|
165
169
|
|
|
166
170
|
# Mock pool_config.update_pool_config to capture the updated configs
|
|
167
171
|
async def mock_pool_config_update_pool_config(
|
|
168
|
-
root_path: Path, pool_config_list:
|
|
172
|
+
root_path: Path, pool_config_list: list[MockPoolWalletConfig]
|
|
169
173
|
) -> None:
|
|
170
174
|
nonlocal updated_configs
|
|
171
175
|
updated_configs = pool_config_list
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import random
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Optional
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
8
|
from clvm_tools import binutils
|
|
@@ -36,7 +36,7 @@ def make_child_solution(
|
|
|
36
36
|
return sol
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
async def assert_db_spends(store: WalletPoolStore, wallet_id: int, spends:
|
|
39
|
+
async def assert_db_spends(store: WalletPoolStore, wallet_id: int, spends: list[CoinSpend]) -> None:
|
|
40
40
|
db_spends = await store.get_spends_for_wallet(wallet_id)
|
|
41
41
|
assert len(db_spends) == len(spends)
|
|
42
42
|
for spend, (_, db_spend) in zip(spends, db_spends):
|
|
@@ -46,7 +46,7 @@ async def assert_db_spends(store: WalletPoolStore, wallet_id: int, spends: List[
|
|
|
46
46
|
@dataclass
|
|
47
47
|
class DummySpends:
|
|
48
48
|
seeded_random: random.Random
|
|
49
|
-
spends_per_wallet:
|
|
49
|
+
spends_per_wallet: dict[int, list[CoinSpend]] = field(default_factory=dict)
|
|
50
50
|
|
|
51
51
|
def generate(self, wallet_id: int, count: int) -> None:
|
|
52
52
|
current = self.spends_per_wallet.setdefault(wallet_id, [])
|
chia/_tests/process_junit.py
CHANGED
|
@@ -7,30 +7,30 @@ from collections import defaultdict
|
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from statistics import StatisticsError, mean, stdev
|
|
10
|
-
from typing import Any,
|
|
10
|
+
from typing import Any, Optional, TextIO, final
|
|
11
11
|
|
|
12
12
|
import click
|
|
13
13
|
import lxml.etree
|
|
14
14
|
|
|
15
|
-
from chia._tests.util.misc import BenchmarkData,
|
|
16
|
-
from chia._tests.util.time_out_assert import TimeOutAssertData
|
|
15
|
+
from chia._tests.util.misc import BenchmarkData, TestId
|
|
16
|
+
from chia._tests.util.time_out_assert import DataTypeProtocol, TimeOutAssertData
|
|
17
17
|
|
|
18
|
-
supported_data_types:
|
|
19
|
-
supported_data_types_by_tag:
|
|
18
|
+
supported_data_types: list[type[DataTypeProtocol]] = [TimeOutAssertData, BenchmarkData]
|
|
19
|
+
supported_data_types_by_tag: dict[str, type[DataTypeProtocol]] = {cls.tag: cls for cls in supported_data_types}
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
@final
|
|
23
23
|
@dataclass(frozen=True, order=True)
|
|
24
24
|
class Result:
|
|
25
25
|
file_path: Path
|
|
26
|
-
test_path:
|
|
27
|
-
ids:
|
|
26
|
+
test_path: tuple[str, ...]
|
|
27
|
+
ids: tuple[str, ...]
|
|
28
28
|
label: str
|
|
29
29
|
line: int = field(compare=False)
|
|
30
|
-
durations:
|
|
30
|
+
durations: tuple[float, ...] = field(compare=False)
|
|
31
31
|
limit: float = field(compare=False)
|
|
32
32
|
|
|
33
|
-
def marshal(self) ->
|
|
33
|
+
def marshal(self) -> dict[str, Any]:
|
|
34
34
|
return {
|
|
35
35
|
"file_path": self.file_path.as_posix(),
|
|
36
36
|
"test_path": self.test_path,
|
|
@@ -133,7 +133,7 @@ def main(
|
|
|
133
133
|
tree = lxml.etree.parse(xml_file)
|
|
134
134
|
root = tree.getroot()
|
|
135
135
|
|
|
136
|
-
cases_by_test_id: defaultdict[TestId,
|
|
136
|
+
cases_by_test_id: defaultdict[TestId, list[lxml.etree.Element]] = defaultdict(list)
|
|
137
137
|
for suite in root.findall("testsuite"):
|
|
138
138
|
for case in suite.findall("testcase"):
|
|
139
139
|
if case.find("skipped") is not None:
|
|
@@ -145,7 +145,7 @@ def main(
|
|
|
145
145
|
)
|
|
146
146
|
cases_by_test_id[test_id].append(case)
|
|
147
147
|
|
|
148
|
-
data_by_event_id: defaultdict[EventId,
|
|
148
|
+
data_by_event_id: defaultdict[EventId, list[DataTypeProtocol]] = defaultdict(list)
|
|
149
149
|
for test_id, cases in cases_by_test_id.items():
|
|
150
150
|
for case in cases:
|
|
151
151
|
for property in case.findall(f"properties/property[@name='{tag}']"):
|
|
@@ -154,7 +154,7 @@ def main(
|
|
|
154
154
|
event_id = EventId(test_id=test_id, tag=tag, line=data.line, path=data.path, label=data.label)
|
|
155
155
|
data_by_event_id[event_id].append(data)
|
|
156
156
|
|
|
157
|
-
results:
|
|
157
|
+
results: list[Result] = []
|
|
158
158
|
for event_id, datas in data_by_event_id.items():
|
|
159
159
|
[limit] = {data.limit for data in datas}
|
|
160
160
|
results.append(
|
|
@@ -196,7 +196,7 @@ def output_benchmark(
|
|
|
196
196
|
output: TextIO,
|
|
197
197
|
percent_margin: int,
|
|
198
198
|
randomoji: bool,
|
|
199
|
-
results:
|
|
199
|
+
results: list[Result],
|
|
200
200
|
) -> None:
|
|
201
201
|
if not markdown:
|
|
202
202
|
for result in sorted(results):
|
|
@@ -206,7 +206,7 @@ def output_benchmark(
|
|
|
206
206
|
else:
|
|
207
207
|
output.write("# Benchmark Metrics\n\n")
|
|
208
208
|
|
|
209
|
-
output.write("| Test | 🍿 | Mean | Max | 3σ | Limit | Percent |\n")
|
|
209
|
+
output.write("| Test | 🍿 | Mean | Max | 3σ | Limit | Percent |\n") # noqa: RUF001
|
|
210
210
|
output.write("| --- | --- | --- | --- | --- | --- | --- |\n")
|
|
211
211
|
for result in sorted(results):
|
|
212
212
|
link_url = result.link(prefix=link_prefix, line_separator=link_line_separator)
|
|
@@ -273,7 +273,7 @@ def output_time_out_assert(
|
|
|
273
273
|
output: TextIO,
|
|
274
274
|
percent_margin: int,
|
|
275
275
|
randomoji: bool,
|
|
276
|
-
results:
|
|
276
|
+
results: list[Result],
|
|
277
277
|
) -> None:
|
|
278
278
|
if not markdown:
|
|
279
279
|
for result in sorted(results):
|
|
@@ -283,7 +283,7 @@ def output_time_out_assert(
|
|
|
283
283
|
else:
|
|
284
284
|
output.write("# Time Out Assert Metrics\n\n")
|
|
285
285
|
|
|
286
|
-
output.write("| Test | 🍿 | Mean | Max | 3σ | Limit | Percent |\n")
|
|
286
|
+
output.write("| Test | 🍿 | Mean | Max | 3σ | Limit | Percent |\n") # noqa: RUF001
|
|
287
287
|
output.write("| --- | --- | --- | --- | --- | --- | --- |\n")
|
|
288
288
|
for result in sorted(results):
|
|
289
289
|
link_url = result.link(prefix=link_prefix, line_separator=link_line_separator)
|
|
@@ -345,5 +345,4 @@ def output_time_out_assert(
|
|
|
345
345
|
|
|
346
346
|
|
|
347
347
|
if __name__ == "__main__":
|
|
348
|
-
# pylint: disable = no-value-for-parameter
|
|
349
348
|
main()
|
|
@@ -1,21 +1,38 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from collections.abc import AsyncIterator, Awaitable
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from pathlib import Path
|
|
5
|
-
from typing import Any,
|
|
6
|
+
from typing import Any, Callable, Optional
|
|
6
7
|
|
|
7
8
|
import pytest
|
|
8
9
|
|
|
9
10
|
from chia._tests.util.misc import Marks, RecordingWebServer, datacases
|
|
10
11
|
from chia.rpc.rpc_client import ResponseFailureError, RpcClient
|
|
12
|
+
from chia.rpc.rpc_server import RpcServer
|
|
13
|
+
from chia.server.outbound_message import NodeType
|
|
11
14
|
from chia.util.ints import uint16
|
|
12
15
|
|
|
16
|
+
non_fetch_client_methods = {
|
|
17
|
+
RpcClient.create,
|
|
18
|
+
RpcClient.create_as_context,
|
|
19
|
+
RpcClient.fetch,
|
|
20
|
+
RpcClient.close,
|
|
21
|
+
RpcClient.await_closed,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
client_fetch_methods = [
|
|
25
|
+
attribute
|
|
26
|
+
for name, attribute in vars(RpcClient).items()
|
|
27
|
+
if callable(attribute) and attribute not in non_fetch_client_methods and not name.startswith("__")
|
|
28
|
+
]
|
|
29
|
+
|
|
13
30
|
|
|
14
31
|
@dataclass
|
|
15
32
|
class InvalidCreateCase:
|
|
16
33
|
id: str
|
|
17
34
|
root_path: Optional[Path] = None
|
|
18
|
-
net_config: Optional[
|
|
35
|
+
net_config: Optional[dict[str, Any]] = None
|
|
19
36
|
marks: Marks = ()
|
|
20
37
|
|
|
21
38
|
|
|
@@ -79,3 +96,43 @@ async def test_failure_exception(
|
|
|
79
96
|
await rpc_client.fetch(path="/table", request_json={"response": expected_response})
|
|
80
97
|
|
|
81
98
|
assert exception_info.value.response == expected_response
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_client_standard_endpoints_match_server() -> None:
|
|
102
|
+
# NOTE: this test assumes that the client method names should match the server
|
|
103
|
+
# route names
|
|
104
|
+
client_method_names = {method.__name__ for method in client_fetch_methods}
|
|
105
|
+
server_route_names = {method.lstrip("/") for method in RpcServer._routes.keys()}
|
|
106
|
+
assert client_method_names == server_route_names
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
@pytest.mark.anyio
|
|
110
|
+
@pytest.mark.parametrize("client_method", client_fetch_methods)
|
|
111
|
+
async def test_client_fetch_methods(
|
|
112
|
+
client_method: Callable[..., Awaitable[object]],
|
|
113
|
+
rpc_client: RpcClient,
|
|
114
|
+
recording_web_server: RecordingWebServer,
|
|
115
|
+
) -> None:
|
|
116
|
+
# NOTE: this test assumes that the client method names should match the server
|
|
117
|
+
# route names
|
|
118
|
+
|
|
119
|
+
parameters: dict[Callable[..., Awaitable[object]], dict[str, object]] = {
|
|
120
|
+
RpcClient.open_connection: {"host": "", "port": 0},
|
|
121
|
+
RpcClient.close_connection: {"node_id": b""},
|
|
122
|
+
RpcClient.get_connections: {"node_type": NodeType.FULL_NODE},
|
|
123
|
+
RpcClient.set_log_level: {"level": "DEBUG"},
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
await client_method(rpc_client, **parameters.get(client_method, {}))
|
|
128
|
+
except Exception as exception:
|
|
129
|
+
if client_method is RpcClient.get_connections and isinstance(exception, KeyError):
|
|
130
|
+
pass
|
|
131
|
+
else: # pragma: no cover
|
|
132
|
+
# this case will fail the test so not normally executed
|
|
133
|
+
raise
|
|
134
|
+
|
|
135
|
+
[request] = recording_web_server.requests
|
|
136
|
+
assert request.content_type == "application/json"
|
|
137
|
+
assert request.method == "POST"
|
|
138
|
+
assert request.path == f"/{client_method.__name__}"
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
import dataclasses
|
|
5
|
+
import logging
|
|
6
|
+
import ssl
|
|
7
|
+
import sys
|
|
8
|
+
from collections.abc import AsyncIterator
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Optional, cast
|
|
11
|
+
|
|
12
|
+
import aiohttp
|
|
13
|
+
import pytest
|
|
14
|
+
|
|
15
|
+
from chia.rpc.rpc_server import Endpoint, EndpointResult, RpcServer, RpcServiceProtocol
|
|
16
|
+
from chia.ssl.create_ssl import create_all_ssl
|
|
17
|
+
from chia.util.config import load_config
|
|
18
|
+
from chia.util.ints import uint16
|
|
19
|
+
from chia.util.ws_message import WsRpcMessage
|
|
20
|
+
|
|
21
|
+
root_logger = logging.getLogger()
|
|
22
|
+
|
|
23
|
+
if sys.version_info >= (3, 11): # pragma: no cover
|
|
24
|
+
name_to_number_level_map = logging.getLevelNamesMapping()
|
|
25
|
+
else:
|
|
26
|
+
name_to_number_level_map = logging._nameToLevel
|
|
27
|
+
|
|
28
|
+
number_to_name_level_map = {number: name for name, number in name_to_number_level_map.items()}
|
|
29
|
+
|
|
30
|
+
# just picking one for which a config is present
|
|
31
|
+
service_name = "full_node"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclasses.dataclass
|
|
35
|
+
class TestRpcApi:
|
|
36
|
+
if TYPE_CHECKING:
|
|
37
|
+
from chia.rpc.rpc_server import RpcApiProtocol
|
|
38
|
+
|
|
39
|
+
_protocol_check: ClassVar[RpcApiProtocol] = cast("TestRpcApi", None)
|
|
40
|
+
|
|
41
|
+
# unused as of the initial writing of these tests
|
|
42
|
+
service: RpcServiceProtocol
|
|
43
|
+
service_name: str = service_name
|
|
44
|
+
|
|
45
|
+
async def _state_changed(self, change: str, change_data: Optional[dict[str, Any]] = None) -> list[WsRpcMessage]:
|
|
46
|
+
# just here to satisfy the complete protocol
|
|
47
|
+
return [] # pragma: no cover
|
|
48
|
+
|
|
49
|
+
def get_routes(self) -> dict[str, Endpoint]:
|
|
50
|
+
return {
|
|
51
|
+
"/log": self.log,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async def log(self, request: dict[str, Any]) -> EndpointResult:
|
|
55
|
+
message = request["message"]
|
|
56
|
+
|
|
57
|
+
level = name_to_number_level_map[request["level"]]
|
|
58
|
+
|
|
59
|
+
root_logger.log(level=level, msg=message)
|
|
60
|
+
|
|
61
|
+
return {}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclasses.dataclass
|
|
65
|
+
class Client:
|
|
66
|
+
session: aiohttp.ClientSession
|
|
67
|
+
ssl_context: ssl.SSLContext
|
|
68
|
+
url: str
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
@contextlib.asynccontextmanager
|
|
72
|
+
async def managed(cls, ssl_context: ssl.SSLContext, url: str) -> AsyncIterator[Client]:
|
|
73
|
+
async with aiohttp.ClientSession() as session:
|
|
74
|
+
yield cls(session=session, ssl_context=ssl_context, url=url)
|
|
75
|
+
|
|
76
|
+
async def request(self, endpoint: str, json: Optional[dict[str, Any]] = None) -> dict[str, Any]:
|
|
77
|
+
if json is None:
|
|
78
|
+
json = {}
|
|
79
|
+
|
|
80
|
+
async with self.session.post(
|
|
81
|
+
self.url.rstrip("/") + "/" + endpoint.lstrip("/"),
|
|
82
|
+
json=json,
|
|
83
|
+
ssl=self.ssl_context,
|
|
84
|
+
) as response:
|
|
85
|
+
response.raise_for_status()
|
|
86
|
+
json = await response.json()
|
|
87
|
+
|
|
88
|
+
assert json is not None
|
|
89
|
+
assert json["success"], json
|
|
90
|
+
|
|
91
|
+
return json
|
|
92
|
+
|
|
93
|
+
async def log(self, level: str, message: str) -> None:
|
|
94
|
+
await self.request("log", json={"message": message, "level": level})
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.fixture(name="server")
|
|
98
|
+
async def server_fixture(
|
|
99
|
+
root_path_populated_with_config: Path,
|
|
100
|
+
self_hostname: str,
|
|
101
|
+
) -> AsyncIterator[RpcServer[TestRpcApi]]:
|
|
102
|
+
config = load_config(root_path=root_path_populated_with_config, filename="config.yaml")
|
|
103
|
+
service_config = config[service_name]
|
|
104
|
+
|
|
105
|
+
create_all_ssl(root_path=root_path_populated_with_config)
|
|
106
|
+
rpc_server = RpcServer.create(
|
|
107
|
+
# the test rpc api doesn't presently need a real service for these tests
|
|
108
|
+
rpc_api=TestRpcApi(service=None), # type: ignore[arg-type]
|
|
109
|
+
service_name="test_rpc_server",
|
|
110
|
+
stop_cb=lambda: None,
|
|
111
|
+
root_path=root_path_populated_with_config,
|
|
112
|
+
net_config=config,
|
|
113
|
+
service_config=service_config,
|
|
114
|
+
prefer_ipv6=False,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
await rpc_server.start(
|
|
119
|
+
self_hostname=self_hostname,
|
|
120
|
+
rpc_port=uint16(0),
|
|
121
|
+
max_request_body_size=2**16,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
yield rpc_server
|
|
125
|
+
finally:
|
|
126
|
+
rpc_server.close()
|
|
127
|
+
await rpc_server.await_closed()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
@pytest.fixture(name="client")
|
|
131
|
+
async def client_fixture(
|
|
132
|
+
server: RpcServer[TestRpcApi],
|
|
133
|
+
) -> AsyncIterator[Client]:
|
|
134
|
+
assert server.webserver is not None
|
|
135
|
+
async with Client.managed(ssl_context=server.ssl_client_context, url=server.webserver.url()) as client:
|
|
136
|
+
yield client
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@pytest.mark.anyio
|
|
140
|
+
async def test_get_log_level(
|
|
141
|
+
client: Client,
|
|
142
|
+
caplog: pytest.LogCaptureFixture,
|
|
143
|
+
) -> None:
|
|
144
|
+
level = "WARNING"
|
|
145
|
+
root_logger.setLevel(level)
|
|
146
|
+
result = await client.request("get_log_level")
|
|
147
|
+
assert result["level"] == number_to_name_level_map[root_logger.level]
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
@pytest.mark.anyio
|
|
151
|
+
async def test_set_log_level(
|
|
152
|
+
client: Client,
|
|
153
|
+
caplog: pytest.LogCaptureFixture,
|
|
154
|
+
) -> None:
|
|
155
|
+
message = "just a maybe unique probably message"
|
|
156
|
+
|
|
157
|
+
level = "WARNING"
|
|
158
|
+
await client.request("set_log_level", json={"level": level})
|
|
159
|
+
assert number_to_name_level_map[root_logger.level] == level
|
|
160
|
+
|
|
161
|
+
caplog.clear()
|
|
162
|
+
await client.log(message=message, level="WARNING")
|
|
163
|
+
assert caplog.messages == [message]
|
|
164
|
+
|
|
165
|
+
caplog.clear()
|
|
166
|
+
await client.log(message=message, level="INFO")
|
|
167
|
+
assert caplog.messages == []
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
@pytest.mark.anyio
|
|
171
|
+
async def test_reset_log_level(
|
|
172
|
+
client: Client,
|
|
173
|
+
server: RpcServer[TestRpcApi],
|
|
174
|
+
) -> None:
|
|
175
|
+
configured_level = server.service_config["logging"]["log_level"]
|
|
176
|
+
temporary_level = "INFO"
|
|
177
|
+
assert configured_level != temporary_level
|
|
178
|
+
|
|
179
|
+
root_logger.setLevel(temporary_level)
|
|
180
|
+
assert number_to_name_level_map[root_logger.level] == temporary_level
|
|
181
|
+
|
|
182
|
+
await client.request("reset_log_level")
|
|
183
|
+
assert number_to_name_level_map[root_logger.level] == configured_level
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import importlib.metadata
|
|
4
4
|
import json
|
|
5
|
-
from
|
|
5
|
+
from collections.abc import AsyncIterator
|
|
6
6
|
|
|
7
7
|
import aiohttp
|
|
8
8
|
import pytest
|
|
@@ -186,7 +186,7 @@ class TestSimulation:
|
|
|
186
186
|
@pytest.mark.anyio
|
|
187
187
|
async def test_simulator_auto_farm_and_get_coins(
|
|
188
188
|
self,
|
|
189
|
-
two_wallet_nodes:
|
|
189
|
+
two_wallet_nodes: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
190
190
|
self_hostname: str,
|
|
191
191
|
) -> None:
|
|
192
192
|
num_blocks = 2
|
|
@@ -194,7 +194,7 @@ class TestSimulation:
|
|
|
194
194
|
full_node_api = full_nodes[0]
|
|
195
195
|
server_1 = full_node_api.full_node.server
|
|
196
196
|
wallet_node, server_2 = wallets[0]
|
|
197
|
-
wallet_node_2,
|
|
197
|
+
wallet_node_2, _server_3 = wallets[1]
|
|
198
198
|
wallet = wallet_node.wallet_state_manager.main_wallet
|
|
199
199
|
ph = await wallet.get_new_puzzlehash()
|
|
200
200
|
wallet_node.config["trusted_peers"] = {}
|
|
@@ -313,7 +313,7 @@ class TestSimulation:
|
|
|
313
313
|
peak = full_node_api.full_node.blockchain.get_peak()
|
|
314
314
|
assert isinstance(peak, BlockRecord)
|
|
315
315
|
start_time = peak.timestamp
|
|
316
|
-
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32
|
|
316
|
+
await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
|
|
317
317
|
peak = full_node_api.full_node.blockchain.get_peak()
|
|
318
318
|
assert isinstance(peak, BlockRecord)
|
|
319
319
|
end_time = peak.timestamp
|
|
@@ -485,7 +485,7 @@ class TestSimulation:
|
|
|
485
485
|
async def test_create_coins_with_invalid_amounts_raises(
|
|
486
486
|
self,
|
|
487
487
|
self_hostname: str,
|
|
488
|
-
amounts:
|
|
488
|
+
amounts: list[uint64],
|
|
489
489
|
simulator_and_wallet: OldSimulatorsAndWallets,
|
|
490
490
|
) -> None:
|
|
491
491
|
[[full_node_api], [[wallet_node, wallet_server]], _] = simulator_and_wallet
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import List, Tuple
|
|
4
|
-
|
|
5
3
|
import pytest
|
|
6
4
|
|
|
7
5
|
from chia._tests.util.setup_nodes import OldSimulatorsAndWallets
|
|
@@ -21,7 +19,7 @@ from chia.wallet.wallet_node import WalletNode
|
|
|
21
19
|
async def test_simulation_farm_blocks_to_puzzlehash(
|
|
22
20
|
count: int,
|
|
23
21
|
guarantee_transaction_blocks: bool,
|
|
24
|
-
simulator_and_wallet:
|
|
22
|
+
simulator_and_wallet: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
25
23
|
) -> None:
|
|
26
24
|
[[full_node_api], _, _] = simulator_and_wallet
|
|
27
25
|
|
|
@@ -41,7 +39,7 @@ async def test_simulation_farm_blocks_to_puzzlehash(
|
|
|
41
39
|
@pytest.mark.parametrize(argnames="count", argvalues=[0, 1, 2, 5, 10])
|
|
42
40
|
async def test_simulation_farm_blocks_to_wallet(
|
|
43
41
|
count: int,
|
|
44
|
-
simulator_and_wallet:
|
|
42
|
+
simulator_and_wallet: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
45
43
|
) -> None:
|
|
46
44
|
[[full_node_api], [[wallet_node, wallet_server]], _] = simulator_and_wallet
|
|
47
45
|
|
|
@@ -79,7 +77,7 @@ async def test_simulation_farm_blocks_to_wallet(
|
|
|
79
77
|
async def test_simulation_farm_rewards_to_wallet(
|
|
80
78
|
amount: int,
|
|
81
79
|
coin_count: int,
|
|
82
|
-
simulator_and_wallet:
|
|
80
|
+
simulator_and_wallet: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
83
81
|
) -> None:
|
|
84
82
|
[[full_node_api], [[wallet_node, wallet_server]], _] = simulator_and_wallet
|
|
85
83
|
|
|
@@ -107,7 +105,7 @@ async def test_simulation_farm_rewards_to_wallet(
|
|
|
107
105
|
|
|
108
106
|
@pytest.mark.anyio
|
|
109
107
|
async def test_wait_transaction_records_entered_mempool(
|
|
110
|
-
simulator_and_wallet:
|
|
108
|
+
simulator_and_wallet: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
111
109
|
) -> None:
|
|
112
110
|
repeats = 50
|
|
113
111
|
tx_amount = 1
|
|
@@ -143,7 +141,7 @@ async def test_wait_transaction_records_entered_mempool(
|
|
|
143
141
|
|
|
144
142
|
@pytest.mark.anyio
|
|
145
143
|
async def test_process_transaction_records(
|
|
146
|
-
simulator_and_wallet:
|
|
144
|
+
simulator_and_wallet: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
147
145
|
) -> None:
|
|
148
146
|
repeats = 50
|
|
149
147
|
tx_amount = 1
|
|
@@ -187,7 +185,7 @@ async def test_process_transaction_records(
|
|
|
187
185
|
],
|
|
188
186
|
)
|
|
189
187
|
async def test_create_coins_with_amounts(
|
|
190
|
-
self_hostname: str, amounts:
|
|
188
|
+
self_hostname: str, amounts: list[uint64], simulator_and_wallet: OldSimulatorsAndWallets
|
|
191
189
|
) -> None:
|
|
192
190
|
[[full_node_api], [[wallet_node, wallet_server]], _] = simulator_and_wallet
|
|
193
191
|
await wallet_server.start_client(PeerInfo(self_hostname, full_node_api.server.get_port()), None)
|
|
@@ -213,8 +211,8 @@ async def test_create_coins_with_amounts(
|
|
|
213
211
|
ids=lambda amounts: ", ".join(str(amount) for amount in amounts),
|
|
214
212
|
)
|
|
215
213
|
async def test_create_coins_with_invalid_amounts_raises(
|
|
216
|
-
amounts:
|
|
217
|
-
simulator_and_wallet:
|
|
214
|
+
amounts: list[int],
|
|
215
|
+
simulator_and_wallet: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
|
|
218
216
|
) -> None:
|
|
219
217
|
[[full_node_api], [[wallet_node, wallet_server]], _] = simulator_and_wallet
|
|
220
218
|
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
from collections.abc import AsyncGenerator
|
|
4
5
|
from pathlib import Path
|
|
5
|
-
from typing import Any
|
|
6
|
+
from typing import Any
|
|
6
7
|
|
|
7
8
|
import pytest
|
|
8
9
|
|
|
@@ -28,15 +29,15 @@ class TestStartSimulator:
|
|
|
28
29
|
@pytest.fixture(scope="function")
|
|
29
30
|
async def get_chia_simulator(
|
|
30
31
|
self, tmp_path: Path, empty_keyring: Keychain
|
|
31
|
-
) -> AsyncGenerator[
|
|
32
|
+
) -> AsyncGenerator[tuple[FullNodeSimulator, Path, dict[str, Any], str, int, Keychain], None]:
|
|
32
33
|
async for simulator_args in get_full_chia_simulator(chia_root=tmp_path, keychain=empty_keyring):
|
|
33
34
|
yield simulator_args
|
|
34
35
|
|
|
35
36
|
@pytest.mark.anyio
|
|
36
37
|
async def test_start_simulator(
|
|
37
|
-
self, get_chia_simulator:
|
|
38
|
+
self, get_chia_simulator: tuple[FullNodeSimulator, Path, dict[str, Any], str, int, Keychain]
|
|
38
39
|
) -> None:
|
|
39
|
-
simulator, root_path, config,
|
|
40
|
+
simulator, root_path, config, _mnemonic, fingerprint, keychain = get_chia_simulator
|
|
40
41
|
ph_1: bytes32 = get_puzzle_hash_from_key(keychain=keychain, fingerprint=fingerprint, key_id=1)
|
|
41
42
|
ph_2: bytes32 = get_puzzle_hash_from_key(keychain=keychain, fingerprint=fingerprint, key_id=2)
|
|
42
43
|
dummy_hash: bytes32 = std_hash(b"test")
|