chia-blockchain 2.5.4rc2__py3-none-any.whl → 2.5.5rc2__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/blockchain/blockchain_test_utils.py +2 -3
- chia/_tests/blockchain/test_augmented_chain.py +2 -3
- chia/_tests/blockchain/test_blockchain.py +261 -44
- chia/_tests/blockchain/test_blockchain_transactions.py +4 -3
- chia/_tests/blockchain/test_build_chains.py +197 -1
- chia/_tests/blockchain/test_get_block_generator.py +1 -1
- chia/_tests/blockchain/test_lookup_fork_chain.py +1 -1
- chia/_tests/clvm/benchmark_costs.py +1 -1
- chia/_tests/clvm/coin_store.py +3 -4
- chia/_tests/clvm/test_message_conditions.py +2 -2
- chia/_tests/clvm/test_puzzle_compression.py +2 -3
- chia/_tests/clvm/test_puzzles.py +1 -2
- chia/_tests/clvm/test_singletons.py +2 -3
- chia/_tests/clvm/test_spend_sim.py +7 -7
- chia/_tests/cmds/cmd_test_utils.py +30 -25
- chia/_tests/cmds/test_dev_gh.py +1 -1
- chia/_tests/cmds/test_farm_cmd.py +1 -1
- chia/_tests/cmds/test_show.py +1 -2
- chia/_tests/cmds/wallet/test_did.py +101 -56
- chia/_tests/cmds/wallet/test_nft.py +109 -84
- chia/_tests/cmds/wallet/test_notifications.py +1 -1
- chia/_tests/cmds/wallet/test_offer.toffer +1 -1
- chia/_tests/cmds/wallet/test_vcs.py +8 -8
- chia/_tests/cmds/wallet/test_wallet.py +100 -46
- chia/_tests/conftest.py +31 -20
- chia/_tests/connection_utils.py +1 -1
- chia/_tests/core/consensus/stores/__init__.py +0 -0
- chia/_tests/core/consensus/stores/test_coin_store_protocol.py +40 -0
- chia/_tests/core/consensus/test_block_creation.py +2 -31
- chia/_tests/core/consensus/test_pot_iterations.py +38 -3
- chia/_tests/core/custom_types/test_proof_of_space.py +154 -26
- chia/_tests/core/custom_types/test_spend_bundle.py +2 -3
- chia/_tests/core/daemon/test_daemon.py +80 -0
- chia/_tests/core/data_layer/test_data_layer.py +1 -1
- chia/_tests/core/data_layer/test_data_layer_util.py +1 -1
- chia/_tests/core/data_layer/test_data_rpc.py +14 -10
- chia/_tests/core/data_layer/test_data_store.py +5 -5
- chia/_tests/core/farmer/test_farmer_api.py +2 -2
- chia/_tests/core/full_node/full_sync/test_full_sync.py +446 -406
- chia/_tests/core/full_node/ram_db.py +3 -1
- chia/_tests/core/full_node/stores/test_block_store.py +28 -16
- chia/_tests/core/full_node/stores/test_coin_store.py +277 -185
- chia/_tests/core/full_node/stores/test_full_node_store.py +11 -4
- chia/_tests/core/full_node/stores/test_hint_store.py +2 -2
- chia/_tests/core/full_node/test_address_manager.py +200 -27
- chia/_tests/core/full_node/test_block_height_map.py +2 -2
- chia/_tests/core/full_node/test_conditions.py +7 -6
- chia/_tests/core/full_node/test_full_node.py +456 -40
- chia/_tests/core/full_node/test_generator_tools.py +32 -2
- chia/_tests/core/full_node/test_hint_management.py +1 -1
- chia/_tests/core/full_node/test_node_load.py +20 -21
- chia/_tests/core/full_node/test_performance.py +3 -4
- chia/_tests/core/full_node/test_prev_tx_block.py +43 -0
- chia/_tests/core/full_node/test_subscriptions.py +1 -2
- chia/_tests/core/full_node/test_transactions.py +9 -5
- chia/_tests/core/full_node/test_tx_processing_queue.py +1 -2
- chia/_tests/core/large_block.py +1 -2
- chia/_tests/core/make_block_generator.py +3 -4
- chia/_tests/core/mempool/test_mempool.py +36 -86
- chia/_tests/core/mempool/test_mempool_fee_estimator.py +1 -1
- chia/_tests/core/mempool/test_mempool_item_queries.py +1 -3
- chia/_tests/core/mempool/test_mempool_manager.py +421 -69
- chia/_tests/core/mempool/test_mempool_performance.py +3 -2
- chia/_tests/core/mempool/test_singleton_fast_forward.py +60 -131
- chia/_tests/core/server/flood.py +1 -1
- chia/_tests/core/server/test_dos.py +1 -1
- chia/_tests/core/server/test_node_discovery.py +41 -27
- chia/_tests/core/server/test_rate_limits.py +1 -1
- chia/_tests/core/server/test_server.py +1 -1
- chia/_tests/core/services/test_services.py +5 -5
- chia/_tests/core/ssl/test_ssl.py +1 -1
- chia/_tests/core/test_cost_calculation.py +6 -6
- chia/_tests/core/test_crawler.py +2 -2
- chia/_tests/core/test_crawler_rpc.py +1 -1
- chia/_tests/core/test_db_conversion.py +3 -1
- chia/_tests/core/test_db_validation.py +5 -3
- chia/_tests/core/test_farmer_harvester_rpc.py +15 -15
- chia/_tests/core/test_filter.py +4 -1
- chia/_tests/core/test_full_node_rpc.py +99 -82
- chia/_tests/core/test_program.py +2 -2
- chia/_tests/core/util/test_block_cache.py +1 -1
- chia/_tests/core/util/test_keychain.py +2 -2
- chia/_tests/core/util/test_lockfile.py +1 -1
- chia/_tests/core/util/test_log_exceptions.py +5 -5
- chia/_tests/core/util/test_streamable.py +81 -22
- chia/_tests/db/test_db_wrapper.py +1 -3
- chia/_tests/environments/wallet.py +5 -5
- chia/_tests/farmer_harvester/test_farmer.py +9 -7
- chia/_tests/farmer_harvester/test_farmer_harvester.py +11 -4
- chia/_tests/farmer_harvester/test_filter_prefix_bits.py +6 -5
- chia/_tests/farmer_harvester/test_third_party_harvesters.py +15 -9
- chia/_tests/fee_estimation/test_fee_estimation_integration.py +1 -2
- chia/_tests/fee_estimation/test_fee_estimation_rpc.py +7 -5
- chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +1 -1
- chia/_tests/generator/test_compression.py +1 -2
- chia/_tests/generator/test_rom.py +8 -4
- chia/_tests/plot_sync/test_plot_sync.py +3 -3
- chia/_tests/plot_sync/test_receiver.py +3 -3
- chia/_tests/plot_sync/test_sender.py +1 -1
- chia/_tests/plot_sync/test_sync_simulated.py +3 -3
- chia/_tests/plot_sync/util.py +2 -2
- chia/_tests/pools/test_pool_cmdline.py +48 -21
- chia/_tests/pools/test_pool_puzzles_lifecycle.py +2 -3
- chia/_tests/pools/test_pool_rpc.py +237 -105
- chia/_tests/pools/test_pool_wallet.py +11 -2
- chia/_tests/pools/test_wallet_pool_store.py +5 -4
- chia/_tests/rpc/test_rpc_client.py +1 -1
- chia/_tests/simulation/test_simulation.py +13 -8
- chia/_tests/simulation/test_simulator.py +2 -2
- chia/_tests/timelord/test_new_peak.py +191 -47
- chia/_tests/timelord/test_timelord.py +1 -1
- chia/_tests/tools/test_full_sync.py +0 -2
- chia/_tests/tools/test_run_block.py +3 -1
- chia/_tests/util/benchmark_cost.py +3 -3
- chia/_tests/util/benchmarks.py +2 -2
- chia/_tests/util/blockchain.py +11 -5
- chia/_tests/util/blockchain_mock.py +1 -4
- chia/_tests/util/coin_store.py +29 -0
- chia/_tests/util/constants.py +2 -18
- chia/_tests/util/full_sync.py +3 -3
- chia/_tests/util/generator_tools_testing.py +2 -3
- chia/_tests/util/key_tool.py +2 -3
- chia/_tests/util/misc.py +33 -31
- chia/_tests/util/network_protocol_data.py +19 -17
- chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
- chia/_tests/util/protocol_messages_json.py +3 -1
- chia/_tests/util/run_block.py +2 -2
- chia/_tests/util/setup_nodes.py +7 -7
- chia/_tests/util/spend_sim.py +47 -55
- chia/_tests/util/test_condition_tools.py +5 -4
- chia/_tests/util/test_config.py +2 -2
- chia/_tests/util/test_dump_keyring.py +1 -1
- chia/_tests/util/test_full_block_utils.py +12 -14
- chia/_tests/util/test_misc.py +2 -2
- chia/_tests/util/test_paginator.py +4 -4
- chia/_tests/util/test_priority_mutex.py +2 -2
- chia/_tests/util/test_replace_str_to_bytes.py +15 -5
- chia/_tests/util/test_ssl_check.py +1 -1
- chia/_tests/util/test_testnet_overrides.py +13 -3
- chia/_tests/util/time_out_assert.py +4 -2
- chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +1 -1
- chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +1 -2
- chia/_tests/wallet/cat_wallet/test_cat_wallet.py +352 -432
- chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +3 -6
- chia/_tests/wallet/cat_wallet/test_trades.py +53 -77
- chia/_tests/wallet/clawback/test_clawback_decorator.py +3 -1
- chia/_tests/wallet/clawback/test_clawback_lifecycle.py +3 -3
- chia/_tests/wallet/clawback/test_clawback_metadata.py +4 -2
- chia/_tests/wallet/conftest.py +11 -12
- chia/_tests/wallet/db_wallet/test_db_graftroot.py +11 -4
- chia/_tests/wallet/db_wallet/test_dl_offers.py +433 -130
- chia/_tests/wallet/db_wallet/test_dl_wallet.py +3 -3
- chia/_tests/wallet/did_wallet/test_did.py +2132 -2000
- chia/_tests/wallet/nft_wallet/config.py +1 -1
- chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1610 -742
- chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +486 -907
- chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +4 -4
- chia/_tests/wallet/nft_wallet/test_nft_wallet.py +517 -294
- chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +133 -62
- chia/_tests/wallet/rpc/test_wallet_rpc.py +495 -265
- chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +10 -6
- chia/_tests/wallet/sync/test_wallet_sync.py +89 -60
- chia/_tests/wallet/test_clvm_casts.py +88 -0
- chia/_tests/wallet/test_coin_management.py +1 -1
- chia/_tests/wallet/test_coin_selection.py +1 -1
- chia/_tests/wallet/test_conditions.py +1 -1
- chia/_tests/wallet/test_new_wallet_protocol.py +13 -11
- chia/_tests/wallet/test_notifications.py +5 -3
- chia/_tests/wallet/test_sign_coin_spends.py +6 -6
- chia/_tests/wallet/test_signer_protocol.py +13 -12
- chia/_tests/wallet/test_singleton.py +1 -1
- chia/_tests/wallet/test_singleton_lifecycle_fast.py +5 -7
- chia/_tests/wallet/test_util.py +2 -2
- chia/_tests/wallet/test_wallet.py +108 -29
- chia/_tests/wallet/test_wallet_action_scope.py +9 -2
- chia/_tests/wallet/test_wallet_blockchain.py +2 -3
- chia/_tests/wallet/test_wallet_key_val_store.py +1 -2
- chia/_tests/wallet/test_wallet_node.py +2 -4
- chia/_tests/wallet/test_wallet_retry.py +4 -2
- chia/_tests/wallet/test_wallet_state_manager.py +191 -5
- chia/_tests/wallet/test_wallet_test_framework.py +1 -1
- chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +8 -8
- chia/_tests/wallet/vc_wallet/test_vc_wallet.py +29 -12
- chia/_tests/wallet/wallet_block_tools.py +6 -6
- chia/_tests/weight_proof/test_weight_proof.py +10 -48
- chia/apis.py +1 -1
- chia/cmds/beta.py +1 -1
- chia/cmds/chia.py +9 -9
- chia/cmds/cmd_classes.py +12 -11
- chia/cmds/cmd_helpers.py +1 -1
- chia/cmds/cmds_util.py +12 -9
- chia/cmds/coin_funcs.py +2 -2
- chia/cmds/configure.py +2 -2
- chia/cmds/data.py +0 -2
- chia/cmds/data_funcs.py +1 -1
- chia/cmds/db_validate_func.py +1 -2
- chia/cmds/dev/__init__.py +0 -0
- chia/cmds/dev/data.py +273 -0
- chia/cmds/{gh.py → dev/gh.py} +5 -5
- chia/cmds/dev/main.py +22 -0
- chia/cmds/dev/mempool.py +78 -0
- chia/cmds/dev/mempool_funcs.py +63 -0
- chia/cmds/farm_funcs.py +5 -4
- chia/cmds/init_funcs.py +11 -11
- chia/cmds/keys.py +2 -2
- chia/cmds/keys_funcs.py +4 -4
- chia/cmds/netspace_funcs.py +1 -1
- chia/cmds/peer_funcs.py +2 -2
- chia/cmds/plotnft_funcs.py +72 -26
- chia/cmds/rpc.py +1 -1
- chia/cmds/show_funcs.py +5 -5
- chia/cmds/signer.py +8 -7
- chia/cmds/sim_funcs.py +8 -9
- chia/cmds/wallet.py +2 -2
- chia/cmds/wallet_funcs.py +165 -131
- chia/{util → consensus}/augmented_chain.py +1 -2
- chia/consensus/block_body_validation.py +54 -40
- chia/consensus/block_creation.py +42 -76
- chia/consensus/block_header_validation.py +32 -26
- chia/consensus/block_record.py +0 -3
- chia/consensus/blockchain.py +23 -32
- chia/consensus/blockchain_interface.py +1 -5
- chia/consensus/check_time_locks.py +57 -0
- chia/consensus/coin_store_protocol.py +151 -0
- chia/consensus/coinbase.py +0 -6
- chia/consensus/condition_costs.py +4 -0
- chia/{util → consensus}/condition_tools.py +4 -5
- chia/consensus/cost_calculator.py +1 -1
- chia/consensus/default_constants.py +32 -9
- chia/consensus/deficit.py +1 -3
- chia/consensus/difficulty_adjustment.py +1 -2
- chia/consensus/find_fork_point.py +1 -3
- chia/consensus/full_block_to_block_record.py +1 -6
- chia/{util → consensus}/generator_tools.py +1 -3
- chia/consensus/get_block_challenge.py +30 -7
- chia/consensus/make_sub_epoch_summary.py +1 -5
- chia/consensus/multiprocess_validation.py +21 -20
- chia/consensus/pot_iterations.py +74 -13
- chia/{util → consensus}/prev_transaction_block.py +1 -1
- chia/consensus/vdf_info_computation.py +1 -3
- chia/daemon/keychain_proxy.py +5 -5
- chia/daemon/server.py +22 -5
- chia/data_layer/data_layer.py +92 -51
- chia/{rpc → data_layer}/data_layer_rpc_api.py +1 -1
- chia/{rpc → data_layer}/data_layer_rpc_util.py +3 -6
- chia/data_layer/data_layer_util.py +4 -6
- chia/data_layer/data_layer_wallet.py +42 -69
- chia/data_layer/dl_wallet_store.py +12 -6
- chia/data_layer/download_data.py +3 -3
- chia/data_layer/s3_plugin_service.py +0 -1
- chia/farmer/farmer.py +3 -4
- chia/farmer/farmer_api.py +11 -7
- chia/{rpc → farmer}/farmer_rpc_client.py +1 -1
- chia/full_node/block_height_map.py +7 -6
- chia/full_node/block_store.py +5 -7
- chia/full_node/bundle_tools.py +1 -2
- chia/full_node/coin_store.py +143 -124
- chia/{types → full_node}/eligible_coin_spends.py +39 -70
- chia/full_node/fee_estimator.py +1 -1
- chia/full_node/fee_estimator_interface.py +0 -8
- chia/full_node/fee_tracker.py +25 -25
- chia/full_node/full_node.py +70 -53
- chia/full_node/full_node_api.py +57 -40
- chia/{rpc → full_node}/full_node_rpc_api.py +87 -8
- chia/{rpc → full_node}/full_node_rpc_client.py +7 -6
- chia/full_node/full_node_store.py +23 -8
- chia/full_node/mempool.py +206 -53
- chia/full_node/mempool_check_conditions.py +20 -63
- chia/full_node/mempool_manager.py +26 -40
- chia/full_node/subscriptions.py +1 -3
- chia/full_node/tx_processing_queue.py +50 -3
- chia/full_node/weight_proof.py +46 -37
- chia/harvester/harvester.py +1 -1
- chia/harvester/harvester_api.py +22 -7
- chia/introducer/introducer.py +1 -1
- chia/introducer/introducer_api.py +1 -1
- chia/plot_sync/exceptions.py +1 -1
- chia/plot_sync/receiver.py +1 -1
- chia/plot_sync/sender.py +2 -2
- chia/pools/pool_puzzles.py +13 -18
- chia/pools/pool_wallet.py +23 -46
- chia/protocols/farmer_protocol.py +11 -3
- chia/protocols/full_node_protocol.py +1 -4
- chia/protocols/harvester_protocol.py +3 -3
- chia/protocols/pool_protocol.py +1 -2
- chia/protocols/shared_protocol.py +3 -3
- chia/protocols/timelord_protocol.py +1 -3
- chia/protocols/wallet_protocol.py +3 -3
- chia/rpc/rpc_client.py +7 -8
- chia/rpc/rpc_server.py +3 -3
- chia/rpc/util.py +3 -1
- chia/seeder/crawler.py +1 -1
- chia/seeder/crawler_api.py +1 -1
- chia/seeder/dns_server.py +2 -0
- chia/seeder/start_crawler.py +3 -3
- chia/server/address_manager.py +286 -38
- chia/server/address_manager_store.py +0 -215
- chia/{types → server}/aliases.py +7 -7
- chia/server/api_protocol.py +1 -1
- chia/server/chia_policy.py +1 -1
- chia/server/node_discovery.py +76 -113
- chia/server/rate_limits.py +1 -1
- chia/server/resolve_peer_info.py +43 -0
- chia/server/server.py +5 -5
- chia/server/start_data_layer.py +4 -4
- chia/server/start_farmer.py +5 -4
- chia/server/start_full_node.py +5 -4
- chia/server/start_harvester.py +7 -5
- chia/server/start_introducer.py +2 -2
- chia/server/start_service.py +1 -1
- chia/server/start_timelord.py +7 -5
- chia/server/start_wallet.py +7 -5
- chia/server/ws_connection.py +1 -1
- chia/simulator/add_blocks_in_batches.py +2 -2
- chia/simulator/block_tools.py +245 -201
- chia/simulator/full_node_simulator.py +38 -10
- chia/simulator/setup_services.py +12 -12
- chia/simulator/simulator_full_node_rpc_api.py +2 -2
- chia/simulator/simulator_full_node_rpc_client.py +2 -2
- chia/simulator/simulator_test_tools.py +2 -2
- chia/simulator/start_simulator.py +1 -1
- chia/simulator/wallet_tools.py +10 -18
- chia/ssl/create_ssl.py +1 -1
- chia/timelord/iters_from_block.py +14 -14
- chia/timelord/timelord.py +15 -11
- chia/timelord/timelord_api.py +14 -2
- chia/timelord/timelord_state.py +20 -14
- chia/types/blockchain_format/program.py +53 -10
- chia/types/blockchain_format/proof_of_space.py +73 -19
- chia/types/coin_spend.py +3 -56
- chia/types/generator_types.py +28 -0
- chia/types/internal_mempool_item.py +1 -2
- chia/types/mempool_item.py +12 -7
- chia/types/unfinished_header_block.py +1 -2
- chia/types/validation_state.py +1 -2
- chia/types/weight_proof.py +1 -3
- chia/util/action_scope.py +3 -3
- chia/util/block_cache.py +1 -2
- chia/util/byte_types.py +1 -1
- chia/util/casts.py +21 -0
- chia/util/config.py +0 -37
- chia/util/db_wrapper.py +8 -1
- chia/util/errors.py +3 -2
- chia/util/initial-config.yaml +21 -5
- chia/util/keychain.py +6 -7
- chia/util/keyring_wrapper.py +5 -5
- chia/util/limited_semaphore.py +1 -1
- chia/util/priority_mutex.py +1 -1
- chia/util/streamable.py +63 -5
- chia/util/task_timing.py +1 -1
- chia/util/virtual_project_analysis.py +1 -1
- chia/wallet/cat_wallet/cat_info.py +7 -3
- chia/wallet/cat_wallet/cat_outer_puzzle.py +9 -5
- chia/wallet/cat_wallet/cat_utils.py +1 -1
- chia/wallet/cat_wallet/cat_wallet.py +44 -36
- chia/wallet/cat_wallet/lineage_store.py +7 -0
- chia/wallet/cat_wallet/r_cat_wallet.py +274 -0
- chia/wallet/conditions.py +5 -10
- chia/wallet/db_wallet/db_wallet_puzzles.py +4 -4
- chia/wallet/derivation_record.py +33 -0
- chia/wallet/derive_keys.py +3 -3
- chia/wallet/did_wallet/did_info.py +12 -3
- chia/wallet/did_wallet/did_wallet.py +132 -101
- chia/wallet/did_wallet/did_wallet_puzzles.py +9 -9
- chia/wallet/driver_protocol.py +3 -1
- chia/{types/spend_bundle.py → wallet/estimate_fees.py} +2 -7
- chia/wallet/nft_wallet/metadata_outer_puzzle.py +5 -3
- chia/wallet/nft_wallet/nft_puzzle_utils.py +1 -1
- chia/wallet/nft_wallet/nft_wallet.py +69 -112
- chia/wallet/nft_wallet/ownership_outer_puzzle.py +5 -3
- chia/wallet/nft_wallet/singleton_outer_puzzle.py +6 -4
- chia/wallet/nft_wallet/transfer_program_puzzle.py +4 -2
- chia/wallet/nft_wallet/uncurry_nft.py +4 -6
- chia/wallet/notification_manager.py +2 -3
- chia/wallet/outer_puzzles.py +7 -2
- chia/wallet/puzzle_drivers.py +1 -1
- chia/wallet/puzzles/clawback/drivers.py +5 -4
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +1 -1
- chia/wallet/puzzles/singleton_top_layer.py +2 -1
- chia/wallet/puzzles/singleton_top_layer_v1_1.py +2 -1
- chia/wallet/puzzles/tails.py +1 -3
- chia/wallet/signer_protocol.py +5 -6
- chia/wallet/singleton.py +5 -4
- chia/wallet/singleton_record.py +1 -1
- chia/wallet/trade_manager.py +18 -20
- chia/wallet/trade_record.py +3 -6
- chia/wallet/trading/offer.py +12 -13
- chia/wallet/uncurried_puzzle.py +2 -2
- chia/wallet/util/compute_additions.py +58 -0
- chia/wallet/util/compute_hints.py +3 -3
- chia/wallet/util/compute_memos.py +4 -4
- chia/wallet/util/curry_and_treehash.py +2 -1
- chia/wallet/util/debug_spend_bundle.py +1 -1
- chia/wallet/util/merkle_tree.py +1 -1
- chia/wallet/util/peer_request_cache.py +1 -2
- chia/wallet/util/tx_config.py +3 -8
- chia/wallet/util/wallet_sync_utils.py +10 -5
- chia/wallet/util/wallet_types.py +1 -0
- chia/wallet/vc_wallet/cr_cat_drivers.py +17 -18
- chia/wallet/vc_wallet/cr_cat_wallet.py +30 -28
- chia/wallet/vc_wallet/cr_outer_puzzle.py +5 -3
- chia/wallet/vc_wallet/vc_drivers.py +50 -8
- chia/wallet/vc_wallet/vc_store.py +3 -5
- chia/wallet/vc_wallet/vc_wallet.py +15 -22
- chia/wallet/wallet.py +36 -46
- chia/wallet/wallet_action_scope.py +73 -4
- chia/wallet/wallet_blockchain.py +1 -3
- chia/wallet/wallet_interested_store.py +1 -1
- chia/wallet/wallet_nft_store.py +3 -3
- chia/wallet/wallet_node.py +17 -16
- chia/wallet/wallet_node_api.py +4 -5
- chia/wallet/wallet_pool_store.py +1 -1
- chia/wallet/wallet_protocol.py +2 -0
- chia/wallet/wallet_puzzle_store.py +1 -1
- chia/{rpc → wallet}/wallet_request_types.py +670 -81
- chia/{rpc → wallet}/wallet_rpc_api.py +735 -766
- chia/{rpc → wallet}/wallet_rpc_client.py +268 -420
- chia/wallet/wallet_singleton_store.py +8 -7
- chia/wallet/wallet_spend_bundle.py +4 -3
- chia/wallet/wallet_state_manager.py +320 -191
- chia/wallet/wallet_weight_proof_handler.py +1 -2
- chia/wallet/wsm_apis.py +98 -0
- {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/METADATA +7 -7
- {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/RECORD +443 -436
- mozilla-ca/cacert.pem +3 -165
- chia/_tests/fee_estimation/test_mempoolitem_height_added.py +0 -145
- chia/cmds/dev.py +0 -18
- chia/types/blockchain_format/slots.py +0 -9
- chia/types/blockchain_format/sub_epoch_summary.py +0 -5
- chia/types/end_of_slot_bundle.py +0 -5
- chia/types/full_block.py +0 -5
- chia/types/header_block.py +0 -5
- chia/types/spend_bundle_conditions.py +0 -7
- chia/types/transaction_queue_entry.py +0 -56
- chia/types/unfinished_block.py +0 -5
- /chia/cmds/{installers.py → dev/installers.py} +0 -0
- /chia/cmds/{sim.py → dev/sim.py} +0 -0
- /chia/{util → cmds}/dump_keyring.py +0 -0
- /chia/{full_node → consensus}/signage_point.py +0 -0
- /chia/{rpc → data_layer}/data_layer_rpc_client.py +0 -0
- /chia/{rpc → farmer}/farmer_rpc_api.py +0 -0
- /chia/{util → full_node}/full_block_utils.py +0 -0
- /chia/{rpc → harvester}/harvester_rpc_api.py +0 -0
- /chia/{rpc → harvester}/harvester_rpc_client.py +0 -0
- /chia/{full_node → protocols}/fee_estimate.py +0 -0
- /chia/{server → protocols}/outbound_message.py +0 -0
- /chia/{rpc → seeder}/crawler_rpc_api.py +0 -0
- /chia/{util → simulator}/vdf_prover.py +0 -0
- /chia/{util → ssl}/ssl_check.py +0 -0
- /chia/{rpc → timelord}/timelord_rpc_api.py +0 -0
- {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/LICENSE +0 -0
- {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/WHEEL +0 -0
- {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/entry_points.txt +0 -0
chia/full_node/coin_store.py
CHANGED
|
@@ -5,21 +5,19 @@ import logging
|
|
|
5
5
|
import sqlite3
|
|
6
6
|
import time
|
|
7
7
|
from collections.abc import Collection
|
|
8
|
-
from typing import Any, Optional
|
|
8
|
+
from typing import Any, ClassVar, Optional
|
|
9
9
|
|
|
10
10
|
import typing_extensions
|
|
11
11
|
from aiosqlite import Cursor
|
|
12
|
+
from chia_rs import CoinState
|
|
12
13
|
from chia_rs.sized_bytes import bytes32
|
|
13
14
|
from chia_rs.sized_ints import uint32, uint64
|
|
14
|
-
from clvm.casts import int_from_bytes
|
|
15
15
|
|
|
16
|
-
from chia.protocols.wallet_protocol import CoinState
|
|
17
16
|
from chia.types.blockchain_format.coin import Coin
|
|
18
17
|
from chia.types.coin_record import CoinRecord
|
|
19
|
-
from chia.types.
|
|
18
|
+
from chia.types.mempool_item import UnspentLineageInfo
|
|
20
19
|
from chia.util.batches import to_batches
|
|
21
20
|
from chia.util.db_wrapper import SQLITE_MAX_VARIABLE_NUMBER, DBWrapper2
|
|
22
|
-
from chia.util.lru_cache import LRUCache
|
|
23
21
|
|
|
24
22
|
log = logging.getLogger(__name__)
|
|
25
23
|
|
|
@@ -32,13 +30,12 @@ class CoinStore:
|
|
|
32
30
|
"""
|
|
33
31
|
|
|
34
32
|
db_wrapper: DBWrapper2
|
|
35
|
-
coins_added_at_height_cache: LRUCache[uint32, list[CoinRecord]]
|
|
36
33
|
|
|
37
34
|
@classmethod
|
|
38
35
|
async def create(cls, db_wrapper: DBWrapper2) -> CoinStore:
|
|
39
36
|
if db_wrapper.db_version != 2:
|
|
40
37
|
raise RuntimeError(f"CoinStore does not support database schema v{db_wrapper.db_version}")
|
|
41
|
-
self = CoinStore(db_wrapper
|
|
38
|
+
self = CoinStore(db_wrapper)
|
|
42
39
|
|
|
43
40
|
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
44
41
|
log.info("DB: Creating coin store tables and indexes.")
|
|
@@ -69,11 +66,28 @@ class CoinStore:
|
|
|
69
66
|
log.info("DB: Creating index coin_parent_index")
|
|
70
67
|
await conn.execute("CREATE INDEX IF NOT EXISTS coin_parent_index on coin_record(coin_parent)")
|
|
71
68
|
|
|
69
|
+
async with conn.execute("SELECT 1 FROM coin_record LIMIT 1") as cursor:
|
|
70
|
+
is_new_db = await cursor.fetchone() is None
|
|
71
|
+
if is_new_db:
|
|
72
|
+
log.info("DB: Creating index coin_record_ph_ff_unspent_idx")
|
|
73
|
+
# This partial index optimizes fast forward singleton latest
|
|
74
|
+
# unspent queries. We're only adding it to new DBs to avoid
|
|
75
|
+
# complex migrations that affect the huge coin records table.
|
|
76
|
+
# The performance benefit outweighs the cost of this partial
|
|
77
|
+
# index as it only includes rows where spent_index is -1.
|
|
78
|
+
await conn.execute(
|
|
79
|
+
"""
|
|
80
|
+
CREATE INDEX IF NOT EXISTS coin_record_ph_ff_unspent_idx
|
|
81
|
+
ON coin_record(puzzle_hash, spent_index)
|
|
82
|
+
WHERE spent_index = -1
|
|
83
|
+
"""
|
|
84
|
+
)
|
|
85
|
+
|
|
72
86
|
return self
|
|
73
87
|
|
|
74
88
|
async def num_unspent(self) -> int:
|
|
75
89
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
76
|
-
async with conn.execute("SELECT COUNT(*) FROM coin_record WHERE spent_index
|
|
90
|
+
async with conn.execute("SELECT COUNT(*) FROM coin_record WHERE spent_index <= 0") as cursor:
|
|
77
91
|
row = await cursor.fetchone()
|
|
78
92
|
if row is not None:
|
|
79
93
|
count: int = row[0]
|
|
@@ -85,27 +99,33 @@ class CoinStore:
|
|
|
85
99
|
height: uint32,
|
|
86
100
|
timestamp: uint64,
|
|
87
101
|
included_reward_coins: Collection[Coin],
|
|
88
|
-
tx_additions: Collection[Coin],
|
|
102
|
+
tx_additions: Collection[tuple[bytes32, Coin, bool]],
|
|
89
103
|
tx_removals: list[bytes32],
|
|
90
|
-
) ->
|
|
104
|
+
) -> None:
|
|
91
105
|
"""
|
|
92
106
|
Only called for blocks which are blocks (and thus have rewards and transactions)
|
|
93
|
-
Returns a list of the CoinRecords that were added by this block
|
|
94
107
|
"""
|
|
95
108
|
|
|
96
109
|
start = time.monotonic()
|
|
97
110
|
|
|
98
|
-
|
|
111
|
+
db_values_to_insert = []
|
|
99
112
|
|
|
100
|
-
for coin in tx_additions:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
113
|
+
for coin_id, coin, same_as_parent in tx_additions:
|
|
114
|
+
db_values_to_insert.append(
|
|
115
|
+
(
|
|
116
|
+
coin_id,
|
|
117
|
+
# confirmed_index
|
|
118
|
+
height,
|
|
119
|
+
# spent_index
|
|
120
|
+
-1 if same_as_parent else 0,
|
|
121
|
+
# coinbase
|
|
122
|
+
0,
|
|
123
|
+
coin.puzzle_hash,
|
|
124
|
+
coin.parent_coin_info,
|
|
125
|
+
coin.amount.stream_to_bytes(),
|
|
126
|
+
timestamp,
|
|
127
|
+
)
|
|
107
128
|
)
|
|
108
|
-
additions.append(record)
|
|
109
129
|
|
|
110
130
|
if height == 0:
|
|
111
131
|
assert len(included_reward_coins) == 0
|
|
@@ -113,16 +133,24 @@ class CoinStore:
|
|
|
113
133
|
assert len(included_reward_coins) >= 2
|
|
114
134
|
|
|
115
135
|
for coin in included_reward_coins:
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
136
|
+
db_values_to_insert.append(
|
|
137
|
+
(
|
|
138
|
+
coin.name(),
|
|
139
|
+
# confirmed_index
|
|
140
|
+
height,
|
|
141
|
+
# spent_index
|
|
142
|
+
0,
|
|
143
|
+
# coinbase
|
|
144
|
+
1,
|
|
145
|
+
coin.puzzle_hash,
|
|
146
|
+
coin.parent_coin_info,
|
|
147
|
+
coin.amount.stream_to_bytes(),
|
|
148
|
+
timestamp,
|
|
149
|
+
)
|
|
122
150
|
)
|
|
123
|
-
additions.append(reward_coin_r)
|
|
124
151
|
|
|
125
|
-
|
|
152
|
+
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
153
|
+
await conn.executemany("INSERT INTO coin_record VALUES(?, ?, ?, ?, ?, ?, ?, ?)", db_values_to_insert)
|
|
126
154
|
await self._set_spent(tx_removals, height)
|
|
127
155
|
|
|
128
156
|
end = time.monotonic()
|
|
@@ -133,8 +161,6 @@ class CoinStore:
|
|
|
133
161
|
+ "blockchain database is on a fast drive",
|
|
134
162
|
)
|
|
135
163
|
|
|
136
|
-
return additions
|
|
137
|
-
|
|
138
164
|
# Checks DB and DiffStores for CoinRecord with coin_name and returns it
|
|
139
165
|
async def get_coin_record(self, coin_name: bytes32) -> Optional[CoinRecord]:
|
|
140
166
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
@@ -146,7 +172,8 @@ class CoinStore:
|
|
|
146
172
|
row = await cursor.fetchone()
|
|
147
173
|
if row is not None:
|
|
148
174
|
coin = self.row_to_coin(row)
|
|
149
|
-
|
|
175
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
176
|
+
return CoinRecord(coin, row[0], spent_index, row[2], row[6])
|
|
150
177
|
return None
|
|
151
178
|
|
|
152
179
|
async def get_coin_records(self, names: Collection[bytes32]) -> list[CoinRecord]:
|
|
@@ -171,16 +198,13 @@ class CoinStore:
|
|
|
171
198
|
for cursor in cursors:
|
|
172
199
|
for row in await cursor.fetchall():
|
|
173
200
|
coin = self.row_to_coin(row)
|
|
174
|
-
|
|
201
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
202
|
+
record = CoinRecord(coin, row[0], spent_index, row[2], row[6])
|
|
175
203
|
coins.append(record)
|
|
176
204
|
|
|
177
205
|
return coins
|
|
178
206
|
|
|
179
207
|
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)
|
|
181
|
-
if coins_added is not None:
|
|
182
|
-
return coins_added
|
|
183
|
-
|
|
184
208
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
185
209
|
async with conn.execute(
|
|
186
210
|
"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
@@ -191,8 +215,8 @@ class CoinStore:
|
|
|
191
215
|
coins = []
|
|
192
216
|
for row in rows:
|
|
193
217
|
coin = self.row_to_coin(row)
|
|
194
|
-
|
|
195
|
-
|
|
218
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
219
|
+
coins.append(CoinRecord(coin, row[0], spent_index, row[2], row[6]))
|
|
196
220
|
return coins
|
|
197
221
|
|
|
198
222
|
async def get_coins_removed_at_height(self, height: uint32) -> list[CoinRecord]:
|
|
@@ -207,29 +231,12 @@ class CoinStore:
|
|
|
207
231
|
) as cursor:
|
|
208
232
|
coins = []
|
|
209
233
|
for row in await cursor.fetchall():
|
|
210
|
-
if row[1]
|
|
234
|
+
if row[1] > 0:
|
|
211
235
|
coin = self.row_to_coin(row)
|
|
212
236
|
coin_record = CoinRecord(coin, row[0], row[1], row[2], row[6])
|
|
213
237
|
coins.append(coin_record)
|
|
214
238
|
return coins
|
|
215
239
|
|
|
216
|
-
async def get_all_coins(self, include_spent_coins: bool) -> list[CoinRecord]:
|
|
217
|
-
# WARNING: this should only be used for testing or in a simulation,
|
|
218
|
-
# running it on a synced testnet or mainnet node will most likely result in an OOM error.
|
|
219
|
-
coins = set()
|
|
220
|
-
|
|
221
|
-
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
222
|
-
async with conn.execute(
|
|
223
|
-
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
224
|
-
f"coin_parent, amount, timestamp FROM coin_record "
|
|
225
|
-
f"{'' if include_spent_coins else 'INDEXED BY coin_spent_index WHERE spent_index=0'}"
|
|
226
|
-
f" ORDER BY confirmed_index"
|
|
227
|
-
) as cursor:
|
|
228
|
-
for row in await cursor.fetchall():
|
|
229
|
-
coin = self.row_to_coin(row)
|
|
230
|
-
coins.add(CoinRecord(coin, row[0], row[1], row[2], row[6]))
|
|
231
|
-
return list(coins)
|
|
232
|
-
|
|
233
240
|
# Checks DB and DiffStores for CoinRecords with puzzle_hash and returns them
|
|
234
241
|
async def get_coin_records_by_puzzle_hash(
|
|
235
242
|
self,
|
|
@@ -245,12 +252,13 @@ class CoinStore:
|
|
|
245
252
|
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
246
253
|
f"coin_parent, amount, timestamp FROM coin_record INDEXED BY coin_puzzle_hash WHERE puzzle_hash=? "
|
|
247
254
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
248
|
-
f"{'' if include_spent_coins else 'AND spent_index
|
|
255
|
+
f"{'' if include_spent_coins else 'AND spent_index <= 0'}",
|
|
249
256
|
(puzzle_hash, start_height, end_height),
|
|
250
257
|
) as cursor:
|
|
251
258
|
for row in await cursor.fetchall():
|
|
252
259
|
coin = self.row_to_coin(row)
|
|
253
|
-
|
|
260
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
261
|
+
coins.add(CoinRecord(coin, row[0], spent_index, row[2], row[6]))
|
|
254
262
|
return list(coins)
|
|
255
263
|
|
|
256
264
|
async def get_coin_records_by_puzzle_hashes(
|
|
@@ -273,12 +281,13 @@ class CoinStore:
|
|
|
273
281
|
f"coin_parent, amount, timestamp FROM coin_record INDEXED BY coin_puzzle_hash "
|
|
274
282
|
f"WHERE puzzle_hash in ({'?,' * (len(puzzle_hashes) - 1)}?) "
|
|
275
283
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
276
|
-
f"{'' if include_spent_coins else 'AND spent_index
|
|
284
|
+
f"{'' if include_spent_coins else 'AND spent_index <= 0'}",
|
|
277
285
|
(*puzzle_hashes_db, start_height, end_height),
|
|
278
286
|
) as cursor:
|
|
279
287
|
for row in await cursor.fetchall():
|
|
280
288
|
coin = self.row_to_coin(row)
|
|
281
|
-
|
|
289
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
290
|
+
coins.add(CoinRecord(coin, row[0], spent_index, row[2], row[6]))
|
|
282
291
|
return list(coins)
|
|
283
292
|
|
|
284
293
|
async def get_coin_records_by_names(
|
|
@@ -299,12 +308,13 @@ class CoinStore:
|
|
|
299
308
|
f"coin_parent, amount, timestamp FROM coin_record INDEXED BY sqlite_autoindex_coin_record_1 "
|
|
300
309
|
f"WHERE coin_name in ({'?,' * (len(names) - 1)}?) "
|
|
301
310
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
302
|
-
f"{'' if include_spent_coins else 'AND spent_index
|
|
311
|
+
f"{'' if include_spent_coins else 'AND spent_index <= 0'}",
|
|
303
312
|
[*names, start_height, end_height],
|
|
304
313
|
) as cursor:
|
|
305
314
|
for row in await cursor.fetchall():
|
|
306
315
|
coin = self.row_to_coin(row)
|
|
307
|
-
|
|
316
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
317
|
+
coins.add(CoinRecord(coin, row[0], spent_index, row[2], row[6]))
|
|
308
318
|
|
|
309
319
|
return list(coins)
|
|
310
320
|
|
|
@@ -314,7 +324,7 @@ class CoinStore:
|
|
|
314
324
|
def row_to_coin_state(self, row: sqlite3.Row) -> CoinState:
|
|
315
325
|
coin = self.row_to_coin(row)
|
|
316
326
|
spent_h = None
|
|
317
|
-
if row[1]
|
|
327
|
+
if row[1] > 0:
|
|
318
328
|
spent_h = row[1]
|
|
319
329
|
return CoinState(coin, spent_h, row[0])
|
|
320
330
|
|
|
@@ -338,7 +348,7 @@ class CoinStore:
|
|
|
338
348
|
f"coin_parent, amount, timestamp FROM coin_record INDEXED BY coin_puzzle_hash "
|
|
339
349
|
f"WHERE puzzle_hash in ({'?,' * (len(batch.entries) - 1)}?) "
|
|
340
350
|
f"AND (confirmed_index>=? OR spent_index>=?)"
|
|
341
|
-
f"{'' if include_spent_coins else 'AND spent_index
|
|
351
|
+
f"{'' if include_spent_coins else ' AND spent_index <= 0'}"
|
|
342
352
|
" LIMIT ?",
|
|
343
353
|
(*puzzle_hashes_db, min_height, min_height, max_items - len(coins)),
|
|
344
354
|
) as cursor:
|
|
@@ -369,12 +379,13 @@ class CoinStore:
|
|
|
369
379
|
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, coin_parent, amount, timestamp "
|
|
370
380
|
f"FROM coin_record WHERE coin_parent in ({'?,' * (len(batch.entries) - 1)}?) "
|
|
371
381
|
f"AND confirmed_index>=? AND confirmed_index<? "
|
|
372
|
-
f"{'' if include_spent_coins else 'AND spent_index
|
|
382
|
+
f"{'' if include_spent_coins else 'AND spent_index <= 0'}",
|
|
373
383
|
(*parent_ids_db, start_height, end_height),
|
|
374
384
|
) as cursor:
|
|
375
385
|
async for row in cursor:
|
|
376
386
|
coin = self.row_to_coin(row)
|
|
377
|
-
|
|
387
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
388
|
+
coins.add(CoinRecord(coin, row[0], spent_index, row[2], row[6]))
|
|
378
389
|
|
|
379
390
|
return list(coins)
|
|
380
391
|
|
|
@@ -403,7 +414,7 @@ class CoinStore:
|
|
|
403
414
|
f"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, coin_parent, amount, timestamp "
|
|
404
415
|
f"FROM coin_record WHERE coin_name in ({'?,' * (len(batch.entries) - 1)}?) "
|
|
405
416
|
f"AND (confirmed_index>=? OR spent_index>=?) {max_height_sql}"
|
|
406
|
-
f"{'' if include_spent_coins else 'AND spent_index
|
|
417
|
+
f"{'' if include_spent_coins else 'AND spent_index <= 0'}"
|
|
407
418
|
" LIMIT ?",
|
|
408
419
|
(*coin_ids_db, min_height, min_height, max_items - len(coins)),
|
|
409
420
|
) as cursor:
|
|
@@ -414,7 +425,7 @@ class CoinStore:
|
|
|
414
425
|
|
|
415
426
|
return coins
|
|
416
427
|
|
|
417
|
-
MAX_PUZZLE_HASH_BATCH_SIZE = SQLITE_MAX_VARIABLE_NUMBER - 10
|
|
428
|
+
MAX_PUZZLE_HASH_BATCH_SIZE: ClassVar[int] = SQLITE_MAX_VARIABLE_NUMBER - 10
|
|
418
429
|
|
|
419
430
|
async def batch_coin_states_by_puzzle_hashes(
|
|
420
431
|
self,
|
|
@@ -448,7 +459,7 @@ class CoinStore:
|
|
|
448
459
|
puzzle_hash_count = len(puzzle_hashes_db)
|
|
449
460
|
|
|
450
461
|
require_spent = "spent_index>0"
|
|
451
|
-
require_unspent = "spent_index
|
|
462
|
+
require_unspent = "spent_index <= 0"
|
|
452
463
|
amount_filter = "AND amount>=? " if min_amount > 0 else ""
|
|
453
464
|
|
|
454
465
|
if include_spent and include_unspent:
|
|
@@ -531,66 +542,70 @@ class CoinStore:
|
|
|
531
542
|
|
|
532
543
|
return coin_states, next_height
|
|
533
544
|
|
|
534
|
-
async def rollback_to_block(self, block_index: int) ->
|
|
545
|
+
async def rollback_to_block(self, block_index: int) -> dict[bytes32, CoinRecord]:
|
|
535
546
|
"""
|
|
536
547
|
Note that block_index can be negative, in which case everything is rolled back
|
|
537
|
-
Returns
|
|
548
|
+
Returns a map of coin ID to coin record for modified items.
|
|
538
549
|
"""
|
|
539
550
|
|
|
540
551
|
coin_changes: dict[bytes32, CoinRecord] = {}
|
|
541
552
|
# Add coins that are confirmed in the reverted blocks to the list of updated coins.
|
|
542
553
|
async with self.db_wrapper.writer_maybe_transaction() as conn:
|
|
543
|
-
|
|
554
|
+
rows = await conn.execute_fetchall(
|
|
544
555
|
"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
545
|
-
"coin_parent, amount, timestamp FROM coin_record WHERE confirmed_index>?",
|
|
556
|
+
"coin_parent, amount, timestamp, coin_name FROM coin_record WHERE confirmed_index>?",
|
|
546
557
|
(block_index,),
|
|
547
|
-
)
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
558
|
+
)
|
|
559
|
+
for row in rows:
|
|
560
|
+
coin = self.row_to_coin(row)
|
|
561
|
+
spent_index = uint32(0) if row[1] <= 0 else uint32(row[1])
|
|
562
|
+
record = CoinRecord(coin, uint32(0), spent_index, row[2], uint64(0))
|
|
563
|
+
coin_name = bytes32(row[7])
|
|
564
|
+
coin_changes[coin_name] = record
|
|
552
565
|
|
|
553
566
|
# Delete reverted blocks from storage
|
|
554
567
|
await conn.execute("DELETE FROM coin_record WHERE confirmed_index>?", (block_index,))
|
|
555
568
|
|
|
556
569
|
# Add coins that are confirmed in the reverted blocks to the list of changed coins.
|
|
557
|
-
|
|
570
|
+
rows = await conn.execute_fetchall(
|
|
558
571
|
"SELECT confirmed_index, spent_index, coinbase, puzzle_hash, "
|
|
559
|
-
"coin_parent, amount, timestamp FROM coin_record WHERE spent_index>?",
|
|
572
|
+
"coin_parent, amount, timestamp, coin_name FROM coin_record WHERE spent_index>?",
|
|
560
573
|
(block_index,),
|
|
561
|
-
) as cursor:
|
|
562
|
-
for row in await cursor.fetchall():
|
|
563
|
-
coin = self.row_to_coin(row)
|
|
564
|
-
record = CoinRecord(coin, row[0], uint32(0), row[2], row[6])
|
|
565
|
-
if record.name not in coin_changes:
|
|
566
|
-
coin_changes[record.name] = record
|
|
567
|
-
|
|
568
|
-
await conn.execute("UPDATE coin_record SET spent_index=0 WHERE spent_index>?", (block_index,))
|
|
569
|
-
self.coins_added_at_height_cache = LRUCache(self.coins_added_at_height_cache.capacity)
|
|
570
|
-
return list(coin_changes.values())
|
|
571
|
-
|
|
572
|
-
# Store CoinRecord in DB
|
|
573
|
-
async def _add_coin_records(self, records: list[CoinRecord]) -> None:
|
|
574
|
-
values2 = []
|
|
575
|
-
for record in records:
|
|
576
|
-
values2.append(
|
|
577
|
-
(
|
|
578
|
-
record.coin.name(),
|
|
579
|
-
record.confirmed_block_index,
|
|
580
|
-
record.spent_block_index,
|
|
581
|
-
int(record.coinbase),
|
|
582
|
-
record.coin.puzzle_hash,
|
|
583
|
-
record.coin.parent_coin_info,
|
|
584
|
-
uint64(record.coin.amount).stream_to_bytes(),
|
|
585
|
-
record.timestamp,
|
|
586
|
-
)
|
|
587
574
|
)
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
575
|
+
for row in rows:
|
|
576
|
+
coin = self.row_to_coin(row)
|
|
577
|
+
record = CoinRecord(coin, row[0], uint32(0), row[2], row[6])
|
|
578
|
+
coin_name = bytes32(row[7])
|
|
579
|
+
if coin_name not in coin_changes:
|
|
580
|
+
coin_changes[coin_name] = record
|
|
581
|
+
|
|
582
|
+
# If the coin to update is not a reward coin and its parent is
|
|
583
|
+
# spent and has the same puzzle hash and amount, we set its
|
|
584
|
+
# spent_index to -1 as a potential fast forward singleton unspent
|
|
585
|
+
# otherwise we set it to 0 as a normal unspent.
|
|
586
|
+
await conn.execute(
|
|
587
|
+
"""
|
|
588
|
+
UPDATE coin_record INDEXED BY coin_spent_index
|
|
589
|
+
SET spent_index = CASE
|
|
590
|
+
WHEN
|
|
591
|
+
coinbase = 0 AND
|
|
592
|
+
EXISTS (
|
|
593
|
+
SELECT 1
|
|
594
|
+
FROM coin_record AS parent INDEXED BY sqlite_autoindex_coin_record_1
|
|
595
|
+
WHERE
|
|
596
|
+
parent.coin_name = coin_record.coin_parent AND
|
|
597
|
+
parent.puzzle_hash = coin_record.puzzle_hash AND
|
|
598
|
+
parent.amount = coin_record.amount AND
|
|
599
|
+
parent.spent_index > 0
|
|
600
|
+
)
|
|
601
|
+
THEN -1
|
|
602
|
+
ELSE 0
|
|
603
|
+
END
|
|
604
|
+
WHERE spent_index > ?
|
|
605
|
+
""",
|
|
606
|
+
(block_index,),
|
|
607
|
+
)
|
|
608
|
+
return coin_changes
|
|
594
609
|
|
|
595
610
|
# Update coin_record to be spent in DB
|
|
596
611
|
async def _set_spent(self, coin_names: list[bytes32], index: uint32) -> None:
|
|
@@ -606,7 +621,7 @@ class CoinStore:
|
|
|
606
621
|
ret: Cursor = await conn.execute(
|
|
607
622
|
f"UPDATE coin_record INDEXED BY sqlite_autoindex_coin_record_1 "
|
|
608
623
|
f"SET spent_index={index} "
|
|
609
|
-
f"WHERE spent_index
|
|
624
|
+
f"WHERE spent_index <= 0 "
|
|
610
625
|
f"AND coin_name IN ({name_params})",
|
|
611
626
|
batch.entries,
|
|
612
627
|
)
|
|
@@ -621,27 +636,31 @@ class CoinStore:
|
|
|
621
636
|
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
622
637
|
async with conn.execute(
|
|
623
638
|
"SELECT unspent.coin_name, "
|
|
624
|
-
"unspent.amount, "
|
|
625
639
|
"unspent.coin_parent, "
|
|
626
|
-
"parent.amount, "
|
|
627
640
|
"parent.coin_parent "
|
|
628
|
-
"FROM coin_record AS unspent
|
|
641
|
+
"FROM coin_record AS unspent "
|
|
629
642
|
"LEFT JOIN coin_record AS parent ON unspent.coin_parent = parent.coin_name "
|
|
630
|
-
"WHERE unspent.spent_index =
|
|
643
|
+
"WHERE unspent.spent_index = -1 "
|
|
631
644
|
"AND parent.spent_index > 0 "
|
|
632
645
|
"AND unspent.puzzle_hash = ? "
|
|
633
|
-
"AND parent.puzzle_hash = unspent.puzzle_hash"
|
|
646
|
+
"AND parent.puzzle_hash = unspent.puzzle_hash "
|
|
647
|
+
"AND parent.amount = unspent.amount",
|
|
634
648
|
(puzzle_hash,),
|
|
635
649
|
) as cursor:
|
|
636
650
|
rows = list(await cursor.fetchall())
|
|
637
651
|
if len(rows) != 1:
|
|
638
652
|
log.debug("Expected 1 unspent with puzzle hash %s, but found %s", puzzle_hash.hex(), len(rows))
|
|
639
653
|
return None
|
|
640
|
-
coin_id,
|
|
654
|
+
coin_id, parent_id, parent_parent_id = rows[0]
|
|
641
655
|
return UnspentLineageInfo(
|
|
642
|
-
coin_id=bytes32(coin_id),
|
|
643
|
-
coin_amount=uint64(int_from_bytes(coin_amount)),
|
|
644
|
-
parent_id=bytes32(parent_id),
|
|
645
|
-
parent_amount=uint64(int_from_bytes(parent_amount)),
|
|
646
|
-
parent_parent_id=bytes32(parent_parent_id),
|
|
656
|
+
coin_id=bytes32(coin_id), parent_id=bytes32(parent_id), parent_parent_id=bytes32(parent_parent_id)
|
|
647
657
|
)
|
|
658
|
+
|
|
659
|
+
async def is_empty(self) -> bool:
|
|
660
|
+
"""
|
|
661
|
+
Returns True if the coin store is empty, False otherwise.
|
|
662
|
+
"""
|
|
663
|
+
async with self.db_wrapper.reader_no_transaction() as conn:
|
|
664
|
+
async with conn.execute("SELECT coin_name FROM coin_record LIMIT 1") as cursor:
|
|
665
|
+
row = await cursor.fetchone()
|
|
666
|
+
return row is None or len(row) == 0
|