chia-blockchain 2.5.1rc1__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/__init__.py +10 -0
- chia/__main__.py +5 -0
- chia/_tests/README.md +53 -0
- chia/_tests/__init__.py +0 -0
- chia/_tests/blockchain/__init__.py +0 -0
- chia/_tests/blockchain/blockchain_test_utils.py +195 -0
- chia/_tests/blockchain/config.py +4 -0
- chia/_tests/blockchain/test_augmented_chain.py +145 -0
- chia/_tests/blockchain/test_blockchain.py +4202 -0
- chia/_tests/blockchain/test_blockchain_transactions.py +1031 -0
- chia/_tests/blockchain/test_build_chains.py +59 -0
- chia/_tests/blockchain/test_get_block_generator.py +72 -0
- chia/_tests/blockchain/test_lookup_fork_chain.py +194 -0
- chia/_tests/build-init-files.py +92 -0
- chia/_tests/build-job-matrix.py +204 -0
- chia/_tests/check_pytest_monitor_output.py +34 -0
- chia/_tests/check_sql_statements.py +72 -0
- chia/_tests/chia-start-sim +42 -0
- chia/_tests/clvm/__init__.py +0 -0
- chia/_tests/clvm/benchmark_costs.py +23 -0
- chia/_tests/clvm/coin_store.py +149 -0
- chia/_tests/clvm/test_chialisp_deserialization.py +101 -0
- chia/_tests/clvm/test_clvm_step.py +37 -0
- chia/_tests/clvm/test_condition_codes.py +13 -0
- chia/_tests/clvm/test_curry_and_treehash.py +55 -0
- chia/_tests/clvm/test_message_conditions.py +184 -0
- chia/_tests/clvm/test_program.py +150 -0
- chia/_tests/clvm/test_puzzle_compression.py +143 -0
- chia/_tests/clvm/test_puzzle_drivers.py +45 -0
- chia/_tests/clvm/test_puzzles.py +242 -0
- chia/_tests/clvm/test_singletons.py +540 -0
- chia/_tests/clvm/test_spend_sim.py +181 -0
- chia/_tests/cmds/__init__.py +0 -0
- chia/_tests/cmds/cmd_test_utils.py +469 -0
- chia/_tests/cmds/config.py +3 -0
- chia/_tests/cmds/conftest.py +23 -0
- chia/_tests/cmds/test_click_types.py +200 -0
- chia/_tests/cmds/test_cmd_framework.py +620 -0
- chia/_tests/cmds/test_cmds_util.py +97 -0
- chia/_tests/cmds/test_daemon.py +92 -0
- chia/_tests/cmds/test_dev_gh.py +131 -0
- chia/_tests/cmds/test_farm_cmd.py +66 -0
- chia/_tests/cmds/test_show.py +116 -0
- chia/_tests/cmds/test_sim.py +207 -0
- chia/_tests/cmds/test_timelock_args.py +75 -0
- chia/_tests/cmds/test_tx_config_args.py +154 -0
- chia/_tests/cmds/testing_classes.py +59 -0
- chia/_tests/cmds/wallet/__init__.py +0 -0
- chia/_tests/cmds/wallet/test_consts.py +47 -0
- chia/_tests/cmds/wallet/test_dao.py +565 -0
- chia/_tests/cmds/wallet/test_did.py +403 -0
- chia/_tests/cmds/wallet/test_nft.py +471 -0
- chia/_tests/cmds/wallet/test_notifications.py +124 -0
- chia/_tests/cmds/wallet/test_offer.toffer +1 -0
- chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
- chia/_tests/cmds/wallet/test_vcs.py +400 -0
- chia/_tests/cmds/wallet/test_wallet.py +1125 -0
- chia/_tests/cmds/wallet/test_wallet_check.py +109 -0
- chia/_tests/conftest.py +1419 -0
- chia/_tests/connection_utils.py +125 -0
- chia/_tests/core/__init__.py +0 -0
- chia/_tests/core/cmds/__init__.py +0 -0
- chia/_tests/core/cmds/test_beta.py +382 -0
- chia/_tests/core/cmds/test_keys.py +1734 -0
- chia/_tests/core/cmds/test_wallet.py +126 -0
- chia/_tests/core/config.py +3 -0
- chia/_tests/core/consensus/__init__.py +0 -0
- chia/_tests/core/consensus/test_block_creation.py +54 -0
- chia/_tests/core/consensus/test_pot_iterations.py +117 -0
- chia/_tests/core/custom_types/__init__.py +0 -0
- chia/_tests/core/custom_types/test_coin.py +107 -0
- chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
- chia/_tests/core/custom_types/test_spend_bundle.py +70 -0
- chia/_tests/core/daemon/__init__.py +0 -0
- chia/_tests/core/daemon/config.py +4 -0
- chia/_tests/core/daemon/test_daemon.py +2128 -0
- chia/_tests/core/daemon/test_daemon_register.py +109 -0
- chia/_tests/core/daemon/test_keychain_proxy.py +101 -0
- chia/_tests/core/data_layer/__init__.py +0 -0
- chia/_tests/core/data_layer/config.py +5 -0
- chia/_tests/core/data_layer/conftest.py +106 -0
- chia/_tests/core/data_layer/test_data_cli.py +56 -0
- chia/_tests/core/data_layer/test_data_layer.py +83 -0
- chia/_tests/core/data_layer/test_data_layer_util.py +218 -0
- chia/_tests/core/data_layer/test_data_rpc.py +3847 -0
- chia/_tests/core/data_layer/test_data_store.py +2424 -0
- chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
- chia/_tests/core/data_layer/test_plugin.py +91 -0
- chia/_tests/core/data_layer/util.py +233 -0
- chia/_tests/core/farmer/__init__.py +0 -0
- chia/_tests/core/farmer/config.py +3 -0
- chia/_tests/core/farmer/test_farmer_api.py +103 -0
- chia/_tests/core/full_node/__init__.py +0 -0
- chia/_tests/core/full_node/config.py +4 -0
- chia/_tests/core/full_node/dos/__init__.py +0 -0
- chia/_tests/core/full_node/dos/config.py +3 -0
- chia/_tests/core/full_node/full_sync/__init__.py +0 -0
- chia/_tests/core/full_node/full_sync/config.py +4 -0
- chia/_tests/core/full_node/full_sync/test_full_sync.py +443 -0
- chia/_tests/core/full_node/ram_db.py +27 -0
- chia/_tests/core/full_node/stores/__init__.py +0 -0
- chia/_tests/core/full_node/stores/config.py +4 -0
- chia/_tests/core/full_node/stores/test_block_store.py +590 -0
- chia/_tests/core/full_node/stores/test_coin_store.py +897 -0
- chia/_tests/core/full_node/stores/test_full_node_store.py +1219 -0
- chia/_tests/core/full_node/stores/test_hint_store.py +229 -0
- chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
- chia/_tests/core/full_node/test_address_manager.py +588 -0
- chia/_tests/core/full_node/test_block_height_map.py +556 -0
- chia/_tests/core/full_node/test_conditions.py +556 -0
- chia/_tests/core/full_node/test_full_node.py +2700 -0
- chia/_tests/core/full_node/test_generator_tools.py +82 -0
- chia/_tests/core/full_node/test_hint_management.py +104 -0
- chia/_tests/core/full_node/test_node_load.py +34 -0
- chia/_tests/core/full_node/test_performance.py +179 -0
- chia/_tests/core/full_node/test_subscriptions.py +492 -0
- chia/_tests/core/full_node/test_transactions.py +203 -0
- chia/_tests/core/full_node/test_tx_processing_queue.py +155 -0
- chia/_tests/core/large_block.py +2388 -0
- chia/_tests/core/make_block_generator.py +70 -0
- chia/_tests/core/mempool/__init__.py +0 -0
- chia/_tests/core/mempool/config.py +4 -0
- chia/_tests/core/mempool/test_mempool.py +3255 -0
- chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
- chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
- chia/_tests/core/mempool/test_mempool_item_queries.py +190 -0
- chia/_tests/core/mempool/test_mempool_manager.py +2084 -0
- chia/_tests/core/mempool/test_mempool_performance.py +64 -0
- chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
- chia/_tests/core/node_height.py +28 -0
- chia/_tests/core/server/__init__.py +0 -0
- chia/_tests/core/server/config.py +3 -0
- chia/_tests/core/server/flood.py +84 -0
- chia/_tests/core/server/serve.py +135 -0
- chia/_tests/core/server/test_api_protocol.py +21 -0
- chia/_tests/core/server/test_capabilities.py +66 -0
- chia/_tests/core/server/test_dos.py +319 -0
- chia/_tests/core/server/test_event_loop.py +109 -0
- chia/_tests/core/server/test_loop.py +294 -0
- chia/_tests/core/server/test_node_discovery.py +73 -0
- chia/_tests/core/server/test_rate_limits.py +482 -0
- chia/_tests/core/server/test_server.py +226 -0
- chia/_tests/core/server/test_upnp.py +8 -0
- chia/_tests/core/services/__init__.py +0 -0
- chia/_tests/core/services/config.py +3 -0
- chia/_tests/core/services/test_services.py +188 -0
- chia/_tests/core/ssl/__init__.py +0 -0
- chia/_tests/core/ssl/config.py +3 -0
- chia/_tests/core/ssl/test_ssl.py +202 -0
- chia/_tests/core/test_coins.py +33 -0
- chia/_tests/core/test_cost_calculation.py +313 -0
- chia/_tests/core/test_crawler.py +175 -0
- chia/_tests/core/test_crawler_rpc.py +53 -0
- chia/_tests/core/test_daemon_rpc.py +24 -0
- chia/_tests/core/test_db_conversion.py +130 -0
- chia/_tests/core/test_db_validation.py +162 -0
- chia/_tests/core/test_farmer_harvester_rpc.py +505 -0
- chia/_tests/core/test_filter.py +35 -0
- chia/_tests/core/test_full_node_rpc.py +768 -0
- chia/_tests/core/test_merkle_set.py +343 -0
- chia/_tests/core/test_program.py +47 -0
- chia/_tests/core/test_rpc_util.py +86 -0
- chia/_tests/core/test_seeder.py +420 -0
- chia/_tests/core/test_setproctitle.py +13 -0
- chia/_tests/core/util/__init__.py +0 -0
- chia/_tests/core/util/config.py +4 -0
- chia/_tests/core/util/test_block_cache.py +44 -0
- chia/_tests/core/util/test_cached_bls.py +57 -0
- chia/_tests/core/util/test_config.py +337 -0
- chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
- chia/_tests/core/util/test_files.py +391 -0
- chia/_tests/core/util/test_jsonify.py +146 -0
- chia/_tests/core/util/test_keychain.py +522 -0
- chia/_tests/core/util/test_keyring_wrapper.py +491 -0
- chia/_tests/core/util/test_lockfile.py +380 -0
- chia/_tests/core/util/test_log_exceptions.py +187 -0
- chia/_tests/core/util/test_lru_cache.py +56 -0
- chia/_tests/core/util/test_significant_bits.py +40 -0
- chia/_tests/core/util/test_streamable.py +883 -0
- chia/_tests/db/__init__.py +0 -0
- chia/_tests/db/test_db_wrapper.py +566 -0
- chia/_tests/environments/__init__.py +0 -0
- chia/_tests/environments/common.py +35 -0
- chia/_tests/environments/full_node.py +47 -0
- chia/_tests/environments/wallet.py +429 -0
- chia/_tests/ether.py +19 -0
- chia/_tests/farmer_harvester/__init__.py +0 -0
- chia/_tests/farmer_harvester/config.py +3 -0
- chia/_tests/farmer_harvester/test_farmer.py +1264 -0
- chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
- chia/_tests/farmer_harvester/test_filter_prefix_bits.py +131 -0
- chia/_tests/farmer_harvester/test_third_party_harvesters.py +528 -0
- chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
- chia/_tests/fee_estimation/__init__.py +0 -0
- chia/_tests/fee_estimation/config.py +3 -0
- chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
- chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
- chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +144 -0
- chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
- chia/_tests/generator/__init__.py +0 -0
- chia/_tests/generator/puzzles/__init__.py +0 -0
- chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
- chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
- chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
- chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
- chia/_tests/generator/test_compression.py +201 -0
- chia/_tests/generator/test_generator_types.py +44 -0
- chia/_tests/generator/test_rom.py +180 -0
- chia/_tests/plot_sync/__init__.py +0 -0
- chia/_tests/plot_sync/config.py +3 -0
- chia/_tests/plot_sync/test_delta.py +101 -0
- chia/_tests/plot_sync/test_plot_sync.py +618 -0
- chia/_tests/plot_sync/test_receiver.py +451 -0
- chia/_tests/plot_sync/test_sender.py +116 -0
- chia/_tests/plot_sync/test_sync_simulated.py +451 -0
- chia/_tests/plot_sync/util.py +68 -0
- chia/_tests/plotting/__init__.py +0 -0
- chia/_tests/plotting/config.py +3 -0
- chia/_tests/plotting/test_plot_manager.py +781 -0
- chia/_tests/plotting/util.py +12 -0
- chia/_tests/pools/__init__.py +0 -0
- chia/_tests/pools/config.py +5 -0
- chia/_tests/pools/test_pool_cli_parsing.py +128 -0
- chia/_tests/pools/test_pool_cmdline.py +1001 -0
- chia/_tests/pools/test_pool_config.py +42 -0
- chia/_tests/pools/test_pool_puzzles_lifecycle.py +397 -0
- chia/_tests/pools/test_pool_rpc.py +1123 -0
- chia/_tests/pools/test_pool_wallet.py +205 -0
- chia/_tests/pools/test_wallet_pool_store.py +161 -0
- chia/_tests/process_junit.py +348 -0
- chia/_tests/rpc/__init__.py +0 -0
- chia/_tests/rpc/test_rpc_client.py +138 -0
- chia/_tests/rpc/test_rpc_server.py +183 -0
- chia/_tests/simulation/__init__.py +0 -0
- chia/_tests/simulation/config.py +6 -0
- chia/_tests/simulation/test_simulation.py +501 -0
- chia/_tests/simulation/test_simulator.py +232 -0
- chia/_tests/simulation/test_start_simulator.py +107 -0
- chia/_tests/testconfig.py +13 -0
- chia/_tests/timelord/__init__.py +0 -0
- chia/_tests/timelord/config.py +3 -0
- chia/_tests/timelord/test_new_peak.py +437 -0
- chia/_tests/timelord/test_timelord.py +11 -0
- chia/_tests/tools/1315537.json +170 -0
- chia/_tests/tools/1315544.json +160 -0
- chia/_tests/tools/1315630.json +150 -0
- chia/_tests/tools/300000.json +105 -0
- chia/_tests/tools/442734.json +140 -0
- chia/_tests/tools/466212.json +130 -0
- chia/_tests/tools/__init__.py +0 -0
- chia/_tests/tools/config.py +5 -0
- chia/_tests/tools/test-blockchain-db.sqlite +0 -0
- chia/_tests/tools/test_full_sync.py +30 -0
- chia/_tests/tools/test_legacy_keyring.py +82 -0
- chia/_tests/tools/test_run_block.py +128 -0
- chia/_tests/tools/test_virtual_project.py +591 -0
- chia/_tests/util/__init__.py +0 -0
- chia/_tests/util/benchmark_cost.py +170 -0
- chia/_tests/util/benchmarks.py +153 -0
- chia/_tests/util/bip39_test_vectors.json +148 -0
- chia/_tests/util/blockchain.py +134 -0
- chia/_tests/util/blockchain_mock.py +132 -0
- chia/_tests/util/build_network_protocol_files.py +302 -0
- chia/_tests/util/clvm_generator.bin +0 -0
- chia/_tests/util/config.py +3 -0
- chia/_tests/util/constants.py +20 -0
- chia/_tests/util/db_connection.py +37 -0
- chia/_tests/util/full_sync.py +253 -0
- chia/_tests/util/gen_ssl_certs.py +114 -0
- chia/_tests/util/generator_tools_testing.py +45 -0
- chia/_tests/util/get_name_puzzle_conditions.py +52 -0
- chia/_tests/util/key_tool.py +36 -0
- chia/_tests/util/misc.py +675 -0
- chia/_tests/util/network_protocol_data.py +1072 -0
- chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
- chia/_tests/util/protocol_messages_json.py +2701 -0
- chia/_tests/util/rpc.py +26 -0
- chia/_tests/util/run_block.py +163 -0
- chia/_tests/util/setup_nodes.py +481 -0
- chia/_tests/util/spend_sim.py +492 -0
- chia/_tests/util/split_managers.py +102 -0
- chia/_tests/util/temp_file.py +14 -0
- chia/_tests/util/test_action_scope.py +144 -0
- chia/_tests/util/test_async_pool.py +366 -0
- chia/_tests/util/test_build_job_matrix.py +42 -0
- chia/_tests/util/test_build_network_protocol_files.py +7 -0
- chia/_tests/util/test_chia_version.py +50 -0
- chia/_tests/util/test_collection.py +11 -0
- chia/_tests/util/test_condition_tools.py +229 -0
- chia/_tests/util/test_config.py +426 -0
- chia/_tests/util/test_dump_keyring.py +60 -0
- chia/_tests/util/test_errors.py +10 -0
- chia/_tests/util/test_full_block_utils.py +279 -0
- chia/_tests/util/test_installed.py +20 -0
- chia/_tests/util/test_limited_semaphore.py +53 -0
- chia/_tests/util/test_logging_filter.py +42 -0
- chia/_tests/util/test_misc.py +445 -0
- chia/_tests/util/test_network.py +73 -0
- chia/_tests/util/test_network_protocol_files.py +578 -0
- chia/_tests/util/test_network_protocol_json.py +267 -0
- chia/_tests/util/test_network_protocol_test.py +256 -0
- chia/_tests/util/test_paginator.py +71 -0
- chia/_tests/util/test_pprint.py +17 -0
- chia/_tests/util/test_priority_mutex.py +488 -0
- chia/_tests/util/test_recursive_replace.py +116 -0
- chia/_tests/util/test_replace_str_to_bytes.py +137 -0
- chia/_tests/util/test_service_groups.py +15 -0
- chia/_tests/util/test_ssl_check.py +31 -0
- chia/_tests/util/test_testnet_overrides.py +19 -0
- chia/_tests/util/test_tests_misc.py +38 -0
- chia/_tests/util/test_timing.py +37 -0
- chia/_tests/util/test_trusted_peer.py +51 -0
- chia/_tests/util/time_out_assert.py +191 -0
- chia/_tests/wallet/__init__.py +0 -0
- chia/_tests/wallet/cat_wallet/__init__.py +0 -0
- chia/_tests/wallet/cat_wallet/config.py +4 -0
- chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
- chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
- chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1826 -0
- chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
- chia/_tests/wallet/cat_wallet/test_trades.py +2600 -0
- chia/_tests/wallet/clawback/__init__.py +0 -0
- chia/_tests/wallet/clawback/config.py +3 -0
- chia/_tests/wallet/clawback/test_clawback_decorator.py +78 -0
- chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
- chia/_tests/wallet/clawback/test_clawback_metadata.py +50 -0
- chia/_tests/wallet/config.py +4 -0
- chia/_tests/wallet/conftest.py +278 -0
- chia/_tests/wallet/dao_wallet/__init__.py +0 -0
- chia/_tests/wallet/dao_wallet/config.py +3 -0
- chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1330 -0
- chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
- chia/_tests/wallet/db_wallet/__init__.py +0 -0
- chia/_tests/wallet/db_wallet/config.py +3 -0
- chia/_tests/wallet/db_wallet/test_db_graftroot.py +141 -0
- chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
- chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
- chia/_tests/wallet/did_wallet/__init__.py +0 -0
- chia/_tests/wallet/did_wallet/config.py +4 -0
- chia/_tests/wallet/did_wallet/test_did.py +2284 -0
- chia/_tests/wallet/nft_wallet/__init__.py +0 -0
- chia/_tests/wallet/nft_wallet/config.py +4 -0
- chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1493 -0
- chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1024 -0
- chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +375 -0
- chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
- chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
- chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2584 -0
- chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
- chia/_tests/wallet/rpc/__init__.py +0 -0
- chia/_tests/wallet/rpc/config.py +4 -0
- chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +285 -0
- chia/_tests/wallet/rpc/test_wallet_rpc.py +3153 -0
- chia/_tests/wallet/simple_sync/__init__.py +0 -0
- chia/_tests/wallet/simple_sync/config.py +3 -0
- chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +718 -0
- chia/_tests/wallet/sync/__init__.py +0 -0
- chia/_tests/wallet/sync/config.py +4 -0
- chia/_tests/wallet/sync/test_wallet_sync.py +1692 -0
- chia/_tests/wallet/test_address_type.py +189 -0
- chia/_tests/wallet/test_bech32m.py +45 -0
- chia/_tests/wallet/test_clvm_streamable.py +244 -0
- chia/_tests/wallet/test_coin_management.py +354 -0
- chia/_tests/wallet/test_coin_selection.py +588 -0
- chia/_tests/wallet/test_conditions.py +400 -0
- chia/_tests/wallet/test_debug_spend_bundle.py +218 -0
- chia/_tests/wallet/test_new_wallet_protocol.py +1174 -0
- chia/_tests/wallet/test_nft_store.py +192 -0
- chia/_tests/wallet/test_notifications.py +196 -0
- chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
- chia/_tests/wallet/test_puzzle_store.py +132 -0
- chia/_tests/wallet/test_sign_coin_spends.py +159 -0
- chia/_tests/wallet/test_signer_protocol.py +947 -0
- chia/_tests/wallet/test_singleton.py +122 -0
- chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
- chia/_tests/wallet/test_singleton_store.py +152 -0
- chia/_tests/wallet/test_taproot.py +19 -0
- chia/_tests/wallet/test_transaction_store.py +945 -0
- chia/_tests/wallet/test_util.py +185 -0
- chia/_tests/wallet/test_wallet.py +2139 -0
- chia/_tests/wallet/test_wallet_action_scope.py +85 -0
- chia/_tests/wallet/test_wallet_blockchain.py +111 -0
- chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
- chia/_tests/wallet/test_wallet_interested_store.py +43 -0
- chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
- chia/_tests/wallet/test_wallet_node.py +780 -0
- chia/_tests/wallet/test_wallet_retry.py +95 -0
- chia/_tests/wallet/test_wallet_state_manager.py +259 -0
- chia/_tests/wallet/test_wallet_test_framework.py +275 -0
- chia/_tests/wallet/test_wallet_trade_store.py +218 -0
- chia/_tests/wallet/test_wallet_user_store.py +34 -0
- chia/_tests/wallet/test_wallet_utils.py +156 -0
- chia/_tests/wallet/vc_wallet/__init__.py +0 -0
- chia/_tests/wallet/vc_wallet/config.py +3 -0
- chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
- chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
- chia/_tests/wallet/vc_wallet/test_vc_wallet.py +830 -0
- chia/_tests/wallet/wallet_block_tools.py +327 -0
- chia/_tests/weight_proof/__init__.py +0 -0
- chia/_tests/weight_proof/config.py +3 -0
- chia/_tests/weight_proof/test_weight_proof.py +528 -0
- chia/apis.py +19 -0
- chia/clvm/__init__.py +0 -0
- chia/cmds/__init__.py +0 -0
- chia/cmds/beta.py +184 -0
- chia/cmds/beta_funcs.py +137 -0
- chia/cmds/check_wallet_db.py +420 -0
- chia/cmds/chia.py +151 -0
- chia/cmds/cmd_classes.py +323 -0
- chia/cmds/cmd_helpers.py +242 -0
- chia/cmds/cmds_util.py +488 -0
- chia/cmds/coin_funcs.py +275 -0
- chia/cmds/coins.py +182 -0
- chia/cmds/completion.py +49 -0
- chia/cmds/configure.py +332 -0
- chia/cmds/dao.py +1064 -0
- chia/cmds/dao_funcs.py +598 -0
- chia/cmds/data.py +708 -0
- chia/cmds/data_funcs.py +385 -0
- chia/cmds/db.py +87 -0
- chia/cmds/db_backup_func.py +77 -0
- chia/cmds/db_upgrade_func.py +452 -0
- chia/cmds/db_validate_func.py +184 -0
- chia/cmds/dev.py +18 -0
- chia/cmds/farm.py +100 -0
- chia/cmds/farm_funcs.py +200 -0
- chia/cmds/gh.py +275 -0
- chia/cmds/init.py +63 -0
- chia/cmds/init_funcs.py +367 -0
- chia/cmds/installers.py +131 -0
- chia/cmds/keys.py +527 -0
- chia/cmds/keys_funcs.py +863 -0
- chia/cmds/netspace.py +50 -0
- chia/cmds/netspace_funcs.py +54 -0
- chia/cmds/options.py +32 -0
- chia/cmds/param_types.py +238 -0
- chia/cmds/passphrase.py +131 -0
- chia/cmds/passphrase_funcs.py +292 -0
- chia/cmds/peer.py +51 -0
- chia/cmds/peer_funcs.py +129 -0
- chia/cmds/plotnft.py +260 -0
- chia/cmds/plotnft_funcs.py +405 -0
- chia/cmds/plots.py +230 -0
- chia/cmds/plotters.py +18 -0
- chia/cmds/rpc.py +208 -0
- chia/cmds/show.py +72 -0
- chia/cmds/show_funcs.py +215 -0
- chia/cmds/signer.py +296 -0
- chia/cmds/sim.py +225 -0
- chia/cmds/sim_funcs.py +509 -0
- chia/cmds/start.py +24 -0
- chia/cmds/start_funcs.py +109 -0
- chia/cmds/stop.py +62 -0
- chia/cmds/units.py +9 -0
- chia/cmds/wallet.py +1901 -0
- chia/cmds/wallet_funcs.py +1874 -0
- chia/consensus/__init__.py +0 -0
- chia/consensus/block_body_validation.py +562 -0
- chia/consensus/block_creation.py +546 -0
- chia/consensus/block_header_validation.py +1059 -0
- chia/consensus/block_record.py +31 -0
- chia/consensus/block_rewards.py +53 -0
- chia/consensus/blockchain.py +1087 -0
- chia/consensus/blockchain_interface.py +56 -0
- chia/consensus/coinbase.py +30 -0
- chia/consensus/condition_costs.py +9 -0
- chia/consensus/constants.py +49 -0
- chia/consensus/cost_calculator.py +15 -0
- chia/consensus/default_constants.py +89 -0
- chia/consensus/deficit.py +55 -0
- chia/consensus/difficulty_adjustment.py +412 -0
- chia/consensus/find_fork_point.py +111 -0
- chia/consensus/full_block_to_block_record.py +167 -0
- chia/consensus/get_block_challenge.py +106 -0
- chia/consensus/get_block_generator.py +27 -0
- chia/consensus/make_sub_epoch_summary.py +210 -0
- chia/consensus/multiprocess_validation.py +268 -0
- chia/consensus/pos_quality.py +19 -0
- chia/consensus/pot_iterations.py +67 -0
- chia/consensus/puzzles/__init__.py +0 -0
- chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
- chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
- chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
- chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
- chia/consensus/vdf_info_computation.py +156 -0
- chia/daemon/__init__.py +0 -0
- chia/daemon/client.py +252 -0
- chia/daemon/keychain_proxy.py +502 -0
- chia/daemon/keychain_server.py +365 -0
- chia/daemon/server.py +1606 -0
- chia/daemon/windows_signal.py +56 -0
- chia/data_layer/__init__.py +0 -0
- chia/data_layer/data_layer.py +1291 -0
- chia/data_layer/data_layer_api.py +33 -0
- chia/data_layer/data_layer_errors.py +50 -0
- chia/data_layer/data_layer_server.py +170 -0
- chia/data_layer/data_layer_util.py +985 -0
- chia/data_layer/data_layer_wallet.py +1311 -0
- chia/data_layer/data_store.py +2267 -0
- chia/data_layer/dl_wallet_store.py +407 -0
- chia/data_layer/download_data.py +389 -0
- chia/data_layer/puzzles/__init__.py +0 -0
- chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
- chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
- chia/data_layer/s3_plugin_config.yml +33 -0
- chia/data_layer/s3_plugin_service.py +468 -0
- chia/data_layer/util/__init__.py +0 -0
- chia/data_layer/util/benchmark.py +107 -0
- chia/data_layer/util/plugin.py +40 -0
- chia/farmer/__init__.py +0 -0
- chia/farmer/farmer.py +923 -0
- chia/farmer/farmer_api.py +820 -0
- chia/full_node/__init__.py +0 -0
- chia/full_node/bitcoin_fee_estimator.py +85 -0
- chia/full_node/block_height_map.py +271 -0
- chia/full_node/block_store.py +576 -0
- chia/full_node/bundle_tools.py +19 -0
- chia/full_node/coin_store.py +647 -0
- chia/full_node/fee_estimate.py +54 -0
- chia/full_node/fee_estimate_store.py +24 -0
- chia/full_node/fee_estimation.py +92 -0
- chia/full_node/fee_estimator.py +90 -0
- chia/full_node/fee_estimator_constants.py +38 -0
- chia/full_node/fee_estimator_interface.py +42 -0
- chia/full_node/fee_history.py +25 -0
- chia/full_node/fee_tracker.py +564 -0
- chia/full_node/full_node.py +3327 -0
- chia/full_node/full_node_api.py +2025 -0
- chia/full_node/full_node_store.py +1033 -0
- chia/full_node/hint_management.py +56 -0
- chia/full_node/hint_store.py +93 -0
- chia/full_node/mempool.py +589 -0
- chia/full_node/mempool_check_conditions.py +146 -0
- chia/full_node/mempool_manager.py +853 -0
- chia/full_node/pending_tx_cache.py +112 -0
- chia/full_node/puzzles/__init__.py +0 -0
- chia/full_node/puzzles/block_program_zero.clsp +14 -0
- chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
- chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
- chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
- chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
- chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
- chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
- chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
- chia/full_node/signage_point.py +16 -0
- chia/full_node/subscriptions.py +247 -0
- chia/full_node/sync_store.py +146 -0
- chia/full_node/tx_processing_queue.py +78 -0
- chia/full_node/util/__init__.py +0 -0
- chia/full_node/weight_proof.py +1720 -0
- chia/harvester/__init__.py +0 -0
- chia/harvester/harvester.py +272 -0
- chia/harvester/harvester_api.py +380 -0
- chia/introducer/__init__.py +0 -0
- chia/introducer/introducer.py +122 -0
- chia/introducer/introducer_api.py +70 -0
- chia/legacy/__init__.py +0 -0
- chia/legacy/keyring.py +155 -0
- chia/plot_sync/__init__.py +0 -0
- chia/plot_sync/delta.py +61 -0
- chia/plot_sync/exceptions.py +56 -0
- chia/plot_sync/receiver.py +386 -0
- chia/plot_sync/sender.py +340 -0
- chia/plot_sync/util.py +43 -0
- chia/plotters/__init__.py +0 -0
- chia/plotters/bladebit.py +388 -0
- chia/plotters/chiapos.py +63 -0
- chia/plotters/madmax.py +224 -0
- chia/plotters/plotters.py +577 -0
- chia/plotters/plotters_util.py +133 -0
- chia/plotting/__init__.py +0 -0
- chia/plotting/cache.py +213 -0
- chia/plotting/check_plots.py +283 -0
- chia/plotting/create_plots.py +278 -0
- chia/plotting/manager.py +436 -0
- chia/plotting/util.py +336 -0
- chia/pools/__init__.py +0 -0
- chia/pools/pool_config.py +110 -0
- chia/pools/pool_puzzles.py +459 -0
- chia/pools/pool_wallet.py +933 -0
- chia/pools/pool_wallet_info.py +118 -0
- chia/pools/puzzles/__init__.py +0 -0
- chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
- chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
- chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
- chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
- chia/protocols/__init__.py +0 -0
- chia/protocols/farmer_protocol.py +102 -0
- chia/protocols/full_node_protocol.py +219 -0
- chia/protocols/harvester_protocol.py +216 -0
- chia/protocols/introducer_protocol.py +25 -0
- chia/protocols/pool_protocol.py +177 -0
- chia/protocols/protocol_message_types.py +139 -0
- chia/protocols/protocol_state_machine.py +87 -0
- chia/protocols/protocol_timing.py +8 -0
- chia/protocols/shared_protocol.py +86 -0
- chia/protocols/timelord_protocol.py +93 -0
- chia/protocols/wallet_protocol.py +401 -0
- chia/py.typed +0 -0
- chia/rpc/__init__.py +0 -0
- chia/rpc/crawler_rpc_api.py +80 -0
- chia/rpc/data_layer_rpc_api.py +644 -0
- chia/rpc/data_layer_rpc_client.py +188 -0
- chia/rpc/data_layer_rpc_util.py +58 -0
- chia/rpc/farmer_rpc_api.py +365 -0
- chia/rpc/farmer_rpc_client.py +86 -0
- chia/rpc/full_node_rpc_api.py +959 -0
- chia/rpc/full_node_rpc_client.py +292 -0
- chia/rpc/harvester_rpc_api.py +141 -0
- chia/rpc/harvester_rpc_client.py +54 -0
- chia/rpc/rpc_client.py +164 -0
- chia/rpc/rpc_server.py +521 -0
- chia/rpc/timelord_rpc_api.py +32 -0
- chia/rpc/util.py +93 -0
- chia/rpc/wallet_request_types.py +904 -0
- chia/rpc/wallet_rpc_api.py +4943 -0
- chia/rpc/wallet_rpc_client.py +1814 -0
- chia/seeder/__init__.py +0 -0
- chia/seeder/crawl_store.py +425 -0
- chia/seeder/crawler.py +410 -0
- chia/seeder/crawler_api.py +135 -0
- chia/seeder/dns_server.py +593 -0
- chia/seeder/peer_record.py +146 -0
- chia/seeder/start_crawler.py +92 -0
- chia/server/__init__.py +0 -0
- chia/server/address_manager.py +658 -0
- chia/server/address_manager_store.py +237 -0
- chia/server/api_protocol.py +116 -0
- chia/server/capabilities.py +24 -0
- chia/server/chia_policy.py +346 -0
- chia/server/introducer_peers.py +76 -0
- chia/server/node_discovery.py +714 -0
- chia/server/outbound_message.py +33 -0
- chia/server/rate_limit_numbers.py +214 -0
- chia/server/rate_limits.py +153 -0
- chia/server/server.py +741 -0
- chia/server/signal_handlers.py +120 -0
- chia/server/ssl_context.py +32 -0
- chia/server/start_data_layer.py +151 -0
- chia/server/start_farmer.py +98 -0
- chia/server/start_full_node.py +112 -0
- chia/server/start_harvester.py +93 -0
- chia/server/start_introducer.py +81 -0
- chia/server/start_service.py +316 -0
- chia/server/start_timelord.py +89 -0
- chia/server/start_wallet.py +113 -0
- chia/server/upnp.py +118 -0
- chia/server/ws_connection.py +766 -0
- chia/simulator/__init__.py +0 -0
- chia/simulator/add_blocks_in_batches.py +54 -0
- chia/simulator/block_tools.py +2054 -0
- chia/simulator/full_node_simulator.py +794 -0
- chia/simulator/keyring.py +128 -0
- chia/simulator/setup_services.py +506 -0
- chia/simulator/simulator_constants.py +13 -0
- chia/simulator/simulator_full_node_rpc_api.py +99 -0
- chia/simulator/simulator_full_node_rpc_client.py +60 -0
- chia/simulator/simulator_protocol.py +29 -0
- chia/simulator/simulator_test_tools.py +164 -0
- chia/simulator/socket.py +24 -0
- chia/simulator/ssl_certs.py +114 -0
- chia/simulator/ssl_certs_1.py +697 -0
- chia/simulator/ssl_certs_10.py +697 -0
- chia/simulator/ssl_certs_2.py +697 -0
- chia/simulator/ssl_certs_3.py +697 -0
- chia/simulator/ssl_certs_4.py +697 -0
- chia/simulator/ssl_certs_5.py +697 -0
- chia/simulator/ssl_certs_6.py +697 -0
- chia/simulator/ssl_certs_7.py +697 -0
- chia/simulator/ssl_certs_8.py +697 -0
- chia/simulator/ssl_certs_9.py +697 -0
- chia/simulator/start_simulator.py +143 -0
- chia/simulator/wallet_tools.py +246 -0
- chia/ssl/__init__.py +0 -0
- chia/ssl/chia_ca.crt +19 -0
- chia/ssl/chia_ca.key +28 -0
- chia/ssl/create_ssl.py +249 -0
- chia/ssl/dst_root_ca.pem +20 -0
- chia/timelord/__init__.py +0 -0
- chia/timelord/iters_from_block.py +50 -0
- chia/timelord/timelord.py +1226 -0
- chia/timelord/timelord_api.py +138 -0
- chia/timelord/timelord_launcher.py +190 -0
- chia/timelord/timelord_state.py +244 -0
- chia/timelord/types.py +22 -0
- chia/types/__init__.py +0 -0
- chia/types/aliases.py +35 -0
- chia/types/block_protocol.py +20 -0
- chia/types/blockchain_format/__init__.py +0 -0
- chia/types/blockchain_format/classgroup.py +5 -0
- chia/types/blockchain_format/coin.py +28 -0
- chia/types/blockchain_format/foliage.py +8 -0
- chia/types/blockchain_format/pool_target.py +5 -0
- chia/types/blockchain_format/program.py +269 -0
- chia/types/blockchain_format/proof_of_space.py +135 -0
- chia/types/blockchain_format/reward_chain_block.py +6 -0
- chia/types/blockchain_format/serialized_program.py +5 -0
- chia/types/blockchain_format/sized_bytes.py +11 -0
- chia/types/blockchain_format/slots.py +9 -0
- chia/types/blockchain_format/sub_epoch_summary.py +5 -0
- chia/types/blockchain_format/tree_hash.py +72 -0
- chia/types/blockchain_format/vdf.py +86 -0
- chia/types/clvm_cost.py +13 -0
- chia/types/coin_record.py +43 -0
- chia/types/coin_spend.py +115 -0
- chia/types/condition_opcodes.py +73 -0
- chia/types/condition_with_args.py +16 -0
- chia/types/eligible_coin_spends.py +365 -0
- chia/types/end_of_slot_bundle.py +5 -0
- chia/types/fee_rate.py +38 -0
- chia/types/full_block.py +5 -0
- chia/types/generator_types.py +13 -0
- chia/types/header_block.py +5 -0
- chia/types/internal_mempool_item.py +18 -0
- chia/types/mempool_inclusion_status.py +9 -0
- chia/types/mempool_item.py +85 -0
- chia/types/mempool_submission_status.py +30 -0
- chia/types/mojos.py +7 -0
- chia/types/peer_info.py +64 -0
- chia/types/signing_mode.py +29 -0
- chia/types/spend_bundle.py +30 -0
- chia/types/spend_bundle_conditions.py +7 -0
- chia/types/transaction_queue_entry.py +55 -0
- chia/types/unfinished_block.py +5 -0
- chia/types/unfinished_header_block.py +37 -0
- chia/types/validation_state.py +14 -0
- chia/types/weight_proof.py +49 -0
- chia/util/__init__.py +0 -0
- chia/util/action_scope.py +168 -0
- chia/util/async_pool.py +226 -0
- chia/util/augmented_chain.py +134 -0
- chia/util/batches.py +42 -0
- chia/util/bech32m.py +126 -0
- chia/util/beta_metrics.py +119 -0
- chia/util/block_cache.py +56 -0
- chia/util/byte_types.py +12 -0
- chia/util/check_fork_next_block.py +33 -0
- chia/util/chia_logging.py +144 -0
- chia/util/chia_version.py +33 -0
- chia/util/collection.py +17 -0
- chia/util/condition_tools.py +201 -0
- chia/util/config.py +367 -0
- chia/util/cpu.py +22 -0
- chia/util/db_synchronous.py +23 -0
- chia/util/db_version.py +32 -0
- chia/util/db_wrapper.py +430 -0
- chia/util/default_root.py +27 -0
- chia/util/dump_keyring.py +93 -0
- chia/util/english.txt +2048 -0
- chia/util/errors.py +353 -0
- chia/util/file_keyring.py +469 -0
- chia/util/files.py +97 -0
- chia/util/full_block_utils.py +345 -0
- chia/util/generator_tools.py +72 -0
- chia/util/hash.py +31 -0
- chia/util/initial-config.yaml +694 -0
- chia/util/inline_executor.py +26 -0
- chia/util/ints.py +19 -0
- chia/util/ip_address.py +39 -0
- chia/util/json_util.py +37 -0
- chia/util/keychain.py +676 -0
- chia/util/keyring_wrapper.py +327 -0
- chia/util/limited_semaphore.py +41 -0
- chia/util/lock.py +49 -0
- chia/util/log_exceptions.py +32 -0
- chia/util/logging.py +36 -0
- chia/util/lru_cache.py +31 -0
- chia/util/math.py +20 -0
- chia/util/network.py +182 -0
- chia/util/paginator.py +48 -0
- chia/util/path.py +31 -0
- chia/util/permissions.py +20 -0
- chia/util/prev_transaction_block.py +21 -0
- chia/util/priority_mutex.py +95 -0
- chia/util/profiler.py +197 -0
- chia/util/recursive_replace.py +24 -0
- chia/util/safe_cancel_task.py +16 -0
- chia/util/service_groups.py +47 -0
- chia/util/setproctitle.py +22 -0
- chia/util/significant_bits.py +32 -0
- chia/util/ssl_check.py +213 -0
- chia/util/streamable.py +642 -0
- chia/util/task_referencer.py +59 -0
- chia/util/task_timing.py +382 -0
- chia/util/timing.py +67 -0
- chia/util/vdf_prover.py +30 -0
- chia/util/virtual_project_analysis.py +540 -0
- chia/util/ws_message.py +66 -0
- chia/wallet/__init__.py +0 -0
- chia/wallet/cat_wallet/__init__.py +0 -0
- chia/wallet/cat_wallet/cat_constants.py +75 -0
- chia/wallet/cat_wallet/cat_info.py +47 -0
- chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
- chia/wallet/cat_wallet/cat_utils.py +164 -0
- chia/wallet/cat_wallet/cat_wallet.py +855 -0
- chia/wallet/cat_wallet/dao_cat_info.py +28 -0
- chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
- chia/wallet/cat_wallet/lineage_store.py +74 -0
- chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
- chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
- chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
- chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
- chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
- chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
- chia/wallet/coin_selection.py +188 -0
- chia/wallet/conditions.py +1512 -0
- chia/wallet/dao_wallet/__init__.py +0 -0
- chia/wallet/dao_wallet/dao_info.py +61 -0
- chia/wallet/dao_wallet/dao_utils.py +811 -0
- chia/wallet/dao_wallet/dao_wallet.py +2119 -0
- chia/wallet/db_wallet/__init__.py +0 -0
- chia/wallet/db_wallet/db_wallet_puzzles.py +111 -0
- chia/wallet/derivation_record.py +30 -0
- chia/wallet/derive_keys.py +146 -0
- chia/wallet/did_wallet/__init__.py +0 -0
- chia/wallet/did_wallet/did_info.py +39 -0
- chia/wallet/did_wallet/did_wallet.py +1494 -0
- chia/wallet/did_wallet/did_wallet_puzzles.py +221 -0
- chia/wallet/did_wallet/puzzles/__init__.py +0 -0
- chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
- chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
- chia/wallet/driver_protocol.py +26 -0
- chia/wallet/key_val_store.py +55 -0
- chia/wallet/lineage_proof.py +58 -0
- chia/wallet/nft_wallet/__init__.py +0 -0
- chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
- chia/wallet/nft_wallet/nft_info.py +120 -0
- chia/wallet/nft_wallet/nft_puzzles.py +305 -0
- chia/wallet/nft_wallet/nft_wallet.py +1687 -0
- chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
- chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
- chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
- chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
- chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
- chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
- chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
- chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
- chia/wallet/nft_wallet/uncurry_nft.py +217 -0
- chia/wallet/notification_manager.py +117 -0
- chia/wallet/notification_store.py +178 -0
- chia/wallet/outer_puzzles.py +84 -0
- chia/wallet/payment.py +33 -0
- chia/wallet/puzzle_drivers.py +118 -0
- chia/wallet/puzzles/__init__.py +0 -0
- chia/wallet/puzzles/augmented_condition.clsp +13 -0
- chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
- chia/wallet/puzzles/clawback/__init__.py +0 -0
- chia/wallet/puzzles/clawback/drivers.py +188 -0
- chia/wallet/puzzles/clawback/metadata.py +38 -0
- chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
- chia/wallet/puzzles/condition_codes.clib +77 -0
- chia/wallet/puzzles/curry-and-treehash.clib +102 -0
- chia/wallet/puzzles/curry.clib +135 -0
- chia/wallet/puzzles/curry_by_index.clib +16 -0
- chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
- chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
- chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
- chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
- chia/wallet/puzzles/dao_finished_state.clsp +35 -0
- chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
- chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_lockup.clsp +288 -0
- chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
- chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_proposal.clsp +377 -0
- chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
- chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
- chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
- chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
- chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
- chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
- chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
- chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_treasury.clsp +115 -0
- chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
- chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
- chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
- chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
- chia/wallet/puzzles/json.clib +25 -0
- chia/wallet/puzzles/load_clvm.py +161 -0
- chia/wallet/puzzles/merkle_utils.clib +18 -0
- chia/wallet/puzzles/notification.clsp +7 -0
- chia/wallet/puzzles/notification.clsp.hex +1 -0
- chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
- chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
- chia/wallet/puzzles/p2_conditions.clsp +3 -0
- chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
- chia/wallet/puzzles/p2_conditions.py +26 -0
- chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
- chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
- chia/wallet/puzzles/p2_delegated_conditions.py +21 -0
- chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
- chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
- chia/wallet/puzzles/p2_delegated_puzzle.py +34 -0
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +160 -0
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +21 -0
- chia/wallet/puzzles/p2_parent.clsp +19 -0
- chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
- chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
- chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
- chia/wallet/puzzles/p2_puzzle_hash.py +27 -0
- chia/wallet/puzzles/p2_singleton.clsp +30 -0
- chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
- chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
- chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
- chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
- chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
- chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
- chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
- chia/wallet/puzzles/puzzle_utils.py +34 -0
- chia/wallet/puzzles/settlement_payments.clsp +49 -0
- chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
- chia/wallet/puzzles/sha256tree.clib +11 -0
- chia/wallet/puzzles/singleton_launcher.clsp +16 -0
- chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
- chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
- chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
- chia/wallet/puzzles/singleton_top_layer.py +296 -0
- chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
- chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
- chia/wallet/puzzles/singleton_top_layer_v1_1.py +345 -0
- chia/wallet/puzzles/singleton_truths.clib +21 -0
- chia/wallet/puzzles/tails.py +348 -0
- chia/wallet/puzzles/utility_macros.clib +48 -0
- chia/wallet/signer_protocol.py +125 -0
- chia/wallet/singleton.py +106 -0
- chia/wallet/singleton_record.py +30 -0
- chia/wallet/trade_manager.py +1102 -0
- chia/wallet/trade_record.py +67 -0
- chia/wallet/trading/__init__.py +0 -0
- chia/wallet/trading/offer.py +702 -0
- chia/wallet/trading/trade_status.py +13 -0
- chia/wallet/trading/trade_store.py +526 -0
- chia/wallet/transaction_record.py +158 -0
- chia/wallet/transaction_sorting.py +14 -0
- chia/wallet/uncurried_puzzle.py +17 -0
- chia/wallet/util/__init__.py +0 -0
- chia/wallet/util/address_type.py +55 -0
- chia/wallet/util/blind_signer_tl.py +164 -0
- chia/wallet/util/clvm_streamable.py +203 -0
- chia/wallet/util/compute_hints.py +66 -0
- chia/wallet/util/compute_memos.py +43 -0
- chia/wallet/util/curry_and_treehash.py +91 -0
- chia/wallet/util/debug_spend_bundle.py +232 -0
- chia/wallet/util/merkle_tree.py +100 -0
- chia/wallet/util/merkle_utils.py +102 -0
- chia/wallet/util/new_peak_queue.py +82 -0
- chia/wallet/util/notifications.py +12 -0
- chia/wallet/util/peer_request_cache.py +174 -0
- chia/wallet/util/pprint.py +39 -0
- chia/wallet/util/puzzle_compression.py +95 -0
- chia/wallet/util/puzzle_decorator.py +100 -0
- chia/wallet/util/puzzle_decorator_type.py +7 -0
- chia/wallet/util/query_filter.py +59 -0
- chia/wallet/util/transaction_type.py +23 -0
- chia/wallet/util/tx_config.py +158 -0
- chia/wallet/util/wallet_sync_utils.py +351 -0
- chia/wallet/util/wallet_types.py +72 -0
- chia/wallet/vc_wallet/__init__.py +0 -0
- chia/wallet/vc_wallet/cr_cat_drivers.py +664 -0
- chia/wallet/vc_wallet/cr_cat_wallet.py +877 -0
- chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
- chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
- chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
- chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
- chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
- chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
- chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
- chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_drivers.py +838 -0
- chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
- chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
- chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
- chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
- chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
- chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
- chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
- chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_store.py +263 -0
- chia/wallet/vc_wallet/vc_wallet.py +638 -0
- chia/wallet/wallet.py +698 -0
- chia/wallet/wallet_action_scope.py +96 -0
- chia/wallet/wallet_blockchain.py +244 -0
- chia/wallet/wallet_coin_record.py +72 -0
- chia/wallet/wallet_coin_store.py +351 -0
- chia/wallet/wallet_info.py +35 -0
- chia/wallet/wallet_interested_store.py +188 -0
- chia/wallet/wallet_nft_store.py +279 -0
- chia/wallet/wallet_node.py +1765 -0
- chia/wallet/wallet_node_api.py +207 -0
- chia/wallet/wallet_pool_store.py +119 -0
- chia/wallet/wallet_protocol.py +90 -0
- chia/wallet/wallet_puzzle_store.py +396 -0
- chia/wallet/wallet_retry_store.py +70 -0
- chia/wallet/wallet_singleton_store.py +259 -0
- chia/wallet/wallet_spend_bundle.py +25 -0
- chia/wallet/wallet_state_manager.py +2819 -0
- chia/wallet/wallet_transaction_store.py +496 -0
- chia/wallet/wallet_user_store.py +110 -0
- chia/wallet/wallet_weight_proof_handler.py +126 -0
- chia_blockchain-2.5.1rc1.dist-info/LICENSE +201 -0
- chia_blockchain-2.5.1rc1.dist-info/METADATA +156 -0
- chia_blockchain-2.5.1rc1.dist-info/RECORD +1042 -0
- chia_blockchain-2.5.1rc1.dist-info/WHEEL +4 -0
- chia_blockchain-2.5.1rc1.dist-info/entry_points.txt +17 -0
- mozilla-ca/cacert.pem +3611 -0
|
@@ -0,0 +1,1033 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import dataclasses
|
|
5
|
+
import logging
|
|
6
|
+
import time
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from chia.consensus.block_record import BlockRecord
|
|
10
|
+
from chia.consensus.blockchain_interface import BlockRecordsProtocol
|
|
11
|
+
from chia.consensus.constants import ConsensusConstants
|
|
12
|
+
from chia.consensus.difficulty_adjustment import can_finish_sub_and_full_epoch
|
|
13
|
+
from chia.consensus.make_sub_epoch_summary import make_sub_epoch_summary
|
|
14
|
+
from chia.consensus.multiprocess_validation import PreValidationResult
|
|
15
|
+
from chia.consensus.pot_iterations import calculate_sp_interval_iters
|
|
16
|
+
from chia.full_node.signage_point import SignagePoint
|
|
17
|
+
from chia.protocols import timelord_protocol
|
|
18
|
+
from chia.server.outbound_message import Message
|
|
19
|
+
from chia.types.blockchain_format.classgroup import ClassgroupElement
|
|
20
|
+
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
21
|
+
from chia.types.blockchain_format.vdf import VDFInfo, validate_vdf
|
|
22
|
+
from chia.types.end_of_slot_bundle import EndOfSubSlotBundle
|
|
23
|
+
from chia.types.full_block import FullBlock
|
|
24
|
+
from chia.types.unfinished_block import UnfinishedBlock
|
|
25
|
+
from chia.util.ints import uint8, uint32, uint64, uint128
|
|
26
|
+
from chia.util.lru_cache import LRUCache
|
|
27
|
+
from chia.util.streamable import Streamable, streamable
|
|
28
|
+
|
|
29
|
+
log = logging.getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@streamable
|
|
33
|
+
@dataclasses.dataclass(frozen=True)
|
|
34
|
+
class FullNodeStorePeakResult(Streamable):
|
|
35
|
+
added_eos: Optional[EndOfSubSlotBundle]
|
|
36
|
+
new_signage_points: list[tuple[uint8, SignagePoint]]
|
|
37
|
+
new_infusion_points: list[timelord_protocol.NewInfusionPointVDF]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclasses.dataclass
|
|
41
|
+
class UnfinishedBlockEntry:
|
|
42
|
+
# if this is None, it means we've requested this block but not yet received
|
|
43
|
+
# it
|
|
44
|
+
unfinished_block: Optional[UnfinishedBlock]
|
|
45
|
+
# If this is None, it means we've initiated validation of this block, but it
|
|
46
|
+
# hasn't completed yet
|
|
47
|
+
result: Optional[PreValidationResult]
|
|
48
|
+
height: uint32
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def find_best_block(
|
|
52
|
+
result: dict[Optional[bytes32], UnfinishedBlockEntry],
|
|
53
|
+
) -> tuple[Optional[bytes32], Optional[UnfinishedBlock]]:
|
|
54
|
+
"""
|
|
55
|
+
Given a collection of UnfinishedBlocks (all with the same reward block
|
|
56
|
+
hash), return the "best" one. i.e. the one with the smallest foliage hash.
|
|
57
|
+
"""
|
|
58
|
+
if len(result) == 0:
|
|
59
|
+
return None, None
|
|
60
|
+
|
|
61
|
+
all_blocks = list(result.items())
|
|
62
|
+
if len(all_blocks) == 1:
|
|
63
|
+
foliage_hash, entry = all_blocks[0]
|
|
64
|
+
# this means we don't have the block yet
|
|
65
|
+
if entry.unfinished_block is None:
|
|
66
|
+
return None, None
|
|
67
|
+
else:
|
|
68
|
+
return foliage_hash, entry.unfinished_block
|
|
69
|
+
|
|
70
|
+
def include_block(item: tuple[Optional[bytes32], UnfinishedBlockEntry]) -> bool:
|
|
71
|
+
foliage_hash, entry = item
|
|
72
|
+
return foliage_hash is not None and entry.unfinished_block is not None
|
|
73
|
+
|
|
74
|
+
# if there are unfinished blocks with foliage (i.e. not None) we prefer
|
|
75
|
+
# those, so drop the first element
|
|
76
|
+
all_blocks = [e for e in all_blocks if include_block(e)]
|
|
77
|
+
all_blocks = sorted(all_blocks)
|
|
78
|
+
|
|
79
|
+
# we may have filtered out some blocks that we have only requested, but not
|
|
80
|
+
# yet received.
|
|
81
|
+
if len(all_blocks) == 0:
|
|
82
|
+
return None, None
|
|
83
|
+
|
|
84
|
+
return all_blocks[0][0], all_blocks[0][1].unfinished_block
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class FullNodeStore:
|
|
88
|
+
constants: ConsensusConstants
|
|
89
|
+
|
|
90
|
+
# Blocks which we have created, but don't have plot signatures yet, so not yet "unfinished blocks"
|
|
91
|
+
candidate_blocks: dict[bytes32, tuple[uint32, UnfinishedBlock]]
|
|
92
|
+
candidate_backup_blocks: dict[bytes32, tuple[uint32, UnfinishedBlock]]
|
|
93
|
+
|
|
94
|
+
# Block hashes of unfinished blocks that we have seen recently. This is
|
|
95
|
+
# effectively a set[bytes32] but in order to evict the oldest items first,
|
|
96
|
+
# we use a Dict that preserves insertion order, and remove from the
|
|
97
|
+
# beginning
|
|
98
|
+
seen_unfinished_blocks: dict[bytes32, None]
|
|
99
|
+
|
|
100
|
+
# Unfinished blocks, keyed from reward hash
|
|
101
|
+
# There may be multiple different unfinished blocks with the same partial
|
|
102
|
+
# hash (reward chain block hash). They are stored under their partial hash
|
|
103
|
+
# though. The inner dictionary uses the foliage hash as the key
|
|
104
|
+
# The UnfinishedBlockEntry is a placeholder for UnfinishedBlocks we have
|
|
105
|
+
# requested (but don't have yet) or that we have but haven't completed
|
|
106
|
+
# validation of (yet).
|
|
107
|
+
# The inner key (the foliage hash) is Optional, where None either means
|
|
108
|
+
# it's not a transaction block, or it's a block we learned about via the old
|
|
109
|
+
# protocol, where all we get is the reward block hash.
|
|
110
|
+
_unfinished_blocks: dict[bytes32, dict[Optional[bytes32], UnfinishedBlockEntry]]
|
|
111
|
+
|
|
112
|
+
# Finished slots and sps from the peak's slot onwards
|
|
113
|
+
# We store all 32 SPs for each slot, starting as 32 Nones and filling them as we go
|
|
114
|
+
# Also stores the total iters at the end of slot
|
|
115
|
+
# For the first sub-slot, EndOfSlotBundle is None
|
|
116
|
+
finished_sub_slots: list[tuple[Optional[EndOfSubSlotBundle], list[Optional[SignagePoint]], uint128]]
|
|
117
|
+
|
|
118
|
+
# These caches maintain objects which depend on infused blocks in the reward chain, that we
|
|
119
|
+
# might receive before the blocks themselves. The dict keys are the reward chain challenge hashes.
|
|
120
|
+
|
|
121
|
+
# End of slots which depend on infusions that we don't have
|
|
122
|
+
future_eos_cache: dict[bytes32, list[EndOfSubSlotBundle]]
|
|
123
|
+
|
|
124
|
+
# Signage points which depend on infusions that we don't have
|
|
125
|
+
future_sp_cache: dict[bytes32, list[tuple[uint8, SignagePoint]]]
|
|
126
|
+
|
|
127
|
+
# Infusion point VDFs which depend on infusions that we don't have
|
|
128
|
+
future_ip_cache: dict[bytes32, list[timelord_protocol.NewInfusionPointVDF]]
|
|
129
|
+
|
|
130
|
+
# This stores the time that each key was added to the future cache, so we can clear old keys
|
|
131
|
+
future_cache_key_times: dict[bytes32, int]
|
|
132
|
+
|
|
133
|
+
# These recent caches are for pooling support
|
|
134
|
+
recent_signage_points: LRUCache[bytes32, tuple[SignagePoint, float]]
|
|
135
|
+
recent_eos: LRUCache[bytes32, tuple[EndOfSubSlotBundle, float]]
|
|
136
|
+
|
|
137
|
+
pending_tx_request: dict[bytes32, bytes32] # tx_id: peer_id
|
|
138
|
+
peers_with_tx: dict[bytes32, set[bytes32]] # tx_id: set[peer_ids}
|
|
139
|
+
tx_fetch_tasks: dict[bytes32, asyncio.Task[None]] # Task id: task
|
|
140
|
+
serialized_wp_message: Optional[Message]
|
|
141
|
+
serialized_wp_message_tip: Optional[bytes32]
|
|
142
|
+
|
|
143
|
+
max_seen_unfinished_blocks: int
|
|
144
|
+
|
|
145
|
+
def __init__(self, constants: ConsensusConstants):
|
|
146
|
+
self.candidate_blocks = {}
|
|
147
|
+
self.candidate_backup_blocks = {}
|
|
148
|
+
self.seen_unfinished_blocks = {}
|
|
149
|
+
self._unfinished_blocks = {}
|
|
150
|
+
self.finished_sub_slots = []
|
|
151
|
+
self.future_eos_cache = {}
|
|
152
|
+
self.future_sp_cache = {}
|
|
153
|
+
self.future_ip_cache = {}
|
|
154
|
+
self.recent_signage_points = LRUCache(500)
|
|
155
|
+
self.recent_eos = LRUCache(50)
|
|
156
|
+
self.future_cache_key_times = {}
|
|
157
|
+
self.constants = constants
|
|
158
|
+
self.clear_slots()
|
|
159
|
+
self.initialize_genesis_sub_slot()
|
|
160
|
+
self.pending_tx_request = {}
|
|
161
|
+
self.peers_with_tx = {}
|
|
162
|
+
self.tx_fetch_tasks = {}
|
|
163
|
+
self.serialized_wp_message = None
|
|
164
|
+
self.serialized_wp_message_tip = None
|
|
165
|
+
self.max_seen_unfinished_blocks = 1000
|
|
166
|
+
|
|
167
|
+
def is_requesting_unfinished_block(
|
|
168
|
+
self, reward_block_hash: bytes32, foliage_hash: Optional[bytes32]
|
|
169
|
+
) -> tuple[bool, int]:
|
|
170
|
+
"""
|
|
171
|
+
Asks if we are already requesting this specific unfinished block (given
|
|
172
|
+
the reward block hash and foliage hash). The returned bool is true if we
|
|
173
|
+
are and false otherwise. The function also returns the number of
|
|
174
|
+
variants of an unfinished block with this reward block hash we are
|
|
175
|
+
currently requesting. This is useful to ensure we limit the number of
|
|
176
|
+
variants we request.
|
|
177
|
+
"""
|
|
178
|
+
ents = self._unfinished_blocks.get(reward_block_hash)
|
|
179
|
+
if ents is None:
|
|
180
|
+
return (False, 0)
|
|
181
|
+
elif foliage_hash is None:
|
|
182
|
+
return (len(ents) > 0, len(ents))
|
|
183
|
+
else:
|
|
184
|
+
return (foliage_hash in ents, len(ents))
|
|
185
|
+
|
|
186
|
+
def mark_requesting_unfinished_block(self, reward_block_hash: bytes32, foliage_hash: Optional[bytes32]) -> None:
|
|
187
|
+
ents = self._unfinished_blocks.setdefault(reward_block_hash, {})
|
|
188
|
+
ents.setdefault(foliage_hash, UnfinishedBlockEntry(None, None, uint32(0)))
|
|
189
|
+
|
|
190
|
+
def remove_requesting_unfinished_block(self, reward_block_hash: bytes32, foliage_hash: Optional[bytes32]) -> None:
|
|
191
|
+
reward_ents = self._unfinished_blocks.get(reward_block_hash)
|
|
192
|
+
if reward_ents is None:
|
|
193
|
+
return
|
|
194
|
+
foliage_ent = reward_ents.get(foliage_hash)
|
|
195
|
+
if foliage_ent is None:
|
|
196
|
+
return
|
|
197
|
+
if foliage_ent.unfinished_block is not None:
|
|
198
|
+
# in this case we've successfully received the unfinished block,
|
|
199
|
+
# it's already considered "not requesting", but actually downloaded
|
|
200
|
+
return
|
|
201
|
+
del reward_ents[foliage_hash]
|
|
202
|
+
if len(reward_ents) == 0:
|
|
203
|
+
del self._unfinished_blocks[reward_block_hash]
|
|
204
|
+
|
|
205
|
+
def add_candidate_block(
|
|
206
|
+
self, quality_string: bytes32, height: uint32, unfinished_block: UnfinishedBlock, backup: bool = False
|
|
207
|
+
) -> None:
|
|
208
|
+
if backup:
|
|
209
|
+
self.candidate_backup_blocks[quality_string] = (height, unfinished_block)
|
|
210
|
+
else:
|
|
211
|
+
self.candidate_blocks[quality_string] = (height, unfinished_block)
|
|
212
|
+
|
|
213
|
+
def get_candidate_block(
|
|
214
|
+
self, quality_string: bytes32, backup: bool = False
|
|
215
|
+
) -> Optional[tuple[uint32, UnfinishedBlock]]:
|
|
216
|
+
if backup:
|
|
217
|
+
return self.candidate_backup_blocks.get(quality_string, None)
|
|
218
|
+
else:
|
|
219
|
+
return self.candidate_blocks.get(quality_string, None)
|
|
220
|
+
|
|
221
|
+
def clear_candidate_blocks_below(self, height: uint32) -> None:
|
|
222
|
+
del_keys = []
|
|
223
|
+
for key, value in self.candidate_blocks.items():
|
|
224
|
+
if value[0] < height:
|
|
225
|
+
del_keys.append(key)
|
|
226
|
+
for key in del_keys:
|
|
227
|
+
try:
|
|
228
|
+
del self.candidate_blocks[key]
|
|
229
|
+
except KeyError:
|
|
230
|
+
pass
|
|
231
|
+
del_keys = []
|
|
232
|
+
for key, value in self.candidate_backup_blocks.items():
|
|
233
|
+
if value[0] < height:
|
|
234
|
+
del_keys.append(key)
|
|
235
|
+
for key in del_keys:
|
|
236
|
+
try:
|
|
237
|
+
del self.candidate_backup_blocks[key]
|
|
238
|
+
except KeyError:
|
|
239
|
+
pass
|
|
240
|
+
|
|
241
|
+
def seen_unfinished_block(self, object_hash: bytes32) -> bool:
|
|
242
|
+
if object_hash in self.seen_unfinished_blocks:
|
|
243
|
+
return True
|
|
244
|
+
self.seen_unfinished_blocks[object_hash] = None
|
|
245
|
+
if len(self.seen_unfinished_blocks) > self.max_seen_unfinished_blocks:
|
|
246
|
+
# remove the least recently added hash
|
|
247
|
+
to_remove = next(iter(self.seen_unfinished_blocks))
|
|
248
|
+
del self.seen_unfinished_blocks[to_remove]
|
|
249
|
+
return False
|
|
250
|
+
|
|
251
|
+
def add_unfinished_block(
|
|
252
|
+
self, height: uint32, unfinished_block: UnfinishedBlock, result: PreValidationResult
|
|
253
|
+
) -> None:
|
|
254
|
+
partial_hash = unfinished_block.partial_hash
|
|
255
|
+
entry = self._unfinished_blocks.setdefault(partial_hash, {})
|
|
256
|
+
entry[unfinished_block.foliage.foliage_transaction_block_hash] = UnfinishedBlockEntry(
|
|
257
|
+
unfinished_block, result, height
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
def get_unfinished_block(self, unfinished_reward_hash: bytes32) -> Optional[UnfinishedBlock]:
|
|
261
|
+
result = self._unfinished_blocks.get(unfinished_reward_hash, None)
|
|
262
|
+
if result is None:
|
|
263
|
+
return None
|
|
264
|
+
# The old API doesn't distinguish between duplicate UnfinishedBlocks,
|
|
265
|
+
# return the *best* UnfinishedBlock. This is the path taken when the
|
|
266
|
+
# timelord sends us an infusion point with this specific reward block
|
|
267
|
+
# hash. We pick one of the unfinished blocks based on an arbitrary but
|
|
268
|
+
# deterministic property.
|
|
269
|
+
# this sorts the UnfinishedBlocks by the foliage hash, and picks the
|
|
270
|
+
# smallest hash
|
|
271
|
+
_foliage_hash, block = find_best_block(result)
|
|
272
|
+
return block
|
|
273
|
+
|
|
274
|
+
def get_unfinished_block2(
|
|
275
|
+
self, unfinished_reward_hash: bytes32, unfinished_foliage_hash: Optional[bytes32]
|
|
276
|
+
) -> tuple[Optional[UnfinishedBlock], int, bool]:
|
|
277
|
+
"""
|
|
278
|
+
Looks up an UnfinishedBlock by its reward block hash and foliage hash.
|
|
279
|
+
If the foliage hash is None (e.g. it's not a transaction block), we fall
|
|
280
|
+
back to the original function that looks up unfinished blocks just by
|
|
281
|
+
their reward block hash.
|
|
282
|
+
Returns:
|
|
283
|
+
1. the (optional) UnfinishedBlock
|
|
284
|
+
2. the number of other candidate blocks we know of with the same
|
|
285
|
+
reward block hash
|
|
286
|
+
3. whether we already have a "better" UnfinishedBlock candidate than
|
|
287
|
+
this
|
|
288
|
+
"""
|
|
289
|
+
result = self._unfinished_blocks.get(unfinished_reward_hash, None)
|
|
290
|
+
if result is None:
|
|
291
|
+
return None, 0, False
|
|
292
|
+
if unfinished_foliage_hash is None:
|
|
293
|
+
foliage_hash, block = find_best_block(result)
|
|
294
|
+
return block, len(result), False
|
|
295
|
+
|
|
296
|
+
foliage_hash, block = find_best_block(result)
|
|
297
|
+
has_better: bool = foliage_hash is not None and foliage_hash < unfinished_foliage_hash
|
|
298
|
+
|
|
299
|
+
entry = result.get(unfinished_foliage_hash)
|
|
300
|
+
|
|
301
|
+
if entry is None:
|
|
302
|
+
return None, len(result), has_better
|
|
303
|
+
else:
|
|
304
|
+
return entry.unfinished_block, len(result), has_better
|
|
305
|
+
|
|
306
|
+
# we only have PreValidationResults for transaction blocks, and they all
|
|
307
|
+
# have a foliage hash. That's why unfinished_foliage_hash is not Optional.
|
|
308
|
+
def get_unfinished_block_result(
|
|
309
|
+
self, unfinished_reward_hash: bytes32, unfinished_foliage_hash: bytes32
|
|
310
|
+
) -> Optional[UnfinishedBlockEntry]:
|
|
311
|
+
result = self._unfinished_blocks.get(unfinished_reward_hash, None)
|
|
312
|
+
if result is None:
|
|
313
|
+
return None
|
|
314
|
+
else:
|
|
315
|
+
return result.get(unfinished_foliage_hash)
|
|
316
|
+
|
|
317
|
+
# returns all unfinished blocks for the specified height
|
|
318
|
+
def get_unfinished_blocks(self, height: uint32) -> list[UnfinishedBlock]:
|
|
319
|
+
ret: list[UnfinishedBlock] = []
|
|
320
|
+
for entry in self._unfinished_blocks.values():
|
|
321
|
+
for ube in entry.values():
|
|
322
|
+
if ube.height == height and ube.unfinished_block is not None:
|
|
323
|
+
ret.append(ube.unfinished_block)
|
|
324
|
+
return ret
|
|
325
|
+
|
|
326
|
+
def clear_unfinished_blocks_below(self, height: uint32) -> None:
|
|
327
|
+
del_partial: list[bytes32] = []
|
|
328
|
+
for partial_hash, entry in self._unfinished_blocks.items():
|
|
329
|
+
del_foliage: list[Optional[bytes32]] = []
|
|
330
|
+
for foliage_hash, ube in entry.items():
|
|
331
|
+
if ube.height < height:
|
|
332
|
+
del_foliage.append(foliage_hash)
|
|
333
|
+
for fh in del_foliage:
|
|
334
|
+
del entry[fh]
|
|
335
|
+
if len(entry) == 0:
|
|
336
|
+
del_partial.append(partial_hash)
|
|
337
|
+
for ph in del_partial:
|
|
338
|
+
del self._unfinished_blocks[ph]
|
|
339
|
+
|
|
340
|
+
# TODO: this should be removed. It's only used by a test
|
|
341
|
+
def remove_unfinished_block(self, partial_reward_hash: bytes32) -> None:
|
|
342
|
+
if partial_reward_hash in self._unfinished_blocks:
|
|
343
|
+
del self._unfinished_blocks[partial_reward_hash]
|
|
344
|
+
|
|
345
|
+
def add_to_future_ip(self, infusion_point: timelord_protocol.NewInfusionPointVDF) -> None:
|
|
346
|
+
ch: bytes32 = infusion_point.reward_chain_ip_vdf.challenge
|
|
347
|
+
if ch not in self.future_ip_cache:
|
|
348
|
+
self.future_ip_cache[ch] = []
|
|
349
|
+
self.future_ip_cache[ch].append(infusion_point)
|
|
350
|
+
|
|
351
|
+
def in_future_sp_cache(self, signage_point: SignagePoint, index: uint8) -> bool:
|
|
352
|
+
if signage_point.rc_vdf is None:
|
|
353
|
+
return False
|
|
354
|
+
|
|
355
|
+
if signage_point.rc_vdf.challenge not in self.future_sp_cache:
|
|
356
|
+
return False
|
|
357
|
+
for cache_index, cache_sp in self.future_sp_cache[signage_point.rc_vdf.challenge]:
|
|
358
|
+
if cache_index == index and cache_sp.rc_vdf == signage_point.rc_vdf:
|
|
359
|
+
return True
|
|
360
|
+
return False
|
|
361
|
+
|
|
362
|
+
def add_to_future_sp(self, signage_point: SignagePoint, index: uint8) -> None:
|
|
363
|
+
# We are missing a block here
|
|
364
|
+
if (
|
|
365
|
+
signage_point.cc_vdf is None
|
|
366
|
+
or signage_point.rc_vdf is None
|
|
367
|
+
or signage_point.cc_proof is None
|
|
368
|
+
or signage_point.rc_proof is None
|
|
369
|
+
):
|
|
370
|
+
return None
|
|
371
|
+
if signage_point.rc_vdf.challenge not in self.future_sp_cache:
|
|
372
|
+
self.future_sp_cache[signage_point.rc_vdf.challenge] = []
|
|
373
|
+
if self.in_future_sp_cache(signage_point, index):
|
|
374
|
+
return None
|
|
375
|
+
|
|
376
|
+
self.future_cache_key_times[signage_point.rc_vdf.challenge] = int(time.time())
|
|
377
|
+
self.future_sp_cache[signage_point.rc_vdf.challenge].append((index, signage_point))
|
|
378
|
+
log.info(f"Don't have rc hash {signage_point.rc_vdf.challenge.hex()}. caching signage point {index}.")
|
|
379
|
+
|
|
380
|
+
def get_future_ip(self, rc_challenge_hash: bytes32) -> list[timelord_protocol.NewInfusionPointVDF]:
|
|
381
|
+
return self.future_ip_cache.get(rc_challenge_hash, [])
|
|
382
|
+
|
|
383
|
+
def clear_old_cache_entries(self) -> None:
|
|
384
|
+
current_time: int = int(time.time())
|
|
385
|
+
remove_keys: list[bytes32] = []
|
|
386
|
+
for rc_hash, time_added in self.future_cache_key_times.items():
|
|
387
|
+
if current_time - time_added > 3600:
|
|
388
|
+
remove_keys.append(rc_hash)
|
|
389
|
+
for k in remove_keys:
|
|
390
|
+
self.future_cache_key_times.pop(k, None)
|
|
391
|
+
self.future_ip_cache.pop(k, [])
|
|
392
|
+
self.future_eos_cache.pop(k, [])
|
|
393
|
+
self.future_sp_cache.pop(k, [])
|
|
394
|
+
|
|
395
|
+
def clear_slots(self) -> None:
|
|
396
|
+
self.finished_sub_slots.clear()
|
|
397
|
+
|
|
398
|
+
def get_sub_slot(self, challenge_hash: bytes32) -> Optional[tuple[EndOfSubSlotBundle, int, uint128]]:
|
|
399
|
+
assert len(self.finished_sub_slots) >= 1
|
|
400
|
+
for index, (sub_slot, _, total_iters) in enumerate(self.finished_sub_slots):
|
|
401
|
+
if sub_slot is not None and sub_slot.challenge_chain.get_hash() == challenge_hash:
|
|
402
|
+
return sub_slot, index, total_iters
|
|
403
|
+
return None
|
|
404
|
+
|
|
405
|
+
def initialize_genesis_sub_slot(self) -> None:
|
|
406
|
+
self.clear_slots()
|
|
407
|
+
self.finished_sub_slots = [(None, [None] * self.constants.NUM_SPS_SUB_SLOT, uint128(0))]
|
|
408
|
+
|
|
409
|
+
def new_finished_sub_slot(
|
|
410
|
+
self,
|
|
411
|
+
eos: EndOfSubSlotBundle,
|
|
412
|
+
blocks: BlockRecordsProtocol,
|
|
413
|
+
peak: Optional[BlockRecord],
|
|
414
|
+
next_sub_slot_iters: uint64,
|
|
415
|
+
next_difficulty: uint64,
|
|
416
|
+
peak_full_block: Optional[FullBlock],
|
|
417
|
+
) -> Optional[list[timelord_protocol.NewInfusionPointVDF]]:
|
|
418
|
+
"""
|
|
419
|
+
Returns false if not added. Returns a list if added. The list contains all infusion points that depended
|
|
420
|
+
on this sub slot
|
|
421
|
+
"""
|
|
422
|
+
assert len(self.finished_sub_slots) >= 1
|
|
423
|
+
assert (peak is None) == (peak_full_block is None)
|
|
424
|
+
|
|
425
|
+
last_slot, _, last_slot_iters = self.finished_sub_slots[-1]
|
|
426
|
+
|
|
427
|
+
cc_challenge: bytes32 = (
|
|
428
|
+
last_slot.challenge_chain.get_hash() if last_slot is not None else self.constants.GENESIS_CHALLENGE
|
|
429
|
+
)
|
|
430
|
+
rc_challenge: bytes32 = (
|
|
431
|
+
last_slot.reward_chain.get_hash() if last_slot is not None else self.constants.GENESIS_CHALLENGE
|
|
432
|
+
)
|
|
433
|
+
icc_challenge: Optional[bytes32] = None
|
|
434
|
+
icc_iters: Optional[uint64] = None
|
|
435
|
+
|
|
436
|
+
# Skip if already present
|
|
437
|
+
for slot, _, _ in self.finished_sub_slots:
|
|
438
|
+
if slot == eos:
|
|
439
|
+
return []
|
|
440
|
+
|
|
441
|
+
if eos.challenge_chain.challenge_chain_end_of_slot_vdf.challenge != cc_challenge:
|
|
442
|
+
# This slot does not append to our next slot
|
|
443
|
+
# This prevent other peers from appending fake VDFs to our cache
|
|
444
|
+
log.error(
|
|
445
|
+
f"bad cc_challenge in new_finished_sub_slot, "
|
|
446
|
+
f"got {eos.challenge_chain.challenge_chain_end_of_slot_vdf.challenge.hex()}"
|
|
447
|
+
f"expected {cc_challenge}"
|
|
448
|
+
)
|
|
449
|
+
return None
|
|
450
|
+
|
|
451
|
+
if peak is None:
|
|
452
|
+
sub_slot_iters = self.constants.SUB_SLOT_ITERS_STARTING
|
|
453
|
+
else:
|
|
454
|
+
sub_slot_iters = peak.sub_slot_iters
|
|
455
|
+
|
|
456
|
+
total_iters = uint128(last_slot_iters + sub_slot_iters)
|
|
457
|
+
|
|
458
|
+
if peak is not None and peak.total_iters > last_slot_iters:
|
|
459
|
+
# Peak is in this slot
|
|
460
|
+
|
|
461
|
+
# Note: Adding an end of subslot does not lock the blockchain, for performance reasons. Only the
|
|
462
|
+
# timelord_lock is used. Therefore, it's possible that we add a new peak at the same time as seeing
|
|
463
|
+
# the finished subslot, and the peak is not fully added yet, so it looks like we still need the subslot.
|
|
464
|
+
# In that case, we will exit here and let the new_peak code add the subslot.
|
|
465
|
+
if total_iters < peak.total_iters:
|
|
466
|
+
log.debug("dont add slot, total_iters < peak.total_iters")
|
|
467
|
+
return None
|
|
468
|
+
|
|
469
|
+
rc_challenge = bytes32(eos.reward_chain.end_of_slot_vdf.challenge)
|
|
470
|
+
cc_start_element = peak.challenge_vdf_output
|
|
471
|
+
iters = uint64(total_iters - peak.total_iters)
|
|
472
|
+
if peak.reward_infusion_new_challenge != rc_challenge:
|
|
473
|
+
# We don't have this challenge hash yet
|
|
474
|
+
if rc_challenge not in self.future_eos_cache:
|
|
475
|
+
self.future_eos_cache[rc_challenge] = []
|
|
476
|
+
self.future_eos_cache[rc_challenge].append(eos)
|
|
477
|
+
self.future_cache_key_times[rc_challenge] = int(time.time())
|
|
478
|
+
log.info(f"Don't have challenge hash {rc_challenge}, caching EOS")
|
|
479
|
+
return None
|
|
480
|
+
|
|
481
|
+
if peak.deficit == 0:
|
|
482
|
+
if eos.reward_chain.deficit != self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK:
|
|
483
|
+
log.error(
|
|
484
|
+
f"eos reward_chain deficit got {eos.reward_chain.deficit} "
|
|
485
|
+
f"expected {self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK}"
|
|
486
|
+
)
|
|
487
|
+
return None
|
|
488
|
+
elif eos.reward_chain.deficit != peak.deficit:
|
|
489
|
+
log.error(f"wrong eos reward_chain deficit got {eos.reward_chain.deficit} expected {peak.deficit}")
|
|
490
|
+
return None
|
|
491
|
+
|
|
492
|
+
if peak.deficit == self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK:
|
|
493
|
+
icc_start_element = None
|
|
494
|
+
elif peak.deficit == self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK - 1:
|
|
495
|
+
icc_start_element = ClassgroupElement.get_default_element()
|
|
496
|
+
else:
|
|
497
|
+
icc_start_element = peak.infused_challenge_vdf_output
|
|
498
|
+
|
|
499
|
+
if peak.deficit < self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK:
|
|
500
|
+
curr = peak
|
|
501
|
+
while not curr.first_in_sub_slot and not curr.is_challenge_block(self.constants):
|
|
502
|
+
curr = blocks.block_record(curr.prev_hash)
|
|
503
|
+
if curr.is_challenge_block(self.constants):
|
|
504
|
+
icc_challenge = curr.challenge_block_info_hash
|
|
505
|
+
icc_iters = uint64(total_iters - curr.total_iters)
|
|
506
|
+
else:
|
|
507
|
+
assert curr.finished_infused_challenge_slot_hashes is not None
|
|
508
|
+
icc_challenge = curr.finished_infused_challenge_slot_hashes[-1]
|
|
509
|
+
icc_iters = sub_slot_iters
|
|
510
|
+
assert icc_challenge is not None
|
|
511
|
+
|
|
512
|
+
finish_se, finish_epoch = can_finish_sub_and_full_epoch(
|
|
513
|
+
self.constants,
|
|
514
|
+
blocks,
|
|
515
|
+
peak.height,
|
|
516
|
+
peak.prev_hash,
|
|
517
|
+
peak.deficit,
|
|
518
|
+
peak.sub_epoch_summary_included is not None,
|
|
519
|
+
)
|
|
520
|
+
if finish_se:
|
|
521
|
+
# this is the first slot in a new sub epoch, should include SES
|
|
522
|
+
expected_sub_epoch_summary = make_sub_epoch_summary(
|
|
523
|
+
self.constants,
|
|
524
|
+
blocks,
|
|
525
|
+
peak.height,
|
|
526
|
+
blocks.block_record(blocks.block_record(peak.prev_hash).prev_hash),
|
|
527
|
+
next_difficulty if finish_epoch else None,
|
|
528
|
+
next_sub_slot_iters if finish_epoch else None,
|
|
529
|
+
)
|
|
530
|
+
|
|
531
|
+
if eos.challenge_chain.subepoch_summary_hash is None:
|
|
532
|
+
log.warning("SES should not be None")
|
|
533
|
+
return None
|
|
534
|
+
|
|
535
|
+
if eos.challenge_chain.subepoch_summary_hash != expected_sub_epoch_summary.get_hash():
|
|
536
|
+
log.warning(
|
|
537
|
+
f"Bad SES, expected {expected_sub_epoch_summary} "
|
|
538
|
+
f"expected hash {expected_sub_epoch_summary.get_hash()}, got {eos.challenge_chain}"
|
|
539
|
+
)
|
|
540
|
+
return None
|
|
541
|
+
|
|
542
|
+
if finish_epoch:
|
|
543
|
+
# this is the first slot in a new epoch check diff and iterations
|
|
544
|
+
if (
|
|
545
|
+
eos.challenge_chain.new_sub_slot_iters is None
|
|
546
|
+
or eos.challenge_chain.new_sub_slot_iters != next_sub_slot_iters
|
|
547
|
+
):
|
|
548
|
+
log.error("wrong new iterations at end of slot bundle")
|
|
549
|
+
return None
|
|
550
|
+
|
|
551
|
+
if (
|
|
552
|
+
eos.challenge_chain.new_difficulty is None
|
|
553
|
+
or eos.challenge_chain.new_difficulty != next_difficulty
|
|
554
|
+
):
|
|
555
|
+
log.info("wrong new difficulty at end of slot bundle")
|
|
556
|
+
return None
|
|
557
|
+
|
|
558
|
+
else:
|
|
559
|
+
if eos.challenge_chain.new_sub_slot_iters is not None:
|
|
560
|
+
log.error("got new iterations at end of slot bundle when it should be None")
|
|
561
|
+
return None
|
|
562
|
+
|
|
563
|
+
if eos.challenge_chain.new_difficulty is not None:
|
|
564
|
+
log.info("got new difficulty at end of slot bundle when it should be None")
|
|
565
|
+
return None
|
|
566
|
+
|
|
567
|
+
else:
|
|
568
|
+
# empty slots dont have sub_epoch_summary
|
|
569
|
+
if eos.challenge_chain.subepoch_summary_hash is not None:
|
|
570
|
+
log.warning("SES not correct, should be None in an empty slot")
|
|
571
|
+
return None
|
|
572
|
+
|
|
573
|
+
# This is on an empty slot
|
|
574
|
+
cc_start_element = ClassgroupElement.get_default_element()
|
|
575
|
+
icc_start_element = ClassgroupElement.get_default_element()
|
|
576
|
+
iters = sub_slot_iters
|
|
577
|
+
icc_iters = sub_slot_iters
|
|
578
|
+
|
|
579
|
+
# The icc should only be present if the previous slot had an icc too, and not deficit 0 (just finished slot)
|
|
580
|
+
icc_challenge = (
|
|
581
|
+
last_slot.infused_challenge_chain.get_hash()
|
|
582
|
+
if last_slot is not None
|
|
583
|
+
and last_slot.infused_challenge_chain is not None
|
|
584
|
+
and last_slot.reward_chain.deficit != self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK
|
|
585
|
+
else None
|
|
586
|
+
)
|
|
587
|
+
|
|
588
|
+
# Validate cc VDF
|
|
589
|
+
partial_cc_vdf_info = VDFInfo(
|
|
590
|
+
cc_challenge,
|
|
591
|
+
iters,
|
|
592
|
+
eos.challenge_chain.challenge_chain_end_of_slot_vdf.output,
|
|
593
|
+
)
|
|
594
|
+
# The EOS will have the whole sub-slot iters, but the proof is only the delta, from the last peak
|
|
595
|
+
if eos.challenge_chain.challenge_chain_end_of_slot_vdf != partial_cc_vdf_info.replace(
|
|
596
|
+
number_of_iterations=sub_slot_iters
|
|
597
|
+
):
|
|
598
|
+
return None
|
|
599
|
+
if not eos.proofs.challenge_chain_slot_proof.normalized_to_identity and not validate_vdf(
|
|
600
|
+
eos.proofs.challenge_chain_slot_proof,
|
|
601
|
+
self.constants,
|
|
602
|
+
cc_start_element,
|
|
603
|
+
partial_cc_vdf_info,
|
|
604
|
+
):
|
|
605
|
+
return None
|
|
606
|
+
if eos.proofs.challenge_chain_slot_proof.normalized_to_identity and not validate_vdf(
|
|
607
|
+
eos.proofs.challenge_chain_slot_proof,
|
|
608
|
+
self.constants,
|
|
609
|
+
ClassgroupElement.get_default_element(),
|
|
610
|
+
eos.challenge_chain.challenge_chain_end_of_slot_vdf,
|
|
611
|
+
):
|
|
612
|
+
return None
|
|
613
|
+
|
|
614
|
+
# Validate reward chain VDF
|
|
615
|
+
if not validate_vdf(
|
|
616
|
+
eos.proofs.reward_chain_slot_proof,
|
|
617
|
+
self.constants,
|
|
618
|
+
ClassgroupElement.get_default_element(),
|
|
619
|
+
eos.reward_chain.end_of_slot_vdf,
|
|
620
|
+
VDFInfo(rc_challenge, iters, eos.reward_chain.end_of_slot_vdf.output),
|
|
621
|
+
):
|
|
622
|
+
return None
|
|
623
|
+
|
|
624
|
+
if icc_challenge is not None:
|
|
625
|
+
assert icc_start_element is not None
|
|
626
|
+
assert icc_iters is not None
|
|
627
|
+
assert eos.infused_challenge_chain is not None
|
|
628
|
+
assert eos.infused_challenge_chain is not None
|
|
629
|
+
assert eos.proofs.infused_challenge_chain_slot_proof is not None
|
|
630
|
+
if eos.reward_chain.deficit == self.constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK:
|
|
631
|
+
# only at the end of a challenge slot
|
|
632
|
+
if eos.infused_challenge_chain.get_hash() != eos.challenge_chain.infused_challenge_chain_sub_slot_hash:
|
|
633
|
+
log.error("infused_challenge_chain mismatch in challenge_chain")
|
|
634
|
+
return None
|
|
635
|
+
else:
|
|
636
|
+
assert eos.challenge_chain.infused_challenge_chain_sub_slot_hash is None
|
|
637
|
+
assert eos.infused_challenge_chain.get_hash() == eos.reward_chain.infused_challenge_chain_sub_slot_hash
|
|
638
|
+
|
|
639
|
+
partial_icc_vdf_info = VDFInfo(
|
|
640
|
+
icc_challenge,
|
|
641
|
+
iters,
|
|
642
|
+
eos.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.output,
|
|
643
|
+
)
|
|
644
|
+
# The EOS will have the whole sub-slot iters, but the proof is only the delta, from the last peak
|
|
645
|
+
if eos.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf != partial_icc_vdf_info.replace(
|
|
646
|
+
number_of_iterations=icc_iters
|
|
647
|
+
):
|
|
648
|
+
return None
|
|
649
|
+
if not eos.proofs.infused_challenge_chain_slot_proof.normalized_to_identity and not validate_vdf(
|
|
650
|
+
eos.proofs.infused_challenge_chain_slot_proof, self.constants, icc_start_element, partial_icc_vdf_info
|
|
651
|
+
):
|
|
652
|
+
return None
|
|
653
|
+
if eos.proofs.infused_challenge_chain_slot_proof.normalized_to_identity and not validate_vdf(
|
|
654
|
+
eos.proofs.infused_challenge_chain_slot_proof,
|
|
655
|
+
self.constants,
|
|
656
|
+
ClassgroupElement.get_default_element(),
|
|
657
|
+
eos.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf,
|
|
658
|
+
):
|
|
659
|
+
return None
|
|
660
|
+
else:
|
|
661
|
+
# This is the first sub slot and it's empty, therefore there is no ICC
|
|
662
|
+
if eos.infused_challenge_chain is not None or eos.proofs.infused_challenge_chain_slot_proof is not None:
|
|
663
|
+
return None
|
|
664
|
+
if eos.challenge_chain.infused_challenge_chain_sub_slot_hash is not None:
|
|
665
|
+
return None
|
|
666
|
+
if eos.reward_chain.infused_challenge_chain_sub_slot_hash is not None:
|
|
667
|
+
return None
|
|
668
|
+
|
|
669
|
+
self.finished_sub_slots.append((eos, [None] * self.constants.NUM_SPS_SUB_SLOT, total_iters))
|
|
670
|
+
|
|
671
|
+
new_cc_hash = eos.challenge_chain.get_hash()
|
|
672
|
+
self.recent_eos.put(new_cc_hash, (eos, time.time()))
|
|
673
|
+
|
|
674
|
+
new_ips: list[timelord_protocol.NewInfusionPointVDF] = []
|
|
675
|
+
for ip in self.future_ip_cache.get(eos.reward_chain.get_hash(), []):
|
|
676
|
+
new_ips.append(ip)
|
|
677
|
+
|
|
678
|
+
return new_ips
|
|
679
|
+
|
|
680
|
+
def new_signage_point(
|
|
681
|
+
self,
|
|
682
|
+
index: uint8,
|
|
683
|
+
blocks: BlockRecordsProtocol,
|
|
684
|
+
peak: Optional[BlockRecord],
|
|
685
|
+
next_sub_slot_iters: uint64,
|
|
686
|
+
signage_point: SignagePoint,
|
|
687
|
+
skip_vdf_validation: bool = False,
|
|
688
|
+
) -> bool:
|
|
689
|
+
"""
|
|
690
|
+
Returns true if sp successfully added
|
|
691
|
+
"""
|
|
692
|
+
assert len(self.finished_sub_slots) >= 1
|
|
693
|
+
|
|
694
|
+
if peak is None or peak.height < 2:
|
|
695
|
+
sub_slot_iters = self.constants.SUB_SLOT_ITERS_STARTING
|
|
696
|
+
else:
|
|
697
|
+
sub_slot_iters = peak.sub_slot_iters
|
|
698
|
+
|
|
699
|
+
# If we don't have this slot, return False
|
|
700
|
+
if index == 0 or index >= self.constants.NUM_SPS_SUB_SLOT:
|
|
701
|
+
return False
|
|
702
|
+
assert (
|
|
703
|
+
signage_point.cc_vdf is not None
|
|
704
|
+
and signage_point.cc_proof is not None
|
|
705
|
+
and signage_point.rc_vdf is not None
|
|
706
|
+
and signage_point.rc_proof is not None
|
|
707
|
+
)
|
|
708
|
+
for sub_slot, sp_arr, start_ss_total_iters in self.finished_sub_slots:
|
|
709
|
+
if sub_slot is None:
|
|
710
|
+
assert start_ss_total_iters == 0
|
|
711
|
+
ss_challenge_hash = self.constants.GENESIS_CHALLENGE
|
|
712
|
+
ss_reward_hash = self.constants.GENESIS_CHALLENGE
|
|
713
|
+
else:
|
|
714
|
+
ss_challenge_hash = sub_slot.challenge_chain.get_hash()
|
|
715
|
+
ss_reward_hash = sub_slot.reward_chain.get_hash()
|
|
716
|
+
if ss_challenge_hash == signage_point.cc_vdf.challenge:
|
|
717
|
+
# If we do have this slot, find the Prev block from SP and validate SP
|
|
718
|
+
if peak is not None and start_ss_total_iters > peak.total_iters:
|
|
719
|
+
# We are in a future sub slot from the peak, so maybe there is a new SSI
|
|
720
|
+
checkpoint_size: uint64 = uint64(next_sub_slot_iters // self.constants.NUM_SPS_SUB_SLOT)
|
|
721
|
+
delta_iters: uint64 = uint64(checkpoint_size * index)
|
|
722
|
+
future_sub_slot: bool = True
|
|
723
|
+
else:
|
|
724
|
+
# We are not in a future sub slot from the peak, so there is no new SSI
|
|
725
|
+
checkpoint_size = uint64(sub_slot_iters // self.constants.NUM_SPS_SUB_SLOT)
|
|
726
|
+
delta_iters = uint64(checkpoint_size * index)
|
|
727
|
+
future_sub_slot = False
|
|
728
|
+
sp_total_iters = start_ss_total_iters + delta_iters
|
|
729
|
+
|
|
730
|
+
curr = peak
|
|
731
|
+
if peak is None or future_sub_slot:
|
|
732
|
+
check_from_start_of_ss = True
|
|
733
|
+
else:
|
|
734
|
+
check_from_start_of_ss = False
|
|
735
|
+
while (
|
|
736
|
+
curr is not None
|
|
737
|
+
and curr.total_iters > start_ss_total_iters
|
|
738
|
+
and curr.total_iters > sp_total_iters
|
|
739
|
+
):
|
|
740
|
+
if curr.first_in_sub_slot:
|
|
741
|
+
# Did not find a block where it's iters are before our sp_total_iters, in this ss
|
|
742
|
+
check_from_start_of_ss = True
|
|
743
|
+
break
|
|
744
|
+
curr = blocks.block_record(curr.prev_hash)
|
|
745
|
+
|
|
746
|
+
if check_from_start_of_ss:
|
|
747
|
+
# Check VDFs from start of sub slot
|
|
748
|
+
cc_vdf_info_expected = VDFInfo(
|
|
749
|
+
ss_challenge_hash,
|
|
750
|
+
delta_iters,
|
|
751
|
+
signage_point.cc_vdf.output,
|
|
752
|
+
)
|
|
753
|
+
|
|
754
|
+
rc_vdf_info_expected = VDFInfo(
|
|
755
|
+
ss_reward_hash,
|
|
756
|
+
delta_iters,
|
|
757
|
+
signage_point.rc_vdf.output,
|
|
758
|
+
)
|
|
759
|
+
else:
|
|
760
|
+
# Check VDFs from curr
|
|
761
|
+
assert curr is not None
|
|
762
|
+
cc_vdf_info_expected = VDFInfo(
|
|
763
|
+
ss_challenge_hash,
|
|
764
|
+
uint64(sp_total_iters - curr.total_iters),
|
|
765
|
+
signage_point.cc_vdf.output,
|
|
766
|
+
)
|
|
767
|
+
rc_vdf_info_expected = VDFInfo(
|
|
768
|
+
curr.reward_infusion_new_challenge,
|
|
769
|
+
uint64(sp_total_iters - curr.total_iters),
|
|
770
|
+
signage_point.rc_vdf.output,
|
|
771
|
+
)
|
|
772
|
+
if not signage_point.cc_vdf == cc_vdf_info_expected.replace(number_of_iterations=delta_iters):
|
|
773
|
+
self.add_to_future_sp(signage_point, index)
|
|
774
|
+
return False
|
|
775
|
+
if check_from_start_of_ss:
|
|
776
|
+
start_ele = ClassgroupElement.get_default_element()
|
|
777
|
+
else:
|
|
778
|
+
assert curr is not None
|
|
779
|
+
start_ele = curr.challenge_vdf_output
|
|
780
|
+
if not skip_vdf_validation:
|
|
781
|
+
if not signage_point.cc_proof.normalized_to_identity and not validate_vdf(
|
|
782
|
+
signage_point.cc_proof,
|
|
783
|
+
self.constants,
|
|
784
|
+
start_ele,
|
|
785
|
+
cc_vdf_info_expected,
|
|
786
|
+
):
|
|
787
|
+
self.add_to_future_sp(signage_point, index)
|
|
788
|
+
return False
|
|
789
|
+
if signage_point.cc_proof.normalized_to_identity and not validate_vdf(
|
|
790
|
+
signage_point.cc_proof,
|
|
791
|
+
self.constants,
|
|
792
|
+
ClassgroupElement.get_default_element(),
|
|
793
|
+
signage_point.cc_vdf,
|
|
794
|
+
):
|
|
795
|
+
self.add_to_future_sp(signage_point, index)
|
|
796
|
+
return False
|
|
797
|
+
|
|
798
|
+
if rc_vdf_info_expected.challenge != signage_point.rc_vdf.challenge:
|
|
799
|
+
# This signage point is probably outdated
|
|
800
|
+
self.add_to_future_sp(signage_point, index)
|
|
801
|
+
return False
|
|
802
|
+
|
|
803
|
+
if not skip_vdf_validation:
|
|
804
|
+
if not validate_vdf(
|
|
805
|
+
signage_point.rc_proof,
|
|
806
|
+
self.constants,
|
|
807
|
+
ClassgroupElement.get_default_element(),
|
|
808
|
+
signage_point.rc_vdf,
|
|
809
|
+
rc_vdf_info_expected,
|
|
810
|
+
):
|
|
811
|
+
self.add_to_future_sp(signage_point, index)
|
|
812
|
+
return False
|
|
813
|
+
|
|
814
|
+
sp_arr[index] = signage_point
|
|
815
|
+
self.recent_signage_points.put(signage_point.cc_vdf.output.get_hash(), (signage_point, time.time()))
|
|
816
|
+
return True
|
|
817
|
+
self.add_to_future_sp(signage_point, index)
|
|
818
|
+
return False
|
|
819
|
+
|
|
820
|
+
def get_signage_point(self, cc_signage_point: bytes32) -> Optional[SignagePoint]:
|
|
821
|
+
assert len(self.finished_sub_slots) >= 1
|
|
822
|
+
if cc_signage_point == self.constants.GENESIS_CHALLENGE:
|
|
823
|
+
return SignagePoint(None, None, None, None)
|
|
824
|
+
|
|
825
|
+
for sub_slot, sps, _ in self.finished_sub_slots:
|
|
826
|
+
if sub_slot is not None and sub_slot.challenge_chain.get_hash() == cc_signage_point:
|
|
827
|
+
return SignagePoint(None, None, None, None)
|
|
828
|
+
for sp in sps:
|
|
829
|
+
if sp is not None:
|
|
830
|
+
assert sp.cc_vdf is not None
|
|
831
|
+
if sp.cc_vdf.output.get_hash() == cc_signage_point:
|
|
832
|
+
return sp
|
|
833
|
+
return None
|
|
834
|
+
|
|
835
|
+
def get_signage_point_by_index(
|
|
836
|
+
self, challenge_hash: bytes32, index: uint8, last_rc_infusion: bytes32
|
|
837
|
+
) -> Optional[SignagePoint]:
|
|
838
|
+
assert len(self.finished_sub_slots) >= 1
|
|
839
|
+
for sub_slot, sps, _ in self.finished_sub_slots:
|
|
840
|
+
if sub_slot is not None:
|
|
841
|
+
cc_hash = sub_slot.challenge_chain.get_hash()
|
|
842
|
+
else:
|
|
843
|
+
cc_hash = self.constants.GENESIS_CHALLENGE
|
|
844
|
+
|
|
845
|
+
if cc_hash == challenge_hash:
|
|
846
|
+
if index == 0:
|
|
847
|
+
return SignagePoint(None, None, None, None)
|
|
848
|
+
sp: Optional[SignagePoint] = sps[index]
|
|
849
|
+
if sp is not None:
|
|
850
|
+
assert sp.rc_vdf is not None
|
|
851
|
+
if sp.rc_vdf.challenge == last_rc_infusion:
|
|
852
|
+
return sp
|
|
853
|
+
return None
|
|
854
|
+
return None
|
|
855
|
+
|
|
856
|
+
def have_newer_signage_point(self, challenge_hash: bytes32, index: uint8, last_rc_infusion: bytes32) -> bool:
|
|
857
|
+
"""
|
|
858
|
+
Returns true if we have a signage point at this index which is based on a newer infusion.
|
|
859
|
+
"""
|
|
860
|
+
assert len(self.finished_sub_slots) >= 1
|
|
861
|
+
for sub_slot, sps, _ in self.finished_sub_slots:
|
|
862
|
+
if sub_slot is not None:
|
|
863
|
+
cc_hash = sub_slot.challenge_chain.get_hash()
|
|
864
|
+
else:
|
|
865
|
+
cc_hash = self.constants.GENESIS_CHALLENGE
|
|
866
|
+
|
|
867
|
+
if cc_hash == challenge_hash:
|
|
868
|
+
found_rc_hash = False
|
|
869
|
+
for i in range(0, index):
|
|
870
|
+
sp: Optional[SignagePoint] = sps[i]
|
|
871
|
+
if sp is not None and sp.rc_vdf is not None and sp.rc_vdf.challenge == last_rc_infusion:
|
|
872
|
+
found_rc_hash = True
|
|
873
|
+
sp = sps[index]
|
|
874
|
+
if (
|
|
875
|
+
found_rc_hash
|
|
876
|
+
and sp is not None
|
|
877
|
+
and sp.rc_vdf is not None
|
|
878
|
+
and sp.rc_vdf.challenge != last_rc_infusion
|
|
879
|
+
):
|
|
880
|
+
return True
|
|
881
|
+
return False
|
|
882
|
+
|
|
883
|
+
def new_peak(
|
|
884
|
+
self,
|
|
885
|
+
peak: BlockRecord,
|
|
886
|
+
peak_full_block: FullBlock,
|
|
887
|
+
sp_sub_slot: Optional[EndOfSubSlotBundle], # None if not overflow, or in first/second slot
|
|
888
|
+
ip_sub_slot: Optional[EndOfSubSlotBundle], # None if in first slot
|
|
889
|
+
fork_block: Optional[BlockRecord],
|
|
890
|
+
blocks: BlockRecordsProtocol,
|
|
891
|
+
next_sub_slot_iters: uint64,
|
|
892
|
+
next_difficulty: uint64,
|
|
893
|
+
) -> FullNodeStorePeakResult:
|
|
894
|
+
"""
|
|
895
|
+
If the peak is an overflow block, must provide two sub-slots: one for the current sub-slot and one for
|
|
896
|
+
the prev sub-slot (since we still might get more blocks with an sp in the previous sub-slot)
|
|
897
|
+
|
|
898
|
+
Results in either one or two sub-slots in finished_sub_slots.
|
|
899
|
+
"""
|
|
900
|
+
assert len(self.finished_sub_slots) >= 1
|
|
901
|
+
|
|
902
|
+
if ip_sub_slot is None:
|
|
903
|
+
# We are still in the first sub-slot, no new sub slots ey
|
|
904
|
+
self.initialize_genesis_sub_slot()
|
|
905
|
+
else:
|
|
906
|
+
# This is not the first sub-slot in the chain
|
|
907
|
+
sp_sub_slot_sps: list[Optional[SignagePoint]] = [None] * self.constants.NUM_SPS_SUB_SLOT
|
|
908
|
+
ip_sub_slot_sps: list[Optional[SignagePoint]] = [None] * self.constants.NUM_SPS_SUB_SLOT
|
|
909
|
+
|
|
910
|
+
if fork_block is not None and fork_block.sub_slot_iters != peak.sub_slot_iters:
|
|
911
|
+
# If there was a reorg and a difficulty adjustment, just clear all the slots
|
|
912
|
+
self.clear_slots()
|
|
913
|
+
else:
|
|
914
|
+
interval_iters = calculate_sp_interval_iters(self.constants, peak.sub_slot_iters)
|
|
915
|
+
# If it's not a reorg, or there is a reorg on the same difficulty, we can keep signage points
|
|
916
|
+
# that we had before, in the cache
|
|
917
|
+
for index, (sub_slot, sps, total_iters) in enumerate(self.finished_sub_slots):
|
|
918
|
+
if sub_slot is None:
|
|
919
|
+
continue
|
|
920
|
+
|
|
921
|
+
if fork_block is None:
|
|
922
|
+
# If this is not a reorg, we still want to remove signage points after the new peak
|
|
923
|
+
fork_block = peak
|
|
924
|
+
replaced_sps: list[Optional[SignagePoint]] = [] # index 0 is the end of sub slot
|
|
925
|
+
for i, sp in enumerate(sps):
|
|
926
|
+
if (total_iters + i * interval_iters) < fork_block.total_iters:
|
|
927
|
+
# Sps before the fork point as still valid
|
|
928
|
+
replaced_sps.append(sp)
|
|
929
|
+
else:
|
|
930
|
+
if sp is not None:
|
|
931
|
+
log.debug(
|
|
932
|
+
f"Reverting {i} {(total_iters + i * interval_iters)} {fork_block.total_iters}"
|
|
933
|
+
)
|
|
934
|
+
# Sps after the fork point should be removed
|
|
935
|
+
replaced_sps.append(None)
|
|
936
|
+
assert len(sps) == len(replaced_sps)
|
|
937
|
+
|
|
938
|
+
if sub_slot == sp_sub_slot:
|
|
939
|
+
sp_sub_slot_sps = replaced_sps
|
|
940
|
+
if sub_slot == ip_sub_slot:
|
|
941
|
+
ip_sub_slot_sps = replaced_sps
|
|
942
|
+
|
|
943
|
+
self.clear_slots()
|
|
944
|
+
|
|
945
|
+
prev_sub_slot_total_iters = peak.sp_sub_slot_total_iters(self.constants)
|
|
946
|
+
if sp_sub_slot is not None or prev_sub_slot_total_iters == 0:
|
|
947
|
+
assert peak.overflow or prev_sub_slot_total_iters
|
|
948
|
+
self.finished_sub_slots.append((sp_sub_slot, sp_sub_slot_sps, prev_sub_slot_total_iters))
|
|
949
|
+
|
|
950
|
+
ip_sub_slot_total_iters = peak.ip_sub_slot_total_iters(self.constants)
|
|
951
|
+
self.finished_sub_slots.append((ip_sub_slot, ip_sub_slot_sps, ip_sub_slot_total_iters))
|
|
952
|
+
|
|
953
|
+
new_eos: Optional[EndOfSubSlotBundle] = None
|
|
954
|
+
new_sps: list[tuple[uint8, SignagePoint]] = []
|
|
955
|
+
new_ips: list[timelord_protocol.NewInfusionPointVDF] = []
|
|
956
|
+
|
|
957
|
+
future_eos: list[EndOfSubSlotBundle] = self.future_eos_cache.get(peak.reward_infusion_new_challenge, []).copy()
|
|
958
|
+
for eos in future_eos:
|
|
959
|
+
if (
|
|
960
|
+
self.new_finished_sub_slot(eos, blocks, peak, next_sub_slot_iters, next_difficulty, peak_full_block)
|
|
961
|
+
is not None
|
|
962
|
+
):
|
|
963
|
+
new_eos = eos
|
|
964
|
+
break
|
|
965
|
+
|
|
966
|
+
future_sps: list[tuple[uint8, SignagePoint]] = self.future_sp_cache.get(
|
|
967
|
+
peak.reward_infusion_new_challenge, []
|
|
968
|
+
).copy()
|
|
969
|
+
for index, sp in future_sps:
|
|
970
|
+
assert sp.cc_vdf is not None
|
|
971
|
+
if self.new_signage_point(index, blocks, peak, peak.sub_slot_iters, sp):
|
|
972
|
+
new_sps.append((index, sp))
|
|
973
|
+
|
|
974
|
+
for ip in self.future_ip_cache.get(peak.reward_infusion_new_challenge, []):
|
|
975
|
+
new_ips.append(ip)
|
|
976
|
+
|
|
977
|
+
self.future_eos_cache.pop(peak.reward_infusion_new_challenge, [])
|
|
978
|
+
self.future_sp_cache.pop(peak.reward_infusion_new_challenge, [])
|
|
979
|
+
self.future_ip_cache.pop(peak.reward_infusion_new_challenge, [])
|
|
980
|
+
|
|
981
|
+
for eos_op, _, _ in self.finished_sub_slots:
|
|
982
|
+
if eos_op is not None:
|
|
983
|
+
self.recent_eos.put(eos_op.challenge_chain.get_hash(), (eos_op, time.time()))
|
|
984
|
+
|
|
985
|
+
# Only forward the last 4 SPs that we have cached, as others will be too old
|
|
986
|
+
return FullNodeStorePeakResult(new_eos, sorted(new_sps)[-4:], new_ips)
|
|
987
|
+
|
|
988
|
+
def get_finished_sub_slots(
|
|
989
|
+
self,
|
|
990
|
+
block_records: BlockRecordsProtocol,
|
|
991
|
+
prev_b: Optional[BlockRecord],
|
|
992
|
+
last_challenge_to_add: bytes32,
|
|
993
|
+
) -> Optional[list[EndOfSubSlotBundle]]:
|
|
994
|
+
"""
|
|
995
|
+
Retrieves the EndOfSubSlotBundles that are in the store either:
|
|
996
|
+
1. From the starting challenge if prev_b is None
|
|
997
|
+
2. That are not included in the blockchain with peak of prev_b if prev_b is not None
|
|
998
|
+
|
|
999
|
+
Stops at last_challenge
|
|
1000
|
+
"""
|
|
1001
|
+
|
|
1002
|
+
if prev_b is None:
|
|
1003
|
+
# The first sub slot must be None
|
|
1004
|
+
assert self.finished_sub_slots[0][0] is None
|
|
1005
|
+
challenge_in_chain: bytes32 = self.constants.GENESIS_CHALLENGE
|
|
1006
|
+
else:
|
|
1007
|
+
curr: BlockRecord = prev_b
|
|
1008
|
+
while not curr.first_in_sub_slot:
|
|
1009
|
+
curr = block_records.block_record(curr.prev_hash)
|
|
1010
|
+
assert curr is not None
|
|
1011
|
+
assert curr.finished_challenge_slot_hashes is not None
|
|
1012
|
+
challenge_in_chain = curr.finished_challenge_slot_hashes[-1]
|
|
1013
|
+
|
|
1014
|
+
if last_challenge_to_add == challenge_in_chain:
|
|
1015
|
+
# No additional slots to add
|
|
1016
|
+
return []
|
|
1017
|
+
|
|
1018
|
+
collected_sub_slots: list[EndOfSubSlotBundle] = []
|
|
1019
|
+
found_last_challenge = False
|
|
1020
|
+
found_connecting_challenge = False
|
|
1021
|
+
for sub_slot, sps, total_iters in self.finished_sub_slots[1:]:
|
|
1022
|
+
assert sub_slot is not None
|
|
1023
|
+
if sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.challenge == challenge_in_chain:
|
|
1024
|
+
found_connecting_challenge = True
|
|
1025
|
+
if found_connecting_challenge:
|
|
1026
|
+
collected_sub_slots.append(sub_slot)
|
|
1027
|
+
if found_connecting_challenge and sub_slot.challenge_chain.get_hash() == last_challenge_to_add:
|
|
1028
|
+
found_last_challenge = True
|
|
1029
|
+
break
|
|
1030
|
+
if not found_last_challenge:
|
|
1031
|
+
log.warning(f"Did not find hash {last_challenge_to_add} connected to {challenge_in_chain}")
|
|
1032
|
+
return None
|
|
1033
|
+
return collected_sub_slots
|