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.
Files changed (1042) hide show
  1. chia/__init__.py +10 -0
  2. chia/__main__.py +5 -0
  3. chia/_tests/README.md +53 -0
  4. chia/_tests/__init__.py +0 -0
  5. chia/_tests/blockchain/__init__.py +0 -0
  6. chia/_tests/blockchain/blockchain_test_utils.py +195 -0
  7. chia/_tests/blockchain/config.py +4 -0
  8. chia/_tests/blockchain/test_augmented_chain.py +145 -0
  9. chia/_tests/blockchain/test_blockchain.py +4202 -0
  10. chia/_tests/blockchain/test_blockchain_transactions.py +1031 -0
  11. chia/_tests/blockchain/test_build_chains.py +59 -0
  12. chia/_tests/blockchain/test_get_block_generator.py +72 -0
  13. chia/_tests/blockchain/test_lookup_fork_chain.py +194 -0
  14. chia/_tests/build-init-files.py +92 -0
  15. chia/_tests/build-job-matrix.py +204 -0
  16. chia/_tests/check_pytest_monitor_output.py +34 -0
  17. chia/_tests/check_sql_statements.py +72 -0
  18. chia/_tests/chia-start-sim +42 -0
  19. chia/_tests/clvm/__init__.py +0 -0
  20. chia/_tests/clvm/benchmark_costs.py +23 -0
  21. chia/_tests/clvm/coin_store.py +149 -0
  22. chia/_tests/clvm/test_chialisp_deserialization.py +101 -0
  23. chia/_tests/clvm/test_clvm_step.py +37 -0
  24. chia/_tests/clvm/test_condition_codes.py +13 -0
  25. chia/_tests/clvm/test_curry_and_treehash.py +55 -0
  26. chia/_tests/clvm/test_message_conditions.py +184 -0
  27. chia/_tests/clvm/test_program.py +150 -0
  28. chia/_tests/clvm/test_puzzle_compression.py +143 -0
  29. chia/_tests/clvm/test_puzzle_drivers.py +45 -0
  30. chia/_tests/clvm/test_puzzles.py +242 -0
  31. chia/_tests/clvm/test_singletons.py +540 -0
  32. chia/_tests/clvm/test_spend_sim.py +181 -0
  33. chia/_tests/cmds/__init__.py +0 -0
  34. chia/_tests/cmds/cmd_test_utils.py +469 -0
  35. chia/_tests/cmds/config.py +3 -0
  36. chia/_tests/cmds/conftest.py +23 -0
  37. chia/_tests/cmds/test_click_types.py +200 -0
  38. chia/_tests/cmds/test_cmd_framework.py +620 -0
  39. chia/_tests/cmds/test_cmds_util.py +97 -0
  40. chia/_tests/cmds/test_daemon.py +92 -0
  41. chia/_tests/cmds/test_dev_gh.py +131 -0
  42. chia/_tests/cmds/test_farm_cmd.py +66 -0
  43. chia/_tests/cmds/test_show.py +116 -0
  44. chia/_tests/cmds/test_sim.py +207 -0
  45. chia/_tests/cmds/test_timelock_args.py +75 -0
  46. chia/_tests/cmds/test_tx_config_args.py +154 -0
  47. chia/_tests/cmds/testing_classes.py +59 -0
  48. chia/_tests/cmds/wallet/__init__.py +0 -0
  49. chia/_tests/cmds/wallet/test_consts.py +47 -0
  50. chia/_tests/cmds/wallet/test_dao.py +565 -0
  51. chia/_tests/cmds/wallet/test_did.py +403 -0
  52. chia/_tests/cmds/wallet/test_nft.py +471 -0
  53. chia/_tests/cmds/wallet/test_notifications.py +124 -0
  54. chia/_tests/cmds/wallet/test_offer.toffer +1 -0
  55. chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
  56. chia/_tests/cmds/wallet/test_vcs.py +400 -0
  57. chia/_tests/cmds/wallet/test_wallet.py +1125 -0
  58. chia/_tests/cmds/wallet/test_wallet_check.py +109 -0
  59. chia/_tests/conftest.py +1419 -0
  60. chia/_tests/connection_utils.py +125 -0
  61. chia/_tests/core/__init__.py +0 -0
  62. chia/_tests/core/cmds/__init__.py +0 -0
  63. chia/_tests/core/cmds/test_beta.py +382 -0
  64. chia/_tests/core/cmds/test_keys.py +1734 -0
  65. chia/_tests/core/cmds/test_wallet.py +126 -0
  66. chia/_tests/core/config.py +3 -0
  67. chia/_tests/core/consensus/__init__.py +0 -0
  68. chia/_tests/core/consensus/test_block_creation.py +54 -0
  69. chia/_tests/core/consensus/test_pot_iterations.py +117 -0
  70. chia/_tests/core/custom_types/__init__.py +0 -0
  71. chia/_tests/core/custom_types/test_coin.py +107 -0
  72. chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
  73. chia/_tests/core/custom_types/test_spend_bundle.py +70 -0
  74. chia/_tests/core/daemon/__init__.py +0 -0
  75. chia/_tests/core/daemon/config.py +4 -0
  76. chia/_tests/core/daemon/test_daemon.py +2128 -0
  77. chia/_tests/core/daemon/test_daemon_register.py +109 -0
  78. chia/_tests/core/daemon/test_keychain_proxy.py +101 -0
  79. chia/_tests/core/data_layer/__init__.py +0 -0
  80. chia/_tests/core/data_layer/config.py +5 -0
  81. chia/_tests/core/data_layer/conftest.py +106 -0
  82. chia/_tests/core/data_layer/test_data_cli.py +56 -0
  83. chia/_tests/core/data_layer/test_data_layer.py +83 -0
  84. chia/_tests/core/data_layer/test_data_layer_util.py +218 -0
  85. chia/_tests/core/data_layer/test_data_rpc.py +3847 -0
  86. chia/_tests/core/data_layer/test_data_store.py +2424 -0
  87. chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
  88. chia/_tests/core/data_layer/test_plugin.py +91 -0
  89. chia/_tests/core/data_layer/util.py +233 -0
  90. chia/_tests/core/farmer/__init__.py +0 -0
  91. chia/_tests/core/farmer/config.py +3 -0
  92. chia/_tests/core/farmer/test_farmer_api.py +103 -0
  93. chia/_tests/core/full_node/__init__.py +0 -0
  94. chia/_tests/core/full_node/config.py +4 -0
  95. chia/_tests/core/full_node/dos/__init__.py +0 -0
  96. chia/_tests/core/full_node/dos/config.py +3 -0
  97. chia/_tests/core/full_node/full_sync/__init__.py +0 -0
  98. chia/_tests/core/full_node/full_sync/config.py +4 -0
  99. chia/_tests/core/full_node/full_sync/test_full_sync.py +443 -0
  100. chia/_tests/core/full_node/ram_db.py +27 -0
  101. chia/_tests/core/full_node/stores/__init__.py +0 -0
  102. chia/_tests/core/full_node/stores/config.py +4 -0
  103. chia/_tests/core/full_node/stores/test_block_store.py +590 -0
  104. chia/_tests/core/full_node/stores/test_coin_store.py +897 -0
  105. chia/_tests/core/full_node/stores/test_full_node_store.py +1219 -0
  106. chia/_tests/core/full_node/stores/test_hint_store.py +229 -0
  107. chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
  108. chia/_tests/core/full_node/test_address_manager.py +588 -0
  109. chia/_tests/core/full_node/test_block_height_map.py +556 -0
  110. chia/_tests/core/full_node/test_conditions.py +556 -0
  111. chia/_tests/core/full_node/test_full_node.py +2700 -0
  112. chia/_tests/core/full_node/test_generator_tools.py +82 -0
  113. chia/_tests/core/full_node/test_hint_management.py +104 -0
  114. chia/_tests/core/full_node/test_node_load.py +34 -0
  115. chia/_tests/core/full_node/test_performance.py +179 -0
  116. chia/_tests/core/full_node/test_subscriptions.py +492 -0
  117. chia/_tests/core/full_node/test_transactions.py +203 -0
  118. chia/_tests/core/full_node/test_tx_processing_queue.py +155 -0
  119. chia/_tests/core/large_block.py +2388 -0
  120. chia/_tests/core/make_block_generator.py +70 -0
  121. chia/_tests/core/mempool/__init__.py +0 -0
  122. chia/_tests/core/mempool/config.py +4 -0
  123. chia/_tests/core/mempool/test_mempool.py +3255 -0
  124. chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
  125. chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
  126. chia/_tests/core/mempool/test_mempool_item_queries.py +190 -0
  127. chia/_tests/core/mempool/test_mempool_manager.py +2084 -0
  128. chia/_tests/core/mempool/test_mempool_performance.py +64 -0
  129. chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
  130. chia/_tests/core/node_height.py +28 -0
  131. chia/_tests/core/server/__init__.py +0 -0
  132. chia/_tests/core/server/config.py +3 -0
  133. chia/_tests/core/server/flood.py +84 -0
  134. chia/_tests/core/server/serve.py +135 -0
  135. chia/_tests/core/server/test_api_protocol.py +21 -0
  136. chia/_tests/core/server/test_capabilities.py +66 -0
  137. chia/_tests/core/server/test_dos.py +319 -0
  138. chia/_tests/core/server/test_event_loop.py +109 -0
  139. chia/_tests/core/server/test_loop.py +294 -0
  140. chia/_tests/core/server/test_node_discovery.py +73 -0
  141. chia/_tests/core/server/test_rate_limits.py +482 -0
  142. chia/_tests/core/server/test_server.py +226 -0
  143. chia/_tests/core/server/test_upnp.py +8 -0
  144. chia/_tests/core/services/__init__.py +0 -0
  145. chia/_tests/core/services/config.py +3 -0
  146. chia/_tests/core/services/test_services.py +188 -0
  147. chia/_tests/core/ssl/__init__.py +0 -0
  148. chia/_tests/core/ssl/config.py +3 -0
  149. chia/_tests/core/ssl/test_ssl.py +202 -0
  150. chia/_tests/core/test_coins.py +33 -0
  151. chia/_tests/core/test_cost_calculation.py +313 -0
  152. chia/_tests/core/test_crawler.py +175 -0
  153. chia/_tests/core/test_crawler_rpc.py +53 -0
  154. chia/_tests/core/test_daemon_rpc.py +24 -0
  155. chia/_tests/core/test_db_conversion.py +130 -0
  156. chia/_tests/core/test_db_validation.py +162 -0
  157. chia/_tests/core/test_farmer_harvester_rpc.py +505 -0
  158. chia/_tests/core/test_filter.py +35 -0
  159. chia/_tests/core/test_full_node_rpc.py +768 -0
  160. chia/_tests/core/test_merkle_set.py +343 -0
  161. chia/_tests/core/test_program.py +47 -0
  162. chia/_tests/core/test_rpc_util.py +86 -0
  163. chia/_tests/core/test_seeder.py +420 -0
  164. chia/_tests/core/test_setproctitle.py +13 -0
  165. chia/_tests/core/util/__init__.py +0 -0
  166. chia/_tests/core/util/config.py +4 -0
  167. chia/_tests/core/util/test_block_cache.py +44 -0
  168. chia/_tests/core/util/test_cached_bls.py +57 -0
  169. chia/_tests/core/util/test_config.py +337 -0
  170. chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
  171. chia/_tests/core/util/test_files.py +391 -0
  172. chia/_tests/core/util/test_jsonify.py +146 -0
  173. chia/_tests/core/util/test_keychain.py +522 -0
  174. chia/_tests/core/util/test_keyring_wrapper.py +491 -0
  175. chia/_tests/core/util/test_lockfile.py +380 -0
  176. chia/_tests/core/util/test_log_exceptions.py +187 -0
  177. chia/_tests/core/util/test_lru_cache.py +56 -0
  178. chia/_tests/core/util/test_significant_bits.py +40 -0
  179. chia/_tests/core/util/test_streamable.py +883 -0
  180. chia/_tests/db/__init__.py +0 -0
  181. chia/_tests/db/test_db_wrapper.py +566 -0
  182. chia/_tests/environments/__init__.py +0 -0
  183. chia/_tests/environments/common.py +35 -0
  184. chia/_tests/environments/full_node.py +47 -0
  185. chia/_tests/environments/wallet.py +429 -0
  186. chia/_tests/ether.py +19 -0
  187. chia/_tests/farmer_harvester/__init__.py +0 -0
  188. chia/_tests/farmer_harvester/config.py +3 -0
  189. chia/_tests/farmer_harvester/test_farmer.py +1264 -0
  190. chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
  191. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +131 -0
  192. chia/_tests/farmer_harvester/test_third_party_harvesters.py +528 -0
  193. chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
  194. chia/_tests/fee_estimation/__init__.py +0 -0
  195. chia/_tests/fee_estimation/config.py +3 -0
  196. chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
  197. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
  198. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +144 -0
  199. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
  200. chia/_tests/generator/__init__.py +0 -0
  201. chia/_tests/generator/puzzles/__init__.py +0 -0
  202. chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
  203. chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
  204. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
  205. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
  206. chia/_tests/generator/test_compression.py +201 -0
  207. chia/_tests/generator/test_generator_types.py +44 -0
  208. chia/_tests/generator/test_rom.py +180 -0
  209. chia/_tests/plot_sync/__init__.py +0 -0
  210. chia/_tests/plot_sync/config.py +3 -0
  211. chia/_tests/plot_sync/test_delta.py +101 -0
  212. chia/_tests/plot_sync/test_plot_sync.py +618 -0
  213. chia/_tests/plot_sync/test_receiver.py +451 -0
  214. chia/_tests/plot_sync/test_sender.py +116 -0
  215. chia/_tests/plot_sync/test_sync_simulated.py +451 -0
  216. chia/_tests/plot_sync/util.py +68 -0
  217. chia/_tests/plotting/__init__.py +0 -0
  218. chia/_tests/plotting/config.py +3 -0
  219. chia/_tests/plotting/test_plot_manager.py +781 -0
  220. chia/_tests/plotting/util.py +12 -0
  221. chia/_tests/pools/__init__.py +0 -0
  222. chia/_tests/pools/config.py +5 -0
  223. chia/_tests/pools/test_pool_cli_parsing.py +128 -0
  224. chia/_tests/pools/test_pool_cmdline.py +1001 -0
  225. chia/_tests/pools/test_pool_config.py +42 -0
  226. chia/_tests/pools/test_pool_puzzles_lifecycle.py +397 -0
  227. chia/_tests/pools/test_pool_rpc.py +1123 -0
  228. chia/_tests/pools/test_pool_wallet.py +205 -0
  229. chia/_tests/pools/test_wallet_pool_store.py +161 -0
  230. chia/_tests/process_junit.py +348 -0
  231. chia/_tests/rpc/__init__.py +0 -0
  232. chia/_tests/rpc/test_rpc_client.py +138 -0
  233. chia/_tests/rpc/test_rpc_server.py +183 -0
  234. chia/_tests/simulation/__init__.py +0 -0
  235. chia/_tests/simulation/config.py +6 -0
  236. chia/_tests/simulation/test_simulation.py +501 -0
  237. chia/_tests/simulation/test_simulator.py +232 -0
  238. chia/_tests/simulation/test_start_simulator.py +107 -0
  239. chia/_tests/testconfig.py +13 -0
  240. chia/_tests/timelord/__init__.py +0 -0
  241. chia/_tests/timelord/config.py +3 -0
  242. chia/_tests/timelord/test_new_peak.py +437 -0
  243. chia/_tests/timelord/test_timelord.py +11 -0
  244. chia/_tests/tools/1315537.json +170 -0
  245. chia/_tests/tools/1315544.json +160 -0
  246. chia/_tests/tools/1315630.json +150 -0
  247. chia/_tests/tools/300000.json +105 -0
  248. chia/_tests/tools/442734.json +140 -0
  249. chia/_tests/tools/466212.json +130 -0
  250. chia/_tests/tools/__init__.py +0 -0
  251. chia/_tests/tools/config.py +5 -0
  252. chia/_tests/tools/test-blockchain-db.sqlite +0 -0
  253. chia/_tests/tools/test_full_sync.py +30 -0
  254. chia/_tests/tools/test_legacy_keyring.py +82 -0
  255. chia/_tests/tools/test_run_block.py +128 -0
  256. chia/_tests/tools/test_virtual_project.py +591 -0
  257. chia/_tests/util/__init__.py +0 -0
  258. chia/_tests/util/benchmark_cost.py +170 -0
  259. chia/_tests/util/benchmarks.py +153 -0
  260. chia/_tests/util/bip39_test_vectors.json +148 -0
  261. chia/_tests/util/blockchain.py +134 -0
  262. chia/_tests/util/blockchain_mock.py +132 -0
  263. chia/_tests/util/build_network_protocol_files.py +302 -0
  264. chia/_tests/util/clvm_generator.bin +0 -0
  265. chia/_tests/util/config.py +3 -0
  266. chia/_tests/util/constants.py +20 -0
  267. chia/_tests/util/db_connection.py +37 -0
  268. chia/_tests/util/full_sync.py +253 -0
  269. chia/_tests/util/gen_ssl_certs.py +114 -0
  270. chia/_tests/util/generator_tools_testing.py +45 -0
  271. chia/_tests/util/get_name_puzzle_conditions.py +52 -0
  272. chia/_tests/util/key_tool.py +36 -0
  273. chia/_tests/util/misc.py +675 -0
  274. chia/_tests/util/network_protocol_data.py +1072 -0
  275. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  276. chia/_tests/util/protocol_messages_json.py +2701 -0
  277. chia/_tests/util/rpc.py +26 -0
  278. chia/_tests/util/run_block.py +163 -0
  279. chia/_tests/util/setup_nodes.py +481 -0
  280. chia/_tests/util/spend_sim.py +492 -0
  281. chia/_tests/util/split_managers.py +102 -0
  282. chia/_tests/util/temp_file.py +14 -0
  283. chia/_tests/util/test_action_scope.py +144 -0
  284. chia/_tests/util/test_async_pool.py +366 -0
  285. chia/_tests/util/test_build_job_matrix.py +42 -0
  286. chia/_tests/util/test_build_network_protocol_files.py +7 -0
  287. chia/_tests/util/test_chia_version.py +50 -0
  288. chia/_tests/util/test_collection.py +11 -0
  289. chia/_tests/util/test_condition_tools.py +229 -0
  290. chia/_tests/util/test_config.py +426 -0
  291. chia/_tests/util/test_dump_keyring.py +60 -0
  292. chia/_tests/util/test_errors.py +10 -0
  293. chia/_tests/util/test_full_block_utils.py +279 -0
  294. chia/_tests/util/test_installed.py +20 -0
  295. chia/_tests/util/test_limited_semaphore.py +53 -0
  296. chia/_tests/util/test_logging_filter.py +42 -0
  297. chia/_tests/util/test_misc.py +445 -0
  298. chia/_tests/util/test_network.py +73 -0
  299. chia/_tests/util/test_network_protocol_files.py +578 -0
  300. chia/_tests/util/test_network_protocol_json.py +267 -0
  301. chia/_tests/util/test_network_protocol_test.py +256 -0
  302. chia/_tests/util/test_paginator.py +71 -0
  303. chia/_tests/util/test_pprint.py +17 -0
  304. chia/_tests/util/test_priority_mutex.py +488 -0
  305. chia/_tests/util/test_recursive_replace.py +116 -0
  306. chia/_tests/util/test_replace_str_to_bytes.py +137 -0
  307. chia/_tests/util/test_service_groups.py +15 -0
  308. chia/_tests/util/test_ssl_check.py +31 -0
  309. chia/_tests/util/test_testnet_overrides.py +19 -0
  310. chia/_tests/util/test_tests_misc.py +38 -0
  311. chia/_tests/util/test_timing.py +37 -0
  312. chia/_tests/util/test_trusted_peer.py +51 -0
  313. chia/_tests/util/time_out_assert.py +191 -0
  314. chia/_tests/wallet/__init__.py +0 -0
  315. chia/_tests/wallet/cat_wallet/__init__.py +0 -0
  316. chia/_tests/wallet/cat_wallet/config.py +4 -0
  317. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
  318. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
  319. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1826 -0
  320. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
  321. chia/_tests/wallet/cat_wallet/test_trades.py +2600 -0
  322. chia/_tests/wallet/clawback/__init__.py +0 -0
  323. chia/_tests/wallet/clawback/config.py +3 -0
  324. chia/_tests/wallet/clawback/test_clawback_decorator.py +78 -0
  325. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
  326. chia/_tests/wallet/clawback/test_clawback_metadata.py +50 -0
  327. chia/_tests/wallet/config.py +4 -0
  328. chia/_tests/wallet/conftest.py +278 -0
  329. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  330. chia/_tests/wallet/dao_wallet/config.py +3 -0
  331. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1330 -0
  332. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
  333. chia/_tests/wallet/db_wallet/__init__.py +0 -0
  334. chia/_tests/wallet/db_wallet/config.py +3 -0
  335. chia/_tests/wallet/db_wallet/test_db_graftroot.py +141 -0
  336. chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
  337. chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
  338. chia/_tests/wallet/did_wallet/__init__.py +0 -0
  339. chia/_tests/wallet/did_wallet/config.py +4 -0
  340. chia/_tests/wallet/did_wallet/test_did.py +2284 -0
  341. chia/_tests/wallet/nft_wallet/__init__.py +0 -0
  342. chia/_tests/wallet/nft_wallet/config.py +4 -0
  343. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1493 -0
  344. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1024 -0
  345. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +375 -0
  346. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
  347. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
  348. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2584 -0
  349. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
  350. chia/_tests/wallet/rpc/__init__.py +0 -0
  351. chia/_tests/wallet/rpc/config.py +4 -0
  352. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +285 -0
  353. chia/_tests/wallet/rpc/test_wallet_rpc.py +3153 -0
  354. chia/_tests/wallet/simple_sync/__init__.py +0 -0
  355. chia/_tests/wallet/simple_sync/config.py +3 -0
  356. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +718 -0
  357. chia/_tests/wallet/sync/__init__.py +0 -0
  358. chia/_tests/wallet/sync/config.py +4 -0
  359. chia/_tests/wallet/sync/test_wallet_sync.py +1692 -0
  360. chia/_tests/wallet/test_address_type.py +189 -0
  361. chia/_tests/wallet/test_bech32m.py +45 -0
  362. chia/_tests/wallet/test_clvm_streamable.py +244 -0
  363. chia/_tests/wallet/test_coin_management.py +354 -0
  364. chia/_tests/wallet/test_coin_selection.py +588 -0
  365. chia/_tests/wallet/test_conditions.py +400 -0
  366. chia/_tests/wallet/test_debug_spend_bundle.py +218 -0
  367. chia/_tests/wallet/test_new_wallet_protocol.py +1174 -0
  368. chia/_tests/wallet/test_nft_store.py +192 -0
  369. chia/_tests/wallet/test_notifications.py +196 -0
  370. chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
  371. chia/_tests/wallet/test_puzzle_store.py +132 -0
  372. chia/_tests/wallet/test_sign_coin_spends.py +159 -0
  373. chia/_tests/wallet/test_signer_protocol.py +947 -0
  374. chia/_tests/wallet/test_singleton.py +122 -0
  375. chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
  376. chia/_tests/wallet/test_singleton_store.py +152 -0
  377. chia/_tests/wallet/test_taproot.py +19 -0
  378. chia/_tests/wallet/test_transaction_store.py +945 -0
  379. chia/_tests/wallet/test_util.py +185 -0
  380. chia/_tests/wallet/test_wallet.py +2139 -0
  381. chia/_tests/wallet/test_wallet_action_scope.py +85 -0
  382. chia/_tests/wallet/test_wallet_blockchain.py +111 -0
  383. chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
  384. chia/_tests/wallet/test_wallet_interested_store.py +43 -0
  385. chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
  386. chia/_tests/wallet/test_wallet_node.py +780 -0
  387. chia/_tests/wallet/test_wallet_retry.py +95 -0
  388. chia/_tests/wallet/test_wallet_state_manager.py +259 -0
  389. chia/_tests/wallet/test_wallet_test_framework.py +275 -0
  390. chia/_tests/wallet/test_wallet_trade_store.py +218 -0
  391. chia/_tests/wallet/test_wallet_user_store.py +34 -0
  392. chia/_tests/wallet/test_wallet_utils.py +156 -0
  393. chia/_tests/wallet/vc_wallet/__init__.py +0 -0
  394. chia/_tests/wallet/vc_wallet/config.py +3 -0
  395. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
  396. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
  397. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +830 -0
  398. chia/_tests/wallet/wallet_block_tools.py +327 -0
  399. chia/_tests/weight_proof/__init__.py +0 -0
  400. chia/_tests/weight_proof/config.py +3 -0
  401. chia/_tests/weight_proof/test_weight_proof.py +528 -0
  402. chia/apis.py +19 -0
  403. chia/clvm/__init__.py +0 -0
  404. chia/cmds/__init__.py +0 -0
  405. chia/cmds/beta.py +184 -0
  406. chia/cmds/beta_funcs.py +137 -0
  407. chia/cmds/check_wallet_db.py +420 -0
  408. chia/cmds/chia.py +151 -0
  409. chia/cmds/cmd_classes.py +323 -0
  410. chia/cmds/cmd_helpers.py +242 -0
  411. chia/cmds/cmds_util.py +488 -0
  412. chia/cmds/coin_funcs.py +275 -0
  413. chia/cmds/coins.py +182 -0
  414. chia/cmds/completion.py +49 -0
  415. chia/cmds/configure.py +332 -0
  416. chia/cmds/dao.py +1064 -0
  417. chia/cmds/dao_funcs.py +598 -0
  418. chia/cmds/data.py +708 -0
  419. chia/cmds/data_funcs.py +385 -0
  420. chia/cmds/db.py +87 -0
  421. chia/cmds/db_backup_func.py +77 -0
  422. chia/cmds/db_upgrade_func.py +452 -0
  423. chia/cmds/db_validate_func.py +184 -0
  424. chia/cmds/dev.py +18 -0
  425. chia/cmds/farm.py +100 -0
  426. chia/cmds/farm_funcs.py +200 -0
  427. chia/cmds/gh.py +275 -0
  428. chia/cmds/init.py +63 -0
  429. chia/cmds/init_funcs.py +367 -0
  430. chia/cmds/installers.py +131 -0
  431. chia/cmds/keys.py +527 -0
  432. chia/cmds/keys_funcs.py +863 -0
  433. chia/cmds/netspace.py +50 -0
  434. chia/cmds/netspace_funcs.py +54 -0
  435. chia/cmds/options.py +32 -0
  436. chia/cmds/param_types.py +238 -0
  437. chia/cmds/passphrase.py +131 -0
  438. chia/cmds/passphrase_funcs.py +292 -0
  439. chia/cmds/peer.py +51 -0
  440. chia/cmds/peer_funcs.py +129 -0
  441. chia/cmds/plotnft.py +260 -0
  442. chia/cmds/plotnft_funcs.py +405 -0
  443. chia/cmds/plots.py +230 -0
  444. chia/cmds/plotters.py +18 -0
  445. chia/cmds/rpc.py +208 -0
  446. chia/cmds/show.py +72 -0
  447. chia/cmds/show_funcs.py +215 -0
  448. chia/cmds/signer.py +296 -0
  449. chia/cmds/sim.py +225 -0
  450. chia/cmds/sim_funcs.py +509 -0
  451. chia/cmds/start.py +24 -0
  452. chia/cmds/start_funcs.py +109 -0
  453. chia/cmds/stop.py +62 -0
  454. chia/cmds/units.py +9 -0
  455. chia/cmds/wallet.py +1901 -0
  456. chia/cmds/wallet_funcs.py +1874 -0
  457. chia/consensus/__init__.py +0 -0
  458. chia/consensus/block_body_validation.py +562 -0
  459. chia/consensus/block_creation.py +546 -0
  460. chia/consensus/block_header_validation.py +1059 -0
  461. chia/consensus/block_record.py +31 -0
  462. chia/consensus/block_rewards.py +53 -0
  463. chia/consensus/blockchain.py +1087 -0
  464. chia/consensus/blockchain_interface.py +56 -0
  465. chia/consensus/coinbase.py +30 -0
  466. chia/consensus/condition_costs.py +9 -0
  467. chia/consensus/constants.py +49 -0
  468. chia/consensus/cost_calculator.py +15 -0
  469. chia/consensus/default_constants.py +89 -0
  470. chia/consensus/deficit.py +55 -0
  471. chia/consensus/difficulty_adjustment.py +412 -0
  472. chia/consensus/find_fork_point.py +111 -0
  473. chia/consensus/full_block_to_block_record.py +167 -0
  474. chia/consensus/get_block_challenge.py +106 -0
  475. chia/consensus/get_block_generator.py +27 -0
  476. chia/consensus/make_sub_epoch_summary.py +210 -0
  477. chia/consensus/multiprocess_validation.py +268 -0
  478. chia/consensus/pos_quality.py +19 -0
  479. chia/consensus/pot_iterations.py +67 -0
  480. chia/consensus/puzzles/__init__.py +0 -0
  481. chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
  482. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
  483. chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
  484. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
  485. chia/consensus/vdf_info_computation.py +156 -0
  486. chia/daemon/__init__.py +0 -0
  487. chia/daemon/client.py +252 -0
  488. chia/daemon/keychain_proxy.py +502 -0
  489. chia/daemon/keychain_server.py +365 -0
  490. chia/daemon/server.py +1606 -0
  491. chia/daemon/windows_signal.py +56 -0
  492. chia/data_layer/__init__.py +0 -0
  493. chia/data_layer/data_layer.py +1291 -0
  494. chia/data_layer/data_layer_api.py +33 -0
  495. chia/data_layer/data_layer_errors.py +50 -0
  496. chia/data_layer/data_layer_server.py +170 -0
  497. chia/data_layer/data_layer_util.py +985 -0
  498. chia/data_layer/data_layer_wallet.py +1311 -0
  499. chia/data_layer/data_store.py +2267 -0
  500. chia/data_layer/dl_wallet_store.py +407 -0
  501. chia/data_layer/download_data.py +389 -0
  502. chia/data_layer/puzzles/__init__.py +0 -0
  503. chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
  504. chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
  505. chia/data_layer/s3_plugin_config.yml +33 -0
  506. chia/data_layer/s3_plugin_service.py +468 -0
  507. chia/data_layer/util/__init__.py +0 -0
  508. chia/data_layer/util/benchmark.py +107 -0
  509. chia/data_layer/util/plugin.py +40 -0
  510. chia/farmer/__init__.py +0 -0
  511. chia/farmer/farmer.py +923 -0
  512. chia/farmer/farmer_api.py +820 -0
  513. chia/full_node/__init__.py +0 -0
  514. chia/full_node/bitcoin_fee_estimator.py +85 -0
  515. chia/full_node/block_height_map.py +271 -0
  516. chia/full_node/block_store.py +576 -0
  517. chia/full_node/bundle_tools.py +19 -0
  518. chia/full_node/coin_store.py +647 -0
  519. chia/full_node/fee_estimate.py +54 -0
  520. chia/full_node/fee_estimate_store.py +24 -0
  521. chia/full_node/fee_estimation.py +92 -0
  522. chia/full_node/fee_estimator.py +90 -0
  523. chia/full_node/fee_estimator_constants.py +38 -0
  524. chia/full_node/fee_estimator_interface.py +42 -0
  525. chia/full_node/fee_history.py +25 -0
  526. chia/full_node/fee_tracker.py +564 -0
  527. chia/full_node/full_node.py +3327 -0
  528. chia/full_node/full_node_api.py +2025 -0
  529. chia/full_node/full_node_store.py +1033 -0
  530. chia/full_node/hint_management.py +56 -0
  531. chia/full_node/hint_store.py +93 -0
  532. chia/full_node/mempool.py +589 -0
  533. chia/full_node/mempool_check_conditions.py +146 -0
  534. chia/full_node/mempool_manager.py +853 -0
  535. chia/full_node/pending_tx_cache.py +112 -0
  536. chia/full_node/puzzles/__init__.py +0 -0
  537. chia/full_node/puzzles/block_program_zero.clsp +14 -0
  538. chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
  539. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
  540. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
  541. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
  542. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
  543. chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
  544. chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
  545. chia/full_node/signage_point.py +16 -0
  546. chia/full_node/subscriptions.py +247 -0
  547. chia/full_node/sync_store.py +146 -0
  548. chia/full_node/tx_processing_queue.py +78 -0
  549. chia/full_node/util/__init__.py +0 -0
  550. chia/full_node/weight_proof.py +1720 -0
  551. chia/harvester/__init__.py +0 -0
  552. chia/harvester/harvester.py +272 -0
  553. chia/harvester/harvester_api.py +380 -0
  554. chia/introducer/__init__.py +0 -0
  555. chia/introducer/introducer.py +122 -0
  556. chia/introducer/introducer_api.py +70 -0
  557. chia/legacy/__init__.py +0 -0
  558. chia/legacy/keyring.py +155 -0
  559. chia/plot_sync/__init__.py +0 -0
  560. chia/plot_sync/delta.py +61 -0
  561. chia/plot_sync/exceptions.py +56 -0
  562. chia/plot_sync/receiver.py +386 -0
  563. chia/plot_sync/sender.py +340 -0
  564. chia/plot_sync/util.py +43 -0
  565. chia/plotters/__init__.py +0 -0
  566. chia/plotters/bladebit.py +388 -0
  567. chia/plotters/chiapos.py +63 -0
  568. chia/plotters/madmax.py +224 -0
  569. chia/plotters/plotters.py +577 -0
  570. chia/plotters/plotters_util.py +133 -0
  571. chia/plotting/__init__.py +0 -0
  572. chia/plotting/cache.py +213 -0
  573. chia/plotting/check_plots.py +283 -0
  574. chia/plotting/create_plots.py +278 -0
  575. chia/plotting/manager.py +436 -0
  576. chia/plotting/util.py +336 -0
  577. chia/pools/__init__.py +0 -0
  578. chia/pools/pool_config.py +110 -0
  579. chia/pools/pool_puzzles.py +459 -0
  580. chia/pools/pool_wallet.py +933 -0
  581. chia/pools/pool_wallet_info.py +118 -0
  582. chia/pools/puzzles/__init__.py +0 -0
  583. chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
  584. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
  585. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
  586. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
  587. chia/protocols/__init__.py +0 -0
  588. chia/protocols/farmer_protocol.py +102 -0
  589. chia/protocols/full_node_protocol.py +219 -0
  590. chia/protocols/harvester_protocol.py +216 -0
  591. chia/protocols/introducer_protocol.py +25 -0
  592. chia/protocols/pool_protocol.py +177 -0
  593. chia/protocols/protocol_message_types.py +139 -0
  594. chia/protocols/protocol_state_machine.py +87 -0
  595. chia/protocols/protocol_timing.py +8 -0
  596. chia/protocols/shared_protocol.py +86 -0
  597. chia/protocols/timelord_protocol.py +93 -0
  598. chia/protocols/wallet_protocol.py +401 -0
  599. chia/py.typed +0 -0
  600. chia/rpc/__init__.py +0 -0
  601. chia/rpc/crawler_rpc_api.py +80 -0
  602. chia/rpc/data_layer_rpc_api.py +644 -0
  603. chia/rpc/data_layer_rpc_client.py +188 -0
  604. chia/rpc/data_layer_rpc_util.py +58 -0
  605. chia/rpc/farmer_rpc_api.py +365 -0
  606. chia/rpc/farmer_rpc_client.py +86 -0
  607. chia/rpc/full_node_rpc_api.py +959 -0
  608. chia/rpc/full_node_rpc_client.py +292 -0
  609. chia/rpc/harvester_rpc_api.py +141 -0
  610. chia/rpc/harvester_rpc_client.py +54 -0
  611. chia/rpc/rpc_client.py +164 -0
  612. chia/rpc/rpc_server.py +521 -0
  613. chia/rpc/timelord_rpc_api.py +32 -0
  614. chia/rpc/util.py +93 -0
  615. chia/rpc/wallet_request_types.py +904 -0
  616. chia/rpc/wallet_rpc_api.py +4943 -0
  617. chia/rpc/wallet_rpc_client.py +1814 -0
  618. chia/seeder/__init__.py +0 -0
  619. chia/seeder/crawl_store.py +425 -0
  620. chia/seeder/crawler.py +410 -0
  621. chia/seeder/crawler_api.py +135 -0
  622. chia/seeder/dns_server.py +593 -0
  623. chia/seeder/peer_record.py +146 -0
  624. chia/seeder/start_crawler.py +92 -0
  625. chia/server/__init__.py +0 -0
  626. chia/server/address_manager.py +658 -0
  627. chia/server/address_manager_store.py +237 -0
  628. chia/server/api_protocol.py +116 -0
  629. chia/server/capabilities.py +24 -0
  630. chia/server/chia_policy.py +346 -0
  631. chia/server/introducer_peers.py +76 -0
  632. chia/server/node_discovery.py +714 -0
  633. chia/server/outbound_message.py +33 -0
  634. chia/server/rate_limit_numbers.py +214 -0
  635. chia/server/rate_limits.py +153 -0
  636. chia/server/server.py +741 -0
  637. chia/server/signal_handlers.py +120 -0
  638. chia/server/ssl_context.py +32 -0
  639. chia/server/start_data_layer.py +151 -0
  640. chia/server/start_farmer.py +98 -0
  641. chia/server/start_full_node.py +112 -0
  642. chia/server/start_harvester.py +93 -0
  643. chia/server/start_introducer.py +81 -0
  644. chia/server/start_service.py +316 -0
  645. chia/server/start_timelord.py +89 -0
  646. chia/server/start_wallet.py +113 -0
  647. chia/server/upnp.py +118 -0
  648. chia/server/ws_connection.py +766 -0
  649. chia/simulator/__init__.py +0 -0
  650. chia/simulator/add_blocks_in_batches.py +54 -0
  651. chia/simulator/block_tools.py +2054 -0
  652. chia/simulator/full_node_simulator.py +794 -0
  653. chia/simulator/keyring.py +128 -0
  654. chia/simulator/setup_services.py +506 -0
  655. chia/simulator/simulator_constants.py +13 -0
  656. chia/simulator/simulator_full_node_rpc_api.py +99 -0
  657. chia/simulator/simulator_full_node_rpc_client.py +60 -0
  658. chia/simulator/simulator_protocol.py +29 -0
  659. chia/simulator/simulator_test_tools.py +164 -0
  660. chia/simulator/socket.py +24 -0
  661. chia/simulator/ssl_certs.py +114 -0
  662. chia/simulator/ssl_certs_1.py +697 -0
  663. chia/simulator/ssl_certs_10.py +697 -0
  664. chia/simulator/ssl_certs_2.py +697 -0
  665. chia/simulator/ssl_certs_3.py +697 -0
  666. chia/simulator/ssl_certs_4.py +697 -0
  667. chia/simulator/ssl_certs_5.py +697 -0
  668. chia/simulator/ssl_certs_6.py +697 -0
  669. chia/simulator/ssl_certs_7.py +697 -0
  670. chia/simulator/ssl_certs_8.py +697 -0
  671. chia/simulator/ssl_certs_9.py +697 -0
  672. chia/simulator/start_simulator.py +143 -0
  673. chia/simulator/wallet_tools.py +246 -0
  674. chia/ssl/__init__.py +0 -0
  675. chia/ssl/chia_ca.crt +19 -0
  676. chia/ssl/chia_ca.key +28 -0
  677. chia/ssl/create_ssl.py +249 -0
  678. chia/ssl/dst_root_ca.pem +20 -0
  679. chia/timelord/__init__.py +0 -0
  680. chia/timelord/iters_from_block.py +50 -0
  681. chia/timelord/timelord.py +1226 -0
  682. chia/timelord/timelord_api.py +138 -0
  683. chia/timelord/timelord_launcher.py +190 -0
  684. chia/timelord/timelord_state.py +244 -0
  685. chia/timelord/types.py +22 -0
  686. chia/types/__init__.py +0 -0
  687. chia/types/aliases.py +35 -0
  688. chia/types/block_protocol.py +20 -0
  689. chia/types/blockchain_format/__init__.py +0 -0
  690. chia/types/blockchain_format/classgroup.py +5 -0
  691. chia/types/blockchain_format/coin.py +28 -0
  692. chia/types/blockchain_format/foliage.py +8 -0
  693. chia/types/blockchain_format/pool_target.py +5 -0
  694. chia/types/blockchain_format/program.py +269 -0
  695. chia/types/blockchain_format/proof_of_space.py +135 -0
  696. chia/types/blockchain_format/reward_chain_block.py +6 -0
  697. chia/types/blockchain_format/serialized_program.py +5 -0
  698. chia/types/blockchain_format/sized_bytes.py +11 -0
  699. chia/types/blockchain_format/slots.py +9 -0
  700. chia/types/blockchain_format/sub_epoch_summary.py +5 -0
  701. chia/types/blockchain_format/tree_hash.py +72 -0
  702. chia/types/blockchain_format/vdf.py +86 -0
  703. chia/types/clvm_cost.py +13 -0
  704. chia/types/coin_record.py +43 -0
  705. chia/types/coin_spend.py +115 -0
  706. chia/types/condition_opcodes.py +73 -0
  707. chia/types/condition_with_args.py +16 -0
  708. chia/types/eligible_coin_spends.py +365 -0
  709. chia/types/end_of_slot_bundle.py +5 -0
  710. chia/types/fee_rate.py +38 -0
  711. chia/types/full_block.py +5 -0
  712. chia/types/generator_types.py +13 -0
  713. chia/types/header_block.py +5 -0
  714. chia/types/internal_mempool_item.py +18 -0
  715. chia/types/mempool_inclusion_status.py +9 -0
  716. chia/types/mempool_item.py +85 -0
  717. chia/types/mempool_submission_status.py +30 -0
  718. chia/types/mojos.py +7 -0
  719. chia/types/peer_info.py +64 -0
  720. chia/types/signing_mode.py +29 -0
  721. chia/types/spend_bundle.py +30 -0
  722. chia/types/spend_bundle_conditions.py +7 -0
  723. chia/types/transaction_queue_entry.py +55 -0
  724. chia/types/unfinished_block.py +5 -0
  725. chia/types/unfinished_header_block.py +37 -0
  726. chia/types/validation_state.py +14 -0
  727. chia/types/weight_proof.py +49 -0
  728. chia/util/__init__.py +0 -0
  729. chia/util/action_scope.py +168 -0
  730. chia/util/async_pool.py +226 -0
  731. chia/util/augmented_chain.py +134 -0
  732. chia/util/batches.py +42 -0
  733. chia/util/bech32m.py +126 -0
  734. chia/util/beta_metrics.py +119 -0
  735. chia/util/block_cache.py +56 -0
  736. chia/util/byte_types.py +12 -0
  737. chia/util/check_fork_next_block.py +33 -0
  738. chia/util/chia_logging.py +144 -0
  739. chia/util/chia_version.py +33 -0
  740. chia/util/collection.py +17 -0
  741. chia/util/condition_tools.py +201 -0
  742. chia/util/config.py +367 -0
  743. chia/util/cpu.py +22 -0
  744. chia/util/db_synchronous.py +23 -0
  745. chia/util/db_version.py +32 -0
  746. chia/util/db_wrapper.py +430 -0
  747. chia/util/default_root.py +27 -0
  748. chia/util/dump_keyring.py +93 -0
  749. chia/util/english.txt +2048 -0
  750. chia/util/errors.py +353 -0
  751. chia/util/file_keyring.py +469 -0
  752. chia/util/files.py +97 -0
  753. chia/util/full_block_utils.py +345 -0
  754. chia/util/generator_tools.py +72 -0
  755. chia/util/hash.py +31 -0
  756. chia/util/initial-config.yaml +694 -0
  757. chia/util/inline_executor.py +26 -0
  758. chia/util/ints.py +19 -0
  759. chia/util/ip_address.py +39 -0
  760. chia/util/json_util.py +37 -0
  761. chia/util/keychain.py +676 -0
  762. chia/util/keyring_wrapper.py +327 -0
  763. chia/util/limited_semaphore.py +41 -0
  764. chia/util/lock.py +49 -0
  765. chia/util/log_exceptions.py +32 -0
  766. chia/util/logging.py +36 -0
  767. chia/util/lru_cache.py +31 -0
  768. chia/util/math.py +20 -0
  769. chia/util/network.py +182 -0
  770. chia/util/paginator.py +48 -0
  771. chia/util/path.py +31 -0
  772. chia/util/permissions.py +20 -0
  773. chia/util/prev_transaction_block.py +21 -0
  774. chia/util/priority_mutex.py +95 -0
  775. chia/util/profiler.py +197 -0
  776. chia/util/recursive_replace.py +24 -0
  777. chia/util/safe_cancel_task.py +16 -0
  778. chia/util/service_groups.py +47 -0
  779. chia/util/setproctitle.py +22 -0
  780. chia/util/significant_bits.py +32 -0
  781. chia/util/ssl_check.py +213 -0
  782. chia/util/streamable.py +642 -0
  783. chia/util/task_referencer.py +59 -0
  784. chia/util/task_timing.py +382 -0
  785. chia/util/timing.py +67 -0
  786. chia/util/vdf_prover.py +30 -0
  787. chia/util/virtual_project_analysis.py +540 -0
  788. chia/util/ws_message.py +66 -0
  789. chia/wallet/__init__.py +0 -0
  790. chia/wallet/cat_wallet/__init__.py +0 -0
  791. chia/wallet/cat_wallet/cat_constants.py +75 -0
  792. chia/wallet/cat_wallet/cat_info.py +47 -0
  793. chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
  794. chia/wallet/cat_wallet/cat_utils.py +164 -0
  795. chia/wallet/cat_wallet/cat_wallet.py +855 -0
  796. chia/wallet/cat_wallet/dao_cat_info.py +28 -0
  797. chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
  798. chia/wallet/cat_wallet/lineage_store.py +74 -0
  799. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  800. chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
  801. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
  802. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
  803. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
  804. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
  805. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
  806. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
  807. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
  808. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
  809. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
  810. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
  811. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
  812. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
  813. chia/wallet/coin_selection.py +188 -0
  814. chia/wallet/conditions.py +1512 -0
  815. chia/wallet/dao_wallet/__init__.py +0 -0
  816. chia/wallet/dao_wallet/dao_info.py +61 -0
  817. chia/wallet/dao_wallet/dao_utils.py +811 -0
  818. chia/wallet/dao_wallet/dao_wallet.py +2119 -0
  819. chia/wallet/db_wallet/__init__.py +0 -0
  820. chia/wallet/db_wallet/db_wallet_puzzles.py +111 -0
  821. chia/wallet/derivation_record.py +30 -0
  822. chia/wallet/derive_keys.py +146 -0
  823. chia/wallet/did_wallet/__init__.py +0 -0
  824. chia/wallet/did_wallet/did_info.py +39 -0
  825. chia/wallet/did_wallet/did_wallet.py +1494 -0
  826. chia/wallet/did_wallet/did_wallet_puzzles.py +221 -0
  827. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  828. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
  829. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
  830. chia/wallet/driver_protocol.py +26 -0
  831. chia/wallet/key_val_store.py +55 -0
  832. chia/wallet/lineage_proof.py +58 -0
  833. chia/wallet/nft_wallet/__init__.py +0 -0
  834. chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
  835. chia/wallet/nft_wallet/nft_info.py +120 -0
  836. chia/wallet/nft_wallet/nft_puzzles.py +305 -0
  837. chia/wallet/nft_wallet/nft_wallet.py +1687 -0
  838. chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
  839. chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
  840. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
  841. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
  842. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
  843. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
  844. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
  845. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
  846. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
  847. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
  848. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
  849. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
  850. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
  851. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
  852. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
  853. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
  854. chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
  855. chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
  856. chia/wallet/nft_wallet/uncurry_nft.py +217 -0
  857. chia/wallet/notification_manager.py +117 -0
  858. chia/wallet/notification_store.py +178 -0
  859. chia/wallet/outer_puzzles.py +84 -0
  860. chia/wallet/payment.py +33 -0
  861. chia/wallet/puzzle_drivers.py +118 -0
  862. chia/wallet/puzzles/__init__.py +0 -0
  863. chia/wallet/puzzles/augmented_condition.clsp +13 -0
  864. chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
  865. chia/wallet/puzzles/clawback/__init__.py +0 -0
  866. chia/wallet/puzzles/clawback/drivers.py +188 -0
  867. chia/wallet/puzzles/clawback/metadata.py +38 -0
  868. chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
  869. chia/wallet/puzzles/condition_codes.clib +77 -0
  870. chia/wallet/puzzles/curry-and-treehash.clib +102 -0
  871. chia/wallet/puzzles/curry.clib +135 -0
  872. chia/wallet/puzzles/curry_by_index.clib +16 -0
  873. chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
  874. chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
  875. chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
  876. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
  877. chia/wallet/puzzles/dao_finished_state.clsp +35 -0
  878. chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
  879. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
  880. chia/wallet/puzzles/dao_lockup.clsp +288 -0
  881. chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
  882. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
  883. chia/wallet/puzzles/dao_proposal.clsp +377 -0
  884. chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
  885. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
  886. chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
  887. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
  888. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
  889. chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
  890. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
  891. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
  892. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
  893. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
  894. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
  895. chia/wallet/puzzles/dao_treasury.clsp +115 -0
  896. chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
  897. chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
  898. chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
  899. chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
  900. chia/wallet/puzzles/json.clib +25 -0
  901. chia/wallet/puzzles/load_clvm.py +161 -0
  902. chia/wallet/puzzles/merkle_utils.clib +18 -0
  903. chia/wallet/puzzles/notification.clsp +7 -0
  904. chia/wallet/puzzles/notification.clsp.hex +1 -0
  905. chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
  906. chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
  907. chia/wallet/puzzles/p2_conditions.clsp +3 -0
  908. chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
  909. chia/wallet/puzzles/p2_conditions.py +26 -0
  910. chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
  911. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
  912. chia/wallet/puzzles/p2_delegated_conditions.py +21 -0
  913. chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
  914. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
  915. chia/wallet/puzzles/p2_delegated_puzzle.py +34 -0
  916. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
  917. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
  918. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +160 -0
  919. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
  920. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
  921. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +21 -0
  922. chia/wallet/puzzles/p2_parent.clsp +19 -0
  923. chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
  924. chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
  925. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
  926. chia/wallet/puzzles/p2_puzzle_hash.py +27 -0
  927. chia/wallet/puzzles/p2_singleton.clsp +30 -0
  928. chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
  929. chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
  930. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
  931. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
  932. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
  933. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
  934. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
  935. chia/wallet/puzzles/puzzle_utils.py +34 -0
  936. chia/wallet/puzzles/settlement_payments.clsp +49 -0
  937. chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
  938. chia/wallet/puzzles/sha256tree.clib +11 -0
  939. chia/wallet/puzzles/singleton_launcher.clsp +16 -0
  940. chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
  941. chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
  942. chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
  943. chia/wallet/puzzles/singleton_top_layer.py +296 -0
  944. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
  945. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
  946. chia/wallet/puzzles/singleton_top_layer_v1_1.py +345 -0
  947. chia/wallet/puzzles/singleton_truths.clib +21 -0
  948. chia/wallet/puzzles/tails.py +348 -0
  949. chia/wallet/puzzles/utility_macros.clib +48 -0
  950. chia/wallet/signer_protocol.py +125 -0
  951. chia/wallet/singleton.py +106 -0
  952. chia/wallet/singleton_record.py +30 -0
  953. chia/wallet/trade_manager.py +1102 -0
  954. chia/wallet/trade_record.py +67 -0
  955. chia/wallet/trading/__init__.py +0 -0
  956. chia/wallet/trading/offer.py +702 -0
  957. chia/wallet/trading/trade_status.py +13 -0
  958. chia/wallet/trading/trade_store.py +526 -0
  959. chia/wallet/transaction_record.py +158 -0
  960. chia/wallet/transaction_sorting.py +14 -0
  961. chia/wallet/uncurried_puzzle.py +17 -0
  962. chia/wallet/util/__init__.py +0 -0
  963. chia/wallet/util/address_type.py +55 -0
  964. chia/wallet/util/blind_signer_tl.py +164 -0
  965. chia/wallet/util/clvm_streamable.py +203 -0
  966. chia/wallet/util/compute_hints.py +66 -0
  967. chia/wallet/util/compute_memos.py +43 -0
  968. chia/wallet/util/curry_and_treehash.py +91 -0
  969. chia/wallet/util/debug_spend_bundle.py +232 -0
  970. chia/wallet/util/merkle_tree.py +100 -0
  971. chia/wallet/util/merkle_utils.py +102 -0
  972. chia/wallet/util/new_peak_queue.py +82 -0
  973. chia/wallet/util/notifications.py +12 -0
  974. chia/wallet/util/peer_request_cache.py +174 -0
  975. chia/wallet/util/pprint.py +39 -0
  976. chia/wallet/util/puzzle_compression.py +95 -0
  977. chia/wallet/util/puzzle_decorator.py +100 -0
  978. chia/wallet/util/puzzle_decorator_type.py +7 -0
  979. chia/wallet/util/query_filter.py +59 -0
  980. chia/wallet/util/transaction_type.py +23 -0
  981. chia/wallet/util/tx_config.py +158 -0
  982. chia/wallet/util/wallet_sync_utils.py +351 -0
  983. chia/wallet/util/wallet_types.py +72 -0
  984. chia/wallet/vc_wallet/__init__.py +0 -0
  985. chia/wallet/vc_wallet/cr_cat_drivers.py +664 -0
  986. chia/wallet/vc_wallet/cr_cat_wallet.py +877 -0
  987. chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
  988. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  989. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
  990. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
  991. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
  992. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
  993. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
  994. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
  995. chia/wallet/vc_wallet/vc_drivers.py +838 -0
  996. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  997. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
  998. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
  999. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
  1000. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
  1001. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
  1002. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
  1003. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
  1004. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
  1005. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
  1006. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
  1007. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
  1008. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
  1009. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
  1010. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
  1011. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
  1012. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
  1013. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
  1014. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
  1015. chia/wallet/vc_wallet/vc_store.py +263 -0
  1016. chia/wallet/vc_wallet/vc_wallet.py +638 -0
  1017. chia/wallet/wallet.py +698 -0
  1018. chia/wallet/wallet_action_scope.py +96 -0
  1019. chia/wallet/wallet_blockchain.py +244 -0
  1020. chia/wallet/wallet_coin_record.py +72 -0
  1021. chia/wallet/wallet_coin_store.py +351 -0
  1022. chia/wallet/wallet_info.py +35 -0
  1023. chia/wallet/wallet_interested_store.py +188 -0
  1024. chia/wallet/wallet_nft_store.py +279 -0
  1025. chia/wallet/wallet_node.py +1765 -0
  1026. chia/wallet/wallet_node_api.py +207 -0
  1027. chia/wallet/wallet_pool_store.py +119 -0
  1028. chia/wallet/wallet_protocol.py +90 -0
  1029. chia/wallet/wallet_puzzle_store.py +396 -0
  1030. chia/wallet/wallet_retry_store.py +70 -0
  1031. chia/wallet/wallet_singleton_store.py +259 -0
  1032. chia/wallet/wallet_spend_bundle.py +25 -0
  1033. chia/wallet/wallet_state_manager.py +2819 -0
  1034. chia/wallet/wallet_transaction_store.py +496 -0
  1035. chia/wallet/wallet_user_store.py +110 -0
  1036. chia/wallet/wallet_weight_proof_handler.py +126 -0
  1037. chia_blockchain-2.5.1rc1.dist-info/LICENSE +201 -0
  1038. chia_blockchain-2.5.1rc1.dist-info/METADATA +156 -0
  1039. chia_blockchain-2.5.1rc1.dist-info/RECORD +1042 -0
  1040. chia_blockchain-2.5.1rc1.dist-info/WHEEL +4 -0
  1041. chia_blockchain-2.5.1rc1.dist-info/entry_points.txt +17 -0
  1042. 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