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
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
# Package: virtual_project_analysis
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
import re
|
|
9
|
+
import sys
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Callable, Literal, Optional, Union
|
|
13
|
+
|
|
14
|
+
import click
|
|
15
|
+
import yaml
|
|
16
|
+
|
|
17
|
+
# This tool enforces digraph dependencies within a "virtual project structure".
|
|
18
|
+
# i.e. files grouped together forming a project are not allowed to have cyclical
|
|
19
|
+
# dependencies on other such groups.
|
|
20
|
+
|
|
21
|
+
# by default, all files are considered part of the "chia-blockchain" project.
|
|
22
|
+
|
|
23
|
+
# To pull out a sub project, annotate its files with a comment (on the first
|
|
24
|
+
# line):
|
|
25
|
+
# Package: <name>
|
|
26
|
+
|
|
27
|
+
# if chia-blockchain depends on this new sub-project, the sub-project may not
|
|
28
|
+
# depend back on chia-blockchain.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass(frozen=True)
|
|
32
|
+
class Annotation:
|
|
33
|
+
package: str
|
|
34
|
+
is_annotated: bool
|
|
35
|
+
|
|
36
|
+
@classmethod
|
|
37
|
+
def parse(cls, file_string: str) -> Annotation:
|
|
38
|
+
result = re.search(r"^# Package: (.+)$", file_string, re.MULTILINE)
|
|
39
|
+
if result is None:
|
|
40
|
+
return cls("chia-blockchain", False)
|
|
41
|
+
|
|
42
|
+
return cls(result.group(1).strip(), True)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class ChiaFile:
|
|
47
|
+
path: Path
|
|
48
|
+
annotations: Annotation
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def parse(cls, file_path: Path) -> ChiaFile:
|
|
52
|
+
# everything under chia/_tests belong to the "tests" subproject. It
|
|
53
|
+
# (obviously) depends on everything, but no production code is allowed
|
|
54
|
+
# to depend back on the tests.
|
|
55
|
+
if list(file_path.parts[0:2]) == ["chia", "_tests"]:
|
|
56
|
+
return cls(file_path, Annotation("tests", True))
|
|
57
|
+
|
|
58
|
+
with open(file_path, encoding="utf-8", errors="ignore") as f:
|
|
59
|
+
file_string = f.read().strip()
|
|
60
|
+
return cls(file_path, Annotation.parse(file_string))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def build_dependency_graph(dir_params: DirectoryParameters) -> dict[Path, list[Path]]:
|
|
64
|
+
dependency_graph: dict[Path, list[Path]] = {}
|
|
65
|
+
for chia_file in dir_params.gather_non_empty_python_files():
|
|
66
|
+
dependency_graph[chia_file.path] = []
|
|
67
|
+
with open(chia_file.path, encoding="utf-8", errors="ignore") as f:
|
|
68
|
+
filestring = f.read()
|
|
69
|
+
tree = ast.parse(filestring, filename=chia_file.path)
|
|
70
|
+
for node in ast.iter_child_nodes(tree):
|
|
71
|
+
if isinstance(node, ast.ImportFrom):
|
|
72
|
+
if node.module is not None and node.module.startswith(dir_params.dir_path.stem):
|
|
73
|
+
imported_path = os.path.join(dir_params.dir_path.parent, node.module.replace(".", "/") + ".py")
|
|
74
|
+
paths_to_search = [
|
|
75
|
+
imported_path,
|
|
76
|
+
*(os.path.join(imported_path[:-3], alias.name + ".py") for alias in node.names),
|
|
77
|
+
]
|
|
78
|
+
for path_to_search in paths_to_search:
|
|
79
|
+
if os.path.exists(path_to_search):
|
|
80
|
+
dependency_graph[chia_file.path].append(Path(path_to_search))
|
|
81
|
+
elif isinstance(node, ast.Import):
|
|
82
|
+
for alias in node.names:
|
|
83
|
+
if alias.name.startswith(dir_params.dir_path.stem):
|
|
84
|
+
imported_path = os.path.join(
|
|
85
|
+
dir_params.dir_path.parent, alias.name.replace(".", "/") + ".py"
|
|
86
|
+
)
|
|
87
|
+
if os.path.exists(imported_path):
|
|
88
|
+
dependency_graph[chia_file.path].append(Path(imported_path))
|
|
89
|
+
return dependency_graph
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def build_virtual_dependency_graph(
|
|
93
|
+
dir_params: DirectoryParameters, *, existing_graph: Optional[dict[Path, list[Path]]] = None
|
|
94
|
+
) -> dict[str, list[str]]:
|
|
95
|
+
if existing_graph is None:
|
|
96
|
+
graph = build_dependency_graph(dir_params)
|
|
97
|
+
else:
|
|
98
|
+
graph = existing_graph
|
|
99
|
+
|
|
100
|
+
virtual_graph: dict[str, list[str]] = {}
|
|
101
|
+
for file, imports in graph.items():
|
|
102
|
+
file_path = Path(file)
|
|
103
|
+
root_file = ChiaFile.parse(file_path)
|
|
104
|
+
if root_file.annotations is None:
|
|
105
|
+
continue
|
|
106
|
+
root = root_file.annotations.package
|
|
107
|
+
virtual_graph.setdefault(root, [])
|
|
108
|
+
|
|
109
|
+
dependency_files = [ChiaFile.parse(Path(imp)) for imp in imports]
|
|
110
|
+
dependencies = [f.annotations.package for f in dependency_files if f.annotations is not None]
|
|
111
|
+
|
|
112
|
+
virtual_graph[root].extend(dependencies)
|
|
113
|
+
|
|
114
|
+
# Filter out self before returning the list
|
|
115
|
+
return {k: list({v for v in vs if v != k}) for k, vs in virtual_graph.items()}
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclass(frozen=True)
|
|
119
|
+
class Cycle:
|
|
120
|
+
dependent_path: Path
|
|
121
|
+
dependent_package: str
|
|
122
|
+
provider_path: Path
|
|
123
|
+
provider_package: str
|
|
124
|
+
packages_after_provider: list[str]
|
|
125
|
+
|
|
126
|
+
def __repr__(self) -> str:
|
|
127
|
+
return "".join(
|
|
128
|
+
(
|
|
129
|
+
f"{self.dependent_path} ({self.dependent_package}) -> ",
|
|
130
|
+
f"{self.provider_path} ({self.provider_package}) -> ",
|
|
131
|
+
*(f"({extra}) -> " for extra in self.packages_after_provider),
|
|
132
|
+
)
|
|
133
|
+
)[:-4]
|
|
134
|
+
|
|
135
|
+
def possible_edge_interpretations(self) -> list[tuple[FileOrPackage, FileOrPackage]]:
|
|
136
|
+
edges_after_initial_files = []
|
|
137
|
+
provider = self.packages_after_provider[0]
|
|
138
|
+
for next_provider in self.packages_after_provider[1:]:
|
|
139
|
+
edges_after_initial_files.append((Package(next_provider), Package(provider)))
|
|
140
|
+
provider = next_provider
|
|
141
|
+
|
|
142
|
+
return [
|
|
143
|
+
# Dependent -> Provider
|
|
144
|
+
(File(self.provider_path), File(self.dependent_path)),
|
|
145
|
+
(Package(self.provider_package), File(self.dependent_path)),
|
|
146
|
+
(File(self.provider_path), Package(self.dependent_package)),
|
|
147
|
+
(Package(self.provider_package), Package(self.dependent_package)),
|
|
148
|
+
# Provider -> Dependent/Other Packages
|
|
149
|
+
(Package(self.packages_after_provider[0]), File(self.provider_path)),
|
|
150
|
+
(Package(self.packages_after_provider[0]), Package(self.provider_package)),
|
|
151
|
+
# the rest
|
|
152
|
+
*edges_after_initial_files,
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def find_all_dependency_paths(dependency_graph: dict[str, list[str]], start: str, end: str) -> list[list[str]]:
|
|
157
|
+
all_paths = []
|
|
158
|
+
visited = set()
|
|
159
|
+
|
|
160
|
+
def dfs(current: str, target: str, path: list[str]) -> None:
|
|
161
|
+
if current in visited:
|
|
162
|
+
return
|
|
163
|
+
if current == target and len(path) > 0:
|
|
164
|
+
all_paths.append(path[1:] + [current])
|
|
165
|
+
return
|
|
166
|
+
visited.add(current)
|
|
167
|
+
for provider in sorted(dependency_graph.get(current, [])):
|
|
168
|
+
dfs(provider, target, [*path, current])
|
|
169
|
+
|
|
170
|
+
dfs(start, end, [])
|
|
171
|
+
return all_paths
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def find_cycles(
|
|
175
|
+
graph: dict[Path, list[Path]],
|
|
176
|
+
virtual_graph: dict[str, list[str]],
|
|
177
|
+
excluded_paths: list[Path],
|
|
178
|
+
ignore_cycles_in: list[str],
|
|
179
|
+
ignore_specific_files: list[Path],
|
|
180
|
+
ignore_specific_edges: list[tuple[FileOrPackage, FileOrPackage]],
|
|
181
|
+
) -> list[Cycle]:
|
|
182
|
+
# Initialize an accumulator for paths that are part of cycles.
|
|
183
|
+
path_accumulator = []
|
|
184
|
+
# Iterate over each package (parent) in the graph.
|
|
185
|
+
for dependent in sorted(graph):
|
|
186
|
+
if dependent in excluded_paths:
|
|
187
|
+
continue
|
|
188
|
+
# Parse the parent package file.
|
|
189
|
+
dependent_file = ChiaFile.parse(dependent)
|
|
190
|
+
# Skip this package if it has no annotations or should be ignored in cycle detection.
|
|
191
|
+
if (
|
|
192
|
+
dependent_file.annotations is None
|
|
193
|
+
or dependent_file.annotations.package in ignore_cycles_in
|
|
194
|
+
or dependent in ignore_specific_files
|
|
195
|
+
):
|
|
196
|
+
continue
|
|
197
|
+
|
|
198
|
+
for provider in sorted(graph[dependent]):
|
|
199
|
+
if provider in excluded_paths:
|
|
200
|
+
continue
|
|
201
|
+
provider_file = ChiaFile.parse(provider)
|
|
202
|
+
if (
|
|
203
|
+
provider_file.annotations is None
|
|
204
|
+
or provider_file.annotations.package == dependent_file.annotations.package
|
|
205
|
+
):
|
|
206
|
+
continue
|
|
207
|
+
|
|
208
|
+
dependency_paths = find_all_dependency_paths(
|
|
209
|
+
virtual_graph, provider_file.annotations.package, dependent_file.annotations.package
|
|
210
|
+
)
|
|
211
|
+
if dependency_paths is None:
|
|
212
|
+
continue
|
|
213
|
+
|
|
214
|
+
for dependency_path in dependency_paths:
|
|
215
|
+
possible_cycle = Cycle(
|
|
216
|
+
dependent_file.path,
|
|
217
|
+
dependent_file.annotations.package,
|
|
218
|
+
provider_file.path,
|
|
219
|
+
provider_file.annotations.package,
|
|
220
|
+
dependency_path,
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
for edge in possible_cycle.possible_edge_interpretations():
|
|
224
|
+
if edge in ignore_specific_edges:
|
|
225
|
+
break
|
|
226
|
+
else:
|
|
227
|
+
path_accumulator.append(possible_cycle)
|
|
228
|
+
|
|
229
|
+
# Format and return the accumulated paths as strings showing the cycles.
|
|
230
|
+
return path_accumulator
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def print_graph(graph: Union[dict[str, list[str]], dict[Path, list[Path]]]) -> None:
|
|
234
|
+
print(json.dumps({str(k): list(str(v) for v in vs) for k, vs in graph.items()}, indent=4))
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@click.group(help="A utility for grouping different parts of the repo into separate projects")
|
|
238
|
+
def cli() -> None:
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@dataclass(frozen=True)
|
|
243
|
+
class DirectoryParameters:
|
|
244
|
+
dir_path: Path
|
|
245
|
+
excluded_paths: list[Path] = field(default_factory=list)
|
|
246
|
+
|
|
247
|
+
def gather_non_empty_python_files(self) -> list[ChiaFile]:
|
|
248
|
+
"""
|
|
249
|
+
Gathers non-empty Python files in the specified directory while
|
|
250
|
+
ignoring files and directories in the excluded paths.
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
A list of paths to non-empty Python files.
|
|
254
|
+
"""
|
|
255
|
+
python_files = []
|
|
256
|
+
for root, dirs, files in os.walk(self.dir_path, topdown=True):
|
|
257
|
+
# Modify dirs in-place to remove excluded directories from search
|
|
258
|
+
dirs[:] = [d for d in dirs if Path(os.path.join(root, d)) not in self.excluded_paths]
|
|
259
|
+
|
|
260
|
+
for file in files:
|
|
261
|
+
file_path = Path(os.path.join(root, file))
|
|
262
|
+
# Check if the file is a Python file and not in the excluded paths
|
|
263
|
+
if file_path.suffix == ".py" and file_path not in self.excluded_paths:
|
|
264
|
+
# Check if the file is non-empty
|
|
265
|
+
if os.path.getsize(file_path) > 0:
|
|
266
|
+
python_files.append(ChiaFile.parse(file_path))
|
|
267
|
+
|
|
268
|
+
return python_files
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
@dataclass(frozen=True)
|
|
272
|
+
class Config:
|
|
273
|
+
directory_parameters: DirectoryParameters
|
|
274
|
+
ignore_cycles_in: list[str]
|
|
275
|
+
ignore_specific_files: list[Path]
|
|
276
|
+
ignore_specific_edges: list[tuple[FileOrPackage, FileOrPackage]] # (parent, child)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
@dataclass(frozen=True)
|
|
280
|
+
class File:
|
|
281
|
+
name: Path
|
|
282
|
+
is_file: Literal[True] = True
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
@dataclass(frozen=True)
|
|
286
|
+
class Package:
|
|
287
|
+
name: str
|
|
288
|
+
is_file: Literal[False] = False
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
FileOrPackage = Union[File, Package]
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def parse_file_or_package(identifier: str) -> FileOrPackage:
|
|
295
|
+
if ".py" in identifier:
|
|
296
|
+
if "(" not in identifier:
|
|
297
|
+
return File(Path(identifier))
|
|
298
|
+
else:
|
|
299
|
+
return File(Path(identifier.split("(")[0].strip()))
|
|
300
|
+
|
|
301
|
+
if ".py" not in identifier and identifier[0] == "(" and identifier[-1] == ")":
|
|
302
|
+
return Package(identifier[1:-1]) # strip parens
|
|
303
|
+
|
|
304
|
+
return Package(identifier)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def parse_edge(user_string: str) -> tuple[FileOrPackage, FileOrPackage]:
|
|
308
|
+
split_string = user_string.split("->")
|
|
309
|
+
dependent_side = split_string[0].strip()
|
|
310
|
+
provider_side = split_string[1].strip()
|
|
311
|
+
|
|
312
|
+
return parse_file_or_package(provider_side), parse_file_or_package(dependent_side)
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def config(func: Callable[..., None]) -> Callable[..., None]:
|
|
316
|
+
@click.option(
|
|
317
|
+
"--directory",
|
|
318
|
+
"include_dir",
|
|
319
|
+
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
320
|
+
required=True,
|
|
321
|
+
help="The directory to include.",
|
|
322
|
+
)
|
|
323
|
+
@click.option(
|
|
324
|
+
"--exclude-path",
|
|
325
|
+
"excluded_paths",
|
|
326
|
+
multiple=True,
|
|
327
|
+
type=click.Path(exists=False, file_okay=True, dir_okay=True),
|
|
328
|
+
help="Optional paths to exclude.",
|
|
329
|
+
)
|
|
330
|
+
@click.option(
|
|
331
|
+
"--config",
|
|
332
|
+
"config_path",
|
|
333
|
+
type=click.Path(exists=True),
|
|
334
|
+
required=False,
|
|
335
|
+
default=None,
|
|
336
|
+
help="Path to the YAML configuration file.",
|
|
337
|
+
)
|
|
338
|
+
def inner(config_path: Optional[str], *args: Any, **kwargs: Any) -> None:
|
|
339
|
+
exclude_paths = []
|
|
340
|
+
ignore_cycles_in: list[str] = []
|
|
341
|
+
ignore_specific_files: list[str] = []
|
|
342
|
+
ignore_specific_edges: list[str] = []
|
|
343
|
+
if config_path is not None:
|
|
344
|
+
# Reading from the YAML configuration file
|
|
345
|
+
with open(config_path) as file:
|
|
346
|
+
config_data = yaml.safe_load(file)
|
|
347
|
+
|
|
348
|
+
# Extracting required configuration values
|
|
349
|
+
exclude_paths = [Path(p) for p in config_data.get("exclude_paths") or []]
|
|
350
|
+
ignore_cycles_in = config_data["ignore"].get("packages") or []
|
|
351
|
+
ignore_specific_files = config_data["ignore"].get("files") or []
|
|
352
|
+
ignore_specific_edges = config_data["ignore"].get("edges") or []
|
|
353
|
+
|
|
354
|
+
# Instantiate DirectoryParameters with the provided options
|
|
355
|
+
dir_params = DirectoryParameters(
|
|
356
|
+
dir_path=Path(kwargs.pop("include_dir")),
|
|
357
|
+
excluded_paths=[*(Path(p) for p in kwargs.pop("excluded_paths")), *exclude_paths],
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
# Make the ignored edge dictionary
|
|
361
|
+
ignore_specific_edges_graph = []
|
|
362
|
+
for ignore in (*kwargs.pop("ignore_specific_edges", []), *ignore_specific_edges):
|
|
363
|
+
parent, child = parse_edge(ignore)
|
|
364
|
+
ignore_specific_edges_graph.append((parent, child))
|
|
365
|
+
|
|
366
|
+
# Instantiating the Config object
|
|
367
|
+
config = Config(
|
|
368
|
+
directory_parameters=dir_params,
|
|
369
|
+
ignore_cycles_in=[*kwargs.pop("ignore_cycles_in", []), *ignore_cycles_in],
|
|
370
|
+
ignore_specific_files=[Path(p) for p in (*kwargs.pop("ignore_specific_files", []), *ignore_specific_files)],
|
|
371
|
+
ignore_specific_edges=ignore_specific_edges_graph,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
# Calling the wrapped function with the Config object and other arguments
|
|
375
|
+
return func(config, *args, **kwargs)
|
|
376
|
+
|
|
377
|
+
return inner
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
@click.command("find_missing_annotations", short_help="Search a directory for chia files without annotations")
|
|
381
|
+
@config
|
|
382
|
+
def find_missing_annotations(config: Config) -> None:
|
|
383
|
+
flag = False
|
|
384
|
+
for file in config.directory_parameters.gather_non_empty_python_files():
|
|
385
|
+
if not file.annotations.is_annotated:
|
|
386
|
+
print(file.path)
|
|
387
|
+
flag = True
|
|
388
|
+
|
|
389
|
+
if flag:
|
|
390
|
+
sys.exit(1)
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
@click.command("print_dependency_graph", short_help="Output a dependency graph of all the files in a directory")
|
|
394
|
+
@config
|
|
395
|
+
def print_dependency_graph(config: Config) -> None:
|
|
396
|
+
print_graph(build_dependency_graph(config.directory_parameters))
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@click.command(
|
|
400
|
+
"print_virtual_dependency_graph", short_help="Output a dependency graph of all the packages in a directory"
|
|
401
|
+
)
|
|
402
|
+
@config
|
|
403
|
+
def print_virtual_dependency_graph(config: Config) -> None:
|
|
404
|
+
print_graph(build_virtual_dependency_graph(config.directory_parameters))
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
@click.command("print_cycles", short_help="Output cycles found in the virtual dependency graph")
|
|
408
|
+
@click.option(
|
|
409
|
+
"--ignore-cycles-in",
|
|
410
|
+
"ignore_cycles_in",
|
|
411
|
+
multiple=True,
|
|
412
|
+
type=str,
|
|
413
|
+
help="Ignore dependency cycles in a package",
|
|
414
|
+
)
|
|
415
|
+
@click.option(
|
|
416
|
+
"--ignore-specific-file",
|
|
417
|
+
"ignore_specific_files",
|
|
418
|
+
multiple=True,
|
|
419
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False),
|
|
420
|
+
help="Ignore cycles involving specific files",
|
|
421
|
+
)
|
|
422
|
+
@click.option(
|
|
423
|
+
"--ignore-specific-edge",
|
|
424
|
+
"ignore_specific_edges",
|
|
425
|
+
multiple=True,
|
|
426
|
+
type=str,
|
|
427
|
+
help="Ignore specific problematic dependencies (format: path/to/file1 -> path/to/file2)",
|
|
428
|
+
)
|
|
429
|
+
@config
|
|
430
|
+
def print_cycles(config: Config) -> None:
|
|
431
|
+
flag = False
|
|
432
|
+
graph = build_dependency_graph(config.directory_parameters)
|
|
433
|
+
for cycle in find_cycles(
|
|
434
|
+
graph,
|
|
435
|
+
build_virtual_dependency_graph(config.directory_parameters, existing_graph=graph),
|
|
436
|
+
config.directory_parameters.excluded_paths,
|
|
437
|
+
config.ignore_cycles_in,
|
|
438
|
+
config.ignore_specific_files,
|
|
439
|
+
config.ignore_specific_edges,
|
|
440
|
+
):
|
|
441
|
+
print(cycle)
|
|
442
|
+
flag = True
|
|
443
|
+
|
|
444
|
+
if flag:
|
|
445
|
+
sys.exit(1)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
@click.command("check_config", short_help="Check the config is as specific as it can be")
|
|
449
|
+
@click.option(
|
|
450
|
+
"--ignore-cycles-in",
|
|
451
|
+
"ignore_cycles_in",
|
|
452
|
+
multiple=True,
|
|
453
|
+
type=str,
|
|
454
|
+
help="Ignore dependency cycles in a package",
|
|
455
|
+
)
|
|
456
|
+
@click.option(
|
|
457
|
+
"--ignore-specific-file",
|
|
458
|
+
"ignore_specific_files",
|
|
459
|
+
multiple=True,
|
|
460
|
+
type=click.Path(exists=True, file_okay=True, dir_okay=False),
|
|
461
|
+
help="Ignore cycles involving specific files",
|
|
462
|
+
)
|
|
463
|
+
@click.option(
|
|
464
|
+
"--ignore-specific-edge",
|
|
465
|
+
"ignore_specific_edges",
|
|
466
|
+
multiple=True,
|
|
467
|
+
type=str,
|
|
468
|
+
help="Ignore specific problematic dependencies (format: path/to/file1 -> path/to/file2)",
|
|
469
|
+
)
|
|
470
|
+
@config
|
|
471
|
+
def check_config(config: Config) -> None:
|
|
472
|
+
graph = build_dependency_graph(config.directory_parameters)
|
|
473
|
+
cycles = find_cycles(
|
|
474
|
+
graph,
|
|
475
|
+
build_virtual_dependency_graph(config.directory_parameters, existing_graph=graph),
|
|
476
|
+
config.directory_parameters.excluded_paths,
|
|
477
|
+
[],
|
|
478
|
+
[],
|
|
479
|
+
[],
|
|
480
|
+
)
|
|
481
|
+
modules_found = set()
|
|
482
|
+
files_found = set()
|
|
483
|
+
edges_found = set()
|
|
484
|
+
for cycle in cycles:
|
|
485
|
+
modules_found.add(cycle.dependent_package)
|
|
486
|
+
files_found.add(cycle.dependent_path)
|
|
487
|
+
edges_found.update(set(cycle.possible_edge_interpretations()))
|
|
488
|
+
|
|
489
|
+
for module in config.ignore_cycles_in:
|
|
490
|
+
if module not in modules_found:
|
|
491
|
+
print(f" module {module} ignored but no cycles were found")
|
|
492
|
+
print()
|
|
493
|
+
for file in config.ignore_specific_files:
|
|
494
|
+
if file not in files_found:
|
|
495
|
+
print(f" file {file} ignored but no cycles were found")
|
|
496
|
+
print()
|
|
497
|
+
for edge in config.ignore_specific_edges:
|
|
498
|
+
if edge not in edges_found:
|
|
499
|
+
print(f" edge {edge[1].name} -> {edge[0].name} ignored but no cycles were found")
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
@click.command("print_edges", short_help="Check for all of the ways a package immediately depends on another")
|
|
503
|
+
@click.option(
|
|
504
|
+
"--dependent-package",
|
|
505
|
+
"from_package",
|
|
506
|
+
type=str,
|
|
507
|
+
help="The package that depends on the other",
|
|
508
|
+
)
|
|
509
|
+
@click.option(
|
|
510
|
+
"--provider-package",
|
|
511
|
+
"to_package",
|
|
512
|
+
type=str,
|
|
513
|
+
help="The package that the dependent package imports from",
|
|
514
|
+
)
|
|
515
|
+
@config
|
|
516
|
+
def print_edges(config: Config, from_package: str, to_package: str) -> None:
|
|
517
|
+
graph = build_dependency_graph(config.directory_parameters)
|
|
518
|
+
for dependent, providers in graph.items():
|
|
519
|
+
dependent_file = ChiaFile.parse(dependent)
|
|
520
|
+
assert dependent_file.annotations is not None
|
|
521
|
+
if dependent_file.annotations.package == from_package:
|
|
522
|
+
for provider in providers:
|
|
523
|
+
provider_file = ChiaFile.parse(provider)
|
|
524
|
+
assert provider_file.annotations is not None
|
|
525
|
+
if provider_file.annotations.package == to_package:
|
|
526
|
+
print(
|
|
527
|
+
f"{dependent} ({dependent_file.annotations.package}) -> "
|
|
528
|
+
f"{provider} ({provider_file.annotations.package})"
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
|
|
532
|
+
cli.add_command(find_missing_annotations)
|
|
533
|
+
cli.add_command(print_dependency_graph)
|
|
534
|
+
cli.add_command(print_virtual_dependency_graph)
|
|
535
|
+
cli.add_command(print_cycles)
|
|
536
|
+
cli.add_command(check_config)
|
|
537
|
+
cli.add_command(print_edges)
|
|
538
|
+
|
|
539
|
+
if __name__ == "__main__":
|
|
540
|
+
cli()
|
chia/util/ws_message.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, Optional
|
|
4
4
|
|
|
5
5
|
from typing_extensions import TypedDict
|
|
6
6
|
|
|
@@ -19,13 +19,13 @@ from chia.util.json_util import dict_to_json_str
|
|
|
19
19
|
class WsRpcMessage(TypedDict):
|
|
20
20
|
command: str
|
|
21
21
|
ack: bool
|
|
22
|
-
data:
|
|
22
|
+
data: dict[str, Any]
|
|
23
23
|
request_id: str
|
|
24
24
|
destination: str
|
|
25
25
|
origin: str
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
def format_response(incoming_msg: WsRpcMessage, response_data:
|
|
28
|
+
def format_response(incoming_msg: WsRpcMessage, response_data: dict[str, Any]) -> str:
|
|
29
29
|
"""
|
|
30
30
|
Formats the response into standard format.
|
|
31
31
|
"""
|
|
@@ -42,12 +42,12 @@ def format_response(incoming_msg: WsRpcMessage, response_data: Dict[str, Any]) -
|
|
|
42
42
|
return json_str
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
def create_payload(command: str, data:
|
|
45
|
+
def create_payload(command: str, data: dict[str, Any], origin: str, destination: str) -> str:
|
|
46
46
|
response = create_payload_dict(command, data, origin, destination)
|
|
47
47
|
return dict_to_json_str(response)
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
def create_payload_dict(command: str, data: Optional[
|
|
50
|
+
def create_payload_dict(command: str, data: Optional[dict[str, Any]], origin: str, destination: str) -> WsRpcMessage:
|
|
51
51
|
if data is None:
|
|
52
52
|
data = {}
|
|
53
53
|
|
|
@@ -61,6 +61,6 @@ def create_payload_dict(command: str, data: Optional[Dict[str, Any]], origin: st
|
|
|
61
61
|
)
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
def pong() ->
|
|
64
|
+
def pong() -> dict[str, Any]:
|
|
65
65
|
response = {"success": True}
|
|
66
66
|
return response
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Optional
|
|
5
5
|
|
|
6
6
|
from chia.types.blockchain_format.program import Program
|
|
7
7
|
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
@@ -35,7 +35,7 @@ class CATCoinData(Streamable):
|
|
|
35
35
|
class LegacyCATInfo(Streamable):
|
|
36
36
|
limitations_program_hash: bytes32
|
|
37
37
|
my_tail: Optional[Program] # this is the program
|
|
38
|
-
lineage_proofs:
|
|
38
|
+
lineage_proofs: list[tuple[bytes32, Optional[LineageProof]]] # {coin.name(): lineage_proof}
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
@streamable
|
|
@@ -43,5 +43,5 @@ class LegacyCATInfo(Streamable):
|
|
|
43
43
|
class CRCATInfo(Streamable):
|
|
44
44
|
limitations_program_hash: bytes32
|
|
45
45
|
my_tail: Optional[Program] # this is the program
|
|
46
|
-
authorized_providers:
|
|
46
|
+
authorized_providers: list[bytes32]
|
|
47
47
|
proofs_checker: ProofsChecker
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import Any, Callable,
|
|
4
|
+
from typing import Any, Callable, Optional
|
|
5
5
|
|
|
6
6
|
from chia.types.blockchain_format.coin import Coin
|
|
7
7
|
from chia.types.blockchain_format.program import Program
|
|
@@ -33,7 +33,7 @@ class CATOuterPuzzle:
|
|
|
33
33
|
if args is None:
|
|
34
34
|
return None
|
|
35
35
|
_, tail_hash, inner_puzzle = args
|
|
36
|
-
constructor_dict:
|
|
36
|
+
constructor_dict: dict[str, Any] = {
|
|
37
37
|
"type": "CAT",
|
|
38
38
|
"tail": "0x" + tail_hash.as_atom().hex(),
|
|
39
39
|
}
|
|
@@ -74,7 +74,7 @@ class CATOuterPuzzle:
|
|
|
74
74
|
|
|
75
75
|
def solve(self, constructor: PuzzleInfo, solver: Solver, inner_puzzle: Program, inner_solution: Program) -> Program:
|
|
76
76
|
tail_hash: bytes32 = constructor["tail"]
|
|
77
|
-
spendable_cats:
|
|
77
|
+
spendable_cats: list[SpendableCAT] = []
|
|
78
78
|
target_coin: Coin
|
|
79
79
|
ring = [
|
|
80
80
|
*zip(
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import dataclasses
|
|
4
|
-
from
|
|
4
|
+
from collections.abc import Iterator
|
|
5
|
+
from typing import Optional, Union
|
|
5
6
|
|
|
6
7
|
from chia_rs import G2Element
|
|
7
8
|
|
|
@@ -77,7 +78,7 @@ def construct_cat_puzzle(
|
|
|
77
78
|
return mod_code.curry(mod_code_hash, limitations_program_hash, inner_puzzle_or_hash)
|
|
78
79
|
|
|
79
80
|
|
|
80
|
-
def subtotals_for_deltas(deltas:
|
|
81
|
+
def subtotals_for_deltas(deltas: list[int]) -> list[int]:
|
|
81
82
|
"""
|
|
82
83
|
Given a list of deltas corresponding to input coins, create the "subtotals" list
|
|
83
84
|
needed in solutions spending those coins.
|
|
@@ -104,7 +105,7 @@ def next_info_for_spendable_cat(spendable_cat: SpendableCAT) -> Program:
|
|
|
104
105
|
|
|
105
106
|
# This should probably return UnsignedSpendBundle if that type ever exists
|
|
106
107
|
def unsigned_spend_bundle_for_spendable_cats(
|
|
107
|
-
mod_code: Program, spendable_cat_list:
|
|
108
|
+
mod_code: Program, spendable_cat_list: list[SpendableCAT]
|
|
108
109
|
) -> WalletSpendBundle:
|
|
109
110
|
"""
|
|
110
111
|
Given a list of `SpendableCAT` objects, create a `WalletSpendBundle` that spends all those coins.
|
|
@@ -114,7 +115,7 @@ def unsigned_spend_bundle_for_spendable_cats(
|
|
|
114
115
|
N = len(spendable_cat_list)
|
|
115
116
|
|
|
116
117
|
# figure out what the deltas are by running the inner puzzles & solutions
|
|
117
|
-
deltas:
|
|
118
|
+
deltas: list[int] = []
|
|
118
119
|
for spend_info in spendable_cat_list:
|
|
119
120
|
conditions = conditions_dict_for_solution(spend_info.inner_puzzle, spend_info.inner_solution, INFINITE_COST)
|
|
120
121
|
total = spend_info.extra_delta * -1
|