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,1720 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import math
|
|
6
|
+
import pathlib
|
|
7
|
+
import random
|
|
8
|
+
import tempfile
|
|
9
|
+
from concurrent.futures.process import ProcessPoolExecutor
|
|
10
|
+
from multiprocessing.context import BaseContext
|
|
11
|
+
from typing import IO, Optional
|
|
12
|
+
|
|
13
|
+
from chia.consensus.block_header_validation import validate_finished_header_block
|
|
14
|
+
from chia.consensus.block_record import BlockRecord
|
|
15
|
+
from chia.consensus.blockchain_interface import BlockchainInterface
|
|
16
|
+
from chia.consensus.constants import ConsensusConstants
|
|
17
|
+
from chia.consensus.deficit import calculate_deficit
|
|
18
|
+
from chia.consensus.full_block_to_block_record import header_block_to_sub_block_record
|
|
19
|
+
from chia.consensus.pot_iterations import (
|
|
20
|
+
calculate_ip_iters,
|
|
21
|
+
calculate_iterations_quality,
|
|
22
|
+
calculate_sp_iters,
|
|
23
|
+
is_overflow_block,
|
|
24
|
+
)
|
|
25
|
+
from chia.consensus.vdf_info_computation import get_signage_point_vdf_info
|
|
26
|
+
from chia.types.blockchain_format.classgroup import ClassgroupElement
|
|
27
|
+
from chia.types.blockchain_format.proof_of_space import verify_and_get_quality_string
|
|
28
|
+
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
29
|
+
from chia.types.blockchain_format.slots import ChallengeChainSubSlot, RewardChainSubSlot
|
|
30
|
+
from chia.types.blockchain_format.sub_epoch_summary import SubEpochSummary
|
|
31
|
+
from chia.types.blockchain_format.vdf import VDFInfo, VDFProof, validate_vdf
|
|
32
|
+
from chia.types.end_of_slot_bundle import EndOfSubSlotBundle
|
|
33
|
+
from chia.types.header_block import HeaderBlock
|
|
34
|
+
from chia.types.validation_state import ValidationState
|
|
35
|
+
from chia.types.weight_proof import (
|
|
36
|
+
RecentChainData,
|
|
37
|
+
SubEpochChallengeSegment,
|
|
38
|
+
SubEpochData,
|
|
39
|
+
SubEpochSegments,
|
|
40
|
+
SubSlotData,
|
|
41
|
+
WeightProof,
|
|
42
|
+
)
|
|
43
|
+
from chia.util.batches import to_batches
|
|
44
|
+
from chia.util.block_cache import BlockCache
|
|
45
|
+
from chia.util.hash import std_hash
|
|
46
|
+
from chia.util.ints import uint8, uint32, uint64, uint128
|
|
47
|
+
from chia.util.setproctitle import getproctitle, setproctitle
|
|
48
|
+
from chia.util.task_referencer import create_referenced_task
|
|
49
|
+
|
|
50
|
+
log = logging.getLogger(__name__)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _create_shutdown_file() -> IO[bytes]:
|
|
54
|
+
return tempfile.NamedTemporaryFile(prefix="chia_full_node_weight_proof_handler_executor_shutdown_trigger")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class WeightProofHandler:
|
|
58
|
+
LAMBDA_L = 100
|
|
59
|
+
C = 0.5
|
|
60
|
+
MAX_SAMPLES = 20
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
constants: ConsensusConstants,
|
|
65
|
+
blockchain: BlockchainInterface,
|
|
66
|
+
multiprocessing_context: Optional[BaseContext] = None,
|
|
67
|
+
):
|
|
68
|
+
self.tip: Optional[bytes32] = None
|
|
69
|
+
self.proof: Optional[WeightProof] = None
|
|
70
|
+
self.constants = constants
|
|
71
|
+
self.blockchain = blockchain
|
|
72
|
+
self.lock = asyncio.Lock()
|
|
73
|
+
self._num_processes = 4
|
|
74
|
+
self.multiprocessing_context = multiprocessing_context
|
|
75
|
+
|
|
76
|
+
async def get_proof_of_weight(self, tip: bytes32) -> Optional[WeightProof]:
|
|
77
|
+
tip_rec = self.blockchain.try_block_record(tip)
|
|
78
|
+
if tip_rec is None:
|
|
79
|
+
log.error("unknown tip")
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
if tip_rec.height < self.constants.WEIGHT_PROOF_RECENT_BLOCKS:
|
|
83
|
+
log.debug("chain to short for weight proof")
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
async with self.lock:
|
|
87
|
+
if self.proof is not None:
|
|
88
|
+
if self.proof.recent_chain_data[-1].header_hash == tip:
|
|
89
|
+
return self.proof
|
|
90
|
+
wp = await self._create_proof_of_weight(tip)
|
|
91
|
+
if wp is None:
|
|
92
|
+
return None
|
|
93
|
+
self.proof = wp
|
|
94
|
+
self.tip = tip
|
|
95
|
+
return wp
|
|
96
|
+
|
|
97
|
+
def get_sub_epoch_data(self, tip_height: uint32, summary_heights: list[uint32]) -> list[SubEpochData]:
|
|
98
|
+
sub_epoch_data: list[SubEpochData] = []
|
|
99
|
+
for sub_epoch_n, ses_height in enumerate(summary_heights):
|
|
100
|
+
if ses_height > tip_height:
|
|
101
|
+
break
|
|
102
|
+
ses = self.blockchain.get_ses(ses_height)
|
|
103
|
+
log.debug("handle sub epoch summary %s at height: %s ses %s", sub_epoch_n, ses_height, ses)
|
|
104
|
+
sub_epoch_data.append(_create_sub_epoch_data(ses))
|
|
105
|
+
return sub_epoch_data
|
|
106
|
+
|
|
107
|
+
async def _create_proof_of_weight(self, tip: bytes32) -> Optional[WeightProof]:
|
|
108
|
+
"""
|
|
109
|
+
Creates a weight proof object
|
|
110
|
+
"""
|
|
111
|
+
assert self.blockchain is not None
|
|
112
|
+
sub_epoch_segments: list[SubEpochChallengeSegment] = []
|
|
113
|
+
tip_rec = self.blockchain.try_block_record(tip)
|
|
114
|
+
if tip_rec is None:
|
|
115
|
+
log.error("failed not tip in cache")
|
|
116
|
+
return None
|
|
117
|
+
log.info(f"create weight proof peak {tip} {tip_rec.height}")
|
|
118
|
+
recent_chain = await self._get_recent_chain(tip_rec.height)
|
|
119
|
+
if recent_chain is None:
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
summary_heights = self.blockchain.get_ses_heights()
|
|
123
|
+
zero_hash = self.blockchain.height_to_hash(uint32(0))
|
|
124
|
+
assert zero_hash is not None
|
|
125
|
+
prev_ses_block = await self.blockchain.get_block_record_from_db(zero_hash)
|
|
126
|
+
if prev_ses_block is None:
|
|
127
|
+
return None
|
|
128
|
+
sub_epoch_data = self.get_sub_epoch_data(tip_rec.height, summary_heights)
|
|
129
|
+
# use second to last ses as seed
|
|
130
|
+
seed = self.get_seed_for_proof(summary_heights, tip_rec.height)
|
|
131
|
+
rng = random.Random(seed)
|
|
132
|
+
weight_to_check = _get_weights_for_sampling(rng, tip_rec.weight, recent_chain)
|
|
133
|
+
sample_n = 0
|
|
134
|
+
ses_blocks = await self.blockchain.get_block_records_at(summary_heights)
|
|
135
|
+
if ses_blocks is None:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
for sub_epoch_n, ses_height in enumerate(summary_heights):
|
|
139
|
+
if ses_height > tip_rec.height:
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
# if we have enough sub_epoch samples, dont sample
|
|
143
|
+
if sample_n >= self.MAX_SAMPLES:
|
|
144
|
+
log.debug("reached sampled sub epoch cap")
|
|
145
|
+
break
|
|
146
|
+
# sample sub epoch
|
|
147
|
+
# next sub block
|
|
148
|
+
ses_block = ses_blocks[sub_epoch_n]
|
|
149
|
+
if ses_block is None or ses_block.sub_epoch_summary_included is None:
|
|
150
|
+
log.error("error while building proof")
|
|
151
|
+
return None
|
|
152
|
+
|
|
153
|
+
if _sample_sub_epoch(prev_ses_block.weight, ses_block.weight, weight_to_check):
|
|
154
|
+
sample_n += 1
|
|
155
|
+
segments = await self.blockchain.get_sub_epoch_challenge_segments(ses_block.header_hash)
|
|
156
|
+
if segments is None:
|
|
157
|
+
segments = await self.__create_sub_epoch_segments(ses_block, prev_ses_block, uint32(sub_epoch_n))
|
|
158
|
+
if segments is None:
|
|
159
|
+
log.error(
|
|
160
|
+
f"failed while building segments for sub epoch {sub_epoch_n}, ses height {ses_height} "
|
|
161
|
+
)
|
|
162
|
+
return None
|
|
163
|
+
await self.blockchain.persist_sub_epoch_challenge_segments(ses_block.header_hash, segments)
|
|
164
|
+
sub_epoch_segments.extend(segments)
|
|
165
|
+
prev_ses_block = ses_block
|
|
166
|
+
log.debug(f"sub_epochs: {len(sub_epoch_data)}")
|
|
167
|
+
return WeightProof(sub_epoch_data, sub_epoch_segments, recent_chain)
|
|
168
|
+
|
|
169
|
+
def get_seed_for_proof(self, summary_heights: list[uint32], tip_height: uint32) -> bytes32:
|
|
170
|
+
count = 0
|
|
171
|
+
ses = None
|
|
172
|
+
for sub_epoch_n, ses_height in enumerate(reversed(summary_heights)):
|
|
173
|
+
if ses_height <= tip_height:
|
|
174
|
+
count += 1
|
|
175
|
+
if count == 2:
|
|
176
|
+
ses = self.blockchain.get_ses(ses_height)
|
|
177
|
+
break
|
|
178
|
+
assert ses is not None
|
|
179
|
+
seed = ses.get_hash()
|
|
180
|
+
return seed
|
|
181
|
+
|
|
182
|
+
async def _get_recent_chain(self, tip_height: uint32) -> Optional[list[HeaderBlock]]:
|
|
183
|
+
recent_chain: list[HeaderBlock] = []
|
|
184
|
+
ses_heights = self.blockchain.get_ses_heights()
|
|
185
|
+
min_height = 0
|
|
186
|
+
count_ses = 0
|
|
187
|
+
for ses_height in reversed(ses_heights):
|
|
188
|
+
if ses_height <= tip_height:
|
|
189
|
+
count_ses += 1
|
|
190
|
+
if count_ses == 2:
|
|
191
|
+
min_height = ses_height - 1
|
|
192
|
+
break
|
|
193
|
+
log.debug(f"start {min_height} end {tip_height}")
|
|
194
|
+
headers = await self.blockchain.get_header_blocks_in_range(min_height, tip_height, tx_filter=False)
|
|
195
|
+
blocks = await self.blockchain.get_block_records_in_range(min_height, tip_height)
|
|
196
|
+
ses_count = 0
|
|
197
|
+
curr_height = tip_height
|
|
198
|
+
blocks_n = 0
|
|
199
|
+
while ses_count < 2:
|
|
200
|
+
if curr_height == 0:
|
|
201
|
+
break
|
|
202
|
+
# add to needed reward chain recent blocks
|
|
203
|
+
header_hash = self.blockchain.height_to_hash(curr_height)
|
|
204
|
+
assert header_hash is not None
|
|
205
|
+
header_block = headers[header_hash]
|
|
206
|
+
block_rec = blocks[header_block.header_hash]
|
|
207
|
+
if header_block is None:
|
|
208
|
+
log.error("creating recent chain failed")
|
|
209
|
+
return None
|
|
210
|
+
recent_chain.insert(0, header_block)
|
|
211
|
+
if block_rec.sub_epoch_summary_included:
|
|
212
|
+
ses_count += 1
|
|
213
|
+
curr_height = uint32(curr_height - 1)
|
|
214
|
+
blocks_n += 1
|
|
215
|
+
|
|
216
|
+
header_hash = self.blockchain.height_to_hash(curr_height)
|
|
217
|
+
assert header_hash is not None
|
|
218
|
+
header_block = headers[header_hash]
|
|
219
|
+
recent_chain.insert(0, header_block)
|
|
220
|
+
|
|
221
|
+
log.info(
|
|
222
|
+
f"recent chain, "
|
|
223
|
+
f"start: {recent_chain[0].reward_chain_block.height} "
|
|
224
|
+
f"end: {recent_chain[-1].reward_chain_block.height} "
|
|
225
|
+
)
|
|
226
|
+
return recent_chain
|
|
227
|
+
|
|
228
|
+
async def create_prev_sub_epoch_segments(self) -> None:
|
|
229
|
+
log.debug("create prev sub_epoch_segments")
|
|
230
|
+
heights = self.blockchain.get_ses_heights()
|
|
231
|
+
if len(heights) < 3:
|
|
232
|
+
return None
|
|
233
|
+
count = len(heights) - 2
|
|
234
|
+
ses_sub_block = self.blockchain.height_to_block_record(heights[-2])
|
|
235
|
+
prev_ses_sub_block = self.blockchain.height_to_block_record(heights[-3])
|
|
236
|
+
assert prev_ses_sub_block.sub_epoch_summary_included is not None
|
|
237
|
+
segments = await self.__create_sub_epoch_segments(ses_sub_block, prev_ses_sub_block, uint32(count))
|
|
238
|
+
assert segments is not None
|
|
239
|
+
await self.blockchain.persist_sub_epoch_challenge_segments(ses_sub_block.header_hash, segments)
|
|
240
|
+
log.debug("sub_epoch_segments done")
|
|
241
|
+
return None
|
|
242
|
+
|
|
243
|
+
async def create_sub_epoch_segments(self) -> None:
|
|
244
|
+
log.debug("check segments in db")
|
|
245
|
+
"""
|
|
246
|
+
Creates a weight proof object
|
|
247
|
+
"""
|
|
248
|
+
assert self.blockchain is not None
|
|
249
|
+
peak_height = self.blockchain.get_peak_height()
|
|
250
|
+
if peak_height is None:
|
|
251
|
+
log.error("no peak yet")
|
|
252
|
+
return None
|
|
253
|
+
|
|
254
|
+
summary_heights = self.blockchain.get_ses_heights()
|
|
255
|
+
h_hash: Optional[bytes32] = self.blockchain.height_to_hash(uint32(0))
|
|
256
|
+
if h_hash is None:
|
|
257
|
+
return None
|
|
258
|
+
prev_ses_block: Optional[BlockRecord] = await self.blockchain.get_block_record_from_db(h_hash)
|
|
259
|
+
if prev_ses_block is None:
|
|
260
|
+
return None
|
|
261
|
+
|
|
262
|
+
ses_blocks = await self.blockchain.get_block_records_at(summary_heights)
|
|
263
|
+
if ses_blocks is None:
|
|
264
|
+
return None
|
|
265
|
+
|
|
266
|
+
for sub_epoch_n, ses_height in enumerate(summary_heights):
|
|
267
|
+
log.debug(f"check db for sub epoch {sub_epoch_n}")
|
|
268
|
+
if ses_height > peak_height:
|
|
269
|
+
break
|
|
270
|
+
ses_block = ses_blocks[sub_epoch_n]
|
|
271
|
+
if ses_block is None or ses_block.sub_epoch_summary_included is None:
|
|
272
|
+
log.error("error while building proof")
|
|
273
|
+
return None
|
|
274
|
+
await self.__create_persist_segment(prev_ses_block, ses_block, ses_height, sub_epoch_n)
|
|
275
|
+
prev_ses_block = ses_block
|
|
276
|
+
await asyncio.sleep(2)
|
|
277
|
+
log.debug("done checking segments")
|
|
278
|
+
return None
|
|
279
|
+
|
|
280
|
+
async def __create_persist_segment(
|
|
281
|
+
self, prev_ses_block: BlockRecord, ses_block: BlockRecord, ses_height: uint32, sub_epoch_n: int
|
|
282
|
+
) -> None:
|
|
283
|
+
segments = await self.blockchain.get_sub_epoch_challenge_segments(ses_block.header_hash)
|
|
284
|
+
if segments is None:
|
|
285
|
+
segments = await self.__create_sub_epoch_segments(ses_block, prev_ses_block, uint32(sub_epoch_n))
|
|
286
|
+
if segments is None:
|
|
287
|
+
log.error(f"failed while building segments for sub epoch {sub_epoch_n}, ses height {ses_height} ")
|
|
288
|
+
return None
|
|
289
|
+
await self.blockchain.persist_sub_epoch_challenge_segments(ses_block.header_hash, segments)
|
|
290
|
+
|
|
291
|
+
async def __create_sub_epoch_segments(
|
|
292
|
+
self, ses_block: BlockRecord, se_start: BlockRecord, sub_epoch_n: uint32
|
|
293
|
+
) -> Optional[list[SubEpochChallengeSegment]]:
|
|
294
|
+
segments: list[SubEpochChallengeSegment] = []
|
|
295
|
+
start_height = await self.get_prev_two_slots_height(se_start)
|
|
296
|
+
|
|
297
|
+
blocks = await self.blockchain.get_block_records_in_range(
|
|
298
|
+
start_height, ses_block.height + self.constants.MAX_SUB_SLOT_BLOCKS
|
|
299
|
+
)
|
|
300
|
+
header_blocks = await self.blockchain.get_header_blocks_in_range(
|
|
301
|
+
start_height, ses_block.height + self.constants.MAX_SUB_SLOT_BLOCKS, tx_filter=False
|
|
302
|
+
)
|
|
303
|
+
curr: Optional[HeaderBlock] = header_blocks[se_start.header_hash]
|
|
304
|
+
height = se_start.height
|
|
305
|
+
assert curr is not None
|
|
306
|
+
first = True
|
|
307
|
+
idx = 0
|
|
308
|
+
while curr.height < ses_block.height:
|
|
309
|
+
if blocks[curr.header_hash].is_challenge_block(self.constants):
|
|
310
|
+
log.debug(f"challenge segment {idx}, starts at {curr.height} ")
|
|
311
|
+
seg, height = await self._create_challenge_segment(curr, sub_epoch_n, header_blocks, blocks, first)
|
|
312
|
+
if seg is None:
|
|
313
|
+
log.error(f"failed creating segment {curr.header_hash} ")
|
|
314
|
+
return None
|
|
315
|
+
segments.append(seg)
|
|
316
|
+
idx += 1
|
|
317
|
+
first = False
|
|
318
|
+
else:
|
|
319
|
+
height = uint32(height + 1)
|
|
320
|
+
header_hash = self.blockchain.height_to_hash(height)
|
|
321
|
+
assert header_hash is not None
|
|
322
|
+
curr = header_blocks[header_hash]
|
|
323
|
+
if curr is None:
|
|
324
|
+
return None
|
|
325
|
+
log.debug(f"next sub epoch starts at {height}")
|
|
326
|
+
return segments
|
|
327
|
+
|
|
328
|
+
async def get_prev_two_slots_height(self, se_start: BlockRecord) -> uint32:
|
|
329
|
+
# find prev 2 slots height
|
|
330
|
+
slot = 0
|
|
331
|
+
batch_size = 50
|
|
332
|
+
curr_rec = se_start
|
|
333
|
+
blocks = await self.blockchain.get_block_records_in_range(curr_rec.height - batch_size, curr_rec.height)
|
|
334
|
+
end = curr_rec.height
|
|
335
|
+
while slot < 2 and curr_rec.height > 0:
|
|
336
|
+
if curr_rec.first_in_sub_slot:
|
|
337
|
+
slot += 1
|
|
338
|
+
if end - curr_rec.height == batch_size - 1:
|
|
339
|
+
blocks = await self.blockchain.get_block_records_in_range(curr_rec.height - batch_size, curr_rec.height)
|
|
340
|
+
end = curr_rec.height
|
|
341
|
+
header_hash = self.blockchain.height_to_hash(uint32(curr_rec.height - 1))
|
|
342
|
+
assert header_hash is not None
|
|
343
|
+
curr_rec = blocks[header_hash]
|
|
344
|
+
return curr_rec.height
|
|
345
|
+
|
|
346
|
+
async def _create_challenge_segment(
|
|
347
|
+
self,
|
|
348
|
+
header_block: HeaderBlock,
|
|
349
|
+
sub_epoch_n: uint32,
|
|
350
|
+
header_blocks: dict[bytes32, HeaderBlock],
|
|
351
|
+
blocks: dict[bytes32, BlockRecord],
|
|
352
|
+
first_segment_in_sub_epoch: bool,
|
|
353
|
+
) -> tuple[Optional[SubEpochChallengeSegment], uint32]:
|
|
354
|
+
assert self.blockchain is not None
|
|
355
|
+
sub_slots: list[SubSlotData] = []
|
|
356
|
+
log.debug(f"create challenge segment block {header_block.header_hash} block height {header_block.height} ")
|
|
357
|
+
# VDFs from sub slots before challenge block
|
|
358
|
+
first_sub_slots, first_rc_end_of_slot_vdf = await self.__first_sub_slot_vdfs(
|
|
359
|
+
header_block, header_blocks, blocks, first_segment_in_sub_epoch
|
|
360
|
+
)
|
|
361
|
+
if first_sub_slots is None:
|
|
362
|
+
log.error("failed building first sub slots")
|
|
363
|
+
return None, uint32(0)
|
|
364
|
+
|
|
365
|
+
sub_slots.extend(first_sub_slots)
|
|
366
|
+
|
|
367
|
+
ssd = await _challenge_block_vdfs(
|
|
368
|
+
self.constants,
|
|
369
|
+
header_block,
|
|
370
|
+
blocks[header_block.header_hash],
|
|
371
|
+
blocks,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
sub_slots.append(ssd)
|
|
375
|
+
|
|
376
|
+
# # VDFs from slot after challenge block to end of slot
|
|
377
|
+
log.debug(f"create slot end vdf for block {header_block.header_hash} height {header_block.height} ")
|
|
378
|
+
|
|
379
|
+
challenge_slot_end_sub_slots, end_height = await self.__slot_end_vdf(
|
|
380
|
+
uint32(header_block.height + 1), header_blocks, blocks
|
|
381
|
+
)
|
|
382
|
+
if challenge_slot_end_sub_slots is None:
|
|
383
|
+
log.error("failed building slot end ")
|
|
384
|
+
return None, uint32(0)
|
|
385
|
+
sub_slots.extend(challenge_slot_end_sub_slots)
|
|
386
|
+
if first_segment_in_sub_epoch and sub_epoch_n != 0:
|
|
387
|
+
return (
|
|
388
|
+
SubEpochChallengeSegment(sub_epoch_n, sub_slots, first_rc_end_of_slot_vdf),
|
|
389
|
+
end_height,
|
|
390
|
+
)
|
|
391
|
+
return SubEpochChallengeSegment(sub_epoch_n, sub_slots, None), end_height
|
|
392
|
+
|
|
393
|
+
# returns a challenge chain vdf from slot start to signage point
|
|
394
|
+
async def __first_sub_slot_vdfs(
|
|
395
|
+
self,
|
|
396
|
+
header_block: HeaderBlock,
|
|
397
|
+
header_blocks: dict[bytes32, HeaderBlock],
|
|
398
|
+
blocks: dict[bytes32, BlockRecord],
|
|
399
|
+
first_in_sub_epoch: bool,
|
|
400
|
+
) -> tuple[Optional[list[SubSlotData]], Optional[VDFInfo]]:
|
|
401
|
+
# combine cc vdfs of all reward blocks from the start of the sub slot to end
|
|
402
|
+
header_block_sub_rec = blocks[header_block.header_hash]
|
|
403
|
+
# find slot start
|
|
404
|
+
curr_sub_rec = header_block_sub_rec
|
|
405
|
+
first_rc_end_of_slot_vdf = None
|
|
406
|
+
if first_in_sub_epoch and curr_sub_rec.height > 0:
|
|
407
|
+
while not curr_sub_rec.sub_epoch_summary_included:
|
|
408
|
+
curr_sub_rec = blocks[curr_sub_rec.prev_hash]
|
|
409
|
+
first_rc_end_of_slot_vdf = self.first_rc_end_of_slot_vdf(header_block, blocks, header_blocks)
|
|
410
|
+
else:
|
|
411
|
+
if header_block_sub_rec.overflow and header_block_sub_rec.first_in_sub_slot:
|
|
412
|
+
sub_slots_num = 2
|
|
413
|
+
while sub_slots_num > 0 and curr_sub_rec.height > 0:
|
|
414
|
+
if curr_sub_rec.first_in_sub_slot:
|
|
415
|
+
assert curr_sub_rec.finished_challenge_slot_hashes is not None
|
|
416
|
+
sub_slots_num -= len(curr_sub_rec.finished_challenge_slot_hashes)
|
|
417
|
+
curr_sub_rec = blocks[curr_sub_rec.prev_hash]
|
|
418
|
+
else:
|
|
419
|
+
while not curr_sub_rec.first_in_sub_slot and curr_sub_rec.height > 0:
|
|
420
|
+
curr_sub_rec = blocks[curr_sub_rec.prev_hash]
|
|
421
|
+
|
|
422
|
+
curr = header_blocks[curr_sub_rec.header_hash]
|
|
423
|
+
sub_slots_data: list[SubSlotData] = []
|
|
424
|
+
tmp_sub_slots_data: list[SubSlotData] = []
|
|
425
|
+
while curr.height < header_block.height:
|
|
426
|
+
if curr is None:
|
|
427
|
+
log.error("failed fetching block")
|
|
428
|
+
return None, None
|
|
429
|
+
if curr.first_in_sub_slot:
|
|
430
|
+
# if not blue boxed
|
|
431
|
+
if not blue_boxed_end_of_slot(curr.finished_sub_slots[0]):
|
|
432
|
+
sub_slots_data.extend(tmp_sub_slots_data)
|
|
433
|
+
|
|
434
|
+
for idx, sub_slot in enumerate(curr.finished_sub_slots):
|
|
435
|
+
curr_icc_info = None
|
|
436
|
+
if sub_slot.infused_challenge_chain is not None:
|
|
437
|
+
curr_icc_info = sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf
|
|
438
|
+
sub_slots_data.append(handle_finished_slots(sub_slot, curr_icc_info))
|
|
439
|
+
tmp_sub_slots_data = []
|
|
440
|
+
ssd = SubSlotData(
|
|
441
|
+
None,
|
|
442
|
+
None,
|
|
443
|
+
None,
|
|
444
|
+
None,
|
|
445
|
+
None,
|
|
446
|
+
curr.reward_chain_block.signage_point_index,
|
|
447
|
+
None,
|
|
448
|
+
None,
|
|
449
|
+
None,
|
|
450
|
+
None,
|
|
451
|
+
curr.reward_chain_block.challenge_chain_ip_vdf,
|
|
452
|
+
curr.reward_chain_block.infused_challenge_chain_ip_vdf,
|
|
453
|
+
curr.total_iters,
|
|
454
|
+
)
|
|
455
|
+
tmp_sub_slots_data.append(ssd)
|
|
456
|
+
header_hash = self.blockchain.height_to_hash(uint32(curr.height + 1))
|
|
457
|
+
assert header_hash is not None
|
|
458
|
+
curr = header_blocks[header_hash]
|
|
459
|
+
|
|
460
|
+
if len(tmp_sub_slots_data) > 0:
|
|
461
|
+
sub_slots_data.extend(tmp_sub_slots_data)
|
|
462
|
+
|
|
463
|
+
for idx, sub_slot in enumerate(header_block.finished_sub_slots):
|
|
464
|
+
curr_icc_info = None
|
|
465
|
+
if sub_slot.infused_challenge_chain is not None:
|
|
466
|
+
curr_icc_info = sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf
|
|
467
|
+
sub_slots_data.append(handle_finished_slots(sub_slot, curr_icc_info))
|
|
468
|
+
|
|
469
|
+
return sub_slots_data, first_rc_end_of_slot_vdf
|
|
470
|
+
|
|
471
|
+
def first_rc_end_of_slot_vdf(
|
|
472
|
+
self,
|
|
473
|
+
header_block: HeaderBlock,
|
|
474
|
+
blocks: dict[bytes32, BlockRecord],
|
|
475
|
+
header_blocks: dict[bytes32, HeaderBlock],
|
|
476
|
+
) -> Optional[VDFInfo]:
|
|
477
|
+
curr = blocks[header_block.header_hash]
|
|
478
|
+
while curr.height > 0 and not curr.sub_epoch_summary_included:
|
|
479
|
+
curr = blocks[curr.prev_hash]
|
|
480
|
+
return header_blocks[curr.header_hash].finished_sub_slots[-1].reward_chain.end_of_slot_vdf
|
|
481
|
+
|
|
482
|
+
async def __slot_end_vdf(
|
|
483
|
+
self, start_height: uint32, header_blocks: dict[bytes32, HeaderBlock], blocks: dict[bytes32, BlockRecord]
|
|
484
|
+
) -> tuple[Optional[list[SubSlotData]], uint32]:
|
|
485
|
+
# gets all vdfs first sub slot after challenge block to last sub slot
|
|
486
|
+
log.debug(f"slot end vdf start height {start_height}")
|
|
487
|
+
header_hash = self.blockchain.height_to_hash(start_height)
|
|
488
|
+
assert header_hash is not None
|
|
489
|
+
curr = header_blocks[header_hash]
|
|
490
|
+
curr_header_hash = curr.header_hash
|
|
491
|
+
sub_slots_data: list[SubSlotData] = []
|
|
492
|
+
tmp_sub_slots_data: list[SubSlotData] = []
|
|
493
|
+
while not blocks[curr_header_hash].is_challenge_block(self.constants):
|
|
494
|
+
if curr.first_in_sub_slot:
|
|
495
|
+
sub_slots_data.extend(tmp_sub_slots_data)
|
|
496
|
+
|
|
497
|
+
curr_prev_header_hash = curr.prev_header_hash
|
|
498
|
+
# add collected vdfs
|
|
499
|
+
for idx, sub_slot in enumerate(curr.finished_sub_slots):
|
|
500
|
+
prev_rec = blocks[curr_prev_header_hash]
|
|
501
|
+
eos_vdf_iters = prev_rec.sub_slot_iters
|
|
502
|
+
if idx == 0:
|
|
503
|
+
eos_vdf_iters = uint64(prev_rec.sub_slot_iters - prev_rec.ip_iters(self.constants))
|
|
504
|
+
sub_slots_data.append(handle_end_of_slot(sub_slot, eos_vdf_iters))
|
|
505
|
+
tmp_sub_slots_data = []
|
|
506
|
+
tmp_sub_slots_data.append(self.handle_block_vdfs(curr, blocks))
|
|
507
|
+
header_hash = self.blockchain.height_to_hash(uint32(curr.height + 1))
|
|
508
|
+
assert header_hash is not None
|
|
509
|
+
curr = header_blocks[header_hash]
|
|
510
|
+
curr_header_hash = curr.header_hash
|
|
511
|
+
|
|
512
|
+
if len(tmp_sub_slots_data) > 0:
|
|
513
|
+
sub_slots_data.extend(tmp_sub_slots_data)
|
|
514
|
+
log.debug(f"slot end vdf end height {curr.height} slots {len(sub_slots_data)} ")
|
|
515
|
+
return sub_slots_data, curr.height
|
|
516
|
+
|
|
517
|
+
def handle_block_vdfs(self, curr: HeaderBlock, blocks: dict[bytes32, BlockRecord]) -> SubSlotData:
|
|
518
|
+
cc_sp_proof = None
|
|
519
|
+
icc_ip_proof = None
|
|
520
|
+
cc_sp_info = None
|
|
521
|
+
icc_ip_info = None
|
|
522
|
+
block_record = blocks[curr.header_hash]
|
|
523
|
+
if curr.infused_challenge_chain_ip_proof is not None:
|
|
524
|
+
assert curr.reward_chain_block.infused_challenge_chain_ip_vdf
|
|
525
|
+
icc_ip_proof = curr.infused_challenge_chain_ip_proof
|
|
526
|
+
icc_ip_info = curr.reward_chain_block.infused_challenge_chain_ip_vdf
|
|
527
|
+
if curr.challenge_chain_sp_proof is not None:
|
|
528
|
+
assert curr.reward_chain_block.challenge_chain_sp_vdf
|
|
529
|
+
cc_sp_vdf_info = curr.reward_chain_block.challenge_chain_sp_vdf
|
|
530
|
+
if not curr.challenge_chain_sp_proof.normalized_to_identity:
|
|
531
|
+
(_, _, _, _, cc_vdf_iters, _) = get_signage_point_vdf_info(
|
|
532
|
+
self.constants,
|
|
533
|
+
curr.finished_sub_slots,
|
|
534
|
+
block_record.overflow,
|
|
535
|
+
None if curr.height == 0 else blocks[curr.prev_header_hash],
|
|
536
|
+
BlockCache(blocks),
|
|
537
|
+
block_record.sp_total_iters(self.constants),
|
|
538
|
+
block_record.sp_iters(self.constants),
|
|
539
|
+
)
|
|
540
|
+
cc_sp_vdf_info = VDFInfo(
|
|
541
|
+
curr.reward_chain_block.challenge_chain_sp_vdf.challenge,
|
|
542
|
+
cc_vdf_iters,
|
|
543
|
+
curr.reward_chain_block.challenge_chain_sp_vdf.output,
|
|
544
|
+
)
|
|
545
|
+
cc_sp_proof = curr.challenge_chain_sp_proof
|
|
546
|
+
cc_sp_info = cc_sp_vdf_info
|
|
547
|
+
return SubSlotData(
|
|
548
|
+
None,
|
|
549
|
+
cc_sp_proof,
|
|
550
|
+
curr.challenge_chain_ip_proof,
|
|
551
|
+
icc_ip_proof,
|
|
552
|
+
cc_sp_info,
|
|
553
|
+
curr.reward_chain_block.signage_point_index,
|
|
554
|
+
None,
|
|
555
|
+
None,
|
|
556
|
+
None,
|
|
557
|
+
None,
|
|
558
|
+
curr.reward_chain_block.challenge_chain_ip_vdf,
|
|
559
|
+
icc_ip_info,
|
|
560
|
+
curr.total_iters,
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
def validate_weight_proof_single_proc(self, weight_proof: WeightProof) -> tuple[bool, uint32]:
|
|
564
|
+
assert self.blockchain is not None
|
|
565
|
+
assert len(weight_proof.sub_epochs) > 0
|
|
566
|
+
if len(weight_proof.sub_epochs) == 0:
|
|
567
|
+
return False, uint32(0)
|
|
568
|
+
|
|
569
|
+
peak_height = weight_proof.recent_chain_data[-1].reward_chain_block.height
|
|
570
|
+
log.info(f"validate weight proof peak height {peak_height}")
|
|
571
|
+
summaries, sub_epoch_weight_list = _validate_sub_epoch_summaries(self.constants, weight_proof)
|
|
572
|
+
if summaries is None:
|
|
573
|
+
log.warning("weight proof failed sub epoch data validation")
|
|
574
|
+
return False, uint32(0)
|
|
575
|
+
summary_bytes, wp_segment_bytes, wp_recent_chain_bytes = vars_to_bytes(summaries, weight_proof)
|
|
576
|
+
log.info("validate sub epoch challenge segments")
|
|
577
|
+
seed = summaries[-2].get_hash()
|
|
578
|
+
rng = random.Random(seed)
|
|
579
|
+
assert sub_epoch_weight_list is not None
|
|
580
|
+
if not validate_sub_epoch_sampling(rng, sub_epoch_weight_list, weight_proof):
|
|
581
|
+
log.error("failed weight proof sub epoch sample validation")
|
|
582
|
+
return False, uint32(0)
|
|
583
|
+
|
|
584
|
+
if _validate_sub_epoch_segments(self.constants, rng, wp_segment_bytes, summary_bytes, peak_height) is None:
|
|
585
|
+
return False, uint32(0)
|
|
586
|
+
log.info("validate weight proof recent blocks")
|
|
587
|
+
success, _ = validate_recent_blocks(self.constants, wp_recent_chain_bytes, summary_bytes)
|
|
588
|
+
if not success:
|
|
589
|
+
return False, uint32(0)
|
|
590
|
+
fork_point, _ = self.get_fork_point(summaries)
|
|
591
|
+
return True, fork_point
|
|
592
|
+
|
|
593
|
+
async def validate_weight_proof(self, weight_proof: WeightProof) -> tuple[bool, uint32, list[SubEpochSummary]]:
|
|
594
|
+
assert self.blockchain is not None
|
|
595
|
+
if len(weight_proof.sub_epochs) == 0:
|
|
596
|
+
return False, uint32(0), []
|
|
597
|
+
|
|
598
|
+
# timing reference: start
|
|
599
|
+
summaries, sub_epoch_weight_list = _validate_sub_epoch_summaries(self.constants, weight_proof)
|
|
600
|
+
await asyncio.sleep(0) # break up otherwise multi-second sync code
|
|
601
|
+
# timing reference: 1 second
|
|
602
|
+
if summaries is None or sub_epoch_weight_list is None:
|
|
603
|
+
log.error("weight proof failed sub epoch data validation")
|
|
604
|
+
return False, uint32(0), []
|
|
605
|
+
|
|
606
|
+
fork_point, ses_fork_idx = self.get_fork_point(summaries)
|
|
607
|
+
# timing reference: 1 second
|
|
608
|
+
# TODO: Consider implementing an async polling closer for the executor.
|
|
609
|
+
with ProcessPoolExecutor(
|
|
610
|
+
max_workers=self._num_processes,
|
|
611
|
+
mp_context=self.multiprocessing_context,
|
|
612
|
+
initializer=setproctitle,
|
|
613
|
+
initargs=(f"{getproctitle()}_weight_proof_worker",),
|
|
614
|
+
) as executor:
|
|
615
|
+
# The shutdown file manager must be inside of the executor manager so that
|
|
616
|
+
# we request the workers close prior to waiting for them to close.
|
|
617
|
+
with _create_shutdown_file() as shutdown_file:
|
|
618
|
+
task = create_referenced_task(
|
|
619
|
+
validate_weight_proof_inner(
|
|
620
|
+
self.constants,
|
|
621
|
+
executor,
|
|
622
|
+
shutdown_file.name,
|
|
623
|
+
self._num_processes,
|
|
624
|
+
weight_proof,
|
|
625
|
+
summaries,
|
|
626
|
+
sub_epoch_weight_list,
|
|
627
|
+
False,
|
|
628
|
+
ses_fork_idx,
|
|
629
|
+
)
|
|
630
|
+
)
|
|
631
|
+
valid, _ = await task
|
|
632
|
+
return valid, fork_point, summaries
|
|
633
|
+
|
|
634
|
+
def get_fork_point(self, received_summaries: list[SubEpochSummary]) -> tuple[uint32, int]:
|
|
635
|
+
# returns the fork height and ses index
|
|
636
|
+
# iterate through sub epoch summaries to find fork point
|
|
637
|
+
fork_point_index = 0
|
|
638
|
+
ses_heights = self.blockchain.get_ses_heights()
|
|
639
|
+
for idx, summary_height in enumerate(ses_heights):
|
|
640
|
+
log.debug(f"check summary {idx} height {summary_height}")
|
|
641
|
+
local_ses = self.blockchain.get_ses(summary_height)
|
|
642
|
+
if idx == len(received_summaries) - 1:
|
|
643
|
+
# end of wp summaries, local chain is longer or equal to wp chain
|
|
644
|
+
break
|
|
645
|
+
if local_ses is None or local_ses.get_hash() != received_summaries[idx].get_hash():
|
|
646
|
+
break
|
|
647
|
+
fork_point_index = idx
|
|
648
|
+
|
|
649
|
+
if fork_point_index <= 2:
|
|
650
|
+
# Two summeries can have different blocks and still be identical
|
|
651
|
+
# This gets resolved after one full sub epoch
|
|
652
|
+
return uint32(0), 0
|
|
653
|
+
|
|
654
|
+
return ses_heights[fork_point_index - 2], fork_point_index
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
def _get_weights_for_sampling(
|
|
658
|
+
rng: random.Random, total_weight: uint128, recent_chain: list[HeaderBlock]
|
|
659
|
+
) -> Optional[list[uint128]]:
|
|
660
|
+
weight_to_check = []
|
|
661
|
+
last_l_weight = recent_chain[-1].reward_chain_block.weight - recent_chain[0].reward_chain_block.weight
|
|
662
|
+
delta = last_l_weight / total_weight
|
|
663
|
+
prob_of_adv_succeeding = 1 - math.log(WeightProofHandler.C, delta)
|
|
664
|
+
if prob_of_adv_succeeding <= 0:
|
|
665
|
+
return None
|
|
666
|
+
queries = -WeightProofHandler.LAMBDA_L * math.log(2, prob_of_adv_succeeding)
|
|
667
|
+
for i in range(int(queries) + 1):
|
|
668
|
+
u = rng.random()
|
|
669
|
+
q = 1 - delta**u
|
|
670
|
+
# todo check division and type conversions
|
|
671
|
+
weight = q * float(total_weight)
|
|
672
|
+
weight_to_check.append(uint128(int(weight)))
|
|
673
|
+
weight_to_check.sort()
|
|
674
|
+
return weight_to_check
|
|
675
|
+
|
|
676
|
+
|
|
677
|
+
def _sample_sub_epoch(
|
|
678
|
+
start_of_epoch_weight: uint128,
|
|
679
|
+
end_of_epoch_weight: uint128,
|
|
680
|
+
weight_to_check: Optional[list[uint128]],
|
|
681
|
+
) -> bool:
|
|
682
|
+
"""
|
|
683
|
+
weight_to_check: list[uint128] is expected to be sorted
|
|
684
|
+
"""
|
|
685
|
+
if weight_to_check is None:
|
|
686
|
+
return True
|
|
687
|
+
if weight_to_check[-1] < start_of_epoch_weight:
|
|
688
|
+
return False
|
|
689
|
+
if weight_to_check[0] > end_of_epoch_weight:
|
|
690
|
+
return False
|
|
691
|
+
choose = False
|
|
692
|
+
for weight in weight_to_check:
|
|
693
|
+
if weight > end_of_epoch_weight:
|
|
694
|
+
return False
|
|
695
|
+
if start_of_epoch_weight < weight < end_of_epoch_weight:
|
|
696
|
+
log.debug(f"start weight: {start_of_epoch_weight}")
|
|
697
|
+
log.debug(f"weight to check {weight}")
|
|
698
|
+
log.debug(f"end weight: {end_of_epoch_weight}")
|
|
699
|
+
choose = True
|
|
700
|
+
break
|
|
701
|
+
|
|
702
|
+
return choose
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
# wp creation methods
|
|
706
|
+
def _create_sub_epoch_data(
|
|
707
|
+
sub_epoch_summary: SubEpochSummary,
|
|
708
|
+
) -> SubEpochData:
|
|
709
|
+
reward_chain_hash: bytes32 = sub_epoch_summary.reward_chain_hash
|
|
710
|
+
# Number of subblocks overflow in previous slot
|
|
711
|
+
previous_sub_epoch_overflows = sub_epoch_summary.num_blocks_overflow # total in sub epoch - expected
|
|
712
|
+
# New work difficulty and iterations per sub-slot
|
|
713
|
+
sub_slot_iters = sub_epoch_summary.new_sub_slot_iters
|
|
714
|
+
new_difficulty = sub_epoch_summary.new_difficulty
|
|
715
|
+
return SubEpochData(reward_chain_hash, previous_sub_epoch_overflows, sub_slot_iters, new_difficulty)
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
async def _challenge_block_vdfs(
|
|
719
|
+
constants: ConsensusConstants,
|
|
720
|
+
header_block: HeaderBlock,
|
|
721
|
+
block_rec: BlockRecord,
|
|
722
|
+
sub_blocks: dict[bytes32, BlockRecord],
|
|
723
|
+
) -> SubSlotData:
|
|
724
|
+
(_, _, _, _, cc_vdf_iters, _) = get_signage_point_vdf_info(
|
|
725
|
+
constants,
|
|
726
|
+
header_block.finished_sub_slots,
|
|
727
|
+
block_rec.overflow,
|
|
728
|
+
None if header_block.height == 0 else sub_blocks[header_block.prev_header_hash],
|
|
729
|
+
BlockCache(sub_blocks),
|
|
730
|
+
block_rec.sp_total_iters(constants),
|
|
731
|
+
block_rec.sp_iters(constants),
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
cc_sp_info = None
|
|
735
|
+
if header_block.reward_chain_block.challenge_chain_sp_vdf:
|
|
736
|
+
cc_sp_info = header_block.reward_chain_block.challenge_chain_sp_vdf
|
|
737
|
+
assert header_block.challenge_chain_sp_proof
|
|
738
|
+
if not header_block.challenge_chain_sp_proof.normalized_to_identity:
|
|
739
|
+
cc_sp_info = VDFInfo(
|
|
740
|
+
header_block.reward_chain_block.challenge_chain_sp_vdf.challenge,
|
|
741
|
+
cc_vdf_iters,
|
|
742
|
+
header_block.reward_chain_block.challenge_chain_sp_vdf.output,
|
|
743
|
+
)
|
|
744
|
+
ssd = SubSlotData(
|
|
745
|
+
header_block.reward_chain_block.proof_of_space,
|
|
746
|
+
header_block.challenge_chain_sp_proof,
|
|
747
|
+
header_block.challenge_chain_ip_proof,
|
|
748
|
+
None,
|
|
749
|
+
cc_sp_info,
|
|
750
|
+
header_block.reward_chain_block.signage_point_index,
|
|
751
|
+
None,
|
|
752
|
+
None,
|
|
753
|
+
None,
|
|
754
|
+
None,
|
|
755
|
+
header_block.reward_chain_block.challenge_chain_ip_vdf,
|
|
756
|
+
header_block.reward_chain_block.infused_challenge_chain_ip_vdf,
|
|
757
|
+
block_rec.total_iters,
|
|
758
|
+
)
|
|
759
|
+
return ssd
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def handle_finished_slots(end_of_slot: EndOfSubSlotBundle, icc_end_of_slot_info: Optional[VDFInfo]) -> SubSlotData:
|
|
763
|
+
return SubSlotData(
|
|
764
|
+
None,
|
|
765
|
+
None,
|
|
766
|
+
None,
|
|
767
|
+
None,
|
|
768
|
+
None,
|
|
769
|
+
None,
|
|
770
|
+
(
|
|
771
|
+
None
|
|
772
|
+
if end_of_slot.proofs.challenge_chain_slot_proof is None
|
|
773
|
+
else end_of_slot.proofs.challenge_chain_slot_proof
|
|
774
|
+
),
|
|
775
|
+
(
|
|
776
|
+
None
|
|
777
|
+
if end_of_slot.proofs.infused_challenge_chain_slot_proof is None
|
|
778
|
+
else end_of_slot.proofs.infused_challenge_chain_slot_proof
|
|
779
|
+
),
|
|
780
|
+
end_of_slot.challenge_chain.challenge_chain_end_of_slot_vdf,
|
|
781
|
+
icc_end_of_slot_info,
|
|
782
|
+
None,
|
|
783
|
+
None,
|
|
784
|
+
None,
|
|
785
|
+
)
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
def handle_end_of_slot(
|
|
789
|
+
sub_slot: EndOfSubSlotBundle,
|
|
790
|
+
eos_vdf_iters: uint64,
|
|
791
|
+
) -> SubSlotData:
|
|
792
|
+
assert sub_slot.infused_challenge_chain
|
|
793
|
+
assert sub_slot.proofs.infused_challenge_chain_slot_proof
|
|
794
|
+
if sub_slot.proofs.infused_challenge_chain_slot_proof.normalized_to_identity:
|
|
795
|
+
icc_info = sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf
|
|
796
|
+
else:
|
|
797
|
+
icc_info = VDFInfo(
|
|
798
|
+
sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.challenge,
|
|
799
|
+
eos_vdf_iters,
|
|
800
|
+
sub_slot.infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.output,
|
|
801
|
+
)
|
|
802
|
+
if sub_slot.proofs.challenge_chain_slot_proof.normalized_to_identity:
|
|
803
|
+
cc_info = sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf
|
|
804
|
+
else:
|
|
805
|
+
cc_info = VDFInfo(
|
|
806
|
+
sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.challenge,
|
|
807
|
+
eos_vdf_iters,
|
|
808
|
+
sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.output,
|
|
809
|
+
)
|
|
810
|
+
|
|
811
|
+
assert sub_slot.proofs.infused_challenge_chain_slot_proof is not None
|
|
812
|
+
return SubSlotData(
|
|
813
|
+
None,
|
|
814
|
+
None,
|
|
815
|
+
None,
|
|
816
|
+
None,
|
|
817
|
+
None,
|
|
818
|
+
None,
|
|
819
|
+
sub_slot.proofs.challenge_chain_slot_proof,
|
|
820
|
+
sub_slot.proofs.infused_challenge_chain_slot_proof,
|
|
821
|
+
cc_info,
|
|
822
|
+
icc_info,
|
|
823
|
+
None,
|
|
824
|
+
None,
|
|
825
|
+
None,
|
|
826
|
+
)
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
# wp validation methods
|
|
830
|
+
def _validate_sub_epoch_summaries(
|
|
831
|
+
constants: ConsensusConstants,
|
|
832
|
+
weight_proof: WeightProof,
|
|
833
|
+
) -> tuple[Optional[list[SubEpochSummary]], Optional[list[uint128]]]:
|
|
834
|
+
last_ses_hash, last_ses_sub_height = _get_last_ses_hash(constants, weight_proof.recent_chain_data)
|
|
835
|
+
if last_ses_hash is None:
|
|
836
|
+
log.warning("could not find last ses block")
|
|
837
|
+
return None, None
|
|
838
|
+
|
|
839
|
+
summaries, total, sub_epoch_weight_list = _map_sub_epoch_summaries(
|
|
840
|
+
constants.SUB_EPOCH_BLOCKS,
|
|
841
|
+
constants.GENESIS_CHALLENGE,
|
|
842
|
+
weight_proof.sub_epochs,
|
|
843
|
+
constants.DIFFICULTY_STARTING,
|
|
844
|
+
)
|
|
845
|
+
|
|
846
|
+
log.info(f"validating {len(summaries)} sub epochs")
|
|
847
|
+
|
|
848
|
+
# validate weight
|
|
849
|
+
if not _validate_summaries_weight(constants, total, summaries, weight_proof):
|
|
850
|
+
log.error("failed validating weight")
|
|
851
|
+
return None, None
|
|
852
|
+
|
|
853
|
+
last_ses = summaries[-1]
|
|
854
|
+
log.debug(f"last ses sub height {last_ses_sub_height}")
|
|
855
|
+
# validate last ses_hash
|
|
856
|
+
if last_ses.get_hash() != last_ses_hash:
|
|
857
|
+
log.error(f"failed to validate ses hashes block height {last_ses_sub_height}")
|
|
858
|
+
return None, None
|
|
859
|
+
|
|
860
|
+
return summaries, sub_epoch_weight_list
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
def _map_sub_epoch_summaries(
|
|
864
|
+
sub_blocks_for_se: uint32,
|
|
865
|
+
ses_hash: bytes32,
|
|
866
|
+
sub_epoch_data: list[SubEpochData],
|
|
867
|
+
curr_difficulty: uint64,
|
|
868
|
+
) -> tuple[list[SubEpochSummary], uint128, list[uint128]]:
|
|
869
|
+
total_weight: uint128 = uint128(0)
|
|
870
|
+
summaries: list[SubEpochSummary] = []
|
|
871
|
+
sub_epoch_weight_list: list[uint128] = []
|
|
872
|
+
for idx, data in enumerate(sub_epoch_data):
|
|
873
|
+
ses = SubEpochSummary(
|
|
874
|
+
ses_hash,
|
|
875
|
+
data.reward_chain_hash,
|
|
876
|
+
data.num_blocks_overflow,
|
|
877
|
+
data.new_difficulty,
|
|
878
|
+
data.new_sub_slot_iters,
|
|
879
|
+
)
|
|
880
|
+
|
|
881
|
+
if idx < len(sub_epoch_data) - 1:
|
|
882
|
+
delta = 0
|
|
883
|
+
if idx > 0:
|
|
884
|
+
delta = data.num_blocks_overflow
|
|
885
|
+
log.debug(f"sub epoch {idx} start weight is {total_weight + curr_difficulty} ")
|
|
886
|
+
sub_epoch_weight_list.append(uint128(total_weight + curr_difficulty))
|
|
887
|
+
total_weight = uint128(
|
|
888
|
+
total_weight
|
|
889
|
+
+ curr_difficulty * (sub_blocks_for_se + sub_epoch_data[idx + 1].num_blocks_overflow - delta)
|
|
890
|
+
)
|
|
891
|
+
|
|
892
|
+
# if new epoch update diff and iters
|
|
893
|
+
if data.new_difficulty is not None:
|
|
894
|
+
curr_difficulty = data.new_difficulty
|
|
895
|
+
|
|
896
|
+
# add to dict
|
|
897
|
+
summaries.append(ses)
|
|
898
|
+
ses_hash = std_hash(ses)
|
|
899
|
+
# add last sub epoch weight
|
|
900
|
+
sub_epoch_weight_list.append(uint128(total_weight + curr_difficulty))
|
|
901
|
+
return summaries, total_weight, sub_epoch_weight_list
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
def _validate_summaries_weight(
|
|
905
|
+
constants: ConsensusConstants,
|
|
906
|
+
sub_epoch_data_weight: uint128,
|
|
907
|
+
summaries: list[SubEpochSummary],
|
|
908
|
+
weight_proof: WeightProof,
|
|
909
|
+
) -> bool:
|
|
910
|
+
num_over = summaries[-1].num_blocks_overflow
|
|
911
|
+
ses_end_height = (len(summaries) - 1) * constants.SUB_EPOCH_BLOCKS + num_over - 1
|
|
912
|
+
curr = None
|
|
913
|
+
for block in weight_proof.recent_chain_data:
|
|
914
|
+
if block.reward_chain_block.height == ses_end_height:
|
|
915
|
+
curr = block
|
|
916
|
+
if curr is None:
|
|
917
|
+
return False
|
|
918
|
+
|
|
919
|
+
return curr.reward_chain_block.weight == sub_epoch_data_weight
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
def _validate_sub_epoch_segments(
|
|
923
|
+
constants: ConsensusConstants,
|
|
924
|
+
rng: random.Random,
|
|
925
|
+
weight_proof_bytes: bytes,
|
|
926
|
+
summaries_bytes: list[bytes],
|
|
927
|
+
height: uint32,
|
|
928
|
+
validate_from: int = 0,
|
|
929
|
+
) -> Optional[list[tuple[VDFProof, ClassgroupElement, VDFInfo]]]:
|
|
930
|
+
summaries = summaries_from_bytes(summaries_bytes)
|
|
931
|
+
sub_epoch_segments: SubEpochSegments = SubEpochSegments.from_bytes(weight_proof_bytes)
|
|
932
|
+
rc_sub_slot_hash = constants.GENESIS_CHALLENGE
|
|
933
|
+
total_blocks, total_ip_iters = 0, 0
|
|
934
|
+
total_slot_iters, total_slots = 0, 0
|
|
935
|
+
total_ip_iters = 0
|
|
936
|
+
prev_ses: Optional[SubEpochSummary] = None
|
|
937
|
+
segments_by_sub_epoch = map_segments_by_sub_epoch(sub_epoch_segments.challenge_segments)
|
|
938
|
+
curr_ssi = constants.SUB_SLOT_ITERS_STARTING
|
|
939
|
+
vdfs_to_validate = []
|
|
940
|
+
for sub_epoch_n, segments in segments_by_sub_epoch.items():
|
|
941
|
+
prev_ssi = curr_ssi
|
|
942
|
+
curr_difficulty, curr_ssi = _get_curr_diff_ssi(constants, sub_epoch_n, summaries)
|
|
943
|
+
log.debug(f"validate sub epoch {sub_epoch_n}")
|
|
944
|
+
# recreate RewardChainSubSlot for next ses rc_hash
|
|
945
|
+
sampled_seg_index = rng.choice(range(len(segments)))
|
|
946
|
+
if sub_epoch_n > 0:
|
|
947
|
+
rc_sub_slot = __get_rc_sub_slot(constants, segments[0], summaries, curr_ssi)
|
|
948
|
+
prev_ses = summaries[sub_epoch_n - 1]
|
|
949
|
+
rc_sub_slot_hash = rc_sub_slot.get_hash()
|
|
950
|
+
if not summaries[sub_epoch_n].reward_chain_hash == rc_sub_slot_hash:
|
|
951
|
+
log.error(f"failed reward_chain_hash validation sub_epoch {sub_epoch_n}")
|
|
952
|
+
return None
|
|
953
|
+
|
|
954
|
+
# skip validation up to fork height
|
|
955
|
+
if sub_epoch_n < validate_from:
|
|
956
|
+
continue
|
|
957
|
+
|
|
958
|
+
for idx, segment in enumerate(segments):
|
|
959
|
+
valid_segment, ip_iters, slot_iters, slots, vdf_list = _validate_segment(
|
|
960
|
+
constants,
|
|
961
|
+
segment,
|
|
962
|
+
curr_ssi,
|
|
963
|
+
prev_ssi,
|
|
964
|
+
curr_difficulty,
|
|
965
|
+
prev_ses,
|
|
966
|
+
idx == 0,
|
|
967
|
+
sampled_seg_index == idx,
|
|
968
|
+
height,
|
|
969
|
+
)
|
|
970
|
+
vdfs_to_validate.extend(vdf_list)
|
|
971
|
+
if not valid_segment:
|
|
972
|
+
log.error(f"failed to validate sub_epoch {segment.sub_epoch_n} segment {idx} slots")
|
|
973
|
+
return None
|
|
974
|
+
prev_ses = None
|
|
975
|
+
total_blocks += 1
|
|
976
|
+
total_slot_iters += slot_iters
|
|
977
|
+
total_slots += slots
|
|
978
|
+
total_ip_iters += ip_iters
|
|
979
|
+
return vdfs_to_validate
|
|
980
|
+
|
|
981
|
+
|
|
982
|
+
def _validate_segment(
|
|
983
|
+
constants: ConsensusConstants,
|
|
984
|
+
segment: SubEpochChallengeSegment,
|
|
985
|
+
curr_ssi: uint64,
|
|
986
|
+
prev_ssi: uint64,
|
|
987
|
+
curr_difficulty: uint64,
|
|
988
|
+
ses: Optional[SubEpochSummary],
|
|
989
|
+
first_segment_in_se: bool,
|
|
990
|
+
sampled: bool,
|
|
991
|
+
height: uint32,
|
|
992
|
+
) -> tuple[bool, int, int, int, list[tuple[VDFProof, ClassgroupElement, VDFInfo]]]:
|
|
993
|
+
ip_iters, slot_iters, slots = 0, 0, 0
|
|
994
|
+
after_challenge = False
|
|
995
|
+
to_validate = []
|
|
996
|
+
for idx, sub_slot_data in enumerate(segment.sub_slots):
|
|
997
|
+
if sampled and sub_slot_data.is_challenge():
|
|
998
|
+
after_challenge = True
|
|
999
|
+
required_iters = __validate_pospace(
|
|
1000
|
+
constants, segment, idx, curr_difficulty, ses, first_segment_in_se, height
|
|
1001
|
+
)
|
|
1002
|
+
if required_iters is None:
|
|
1003
|
+
return False, uint64(0), uint64(0), uint64(0), []
|
|
1004
|
+
assert sub_slot_data.signage_point_index is not None
|
|
1005
|
+
ip_iters += calculate_ip_iters(constants, curr_ssi, sub_slot_data.signage_point_index, required_iters)
|
|
1006
|
+
vdf_list = _get_challenge_block_vdfs(constants, idx, segment.sub_slots, curr_ssi)
|
|
1007
|
+
to_validate.extend(vdf_list)
|
|
1008
|
+
elif sampled and after_challenge:
|
|
1009
|
+
validated, vdf_list = _validate_sub_slot_data(constants, idx, segment.sub_slots, curr_ssi)
|
|
1010
|
+
if not validated:
|
|
1011
|
+
log.error(f"failed to validate sub slot data {idx} vdfs")
|
|
1012
|
+
return False, uint64(0), uint64(0), uint64(0), []
|
|
1013
|
+
to_validate.extend(vdf_list)
|
|
1014
|
+
slot_iters += curr_ssi
|
|
1015
|
+
slots += uint64(1)
|
|
1016
|
+
return True, ip_iters, slot_iters, slots, to_validate
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
def _get_challenge_block_vdfs(
|
|
1020
|
+
constants: ConsensusConstants,
|
|
1021
|
+
sub_slot_idx: int,
|
|
1022
|
+
sub_slots: list[SubSlotData],
|
|
1023
|
+
ssi: uint64,
|
|
1024
|
+
) -> list[tuple[VDFProof, ClassgroupElement, VDFInfo]]:
|
|
1025
|
+
to_validate = []
|
|
1026
|
+
sub_slot_data = sub_slots[sub_slot_idx]
|
|
1027
|
+
if sub_slot_data.cc_signage_point is not None and sub_slot_data.cc_sp_vdf_info:
|
|
1028
|
+
assert sub_slot_data.signage_point_index
|
|
1029
|
+
sp_input = ClassgroupElement.get_default_element()
|
|
1030
|
+
if not sub_slot_data.cc_signage_point.normalized_to_identity and sub_slot_idx >= 1:
|
|
1031
|
+
is_overflow = is_overflow_block(constants, sub_slot_data.signage_point_index)
|
|
1032
|
+
prev_ssd = sub_slots[sub_slot_idx - 1]
|
|
1033
|
+
sp_input = sub_slot_data_vdf_input(
|
|
1034
|
+
constants, sub_slot_data, sub_slot_idx, sub_slots, is_overflow, prev_ssd.is_end_of_slot(), ssi
|
|
1035
|
+
)
|
|
1036
|
+
to_validate.append((sub_slot_data.cc_signage_point, sp_input, sub_slot_data.cc_sp_vdf_info))
|
|
1037
|
+
|
|
1038
|
+
assert sub_slot_data.cc_infusion_point
|
|
1039
|
+
assert sub_slot_data.cc_ip_vdf_info
|
|
1040
|
+
ip_input = ClassgroupElement.get_default_element()
|
|
1041
|
+
cc_ip_vdf_info = sub_slot_data.cc_ip_vdf_info
|
|
1042
|
+
if not sub_slot_data.cc_infusion_point.normalized_to_identity and sub_slot_idx >= 1:
|
|
1043
|
+
prev_ssd = sub_slots[sub_slot_idx - 1]
|
|
1044
|
+
if prev_ssd.cc_slot_end is None:
|
|
1045
|
+
assert prev_ssd.cc_ip_vdf_info
|
|
1046
|
+
assert prev_ssd.total_iters
|
|
1047
|
+
assert sub_slot_data.total_iters
|
|
1048
|
+
ip_input = prev_ssd.cc_ip_vdf_info.output
|
|
1049
|
+
ip_vdf_iters = uint64(sub_slot_data.total_iters - prev_ssd.total_iters)
|
|
1050
|
+
cc_ip_vdf_info = VDFInfo(
|
|
1051
|
+
sub_slot_data.cc_ip_vdf_info.challenge, ip_vdf_iters, sub_slot_data.cc_ip_vdf_info.output
|
|
1052
|
+
)
|
|
1053
|
+
to_validate.append((sub_slot_data.cc_infusion_point, ip_input, cc_ip_vdf_info))
|
|
1054
|
+
|
|
1055
|
+
return to_validate
|
|
1056
|
+
|
|
1057
|
+
|
|
1058
|
+
def _validate_sub_slot_data(
|
|
1059
|
+
constants: ConsensusConstants,
|
|
1060
|
+
sub_slot_idx: int,
|
|
1061
|
+
sub_slots: list[SubSlotData],
|
|
1062
|
+
ssi: uint64,
|
|
1063
|
+
) -> tuple[bool, list[tuple[VDFProof, ClassgroupElement, VDFInfo]]]:
|
|
1064
|
+
sub_slot_data = sub_slots[sub_slot_idx]
|
|
1065
|
+
assert sub_slot_idx > 0
|
|
1066
|
+
prev_ssd = sub_slots[sub_slot_idx - 1]
|
|
1067
|
+
to_validate = []
|
|
1068
|
+
if sub_slot_data.is_end_of_slot():
|
|
1069
|
+
if sub_slot_data.icc_slot_end is not None:
|
|
1070
|
+
input = ClassgroupElement.get_default_element()
|
|
1071
|
+
if not sub_slot_data.icc_slot_end.normalized_to_identity and prev_ssd.icc_ip_vdf_info is not None:
|
|
1072
|
+
assert prev_ssd.icc_ip_vdf_info
|
|
1073
|
+
input = prev_ssd.icc_ip_vdf_info.output
|
|
1074
|
+
assert sub_slot_data.icc_slot_end_info
|
|
1075
|
+
to_validate.append((sub_slot_data.icc_slot_end, input, sub_slot_data.icc_slot_end_info))
|
|
1076
|
+
assert sub_slot_data.cc_slot_end_info
|
|
1077
|
+
assert sub_slot_data.cc_slot_end
|
|
1078
|
+
input = ClassgroupElement.get_default_element()
|
|
1079
|
+
if (not prev_ssd.is_end_of_slot()) and (not sub_slot_data.cc_slot_end.normalized_to_identity):
|
|
1080
|
+
assert prev_ssd.cc_ip_vdf_info
|
|
1081
|
+
input = prev_ssd.cc_ip_vdf_info.output
|
|
1082
|
+
if not validate_vdf(sub_slot_data.cc_slot_end, constants, input, sub_slot_data.cc_slot_end_info):
|
|
1083
|
+
log.error(f"failed cc slot end validation {sub_slot_data.cc_slot_end_info}")
|
|
1084
|
+
return False, []
|
|
1085
|
+
else:
|
|
1086
|
+
# find end of slot
|
|
1087
|
+
idx = sub_slot_idx
|
|
1088
|
+
while idx < len(sub_slots) - 1:
|
|
1089
|
+
curr_slot = sub_slots[idx]
|
|
1090
|
+
if curr_slot.is_end_of_slot():
|
|
1091
|
+
# dont validate intermediate vdfs if slot is blue boxed
|
|
1092
|
+
assert curr_slot.cc_slot_end
|
|
1093
|
+
if curr_slot.cc_slot_end.normalized_to_identity is True:
|
|
1094
|
+
log.debug(f"skip intermediate vdfs slot {sub_slot_idx}")
|
|
1095
|
+
return True, to_validate
|
|
1096
|
+
else:
|
|
1097
|
+
break
|
|
1098
|
+
idx += 1
|
|
1099
|
+
if sub_slot_data.icc_infusion_point is not None and sub_slot_data.icc_ip_vdf_info is not None:
|
|
1100
|
+
input = ClassgroupElement.get_default_element()
|
|
1101
|
+
if not prev_ssd.is_challenge() and prev_ssd.icc_ip_vdf_info is not None:
|
|
1102
|
+
input = prev_ssd.icc_ip_vdf_info.output
|
|
1103
|
+
to_validate.append((sub_slot_data.icc_infusion_point, input, sub_slot_data.icc_ip_vdf_info))
|
|
1104
|
+
assert sub_slot_data.signage_point_index is not None
|
|
1105
|
+
if sub_slot_data.cc_signage_point:
|
|
1106
|
+
assert sub_slot_data.cc_sp_vdf_info
|
|
1107
|
+
input = ClassgroupElement.get_default_element()
|
|
1108
|
+
if not sub_slot_data.cc_signage_point.normalized_to_identity:
|
|
1109
|
+
is_overflow = is_overflow_block(constants, sub_slot_data.signage_point_index)
|
|
1110
|
+
input = sub_slot_data_vdf_input(
|
|
1111
|
+
constants, sub_slot_data, sub_slot_idx, sub_slots, is_overflow, prev_ssd.is_end_of_slot(), ssi
|
|
1112
|
+
)
|
|
1113
|
+
to_validate.append((sub_slot_data.cc_signage_point, input, sub_slot_data.cc_sp_vdf_info))
|
|
1114
|
+
|
|
1115
|
+
input = ClassgroupElement.get_default_element()
|
|
1116
|
+
assert sub_slot_data.cc_ip_vdf_info
|
|
1117
|
+
assert sub_slot_data.cc_infusion_point
|
|
1118
|
+
cc_ip_vdf_info = sub_slot_data.cc_ip_vdf_info
|
|
1119
|
+
if not sub_slot_data.cc_infusion_point.normalized_to_identity and prev_ssd.cc_slot_end is None:
|
|
1120
|
+
assert prev_ssd.cc_ip_vdf_info
|
|
1121
|
+
input = prev_ssd.cc_ip_vdf_info.output
|
|
1122
|
+
assert sub_slot_data.total_iters
|
|
1123
|
+
assert prev_ssd.total_iters
|
|
1124
|
+
ip_vdf_iters = uint64(sub_slot_data.total_iters - prev_ssd.total_iters)
|
|
1125
|
+
cc_ip_vdf_info = VDFInfo(
|
|
1126
|
+
sub_slot_data.cc_ip_vdf_info.challenge, ip_vdf_iters, sub_slot_data.cc_ip_vdf_info.output
|
|
1127
|
+
)
|
|
1128
|
+
to_validate.append((sub_slot_data.cc_infusion_point, input, cc_ip_vdf_info))
|
|
1129
|
+
|
|
1130
|
+
return True, to_validate
|
|
1131
|
+
|
|
1132
|
+
|
|
1133
|
+
def sub_slot_data_vdf_input(
|
|
1134
|
+
constants: ConsensusConstants,
|
|
1135
|
+
sub_slot_data: SubSlotData,
|
|
1136
|
+
sub_slot_idx: int,
|
|
1137
|
+
sub_slots: list[SubSlotData],
|
|
1138
|
+
is_overflow: bool,
|
|
1139
|
+
new_sub_slot: bool,
|
|
1140
|
+
ssi: uint64,
|
|
1141
|
+
) -> ClassgroupElement:
|
|
1142
|
+
cc_input = ClassgroupElement.get_default_element()
|
|
1143
|
+
sp_total_iters = get_sp_total_iters(constants, is_overflow, ssi, sub_slot_data)
|
|
1144
|
+
ssd: Optional[SubSlotData] = None
|
|
1145
|
+
if is_overflow and new_sub_slot:
|
|
1146
|
+
if sub_slot_idx >= 2:
|
|
1147
|
+
if sub_slots[sub_slot_idx - 2].cc_slot_end_info is None:
|
|
1148
|
+
for ssd_idx in reversed(range(0, sub_slot_idx - 1)):
|
|
1149
|
+
ssd = sub_slots[ssd_idx]
|
|
1150
|
+
if ssd.cc_slot_end_info is not None:
|
|
1151
|
+
ssd = sub_slots[ssd_idx + 1]
|
|
1152
|
+
break
|
|
1153
|
+
assert ssd.total_iters is not None
|
|
1154
|
+
if not (ssd.total_iters > sp_total_iters):
|
|
1155
|
+
break
|
|
1156
|
+
if ssd and ssd.cc_ip_vdf_info is not None:
|
|
1157
|
+
assert ssd.total_iters is not None
|
|
1158
|
+
if ssd.total_iters < sp_total_iters:
|
|
1159
|
+
cc_input = ssd.cc_ip_vdf_info.output
|
|
1160
|
+
return cc_input
|
|
1161
|
+
|
|
1162
|
+
elif not is_overflow and not new_sub_slot:
|
|
1163
|
+
for ssd_idx in reversed(range(0, sub_slot_idx)):
|
|
1164
|
+
ssd = sub_slots[ssd_idx]
|
|
1165
|
+
if ssd.cc_slot_end_info is not None:
|
|
1166
|
+
ssd = sub_slots[ssd_idx + 1]
|
|
1167
|
+
break
|
|
1168
|
+
assert ssd.total_iters is not None
|
|
1169
|
+
if not (ssd.total_iters > sp_total_iters):
|
|
1170
|
+
break
|
|
1171
|
+
assert ssd is not None
|
|
1172
|
+
if ssd.cc_ip_vdf_info is not None:
|
|
1173
|
+
assert ssd.total_iters is not None
|
|
1174
|
+
if ssd.total_iters < sp_total_iters:
|
|
1175
|
+
cc_input = ssd.cc_ip_vdf_info.output
|
|
1176
|
+
return cc_input
|
|
1177
|
+
|
|
1178
|
+
elif not new_sub_slot and is_overflow:
|
|
1179
|
+
slots_seen = 0
|
|
1180
|
+
for ssd_idx in reversed(range(0, sub_slot_idx)):
|
|
1181
|
+
ssd = sub_slots[ssd_idx]
|
|
1182
|
+
if ssd.cc_slot_end_info is not None:
|
|
1183
|
+
slots_seen += 1
|
|
1184
|
+
if slots_seen == 2:
|
|
1185
|
+
return ClassgroupElement.get_default_element()
|
|
1186
|
+
if ssd.cc_slot_end_info is None:
|
|
1187
|
+
assert ssd.total_iters is not None
|
|
1188
|
+
if not (ssd.total_iters > sp_total_iters):
|
|
1189
|
+
break
|
|
1190
|
+
assert ssd is not None
|
|
1191
|
+
if ssd.cc_ip_vdf_info is not None:
|
|
1192
|
+
assert ssd.total_iters is not None
|
|
1193
|
+
if ssd.total_iters < sp_total_iters:
|
|
1194
|
+
cc_input = ssd.cc_ip_vdf_info.output
|
|
1195
|
+
return cc_input
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
def validate_recent_blocks(
|
|
1199
|
+
constants: ConsensusConstants,
|
|
1200
|
+
recent_chain_bytes: bytes,
|
|
1201
|
+
summaries_bytes: list[bytes],
|
|
1202
|
+
shutdown_file_path: Optional[pathlib.Path] = None,
|
|
1203
|
+
) -> tuple[bool, list[bytes]]:
|
|
1204
|
+
recent_chain: RecentChainData = RecentChainData.from_bytes(recent_chain_bytes)
|
|
1205
|
+
summaries = summaries_from_bytes(summaries_bytes)
|
|
1206
|
+
sub_blocks = BlockCache({})
|
|
1207
|
+
first_ses_idx = _get_ses_idx(recent_chain.recent_chain_data)
|
|
1208
|
+
ses_idx = len(summaries) - len(first_ses_idx)
|
|
1209
|
+
ssi: uint64 = constants.SUB_SLOT_ITERS_STARTING
|
|
1210
|
+
diff: uint64 = constants.DIFFICULTY_STARTING
|
|
1211
|
+
last_blocks_to_validate = 100 # todo remove cap after benchmarks
|
|
1212
|
+
for summary in summaries[:ses_idx]:
|
|
1213
|
+
if summary.new_sub_slot_iters is not None:
|
|
1214
|
+
ssi = summary.new_sub_slot_iters
|
|
1215
|
+
if summary.new_difficulty is not None:
|
|
1216
|
+
diff = summary.new_difficulty
|
|
1217
|
+
|
|
1218
|
+
ses_blocks, sub_slots, transaction_blocks = 0, 0, 0
|
|
1219
|
+
challenge, prev_challenge = recent_chain.recent_chain_data[0].reward_chain_block.pos_ss_cc_challenge_hash, None
|
|
1220
|
+
tip_height = recent_chain.recent_chain_data[-1].height
|
|
1221
|
+
prev_block_record: Optional[BlockRecord] = None
|
|
1222
|
+
deficit = uint8(0)
|
|
1223
|
+
adjusted = False
|
|
1224
|
+
validated_block_count = 0
|
|
1225
|
+
for idx, block in enumerate(recent_chain.recent_chain_data):
|
|
1226
|
+
required_iters = uint64(0)
|
|
1227
|
+
overflow = False
|
|
1228
|
+
ses = False
|
|
1229
|
+
height = block.height
|
|
1230
|
+
for sub_slot in block.finished_sub_slots:
|
|
1231
|
+
prev_challenge = sub_slot.challenge_chain.challenge_chain_end_of_slot_vdf.challenge
|
|
1232
|
+
challenge = sub_slot.challenge_chain.get_hash()
|
|
1233
|
+
deficit = sub_slot.reward_chain.deficit
|
|
1234
|
+
if sub_slot.challenge_chain.subepoch_summary_hash is not None:
|
|
1235
|
+
ses = True
|
|
1236
|
+
if summaries[ses_idx].get_hash() != sub_slot.challenge_chain.subepoch_summary_hash:
|
|
1237
|
+
log.info("sub epoch summary mismatch")
|
|
1238
|
+
return False, []
|
|
1239
|
+
ses_idx += 1
|
|
1240
|
+
if sub_slot.challenge_chain.new_sub_slot_iters is not None:
|
|
1241
|
+
ssi = sub_slot.challenge_chain.new_sub_slot_iters
|
|
1242
|
+
if sub_slot.challenge_chain.new_difficulty is not None:
|
|
1243
|
+
diff = sub_slot.challenge_chain.new_difficulty
|
|
1244
|
+
|
|
1245
|
+
if (challenge is not None) and (prev_challenge is not None):
|
|
1246
|
+
overflow = is_overflow_block(constants, block.reward_chain_block.signage_point_index)
|
|
1247
|
+
if not adjusted:
|
|
1248
|
+
assert prev_block_record is not None
|
|
1249
|
+
prev_block_record = prev_block_record.replace(
|
|
1250
|
+
deficit=uint8(deficit % constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK)
|
|
1251
|
+
)
|
|
1252
|
+
sub_blocks.add_block(prev_block_record)
|
|
1253
|
+
adjusted = True
|
|
1254
|
+
deficit = get_deficit(constants, deficit, prev_block_record, overflow, len(block.finished_sub_slots))
|
|
1255
|
+
if sub_slots > 2 and transaction_blocks > 11 and (tip_height - block.height < last_blocks_to_validate):
|
|
1256
|
+
expected_vs = ValidationState(ssi, diff, None)
|
|
1257
|
+
caluclated_required_iters, error = validate_finished_header_block(
|
|
1258
|
+
constants, sub_blocks, block, False, expected_vs, ses_blocks > 2
|
|
1259
|
+
)
|
|
1260
|
+
if error is not None:
|
|
1261
|
+
log.error(f"block {block.header_hash} failed validation {error}")
|
|
1262
|
+
return False, []
|
|
1263
|
+
assert caluclated_required_iters is not None
|
|
1264
|
+
required_iters = caluclated_required_iters
|
|
1265
|
+
else:
|
|
1266
|
+
ret = _validate_pospace_recent_chain(constants, block, challenge, diff, overflow, prev_challenge)
|
|
1267
|
+
if ret is None:
|
|
1268
|
+
return False, []
|
|
1269
|
+
required_iters = ret
|
|
1270
|
+
validated_block_count += 1
|
|
1271
|
+
|
|
1272
|
+
curr_block_ses = None if not ses else summaries[ses_idx - 1]
|
|
1273
|
+
block_record = header_block_to_sub_block_record(
|
|
1274
|
+
constants, required_iters, block, ssi, overflow, deficit, height, curr_block_ses
|
|
1275
|
+
)
|
|
1276
|
+
log.debug(f"add block {block_record.height} to tmp sub blocks")
|
|
1277
|
+
sub_blocks.add_block(block_record)
|
|
1278
|
+
|
|
1279
|
+
if block.first_in_sub_slot:
|
|
1280
|
+
sub_slots += 1
|
|
1281
|
+
if block.is_transaction_block:
|
|
1282
|
+
transaction_blocks += 1
|
|
1283
|
+
if ses:
|
|
1284
|
+
ses_blocks += 1
|
|
1285
|
+
prev_block_record = block_record
|
|
1286
|
+
|
|
1287
|
+
if shutdown_file_path is not None and not shutdown_file_path.is_file():
|
|
1288
|
+
log.info(f"cancelling block {block.header_hash} validation, shutdown requested")
|
|
1289
|
+
return False, []
|
|
1290
|
+
|
|
1291
|
+
if len(summaries) > 2 and prev_challenge is None:
|
|
1292
|
+
log.info("did not find two challenges in recent chain")
|
|
1293
|
+
return False, []
|
|
1294
|
+
|
|
1295
|
+
if len(summaries) > 2 and validated_block_count < constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK:
|
|
1296
|
+
log.info("did not validate enough blocks in recent chain part")
|
|
1297
|
+
return False, []
|
|
1298
|
+
|
|
1299
|
+
return True, [bytes(sub) for sub in sub_blocks._block_records.values()]
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
def _validate_pospace_recent_chain(
|
|
1303
|
+
constants: ConsensusConstants,
|
|
1304
|
+
block: HeaderBlock,
|
|
1305
|
+
challenge: bytes32,
|
|
1306
|
+
diff: uint64,
|
|
1307
|
+
overflow: bool,
|
|
1308
|
+
prev_challenge: bytes32,
|
|
1309
|
+
) -> Optional[uint64]:
|
|
1310
|
+
if block.reward_chain_block.challenge_chain_sp_vdf is None:
|
|
1311
|
+
# Edge case of first sp (start of slot), where sp_iters == 0
|
|
1312
|
+
cc_sp_hash: bytes32 = challenge
|
|
1313
|
+
else:
|
|
1314
|
+
cc_sp_hash = block.reward_chain_block.challenge_chain_sp_vdf.output.get_hash()
|
|
1315
|
+
assert cc_sp_hash is not None
|
|
1316
|
+
q_str = verify_and_get_quality_string(
|
|
1317
|
+
block.reward_chain_block.proof_of_space,
|
|
1318
|
+
constants,
|
|
1319
|
+
challenge if not overflow else prev_challenge,
|
|
1320
|
+
cc_sp_hash,
|
|
1321
|
+
height=block.height,
|
|
1322
|
+
)
|
|
1323
|
+
if q_str is None:
|
|
1324
|
+
log.error(f"could not verify proof of space block {block.height} {overflow}")
|
|
1325
|
+
return None
|
|
1326
|
+
required_iters = calculate_iterations_quality(
|
|
1327
|
+
constants.DIFFICULTY_CONSTANT_FACTOR,
|
|
1328
|
+
q_str,
|
|
1329
|
+
block.reward_chain_block.proof_of_space.size,
|
|
1330
|
+
diff,
|
|
1331
|
+
cc_sp_hash,
|
|
1332
|
+
)
|
|
1333
|
+
return required_iters
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
def __validate_pospace(
|
|
1337
|
+
constants: ConsensusConstants,
|
|
1338
|
+
segment: SubEpochChallengeSegment,
|
|
1339
|
+
idx: int,
|
|
1340
|
+
curr_diff: uint64,
|
|
1341
|
+
ses: Optional[SubEpochSummary],
|
|
1342
|
+
first_in_sub_epoch: bool,
|
|
1343
|
+
height: uint32,
|
|
1344
|
+
) -> Optional[uint64]:
|
|
1345
|
+
if first_in_sub_epoch and segment.sub_epoch_n == 0 and idx == 0:
|
|
1346
|
+
cc_sub_slot_hash = constants.GENESIS_CHALLENGE
|
|
1347
|
+
else:
|
|
1348
|
+
cc_sub_slot_hash = __get_cc_sub_slot(segment.sub_slots, idx, ses).get_hash()
|
|
1349
|
+
|
|
1350
|
+
sub_slot_data: SubSlotData = segment.sub_slots[idx]
|
|
1351
|
+
|
|
1352
|
+
if sub_slot_data.signage_point_index and is_overflow_block(constants, sub_slot_data.signage_point_index):
|
|
1353
|
+
curr_slot = segment.sub_slots[idx - 1]
|
|
1354
|
+
assert curr_slot.cc_slot_end_info
|
|
1355
|
+
challenge = curr_slot.cc_slot_end_info.challenge
|
|
1356
|
+
else:
|
|
1357
|
+
challenge = cc_sub_slot_hash
|
|
1358
|
+
|
|
1359
|
+
if sub_slot_data.cc_sp_vdf_info is None:
|
|
1360
|
+
cc_sp_hash = cc_sub_slot_hash
|
|
1361
|
+
else:
|
|
1362
|
+
cc_sp_hash = sub_slot_data.cc_sp_vdf_info.output.get_hash()
|
|
1363
|
+
|
|
1364
|
+
# validate proof of space
|
|
1365
|
+
assert sub_slot_data.proof_of_space is not None
|
|
1366
|
+
q_str = verify_and_get_quality_string(
|
|
1367
|
+
sub_slot_data.proof_of_space,
|
|
1368
|
+
constants,
|
|
1369
|
+
challenge,
|
|
1370
|
+
cc_sp_hash,
|
|
1371
|
+
height=height,
|
|
1372
|
+
)
|
|
1373
|
+
if q_str is None:
|
|
1374
|
+
log.error("could not verify proof of space")
|
|
1375
|
+
return None
|
|
1376
|
+
return calculate_iterations_quality(
|
|
1377
|
+
constants.DIFFICULTY_CONSTANT_FACTOR,
|
|
1378
|
+
q_str,
|
|
1379
|
+
sub_slot_data.proof_of_space.size,
|
|
1380
|
+
curr_diff,
|
|
1381
|
+
cc_sp_hash,
|
|
1382
|
+
)
|
|
1383
|
+
|
|
1384
|
+
|
|
1385
|
+
def __get_rc_sub_slot(
|
|
1386
|
+
constants: ConsensusConstants,
|
|
1387
|
+
segment: SubEpochChallengeSegment,
|
|
1388
|
+
summaries: list[SubEpochSummary],
|
|
1389
|
+
curr_ssi: uint64,
|
|
1390
|
+
) -> RewardChainSubSlot:
|
|
1391
|
+
ses = summaries[uint32(segment.sub_epoch_n - 1)]
|
|
1392
|
+
# find first challenge in sub epoch
|
|
1393
|
+
first_idx = None
|
|
1394
|
+
first = None
|
|
1395
|
+
for idx, curr in enumerate(segment.sub_slots):
|
|
1396
|
+
if curr.cc_slot_end is None:
|
|
1397
|
+
first_idx = idx
|
|
1398
|
+
first = curr
|
|
1399
|
+
break
|
|
1400
|
+
|
|
1401
|
+
assert first_idx
|
|
1402
|
+
idx = first_idx
|
|
1403
|
+
slots = segment.sub_slots
|
|
1404
|
+
|
|
1405
|
+
# number of slots to look for
|
|
1406
|
+
slots_n = 1
|
|
1407
|
+
assert first
|
|
1408
|
+
assert first.signage_point_index is not None
|
|
1409
|
+
if is_overflow_block(constants, first.signage_point_index):
|
|
1410
|
+
if idx >= 2 and slots[idx - 2].cc_slot_end is None:
|
|
1411
|
+
slots_n = 2
|
|
1412
|
+
|
|
1413
|
+
new_diff = None if ses is None else ses.new_difficulty
|
|
1414
|
+
new_ssi = None if ses is None else ses.new_sub_slot_iters
|
|
1415
|
+
ses_hash: Optional[bytes32] = None if ses is None else ses.get_hash()
|
|
1416
|
+
overflow = is_overflow_block(constants, first.signage_point_index)
|
|
1417
|
+
if overflow:
|
|
1418
|
+
if idx >= 2 and slots[idx - 2].cc_slot_end is not None and slots[idx - 1].cc_slot_end is not None:
|
|
1419
|
+
ses_hash = None
|
|
1420
|
+
new_ssi = None
|
|
1421
|
+
new_diff = None
|
|
1422
|
+
|
|
1423
|
+
sub_slot = slots[idx]
|
|
1424
|
+
while True:
|
|
1425
|
+
if sub_slot.cc_slot_end:
|
|
1426
|
+
slots_n -= 1
|
|
1427
|
+
if slots_n == 0:
|
|
1428
|
+
break
|
|
1429
|
+
idx -= 1
|
|
1430
|
+
sub_slot = slots[idx]
|
|
1431
|
+
|
|
1432
|
+
icc_sub_slot_hash: Optional[bytes32] = None
|
|
1433
|
+
assert sub_slot is not None
|
|
1434
|
+
assert sub_slot.cc_slot_end_info is not None
|
|
1435
|
+
|
|
1436
|
+
assert segment.rc_slot_end_info is not None
|
|
1437
|
+
if idx != 0:
|
|
1438
|
+
# this is not the first slot, ses details should not be included
|
|
1439
|
+
ses_hash = None
|
|
1440
|
+
new_ssi = None
|
|
1441
|
+
new_diff = None
|
|
1442
|
+
cc_vdf_info = VDFInfo(sub_slot.cc_slot_end_info.challenge, curr_ssi, sub_slot.cc_slot_end_info.output)
|
|
1443
|
+
if sub_slot.icc_slot_end_info is not None:
|
|
1444
|
+
icc_slot_end_info = VDFInfo(
|
|
1445
|
+
sub_slot.icc_slot_end_info.challenge, curr_ssi, sub_slot.icc_slot_end_info.output
|
|
1446
|
+
)
|
|
1447
|
+
icc_sub_slot_hash = icc_slot_end_info.get_hash()
|
|
1448
|
+
else:
|
|
1449
|
+
cc_vdf_info = sub_slot.cc_slot_end_info
|
|
1450
|
+
if sub_slot.icc_slot_end_info is not None:
|
|
1451
|
+
icc_sub_slot_hash = sub_slot.icc_slot_end_info.get_hash()
|
|
1452
|
+
cc_sub_slot = ChallengeChainSubSlot(
|
|
1453
|
+
cc_vdf_info,
|
|
1454
|
+
icc_sub_slot_hash,
|
|
1455
|
+
ses_hash,
|
|
1456
|
+
new_ssi,
|
|
1457
|
+
new_diff,
|
|
1458
|
+
)
|
|
1459
|
+
|
|
1460
|
+
rc_sub_slot = RewardChainSubSlot(
|
|
1461
|
+
segment.rc_slot_end_info,
|
|
1462
|
+
cc_sub_slot.get_hash(),
|
|
1463
|
+
icc_sub_slot_hash,
|
|
1464
|
+
constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK,
|
|
1465
|
+
)
|
|
1466
|
+
return rc_sub_slot
|
|
1467
|
+
|
|
1468
|
+
|
|
1469
|
+
def __get_cc_sub_slot(sub_slots: list[SubSlotData], idx: int, ses: Optional[SubEpochSummary]) -> ChallengeChainSubSlot:
|
|
1470
|
+
sub_slot: Optional[SubSlotData] = None
|
|
1471
|
+
for i in reversed(range(0, idx)):
|
|
1472
|
+
sub_slot = sub_slots[i]
|
|
1473
|
+
if sub_slot.cc_slot_end_info is not None:
|
|
1474
|
+
break
|
|
1475
|
+
|
|
1476
|
+
assert sub_slot is not None
|
|
1477
|
+
assert sub_slot.cc_slot_end_info is not None
|
|
1478
|
+
|
|
1479
|
+
icc_vdf = sub_slot.icc_slot_end_info
|
|
1480
|
+
icc_vdf_hash: Optional[bytes32] = None
|
|
1481
|
+
if icc_vdf is not None:
|
|
1482
|
+
icc_vdf_hash = icc_vdf.get_hash()
|
|
1483
|
+
cc_sub_slot = ChallengeChainSubSlot(
|
|
1484
|
+
sub_slot.cc_slot_end_info,
|
|
1485
|
+
icc_vdf_hash,
|
|
1486
|
+
None if ses is None else ses.get_hash(),
|
|
1487
|
+
None if ses is None else ses.new_sub_slot_iters,
|
|
1488
|
+
None if ses is None else ses.new_difficulty,
|
|
1489
|
+
)
|
|
1490
|
+
|
|
1491
|
+
return cc_sub_slot
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
def _get_curr_diff_ssi(
|
|
1495
|
+
constants: ConsensusConstants, idx: int, summaries: list[SubEpochSummary]
|
|
1496
|
+
) -> tuple[uint64, uint64]:
|
|
1497
|
+
curr_difficulty = constants.DIFFICULTY_STARTING
|
|
1498
|
+
curr_ssi = constants.SUB_SLOT_ITERS_STARTING
|
|
1499
|
+
for ses in reversed(summaries[0:idx]):
|
|
1500
|
+
if ses.new_sub_slot_iters is not None:
|
|
1501
|
+
curr_ssi = ses.new_sub_slot_iters
|
|
1502
|
+
assert ses.new_difficulty is not None
|
|
1503
|
+
curr_difficulty = ses.new_difficulty
|
|
1504
|
+
break
|
|
1505
|
+
|
|
1506
|
+
return curr_difficulty, curr_ssi
|
|
1507
|
+
|
|
1508
|
+
|
|
1509
|
+
def vars_to_bytes(summaries: list[SubEpochSummary], weight_proof: WeightProof) -> tuple[list[bytes], bytes, bytes]:
|
|
1510
|
+
wp_recent_chain_bytes = bytes(RecentChainData(weight_proof.recent_chain_data))
|
|
1511
|
+
wp_segment_bytes = bytes(SubEpochSegments(weight_proof.sub_epoch_segments))
|
|
1512
|
+
summary_bytes = []
|
|
1513
|
+
for summary in summaries:
|
|
1514
|
+
summary_bytes.append(bytes(summary))
|
|
1515
|
+
return summary_bytes, wp_segment_bytes, wp_recent_chain_bytes
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
def summaries_from_bytes(summaries_bytes: list[bytes]) -> list[SubEpochSummary]:
|
|
1519
|
+
summaries = []
|
|
1520
|
+
for summary in summaries_bytes:
|
|
1521
|
+
summaries.append(SubEpochSummary.from_bytes(summary))
|
|
1522
|
+
return summaries
|
|
1523
|
+
|
|
1524
|
+
|
|
1525
|
+
def _get_last_ses_hash(
|
|
1526
|
+
constants: ConsensusConstants, recent_reward_chain: list[HeaderBlock]
|
|
1527
|
+
) -> tuple[Optional[bytes32], uint32]:
|
|
1528
|
+
for idx, block in enumerate(reversed(recent_reward_chain)):
|
|
1529
|
+
if (block.reward_chain_block.height % constants.SUB_EPOCH_BLOCKS) == 0:
|
|
1530
|
+
idx = len(recent_reward_chain) - 1 - idx # reverse
|
|
1531
|
+
# find first block after sub slot end
|
|
1532
|
+
while idx < len(recent_reward_chain):
|
|
1533
|
+
curr = recent_reward_chain[idx]
|
|
1534
|
+
if len(curr.finished_sub_slots) > 0:
|
|
1535
|
+
for slot in curr.finished_sub_slots:
|
|
1536
|
+
if slot.challenge_chain.subepoch_summary_hash is not None:
|
|
1537
|
+
return (
|
|
1538
|
+
slot.challenge_chain.subepoch_summary_hash,
|
|
1539
|
+
curr.reward_chain_block.height,
|
|
1540
|
+
)
|
|
1541
|
+
idx += 1
|
|
1542
|
+
return None, uint32(0)
|
|
1543
|
+
|
|
1544
|
+
|
|
1545
|
+
def _get_ses_idx(recent_reward_chain: list[HeaderBlock]) -> list[int]:
|
|
1546
|
+
idxs: list[int] = []
|
|
1547
|
+
for idx, curr in enumerate(recent_reward_chain):
|
|
1548
|
+
if len(curr.finished_sub_slots) > 0:
|
|
1549
|
+
for slot in curr.finished_sub_slots:
|
|
1550
|
+
if slot.challenge_chain.subepoch_summary_hash is not None:
|
|
1551
|
+
idxs.append(idx)
|
|
1552
|
+
return idxs
|
|
1553
|
+
|
|
1554
|
+
|
|
1555
|
+
def get_deficit(
|
|
1556
|
+
constants: ConsensusConstants,
|
|
1557
|
+
curr_deficit: uint8,
|
|
1558
|
+
prev_block: Optional[BlockRecord],
|
|
1559
|
+
overflow: bool,
|
|
1560
|
+
num_finished_sub_slots: int,
|
|
1561
|
+
) -> uint8:
|
|
1562
|
+
if prev_block is None:
|
|
1563
|
+
if curr_deficit >= 1 and not (overflow and curr_deficit == constants.MIN_BLOCKS_PER_CHALLENGE_BLOCK):
|
|
1564
|
+
curr_deficit = uint8(curr_deficit - 1)
|
|
1565
|
+
return curr_deficit
|
|
1566
|
+
|
|
1567
|
+
return calculate_deficit(constants, uint32(prev_block.height + 1), prev_block, overflow, num_finished_sub_slots)
|
|
1568
|
+
|
|
1569
|
+
|
|
1570
|
+
def get_sp_total_iters(
|
|
1571
|
+
constants: ConsensusConstants, is_overflow: bool, ssi: uint64, sub_slot_data: SubSlotData
|
|
1572
|
+
) -> int:
|
|
1573
|
+
assert sub_slot_data.cc_ip_vdf_info is not None
|
|
1574
|
+
assert sub_slot_data.total_iters is not None
|
|
1575
|
+
assert sub_slot_data.signage_point_index is not None
|
|
1576
|
+
sp_iters = calculate_sp_iters(constants, ssi, sub_slot_data.signage_point_index)
|
|
1577
|
+
ip_iters = sub_slot_data.cc_ip_vdf_info.number_of_iterations
|
|
1578
|
+
sp_sub_slot_total_iters = uint128(sub_slot_data.total_iters - ip_iters)
|
|
1579
|
+
if is_overflow:
|
|
1580
|
+
sp_sub_slot_total_iters = uint128(sp_sub_slot_total_iters - ssi)
|
|
1581
|
+
return sp_sub_slot_total_iters + sp_iters
|
|
1582
|
+
|
|
1583
|
+
|
|
1584
|
+
def blue_boxed_end_of_slot(sub_slot: EndOfSubSlotBundle) -> bool:
|
|
1585
|
+
if sub_slot.proofs.challenge_chain_slot_proof.normalized_to_identity:
|
|
1586
|
+
if sub_slot.proofs.infused_challenge_chain_slot_proof is not None:
|
|
1587
|
+
if sub_slot.proofs.infused_challenge_chain_slot_proof.normalized_to_identity:
|
|
1588
|
+
return True
|
|
1589
|
+
else:
|
|
1590
|
+
return True
|
|
1591
|
+
return False
|
|
1592
|
+
|
|
1593
|
+
|
|
1594
|
+
def validate_sub_epoch_sampling(
|
|
1595
|
+
rng: random.Random, sub_epoch_weight_list: list[uint128], weight_proof: WeightProof
|
|
1596
|
+
) -> bool:
|
|
1597
|
+
tip = weight_proof.recent_chain_data[-1]
|
|
1598
|
+
weight_to_check = _get_weights_for_sampling(rng, tip.weight, weight_proof.recent_chain_data)
|
|
1599
|
+
sampled_sub_epochs: dict[int, bool] = {}
|
|
1600
|
+
for idx in range(1, len(sub_epoch_weight_list)):
|
|
1601
|
+
if _sample_sub_epoch(sub_epoch_weight_list[idx - 1], sub_epoch_weight_list[idx], weight_to_check):
|
|
1602
|
+
sampled_sub_epochs[idx - 1] = True
|
|
1603
|
+
if len(sampled_sub_epochs) == WeightProofHandler.MAX_SAMPLES:
|
|
1604
|
+
break
|
|
1605
|
+
curr_sub_epoch_n = -1
|
|
1606
|
+
for sub_epoch_segment in weight_proof.sub_epoch_segments:
|
|
1607
|
+
if curr_sub_epoch_n < sub_epoch_segment.sub_epoch_n:
|
|
1608
|
+
if sub_epoch_segment.sub_epoch_n in sampled_sub_epochs:
|
|
1609
|
+
del sampled_sub_epochs[sub_epoch_segment.sub_epoch_n]
|
|
1610
|
+
curr_sub_epoch_n = sub_epoch_segment.sub_epoch_n
|
|
1611
|
+
if len(sampled_sub_epochs) > 0:
|
|
1612
|
+
return False
|
|
1613
|
+
return True
|
|
1614
|
+
|
|
1615
|
+
|
|
1616
|
+
def map_segments_by_sub_epoch(
|
|
1617
|
+
sub_epoch_segments: list[SubEpochChallengeSegment],
|
|
1618
|
+
) -> dict[int, list[SubEpochChallengeSegment]]:
|
|
1619
|
+
segments: dict[int, list[SubEpochChallengeSegment]] = {}
|
|
1620
|
+
curr_sub_epoch_n = -1
|
|
1621
|
+
for idx, segment in enumerate(sub_epoch_segments):
|
|
1622
|
+
if curr_sub_epoch_n < segment.sub_epoch_n:
|
|
1623
|
+
curr_sub_epoch_n = segment.sub_epoch_n
|
|
1624
|
+
segments[curr_sub_epoch_n] = []
|
|
1625
|
+
segments[curr_sub_epoch_n].append(segment)
|
|
1626
|
+
return segments
|
|
1627
|
+
|
|
1628
|
+
|
|
1629
|
+
def _validate_vdf_batch(
|
|
1630
|
+
constants: ConsensusConstants,
|
|
1631
|
+
vdf_list: list[tuple[bytes, bytes, bytes]],
|
|
1632
|
+
shutdown_file_path: Optional[pathlib.Path] = None,
|
|
1633
|
+
) -> bool:
|
|
1634
|
+
for vdf_proof_bytes, class_group_bytes, info in vdf_list:
|
|
1635
|
+
vdf = VDFProof.from_bytes(vdf_proof_bytes)
|
|
1636
|
+
class_group = ClassgroupElement.create(class_group_bytes)
|
|
1637
|
+
vdf_info = VDFInfo.from_bytes(info)
|
|
1638
|
+
if not validate_vdf(vdf, constants, class_group, vdf_info):
|
|
1639
|
+
return False
|
|
1640
|
+
|
|
1641
|
+
if shutdown_file_path is not None and not shutdown_file_path.is_file():
|
|
1642
|
+
log.info("cancelling VDF validation, shutdown requested")
|
|
1643
|
+
return False
|
|
1644
|
+
|
|
1645
|
+
return True
|
|
1646
|
+
|
|
1647
|
+
|
|
1648
|
+
async def validate_weight_proof_inner(
|
|
1649
|
+
constants: ConsensusConstants,
|
|
1650
|
+
executor: ProcessPoolExecutor,
|
|
1651
|
+
shutdown_file_name: str,
|
|
1652
|
+
num_processes: int,
|
|
1653
|
+
weight_proof: WeightProof,
|
|
1654
|
+
summaries: list[SubEpochSummary],
|
|
1655
|
+
sub_epoch_weight_list: list[uint128],
|
|
1656
|
+
skip_segment_validation: bool,
|
|
1657
|
+
validate_from: int,
|
|
1658
|
+
) -> tuple[bool, list[BlockRecord]]:
|
|
1659
|
+
assert len(weight_proof.sub_epochs) > 0
|
|
1660
|
+
if len(weight_proof.sub_epochs) == 0:
|
|
1661
|
+
return False, []
|
|
1662
|
+
|
|
1663
|
+
peak_height = weight_proof.recent_chain_data[-1].reward_chain_block.height
|
|
1664
|
+
log.info(f"validate weight proof peak height {peak_height}")
|
|
1665
|
+
seed = summaries[-2].get_hash()
|
|
1666
|
+
rng = random.Random(seed)
|
|
1667
|
+
if not validate_sub_epoch_sampling(rng, sub_epoch_weight_list, weight_proof):
|
|
1668
|
+
log.error("failed weight proof sub epoch sample validation")
|
|
1669
|
+
return False, []
|
|
1670
|
+
|
|
1671
|
+
loop = asyncio.get_running_loop()
|
|
1672
|
+
summary_bytes, wp_segment_bytes, wp_recent_chain_bytes = vars_to_bytes(summaries, weight_proof)
|
|
1673
|
+
recent_blocks_validation_task = loop.run_in_executor(
|
|
1674
|
+
executor,
|
|
1675
|
+
validate_recent_blocks,
|
|
1676
|
+
constants,
|
|
1677
|
+
wp_recent_chain_bytes,
|
|
1678
|
+
summary_bytes,
|
|
1679
|
+
pathlib.Path(shutdown_file_name),
|
|
1680
|
+
)
|
|
1681
|
+
|
|
1682
|
+
if not skip_segment_validation:
|
|
1683
|
+
vdfs_to_validate = _validate_sub_epoch_segments(
|
|
1684
|
+
constants, rng, wp_segment_bytes, summary_bytes, peak_height, validate_from
|
|
1685
|
+
)
|
|
1686
|
+
await asyncio.sleep(0) # break up otherwise multi-second sync code
|
|
1687
|
+
|
|
1688
|
+
if vdfs_to_validate is None:
|
|
1689
|
+
return False, []
|
|
1690
|
+
|
|
1691
|
+
vdf_tasks = []
|
|
1692
|
+
for batch in to_batches(vdfs_to_validate, num_processes):
|
|
1693
|
+
byte_chunks = []
|
|
1694
|
+
for vdf_proof, classgroup, vdf_info in batch.entries:
|
|
1695
|
+
byte_chunks.append((bytes(vdf_proof), bytes(classgroup), bytes(vdf_info)))
|
|
1696
|
+
vdf_task = asyncio.get_running_loop().run_in_executor(
|
|
1697
|
+
executor,
|
|
1698
|
+
_validate_vdf_batch,
|
|
1699
|
+
constants,
|
|
1700
|
+
byte_chunks,
|
|
1701
|
+
pathlib.Path(shutdown_file_name),
|
|
1702
|
+
)
|
|
1703
|
+
vdf_tasks.append(vdf_task)
|
|
1704
|
+
# give other stuff a turn
|
|
1705
|
+
await asyncio.sleep(0)
|
|
1706
|
+
|
|
1707
|
+
for vdf_task in asyncio.as_completed(fs=vdf_tasks):
|
|
1708
|
+
validated = await vdf_task
|
|
1709
|
+
if not validated:
|
|
1710
|
+
return False, []
|
|
1711
|
+
|
|
1712
|
+
valid_recent_blocks, records_bytes = await recent_blocks_validation_task
|
|
1713
|
+
|
|
1714
|
+
if not valid_recent_blocks or records_bytes is None:
|
|
1715
|
+
log.error("failed validating weight proof recent blocks")
|
|
1716
|
+
# Verify the data
|
|
1717
|
+
return False, []
|
|
1718
|
+
|
|
1719
|
+
records = [BlockRecord.from_bytes(b) for b in records_bytes]
|
|
1720
|
+
return True, records
|