chia-blockchain 2.5.0rc2__py3-none-any.whl → 2.5.1rc2__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.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/LICENSE +1 -1
- {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/METADATA +67 -72
- chia_blockchain-2.5.1rc2.dist-info/RECORD +1042 -0
- {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.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.0rc2.dist-info/RECORD +0 -1028
- {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/entry_points.txt +0 -0
chia/full_node/block_store.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import dataclasses
|
|
4
4
|
import logging
|
|
5
5
|
import sqlite3
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Optional
|
|
7
7
|
|
|
8
8
|
import typing_extensions
|
|
9
9
|
import zstd
|
|
@@ -40,7 +40,7 @@ def decompress_blob(block_bytes: bytes) -> bytes:
|
|
|
40
40
|
class BlockStore:
|
|
41
41
|
block_cache: LRUCache[bytes32, FullBlock]
|
|
42
42
|
db_wrapper: DBWrapper2
|
|
43
|
-
ses_challenge_cache: LRUCache[bytes32,
|
|
43
|
+
ses_challenge_cache: LRUCache[bytes32, list[SubEpochChallengeSegment]]
|
|
44
44
|
|
|
45
45
|
@classmethod
|
|
46
46
|
async def create(cls, db_wrapper: DBWrapper2, *, use_cache: bool = True) -> BlockStore:
|
|
@@ -105,7 +105,7 @@ class BlockStore:
|
|
|
105
105
|
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
106
106
|
await conn.execute("UPDATE full_blocks SET in_main_chain=0 WHERE height>? AND in_main_chain=1", (height,))
|
|
107
107
|
|
|
108
|
-
async def set_in_chain(self, header_hashes:
|
|
108
|
+
async def set_in_chain(self, header_hashes: list[tuple[bytes32]]) -> None:
|
|
109
109
|
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
110
110
|
async with await conn.executemany(
|
|
111
111
|
"UPDATE full_blocks SET in_main_chain=1 WHERE header_hash=?", header_hashes
|
|
@@ -162,7 +162,7 @@ class BlockStore:
|
|
|
162
162
|
)
|
|
163
163
|
|
|
164
164
|
async def persist_sub_epoch_challenge_segments(
|
|
165
|
-
self, ses_block_hash: bytes32, segments:
|
|
165
|
+
self, ses_block_hash: bytes32, segments: list[SubEpochChallengeSegment]
|
|
166
166
|
) -> None:
|
|
167
167
|
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
168
168
|
await conn.execute(
|
|
@@ -173,8 +173,8 @@ class BlockStore:
|
|
|
173
173
|
async def get_sub_epoch_challenge_segments(
|
|
174
174
|
self,
|
|
175
175
|
ses_block_hash: bytes32,
|
|
176
|
-
) -> Optional[
|
|
177
|
-
cached: Optional[
|
|
176
|
+
) -> Optional[list[SubEpochChallengeSegment]]:
|
|
177
|
+
cached: Optional[list[SubEpochChallengeSegment]] = self.ses_challenge_cache.get(ses_block_hash)
|
|
178
178
|
if cached is not None:
|
|
179
179
|
return cached
|
|
180
180
|
|
|
@@ -186,7 +186,7 @@ class BlockStore:
|
|
|
186
186
|
row = await cursor.fetchone()
|
|
187
187
|
|
|
188
188
|
if row is not None:
|
|
189
|
-
challenge_segments:
|
|
189
|
+
challenge_segments: list[SubEpochChallengeSegment] = SubEpochSegments.from_bytes(row[0]).challenge_segments
|
|
190
190
|
self.ses_challenge_cache.put(ses_block_hash, challenge_segments)
|
|
191
191
|
return challenge_segments
|
|
192
192
|
return None
|
|
@@ -225,14 +225,17 @@ class BlockStore:
|
|
|
225
225
|
|
|
226
226
|
return None
|
|
227
227
|
|
|
228
|
-
async def get_full_blocks_at(self, heights:
|
|
228
|
+
async def get_full_blocks_at(self, heights: list[uint32]) -> list[FullBlock]:
|
|
229
|
+
"""
|
|
230
|
+
Returns all blocks at the given heights, including orphans.
|
|
231
|
+
"""
|
|
229
232
|
if len(heights) == 0:
|
|
230
233
|
return []
|
|
231
234
|
|
|
232
235
|
formatted_str = f'SELECT block from full_blocks WHERE height in ({"?," * (len(heights) - 1)}?)'
|
|
233
236
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
234
237
|
async with conn.execute(formatted_str, heights) as cursor:
|
|
235
|
-
ret:
|
|
238
|
+
ret: list[FullBlock] = []
|
|
236
239
|
for row in await cursor.fetchall():
|
|
237
240
|
ret.append(decompress(row[0]))
|
|
238
241
|
return ret
|
|
@@ -285,11 +288,11 @@ class BlockStore:
|
|
|
285
288
|
b = FullBlock.from_bytes(block_bytes)
|
|
286
289
|
return None if b.transactions_generator is None else bytes(b.transactions_generator)
|
|
287
290
|
|
|
288
|
-
async def get_generators_at(self, heights:
|
|
291
|
+
async def get_generators_at(self, heights: set[uint32]) -> dict[uint32, bytes]:
|
|
289
292
|
if len(heights) == 0:
|
|
290
293
|
return {}
|
|
291
294
|
|
|
292
|
-
generators:
|
|
295
|
+
generators: dict[uint32, bytes] = {}
|
|
293
296
|
formatted_str = (
|
|
294
297
|
f"SELECT block, height from full_blocks "
|
|
295
298
|
f'WHERE in_main_chain=1 AND height in ({"?," * (len(heights) - 1)}?)'
|
|
@@ -317,7 +320,7 @@ class BlockStore:
|
|
|
317
320
|
|
|
318
321
|
return generators
|
|
319
322
|
|
|
320
|
-
async def get_block_records_by_hash(self, header_hashes:
|
|
323
|
+
async def get_block_records_by_hash(self, header_hashes: list[bytes32]) -> list[BlockRecord]:
|
|
321
324
|
"""
|
|
322
325
|
Returns a list of Block Records, ordered by the same order in which header_hashes are passed in.
|
|
323
326
|
Throws an exception if the blocks are not present
|
|
@@ -325,7 +328,7 @@ class BlockStore:
|
|
|
325
328
|
if len(header_hashes) == 0:
|
|
326
329
|
return []
|
|
327
330
|
|
|
328
|
-
all_blocks:
|
|
331
|
+
all_blocks: dict[bytes32, BlockRecord] = {}
|
|
329
332
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
330
333
|
async with conn.execute(
|
|
331
334
|
"SELECT header_hash,block_record "
|
|
@@ -337,7 +340,7 @@ class BlockStore:
|
|
|
337
340
|
block_rec = BlockRecord.from_bytes(row[1])
|
|
338
341
|
all_blocks[block_rec.header_hash] = block_rec
|
|
339
342
|
|
|
340
|
-
ret:
|
|
343
|
+
ret: list[BlockRecord] = []
|
|
341
344
|
for hh in header_hashes:
|
|
342
345
|
if hh not in all_blocks:
|
|
343
346
|
raise ValueError(f"Header hash {hh} not in the blockchain")
|
|
@@ -363,7 +366,7 @@ class BlockStore:
|
|
|
363
366
|
raise KeyError("missing block in chain")
|
|
364
367
|
return bytes32(row[0])
|
|
365
368
|
|
|
366
|
-
async def get_block_bytes_by_hash(self, header_hashes:
|
|
369
|
+
async def get_block_bytes_by_hash(self, header_hashes: list[bytes32]) -> list[bytes]:
|
|
367
370
|
"""
|
|
368
371
|
Returns a list of Full Blocks block blobs, ordered by the same order in which header_hashes are passed in.
|
|
369
372
|
Throws an exception if the blocks are not present
|
|
@@ -376,14 +379,14 @@ class BlockStore:
|
|
|
376
379
|
formatted_str = (
|
|
377
380
|
f'SELECT header_hash, block from full_blocks WHERE header_hash in ({"?," * (len(header_hashes) - 1)}?)'
|
|
378
381
|
)
|
|
379
|
-
all_blocks:
|
|
382
|
+
all_blocks: dict[bytes32, bytes] = {}
|
|
380
383
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
381
384
|
async with conn.execute(formatted_str, header_hashes) as cursor:
|
|
382
385
|
for row in await cursor.fetchall():
|
|
383
386
|
header_hash = bytes32(row[0])
|
|
384
387
|
all_blocks[header_hash] = decompress_blob(row[1])
|
|
385
388
|
|
|
386
|
-
ret:
|
|
389
|
+
ret: list[bytes] = []
|
|
387
390
|
for hh in header_hashes:
|
|
388
391
|
block = all_blocks.get(hh)
|
|
389
392
|
if block is not None:
|
|
@@ -392,7 +395,7 @@ class BlockStore:
|
|
|
392
395
|
raise ValueError(f"Header hash {hh} not in the blockchain")
|
|
393
396
|
return ret
|
|
394
397
|
|
|
395
|
-
async def get_blocks_by_hash(self, header_hashes:
|
|
398
|
+
async def get_blocks_by_hash(self, header_hashes: list[bytes32]) -> list[FullBlock]:
|
|
396
399
|
"""
|
|
397
400
|
Returns a list of Full Blocks blocks, ordered by the same order in which header_hashes are passed in.
|
|
398
401
|
Throws an exception if the blocks are not present
|
|
@@ -404,7 +407,7 @@ class BlockStore:
|
|
|
404
407
|
formatted_str = (
|
|
405
408
|
f'SELECT header_hash, block from full_blocks WHERE header_hash in ({"?," * (len(header_hashes) - 1)}?)'
|
|
406
409
|
)
|
|
407
|
-
all_blocks:
|
|
410
|
+
all_blocks: dict[bytes32, FullBlock] = {}
|
|
408
411
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
409
412
|
async with conn.execute(formatted_str, header_hashes) as cursor:
|
|
410
413
|
for row in await cursor.fetchall():
|
|
@@ -412,7 +415,7 @@ class BlockStore:
|
|
|
412
415
|
full_block: FullBlock = decompress(row[1])
|
|
413
416
|
all_blocks[header_hash] = full_block
|
|
414
417
|
self.block_cache.put(header_hash, full_block)
|
|
415
|
-
ret:
|
|
418
|
+
ret: list[FullBlock] = []
|
|
416
419
|
for hh in header_hashes:
|
|
417
420
|
if hh not in all_blocks:
|
|
418
421
|
raise ValueError(f"Header hash {hh} not in the blockchain")
|
|
@@ -422,7 +425,7 @@ class BlockStore:
|
|
|
422
425
|
async def get_block_record(self, header_hash: bytes32) -> Optional[BlockRecord]:
|
|
423
426
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
424
427
|
async with conn.execute(
|
|
425
|
-
"SELECT block_record
|
|
428
|
+
"SELECT block_record FROM full_blocks WHERE header_hash=?",
|
|
426
429
|
(header_hash,),
|
|
427
430
|
) as cursor:
|
|
428
431
|
row = await cursor.fetchone()
|
|
@@ -436,16 +439,18 @@ class BlockStore:
|
|
|
436
439
|
self,
|
|
437
440
|
start: int,
|
|
438
441
|
stop: int,
|
|
439
|
-
) ->
|
|
442
|
+
) -> dict[bytes32, BlockRecord]:
|
|
440
443
|
"""
|
|
441
444
|
Returns a dictionary with all blocks in range between start and stop
|
|
442
|
-
if present.
|
|
445
|
+
if present. Only blocks part of the main chain/current peak are returned.
|
|
446
|
+
i.e. No orphan blocks
|
|
443
447
|
"""
|
|
444
448
|
|
|
445
|
-
ret:
|
|
449
|
+
ret: dict[bytes32, BlockRecord] = {}
|
|
446
450
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
447
451
|
async with conn.execute(
|
|
448
|
-
"SELECT header_hash,block_record
|
|
452
|
+
"SELECT header_hash,block_record FROM full_blocks "
|
|
453
|
+
"WHERE height >= ? AND height <= ? AND in_main_chain=1",
|
|
449
454
|
(start, stop),
|
|
450
455
|
) as cursor:
|
|
451
456
|
for row in await cursor.fetchall():
|
|
@@ -459,24 +464,25 @@ class BlockStore:
|
|
|
459
464
|
self,
|
|
460
465
|
start: int,
|
|
461
466
|
stop: int,
|
|
462
|
-
) ->
|
|
467
|
+
) -> list[bytes]:
|
|
463
468
|
"""
|
|
464
469
|
Returns a list with all full blocks in range between start and stop
|
|
465
|
-
if present.
|
|
470
|
+
if present. Only includes blocks in the main chain, in the current peak.
|
|
471
|
+
No orphan blocks.
|
|
466
472
|
"""
|
|
467
473
|
|
|
468
474
|
assert self.db_wrapper.db_version == 2
|
|
469
475
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
470
476
|
async with conn.execute(
|
|
471
|
-
"SELECT block FROM full_blocks WHERE height >= ? AND height <= ?
|
|
477
|
+
"SELECT block FROM full_blocks WHERE height >= ? AND height <= ? AND in_main_chain=1",
|
|
472
478
|
(start, stop),
|
|
473
479
|
) as cursor:
|
|
474
|
-
rows:
|
|
480
|
+
rows: list[sqlite3.Row] = list(await cursor.fetchall())
|
|
475
481
|
if len(rows) != (stop - start) + 1:
|
|
476
482
|
raise ValueError(f"Some blocks in range {start}-{stop} were not found.")
|
|
477
483
|
return [decompress_blob(row[0]) for row in rows]
|
|
478
484
|
|
|
479
|
-
async def get_peak(self) -> Optional[
|
|
485
|
+
async def get_peak(self) -> Optional[tuple[bytes32, uint32]]:
|
|
480
486
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
481
487
|
async with conn.execute("SELECT hash FROM current_peak WHERE key = 0") as cursor:
|
|
482
488
|
peak_row = await cursor.fetchone()
|
|
@@ -491,20 +497,20 @@ class BlockStore:
|
|
|
491
497
|
|
|
492
498
|
async def get_block_records_close_to_peak(
|
|
493
499
|
self, blocks_n: int
|
|
494
|
-
) ->
|
|
500
|
+
) -> tuple[dict[bytes32, BlockRecord], Optional[bytes32]]:
|
|
495
501
|
"""
|
|
496
502
|
Returns a dictionary with all blocks that have height >= peak height - blocks_n, as well as the
|
|
497
|
-
peak header hash.
|
|
503
|
+
peak header hash. Only blocks that are part of the main chain/current peak are included.
|
|
498
504
|
"""
|
|
499
505
|
|
|
500
506
|
peak = await self.get_peak()
|
|
501
507
|
if peak is None:
|
|
502
508
|
return {}, None
|
|
503
509
|
|
|
504
|
-
ret:
|
|
510
|
+
ret: dict[bytes32, BlockRecord] = {}
|
|
505
511
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
506
512
|
async with conn.execute(
|
|
507
|
-
"SELECT header_hash, block_record
|
|
513
|
+
"SELECT header_hash, block_record FROM full_blocks WHERE height >= ? AND in_main_chain=1",
|
|
508
514
|
(peak[1] - blocks_n,),
|
|
509
515
|
) as cursor:
|
|
510
516
|
for row in await cursor.fetchall():
|
|
@@ -531,7 +537,7 @@ class BlockStore:
|
|
|
531
537
|
return None
|
|
532
538
|
return bool(row[0])
|
|
533
539
|
|
|
534
|
-
async def get_random_not_compactified(self, number: int) ->
|
|
540
|
+
async def get_random_not_compactified(self, number: int) -> list[int]:
|
|
535
541
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
536
542
|
async with conn.execute(
|
|
537
543
|
f"SELECT height FROM full_blocks WHERE in_main_chain=1 AND is_fully_compactified=0 "
|
chia/full_node/coin_store.py
CHANGED
|
@@ -4,7 +4,8 @@ import dataclasses
|
|
|
4
4
|
import logging
|
|
5
5
|
import sqlite3
|
|
6
6
|
import time
|
|
7
|
-
from
|
|
7
|
+
from collections.abc import Collection
|
|
8
|
+
from typing import Any, Optional
|
|
8
9
|
|
|
9
10
|
import typing_extensions
|
|
10
11
|
from aiosqlite import Cursor
|
|
@@ -31,7 +32,7 @@ class CoinStore:
|
|
|
31
32
|
"""
|
|
32
33
|
|
|
33
34
|
db_wrapper: DBWrapper2
|
|
34
|
-
coins_added_at_height_cache: LRUCache[uint32,
|
|
35
|
+
coins_added_at_height_cache: LRUCache[uint32, list[CoinRecord]]
|
|
35
36
|
|
|
36
37
|
@classmethod
|
|
37
38
|
async def create(cls, db_wrapper: DBWrapper2) -> CoinStore:
|
|
@@ -85,8 +86,8 @@ class CoinStore:
|
|
|
85
86
|
timestamp: uint64,
|
|
86
87
|
included_reward_coins: Collection[Coin],
|
|
87
88
|
tx_additions: Collection[Coin],
|
|
88
|
-
tx_removals:
|
|
89
|
-
) ->
|
|
89
|
+
tx_removals: list[bytes32],
|
|
90
|
+
) -> list[CoinRecord]:
|
|
90
91
|
"""
|
|
91
92
|
Only called for blocks which are blocks (and thus have rewards and transactions)
|
|
92
93
|
Returns a list of the CoinRecords that were added by this block
|
|
@@ -148,16 +149,16 @@ class CoinStore:
|
|
|
148
149
|
return CoinRecord(coin, row[0], row[1], row[2], row[6])
|
|
149
150
|
return None
|
|
150
151
|
|
|
151
|
-
async def get_coin_records(self, names: Collection[bytes32]) ->
|
|
152
|
+
async def get_coin_records(self, names: Collection[bytes32]) -> list[CoinRecord]:
|
|
152
153
|
if len(names) == 0:
|
|
153
154
|
return []
|
|
154
155
|
|
|
155
|
-
coins:
|
|
156
|
+
coins: list[CoinRecord] = []
|
|
156
157
|
|
|
157
158
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
158
|
-
cursors:
|
|
159
|
+
cursors: list[Cursor] = []
|
|
159
160
|
for batch in to_batches(names, SQLITE_MAX_VARIABLE_NUMBER):
|
|
160
|
-
names_db:
|
|
161
|
+
names_db: tuple[Any, ...] = tuple(batch.entries)
|
|
161
162
|
cursors.append(
|
|
162
163
|
await conn.execute(
|
|
163
164
|
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
@@ -175,8 +176,8 @@ class CoinStore:
|
|
|
175
176
|
|
|
176
177
|
return coins
|
|
177
178
|
|
|
178
|
-
async def get_coins_added_at_height(self, height: uint32) ->
|
|
179
|
-
coins_added: Optional[
|
|
179
|
+
async def get_coins_added_at_height(self, height: uint32) -> list[CoinRecord]:
|
|
180
|
+
coins_added: Optional[list[CoinRecord]] = self.coins_added_at_height_cache.get(height)
|
|
180
181
|
if coins_added is not None:
|
|
181
182
|
return coins_added
|
|
182
183
|
|
|
@@ -194,7 +195,7 @@ class CoinStore:
|
|
|
194
195
|
self.coins_added_at_height_cache.put(height, coins)
|
|
195
196
|
return coins
|
|
196
197
|
|
|
197
|
-
async def get_coins_removed_at_height(self, height: uint32) ->
|
|
198
|
+
async def get_coins_removed_at_height(self, height: uint32) -> list[CoinRecord]:
|
|
198
199
|
# Special case to avoid querying all unspent coins (spent_index=0)
|
|
199
200
|
if height == 0:
|
|
200
201
|
return []
|
|
@@ -212,7 +213,7 @@ class CoinStore:
|
|
|
212
213
|
coins.append(coin_record)
|
|
213
214
|
return coins
|
|
214
215
|
|
|
215
|
-
async def get_all_coins(self, include_spent_coins: bool) ->
|
|
216
|
+
async def get_all_coins(self, include_spent_coins: bool) -> list[CoinRecord]:
|
|
216
217
|
# WARNING: this should only be used for testing or in a simulation,
|
|
217
218
|
# running it on a synced testnet or mainnet node will most likely result in an OOM error.
|
|
218
219
|
coins = set()
|
|
@@ -236,7 +237,7 @@ class CoinStore:
|
|
|
236
237
|
puzzle_hash: bytes32,
|
|
237
238
|
start_height: uint32 = uint32(0),
|
|
238
239
|
end_height: uint32 = uint32((2**32) - 1),
|
|
239
|
-
) ->
|
|
240
|
+
) -> list[CoinRecord]:
|
|
240
241
|
coins = set()
|
|
241
242
|
|
|
242
243
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
@@ -255,15 +256,15 @@ class CoinStore:
|
|
|
255
256
|
async def get_coin_records_by_puzzle_hashes(
|
|
256
257
|
self,
|
|
257
258
|
include_spent_coins: bool,
|
|
258
|
-
puzzle_hashes:
|
|
259
|
+
puzzle_hashes: list[bytes32],
|
|
259
260
|
start_height: uint32 = uint32(0),
|
|
260
261
|
end_height: uint32 = uint32((2**32) - 1),
|
|
261
|
-
) ->
|
|
262
|
+
) -> list[CoinRecord]:
|
|
262
263
|
if len(puzzle_hashes) == 0:
|
|
263
264
|
return []
|
|
264
265
|
|
|
265
266
|
coins = set()
|
|
266
|
-
puzzle_hashes_db:
|
|
267
|
+
puzzle_hashes_db: tuple[Any, ...]
|
|
267
268
|
puzzle_hashes_db = tuple(puzzle_hashes)
|
|
268
269
|
|
|
269
270
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
@@ -273,7 +274,7 @@ class CoinStore:
|
|
|
273
274
|
f'WHERE puzzle_hash in ({"?," * (len(puzzle_hashes) - 1)}?) '
|
|
274
275
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
275
276
|
f"{'' if include_spent_coins else 'AND spent_index=0'}",
|
|
276
|
-
puzzle_hashes_db
|
|
277
|
+
(*puzzle_hashes_db, start_height, end_height),
|
|
277
278
|
) as cursor:
|
|
278
279
|
for row in await cursor.fetchall():
|
|
279
280
|
coin = self.row_to_coin(row)
|
|
@@ -283,10 +284,10 @@ class CoinStore:
|
|
|
283
284
|
async def get_coin_records_by_names(
|
|
284
285
|
self,
|
|
285
286
|
include_spent_coins: bool,
|
|
286
|
-
names:
|
|
287
|
+
names: list[bytes32],
|
|
287
288
|
start_height: uint32 = uint32(0),
|
|
288
289
|
end_height: uint32 = uint32((2**32) - 1),
|
|
289
|
-
) ->
|
|
290
|
+
) -> list[CoinRecord]:
|
|
290
291
|
if len(names) == 0:
|
|
291
292
|
return []
|
|
292
293
|
|
|
@@ -299,7 +300,7 @@ class CoinStore:
|
|
|
299
300
|
f'WHERE coin_name in ({"?," * (len(names) - 1)}?) '
|
|
300
301
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
301
302
|
f"{'' if include_spent_coins else 'AND spent_index=0'}",
|
|
302
|
-
names
|
|
303
|
+
[*names, start_height, end_height],
|
|
303
304
|
) as cursor:
|
|
304
305
|
for row in await cursor.fetchall():
|
|
305
306
|
coin = self.row_to_coin(row)
|
|
@@ -320,18 +321,18 @@ class CoinStore:
|
|
|
320
321
|
async def get_coin_states_by_puzzle_hashes(
|
|
321
322
|
self,
|
|
322
323
|
include_spent_coins: bool,
|
|
323
|
-
puzzle_hashes:
|
|
324
|
+
puzzle_hashes: set[bytes32],
|
|
324
325
|
min_height: uint32 = uint32(0),
|
|
325
326
|
*,
|
|
326
327
|
max_items: int = 50000,
|
|
327
|
-
) ->
|
|
328
|
+
) -> set[CoinState]:
|
|
328
329
|
if len(puzzle_hashes) == 0:
|
|
329
330
|
return set()
|
|
330
331
|
|
|
331
|
-
coins:
|
|
332
|
+
coins: set[CoinState] = set()
|
|
332
333
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
333
334
|
for batch in to_batches(puzzle_hashes, SQLITE_MAX_VARIABLE_NUMBER):
|
|
334
|
-
puzzle_hashes_db:
|
|
335
|
+
puzzle_hashes_db: tuple[Any, ...] = tuple(batch.entries)
|
|
335
336
|
async with conn.execute(
|
|
336
337
|
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
337
338
|
f"coin_parent, amount, timestamp FROM coin_record INDEXED BY coin_puzzle_hash "
|
|
@@ -339,7 +340,7 @@ class CoinStore:
|
|
|
339
340
|
f"AND (confirmed_index>=? OR spent_index>=?)"
|
|
340
341
|
f"{'' if include_spent_coins else 'AND spent_index=0'}"
|
|
341
342
|
" LIMIT ?",
|
|
342
|
-
puzzle_hashes_db
|
|
343
|
+
(*puzzle_hashes_db, min_height, min_height, max_items - len(coins)),
|
|
343
344
|
) as cursor:
|
|
344
345
|
row: sqlite3.Row
|
|
345
346
|
for row in await cursor.fetchall():
|
|
@@ -353,23 +354,23 @@ class CoinStore:
|
|
|
353
354
|
async def get_coin_records_by_parent_ids(
|
|
354
355
|
self,
|
|
355
356
|
include_spent_coins: bool,
|
|
356
|
-
parent_ids:
|
|
357
|
+
parent_ids: list[bytes32],
|
|
357
358
|
start_height: uint32 = uint32(0),
|
|
358
359
|
end_height: uint32 = uint32((2**32) - 1),
|
|
359
|
-
) ->
|
|
360
|
+
) -> list[CoinRecord]:
|
|
360
361
|
if len(parent_ids) == 0:
|
|
361
362
|
return []
|
|
362
363
|
|
|
363
364
|
coins = set()
|
|
364
365
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
365
366
|
for batch in to_batches(parent_ids, SQLITE_MAX_VARIABLE_NUMBER):
|
|
366
|
-
parent_ids_db:
|
|
367
|
+
parent_ids_db: tuple[Any, ...] = tuple(batch.entries)
|
|
367
368
|
async with conn.execute(
|
|
368
369
|
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, coin_parent, amount, timestamp "
|
|
369
370
|
f'FROM coin_record WHERE coin_parent in ({"?," * (len(batch.entries) - 1)}?) '
|
|
370
371
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
371
372
|
f"{'' if include_spent_coins else 'AND spent_index=0'}",
|
|
372
|
-
parent_ids_db
|
|
373
|
+
(*parent_ids_db, start_height, end_height),
|
|
373
374
|
) as cursor:
|
|
374
375
|
async for row in cursor:
|
|
375
376
|
coin = self.row_to_coin(row)
|
|
@@ -385,14 +386,14 @@ class CoinStore:
|
|
|
385
386
|
*,
|
|
386
387
|
max_height: uint32 = uint32.MAXIMUM,
|
|
387
388
|
max_items: int = 50000,
|
|
388
|
-
) ->
|
|
389
|
+
) -> list[CoinState]:
|
|
389
390
|
if len(coin_ids) == 0:
|
|
390
391
|
return []
|
|
391
392
|
|
|
392
|
-
coins:
|
|
393
|
+
coins: list[CoinState] = []
|
|
393
394
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
394
395
|
for batch in to_batches(coin_ids, SQLITE_MAX_VARIABLE_NUMBER):
|
|
395
|
-
coin_ids_db:
|
|
396
|
+
coin_ids_db: tuple[Any, ...] = tuple(batch.entries)
|
|
396
397
|
|
|
397
398
|
max_height_sql = ""
|
|
398
399
|
if max_height != uint32.MAXIMUM:
|
|
@@ -404,7 +405,7 @@ class CoinStore:
|
|
|
404
405
|
f"AND (confirmed_index>=? OR spent_index>=?) {max_height_sql}"
|
|
405
406
|
f"{'' if include_spent_coins else 'AND spent_index=0'}"
|
|
406
407
|
" LIMIT ?",
|
|
407
|
-
coin_ids_db
|
|
408
|
+
(*coin_ids_db, min_height, min_height, max_items - len(coins)),
|
|
408
409
|
) as cursor:
|
|
409
410
|
for row in await cursor.fetchall():
|
|
410
411
|
coins.append(self.row_to_coin_state(row))
|
|
@@ -417,7 +418,7 @@ class CoinStore:
|
|
|
417
418
|
|
|
418
419
|
async def batch_coin_states_by_puzzle_hashes(
|
|
419
420
|
self,
|
|
420
|
-
puzzle_hashes:
|
|
421
|
+
puzzle_hashes: list[bytes32],
|
|
421
422
|
*,
|
|
422
423
|
min_height: uint32 = uint32(0),
|
|
423
424
|
include_spent: bool = True,
|
|
@@ -425,7 +426,7 @@ class CoinStore:
|
|
|
425
426
|
include_hinted: bool = True,
|
|
426
427
|
min_amount: uint64 = uint64(0),
|
|
427
428
|
max_items: int = 50000,
|
|
428
|
-
) ->
|
|
429
|
+
) -> tuple[list[CoinState], Optional[uint32]]:
|
|
429
430
|
"""
|
|
430
431
|
Returns the coin states, as well as the next block height (or `None` if finished).
|
|
431
432
|
You cannot exceed `CoinStore.MAX_PUZZLE_HASH_BATCH_SIZE` puzzle hashes in the query.
|
|
@@ -439,8 +440,8 @@ class CoinStore:
|
|
|
439
440
|
return [], None
|
|
440
441
|
|
|
441
442
|
# Coin states are keyed by coin id to filter out and prevent duplicates.
|
|
442
|
-
coin_states_dict:
|
|
443
|
-
coin_states:
|
|
443
|
+
coin_states_dict: dict[bytes32, CoinState] = dict()
|
|
444
|
+
coin_states: list[CoinState]
|
|
444
445
|
|
|
445
446
|
async with self.db_wrapper.reader() as conn:
|
|
446
447
|
puzzle_hashes_db = tuple(puzzle_hashes)
|
|
@@ -530,13 +531,13 @@ class CoinStore:
|
|
|
530
531
|
|
|
531
532
|
return coin_states, next_height
|
|
532
533
|
|
|
533
|
-
async def rollback_to_block(self, block_index: int) ->
|
|
534
|
+
async def rollback_to_block(self, block_index: int) -> list[CoinRecord]:
|
|
534
535
|
"""
|
|
535
536
|
Note that block_index can be negative, in which case everything is rolled back
|
|
536
537
|
Returns the list of coin records that have been modified
|
|
537
538
|
"""
|
|
538
539
|
|
|
539
|
-
coin_changes:
|
|
540
|
+
coin_changes: dict[bytes32, CoinRecord] = {}
|
|
540
541
|
# Add coins that are confirmed in the reverted blocks to the list of updated coins.
|
|
541
542
|
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
542
543
|
async with conn.execute(
|
|
@@ -569,7 +570,7 @@ class CoinStore:
|
|
|
569
570
|
return list(coin_changes.values())
|
|
570
571
|
|
|
571
572
|
# Store CoinRecord in DB
|
|
572
|
-
async def _add_coin_records(self, records:
|
|
573
|
+
async def _add_coin_records(self, records: list[CoinRecord]) -> None:
|
|
573
574
|
values2 = []
|
|
574
575
|
for record in records:
|
|
575
576
|
values2.append(
|
|
@@ -592,7 +593,7 @@ class CoinStore:
|
|
|
592
593
|
)
|
|
593
594
|
|
|
594
595
|
# Update coin_record to be spent in DB
|
|
595
|
-
async def _set_spent(self, coin_names:
|
|
596
|
+
async def _set_spent(self, coin_names: list[bytes32], index: uint32) -> None:
|
|
596
597
|
assert len(coin_names) == 0 or index > 0
|
|
597
598
|
|
|
598
599
|
if len(coin_names) == 0:
|
chia/full_node/fee_estimate.py
CHANGED
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import math
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import Optional
|
|
6
6
|
|
|
7
7
|
from chia.types.fee_rate import FeeRate, FeeRateV2
|
|
8
8
|
from chia.util.ints import uint64
|
|
@@ -51,4 +51,4 @@ class FeeEstimateGroup(Streamable):
|
|
|
51
51
|
"""
|
|
52
52
|
|
|
53
53
|
error: Optional[str]
|
|
54
|
-
estimates:
|
|
54
|
+
estimates: list[FeeEstimate]
|
chia/full_node/fee_estimation.py
CHANGED
|
@@ -2,7 +2,6 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from datetime import datetime
|
|
5
|
-
from typing import List
|
|
6
5
|
|
|
7
6
|
from chia.types.clvm_cost import CLVMCost
|
|
8
7
|
from chia.types.fee_rate import FeeRate
|
|
@@ -90,4 +89,4 @@ class FeeBlockInfo: # See BlockRecord
|
|
|
90
89
|
"""
|
|
91
90
|
|
|
92
91
|
block_height: uint32
|
|
93
|
-
included_items:
|
|
92
|
+
included_items: list[MempoolItemInfo]
|
chia/full_node/fee_history.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import List
|
|
5
4
|
|
|
6
5
|
from chia.util.ints import uint8, uint32
|
|
7
6
|
from chia.util.streamable import Streamable, streamable
|
|
@@ -11,10 +10,10 @@ from chia.util.streamable import Streamable, streamable
|
|
|
11
10
|
@dataclass(frozen=True)
|
|
12
11
|
class FeeStatBackup(Streamable):
|
|
13
12
|
type: str
|
|
14
|
-
tx_ct_avg:
|
|
15
|
-
confirmed_average:
|
|
16
|
-
failed_average:
|
|
17
|
-
m_fee_rate_avg:
|
|
13
|
+
tx_ct_avg: list[str]
|
|
14
|
+
confirmed_average: list[list[str]]
|
|
15
|
+
failed_average: list[list[str]]
|
|
16
|
+
m_fee_rate_avg: list[str]
|
|
18
17
|
|
|
19
18
|
|
|
20
19
|
@streamable
|
|
@@ -23,4 +22,4 @@ class FeeTrackerBackup(Streamable):
|
|
|
23
22
|
fee_estimator_version: uint8
|
|
24
23
|
first_recorded_height: uint32
|
|
25
24
|
latest_seen_height: uint32
|
|
26
|
-
stats:
|
|
25
|
+
stats: list[FeeStatBackup]
|