chia-blockchain 2.5.0rc2__py3-none-any.whl → 2.5.1rc2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. chia/_tests/README.md +1 -1
  2. chia/_tests/blockchain/blockchain_test_utils.py +24 -26
  3. chia/_tests/blockchain/test_augmented_chain.py +6 -8
  4. chia/_tests/blockchain/test_blockchain.py +409 -307
  5. chia/_tests/blockchain/test_blockchain_transactions.py +56 -75
  6. chia/_tests/blockchain/test_build_chains.py +11 -13
  7. chia/_tests/blockchain/test_get_block_generator.py +8 -8
  8. chia/_tests/blockchain/test_lookup_fork_chain.py +3 -4
  9. chia/_tests/build-init-files.py +3 -4
  10. chia/_tests/build-job-matrix.py +9 -9
  11. chia/_tests/check_sql_statements.py +2 -3
  12. chia/_tests/clvm/benchmark_costs.py +1 -1
  13. chia/_tests/clvm/coin_store.py +7 -5
  14. chia/_tests/clvm/test_chialisp_deserialization.py +8 -8
  15. chia/_tests/clvm/test_condition_codes.py +2 -2
  16. chia/_tests/clvm/test_curry_and_treehash.py +2 -4
  17. chia/_tests/clvm/test_message_conditions.py +184 -0
  18. chia/_tests/clvm/test_puzzle_compression.py +1 -2
  19. chia/_tests/clvm/test_puzzle_drivers.py +3 -3
  20. chia/_tests/clvm/test_puzzles.py +13 -18
  21. chia/_tests/clvm/test_singletons.py +17 -17
  22. chia/_tests/clvm/test_spend_sim.py +7 -7
  23. chia/_tests/cmds/cmd_test_utils.py +42 -45
  24. chia/_tests/cmds/conftest.py +2 -2
  25. chia/_tests/cmds/test_click_types.py +21 -16
  26. chia/_tests/cmds/test_cmd_framework.py +255 -35
  27. chia/_tests/cmds/test_cmds_util.py +2 -2
  28. chia/_tests/cmds/test_daemon.py +3 -3
  29. chia/_tests/cmds/test_dev_gh.py +131 -0
  30. chia/_tests/cmds/test_farm_cmd.py +1 -2
  31. chia/_tests/cmds/test_show.py +6 -6
  32. chia/_tests/cmds/test_tx_config_args.py +2 -1
  33. chia/_tests/cmds/wallet/test_dao.py +23 -23
  34. chia/_tests/cmds/wallet/test_did.py +29 -29
  35. chia/_tests/cmds/wallet/test_nft.py +24 -23
  36. chia/_tests/cmds/wallet/test_notifications.py +8 -8
  37. chia/_tests/cmds/wallet/test_tx_decorators.py +3 -3
  38. chia/_tests/cmds/wallet/test_vcs.py +97 -73
  39. chia/_tests/cmds/wallet/test_wallet.py +74 -75
  40. chia/_tests/cmds/wallet/test_wallet_check.py +5 -7
  41. chia/_tests/conftest.py +153 -38
  42. chia/_tests/connection_utils.py +7 -6
  43. chia/_tests/core/cmds/test_beta.py +3 -3
  44. chia/_tests/core/cmds/test_keys.py +6 -6
  45. chia/_tests/core/cmds/test_wallet.py +3 -3
  46. chia/_tests/core/consensus/test_block_creation.py +3 -5
  47. chia/_tests/core/custom_types/test_coin.py +1 -3
  48. chia/_tests/core/custom_types/test_spend_bundle.py +3 -4
  49. chia/_tests/core/daemon/test_daemon.py +58 -58
  50. chia/_tests/core/daemon/test_keychain_proxy.py +2 -1
  51. chia/_tests/core/data_layer/conftest.py +4 -3
  52. chia/_tests/core/data_layer/test_data_cli.py +1 -2
  53. chia/_tests/core/data_layer/test_data_layer.py +5 -5
  54. chia/_tests/core/data_layer/test_data_layer_util.py +8 -9
  55. chia/_tests/core/data_layer/test_data_rpc.py +75 -93
  56. chia/_tests/core/data_layer/test_data_store.py +38 -37
  57. chia/_tests/core/data_layer/test_data_store_schema.py +11 -11
  58. chia/_tests/core/data_layer/util.py +11 -10
  59. chia/_tests/core/farmer/test_farmer_api.py +6 -4
  60. chia/_tests/core/full_node/full_sync/test_full_sync.py +5 -10
  61. chia/_tests/core/full_node/ram_db.py +2 -2
  62. chia/_tests/core/full_node/stores/test_block_store.py +113 -11
  63. chia/_tests/core/full_node/stores/test_coin_store.py +37 -28
  64. chia/_tests/core/full_node/stores/test_full_node_store.py +34 -30
  65. chia/_tests/core/full_node/stores/test_hint_store.py +3 -4
  66. chia/_tests/core/full_node/test_address_manager.py +2 -2
  67. chia/_tests/core/full_node/test_block_height_map.py +1 -1
  68. chia/_tests/core/full_node/test_conditions.py +10 -12
  69. chia/_tests/core/full_node/test_full_node.py +2077 -1822
  70. chia/_tests/core/full_node/test_generator_tools.py +4 -4
  71. chia/_tests/core/full_node/test_hint_management.py +2 -2
  72. chia/_tests/core/full_node/test_performance.py +2 -5
  73. chia/_tests/core/full_node/test_subscriptions.py +4 -4
  74. chia/_tests/core/full_node/test_tx_processing_queue.py +5 -4
  75. chia/_tests/core/make_block_generator.py +5 -7
  76. chia/_tests/core/mempool/test_mempool.py +205 -208
  77. chia/_tests/core/mempool/test_mempool_fee_protocol.py +5 -5
  78. chia/_tests/core/mempool/test_mempool_item_queries.py +2 -4
  79. chia/_tests/core/mempool/test_mempool_manager.py +109 -80
  80. chia/_tests/core/mempool/test_mempool_performance.py +3 -4
  81. chia/_tests/core/mempool/test_singleton_fast_forward.py +12 -12
  82. chia/_tests/core/server/flood.py +6 -4
  83. chia/_tests/core/server/serve.py +10 -7
  84. chia/_tests/core/server/test_api_protocol.py +21 -0
  85. chia/_tests/core/server/test_capabilities.py +3 -5
  86. chia/_tests/core/server/test_dos.py +15 -16
  87. chia/_tests/core/server/test_loop.py +14 -10
  88. chia/_tests/core/server/test_node_discovery.py +1 -2
  89. chia/_tests/core/server/test_rate_limits.py +156 -44
  90. chia/_tests/core/server/test_server.py +8 -7
  91. chia/_tests/core/services/test_services.py +59 -37
  92. chia/_tests/core/ssl/test_ssl.py +5 -3
  93. chia/_tests/core/test_cost_calculation.py +5 -6
  94. chia/_tests/core/test_crawler.py +2 -2
  95. chia/_tests/core/test_db_conversion.py +5 -4
  96. chia/_tests/core/test_db_validation.py +6 -5
  97. chia/_tests/core/test_farmer_harvester_rpc.py +8 -7
  98. chia/_tests/core/test_filter.py +3 -5
  99. chia/_tests/core/test_full_node_rpc.py +64 -90
  100. chia/_tests/core/test_merkle_set.py +10 -10
  101. chia/_tests/core/test_program.py +2 -4
  102. chia/_tests/core/test_rpc_util.py +1 -2
  103. chia/_tests/core/test_seeder.py +124 -12
  104. chia/_tests/core/util/test_block_cache.py +5 -5
  105. chia/_tests/core/util/test_cached_bls.py +3 -3
  106. chia/_tests/core/util/test_config.py +13 -13
  107. chia/_tests/core/util/test_files.py +2 -2
  108. chia/_tests/core/util/test_jsonify.py +9 -9
  109. chia/_tests/core/util/test_keychain.py +13 -5
  110. chia/_tests/core/util/test_keyring_wrapper.py +6 -5
  111. chia/_tests/core/util/test_log_exceptions.py +3 -3
  112. chia/_tests/core/util/test_streamable.py +38 -38
  113. chia/_tests/db/test_db_wrapper.py +13 -12
  114. chia/_tests/environments/common.py +2 -2
  115. chia/_tests/environments/full_node.py +2 -2
  116. chia/_tests/environments/wallet.py +109 -48
  117. chia/_tests/farmer_harvester/test_farmer.py +35 -35
  118. chia/_tests/farmer_harvester/test_farmer_harvester.py +17 -17
  119. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +6 -5
  120. chia/_tests/farmer_harvester/test_third_party_harvesters.py +73 -46
  121. chia/_tests/fee_estimation/test_fee_estimation_integration.py +8 -8
  122. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +47 -47
  123. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +6 -7
  124. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +11 -11
  125. chia/_tests/generator/test_compression.py +13 -30
  126. chia/_tests/generator/test_generator_types.py +3 -3
  127. chia/_tests/generator/test_rom.py +7 -9
  128. chia/_tests/plot_sync/test_delta.py +2 -3
  129. chia/_tests/plot_sync/test_plot_sync.py +25 -24
  130. chia/_tests/plot_sync/test_receiver.py +9 -9
  131. chia/_tests/plot_sync/test_sender.py +1 -1
  132. chia/_tests/plot_sync/test_sync_simulated.py +27 -26
  133. chia/_tests/plot_sync/util.py +2 -1
  134. chia/_tests/plotting/test_plot_manager.py +54 -11
  135. chia/_tests/plotting/util.py +2 -3
  136. chia/_tests/pools/test_pool_cli_parsing.py +128 -0
  137. chia/_tests/pools/test_pool_cmdline.py +993 -15
  138. chia/_tests/pools/test_pool_config.py +3 -5
  139. chia/_tests/pools/test_pool_puzzles_lifecycle.py +10 -11
  140. chia/_tests/pools/test_pool_rpc.py +203 -90
  141. chia/_tests/pools/test_pool_wallet.py +12 -8
  142. chia/_tests/pools/test_wallet_pool_store.py +3 -3
  143. chia/_tests/process_junit.py +16 -17
  144. chia/_tests/rpc/test_rpc_client.py +59 -2
  145. chia/_tests/rpc/test_rpc_server.py +183 -0
  146. chia/_tests/simulation/test_simulation.py +5 -5
  147. chia/_tests/simulation/test_simulator.py +8 -10
  148. chia/_tests/simulation/test_start_simulator.py +5 -4
  149. chia/_tests/timelord/test_new_peak.py +19 -19
  150. chia/_tests/tools/test_run_block.py +1 -2
  151. chia/_tests/tools/test_virtual_project.py +591 -0
  152. chia/_tests/util/benchmark_cost.py +9 -9
  153. chia/_tests/util/benchmarks.py +1 -2
  154. chia/_tests/util/blockchain.py +12 -11
  155. chia/_tests/util/blockchain_mock.py +15 -15
  156. chia/_tests/util/build_network_protocol_files.py +12 -12
  157. chia/_tests/util/db_connection.py +3 -2
  158. chia/_tests/util/full_sync.py +14 -6
  159. chia/_tests/util/gen_ssl_certs.py +4 -5
  160. chia/_tests/util/generator_tools_testing.py +5 -7
  161. chia/_tests/util/get_name_puzzle_conditions.py +52 -0
  162. chia/_tests/util/key_tool.py +2 -3
  163. chia/_tests/util/misc.py +59 -106
  164. chia/_tests/util/network_protocol_data.py +7 -9
  165. chia/_tests/util/protocol_messages_json.py +112 -111
  166. chia/_tests/util/rpc.py +3 -0
  167. chia/_tests/util/run_block.py +16 -16
  168. chia/_tests/util/setup_nodes.py +25 -23
  169. chia/{clvm → _tests/util}/spend_sim.py +59 -55
  170. chia/_tests/util/split_managers.py +12 -9
  171. chia/_tests/util/temp_file.py +1 -1
  172. chia/_tests/util/test_action_scope.py +2 -1
  173. chia/_tests/util/test_async_pool.py +8 -8
  174. chia/_tests/util/test_build_job_matrix.py +2 -3
  175. chia/_tests/util/test_condition_tools.py +4 -6
  176. chia/_tests/util/test_config.py +5 -5
  177. chia/_tests/util/test_dump_keyring.py +1 -1
  178. chia/_tests/util/test_full_block_utils.py +19 -11
  179. chia/_tests/util/test_limited_semaphore.py +4 -3
  180. chia/_tests/util/test_logging_filter.py +2 -3
  181. chia/_tests/util/test_misc.py +29 -28
  182. chia/_tests/util/test_network.py +32 -31
  183. chia/_tests/util/test_network_protocol_files.py +2 -3
  184. chia/_tests/util/test_network_protocol_json.py +1 -0
  185. chia/_tests/util/test_network_protocol_test.py +18 -19
  186. chia/_tests/util/test_paginator.py +3 -4
  187. chia/_tests/util/test_pprint.py +1 -1
  188. chia/_tests/util/test_priority_mutex.py +18 -17
  189. chia/_tests/util/test_recursive_replace.py +2 -2
  190. chia/_tests/util/test_testnet_overrides.py +3 -3
  191. chia/_tests/util/test_timing.py +1 -1
  192. chia/_tests/util/test_trusted_peer.py +2 -2
  193. chia/_tests/util/time_out_assert.py +43 -6
  194. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +13 -13
  195. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +1 -1
  196. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +117 -29
  197. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +15 -15
  198. chia/_tests/wallet/cat_wallet/test_trades.py +50 -28
  199. chia/_tests/wallet/clawback/test_clawback_decorator.py +3 -5
  200. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +6 -6
  201. chia/_tests/wallet/clawback/test_clawback_metadata.py +1 -2
  202. chia/_tests/wallet/conftest.py +135 -74
  203. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +25 -17
  204. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +75 -75
  205. chia/_tests/wallet/db_wallet/test_db_graftroot.py +10 -12
  206. chia/_tests/wallet/db_wallet/test_dl_offers.py +6 -6
  207. chia/_tests/wallet/db_wallet/test_dl_wallet.py +18 -18
  208. chia/_tests/wallet/did_wallet/test_did.py +1277 -474
  209. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +12 -11
  210. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +115 -105
  211. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +6 -7
  212. chia/_tests/wallet/nft_wallet/test_nft_offers.py +16 -16
  213. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +3 -3
  214. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +38 -12
  215. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +1 -1
  216. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +31 -33
  217. chia/_tests/wallet/rpc/test_wallet_rpc.py +218 -171
  218. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +36 -37
  219. chia/_tests/wallet/sync/test_wallet_sync.py +241 -78
  220. chia/_tests/wallet/test_address_type.py +20 -20
  221. chia/_tests/wallet/test_clvm_streamable.py +5 -5
  222. chia/_tests/wallet/test_coin_management.py +354 -0
  223. chia/_tests/wallet/test_coin_selection.py +34 -35
  224. chia/_tests/wallet/test_conditions.py +28 -16
  225. chia/_tests/wallet/test_debug_spend_bundle.py +156 -14
  226. chia/_tests/wallet/test_new_wallet_protocol.py +29 -31
  227. chia/_tests/wallet/test_nft_store.py +1 -2
  228. chia/_tests/wallet/test_notifications.py +2 -2
  229. chia/_tests/wallet/test_offer_parsing_performance.py +1 -1
  230. chia/_tests/wallet/test_puzzle_store.py +2 -3
  231. chia/_tests/wallet/test_sign_coin_spends.py +3 -3
  232. chia/_tests/wallet/test_signer_protocol.py +33 -34
  233. chia/_tests/wallet/test_singleton_lifecycle_fast.py +29 -29
  234. chia/_tests/wallet/test_taproot.py +1 -1
  235. chia/_tests/wallet/test_transaction_store.py +23 -19
  236. chia/_tests/wallet/test_util.py +36 -32
  237. chia/_tests/wallet/test_wallet.py +37 -37
  238. chia/_tests/wallet/test_wallet_action_scope.py +8 -8
  239. chia/_tests/wallet/test_wallet_blockchain.py +4 -6
  240. chia/_tests/wallet/test_wallet_coin_store.py +34 -34
  241. chia/_tests/wallet/test_wallet_node.py +69 -72
  242. chia/_tests/wallet/test_wallet_retry.py +3 -3
  243. chia/_tests/wallet/test_wallet_state_manager.py +12 -5
  244. chia/_tests/wallet/test_wallet_trade_store.py +2 -2
  245. chia/_tests/wallet/test_wallet_utils.py +5 -4
  246. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +3 -3
  247. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +18 -18
  248. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +69 -40
  249. chia/_tests/wallet/wallet_block_tools.py +27 -27
  250. chia/_tests/weight_proof/test_weight_proof.py +30 -30
  251. chia/apis.py +19 -0
  252. chia/cmds/beta.py +8 -7
  253. chia/cmds/beta_funcs.py +15 -11
  254. chia/cmds/check_wallet_db.py +29 -27
  255. chia/cmds/chia.py +17 -9
  256. chia/cmds/cmd_classes.py +87 -79
  257. chia/cmds/cmd_helpers.py +242 -0
  258. chia/cmds/cmds_util.py +56 -66
  259. chia/cmds/coin_funcs.py +168 -153
  260. chia/cmds/coins.py +156 -194
  261. chia/cmds/configure.py +4 -3
  262. chia/cmds/dao.py +89 -33
  263. chia/cmds/dao_funcs.py +55 -33
  264. chia/cmds/data.py +7 -6
  265. chia/cmds/data_funcs.py +26 -21
  266. chia/cmds/db.py +4 -3
  267. chia/cmds/db_backup_func.py +2 -2
  268. chia/cmds/db_upgrade_func.py +3 -3
  269. chia/cmds/db_validate_func.py +2 -2
  270. chia/cmds/dev.py +2 -0
  271. chia/cmds/farm.py +18 -5
  272. chia/cmds/farm_funcs.py +17 -24
  273. chia/cmds/gh.py +275 -0
  274. chia/cmds/init.py +4 -11
  275. chia/cmds/init_funcs.py +9 -9
  276. chia/cmds/installers.py +5 -3
  277. chia/cmds/keys.py +56 -39
  278. chia/cmds/keys_funcs.py +30 -31
  279. chia/cmds/netspace.py +6 -3
  280. chia/cmds/netspace_funcs.py +3 -2
  281. chia/cmds/param_types.py +16 -6
  282. chia/cmds/passphrase.py +8 -7
  283. chia/cmds/passphrase_funcs.py +7 -61
  284. chia/cmds/peer.py +2 -1
  285. chia/cmds/peer_funcs.py +5 -5
  286. chia/cmds/plotnft.py +207 -153
  287. chia/cmds/plotnft_funcs.py +205 -174
  288. chia/cmds/plots.py +14 -6
  289. chia/cmds/plotters.py +2 -1
  290. chia/cmds/rpc.py +48 -28
  291. chia/cmds/show.py +2 -1
  292. chia/cmds/show_funcs.py +7 -6
  293. chia/cmds/signer.py +50 -58
  294. chia/cmds/sim.py +22 -14
  295. chia/cmds/sim_funcs.py +11 -11
  296. chia/cmds/start.py +3 -3
  297. chia/cmds/start_funcs.py +9 -12
  298. chia/cmds/stop.py +4 -3
  299. chia/cmds/units.py +1 -3
  300. chia/cmds/wallet.py +252 -96
  301. chia/cmds/wallet_funcs.py +217 -143
  302. chia/consensus/block_body_validation.py +133 -86
  303. chia/consensus/block_creation.py +42 -21
  304. chia/consensus/block_header_validation.py +32 -37
  305. chia/consensus/block_record.py +1 -2
  306. chia/consensus/blockchain.py +167 -180
  307. chia/consensus/blockchain_interface.py +10 -10
  308. chia/consensus/constants.py +2 -2
  309. chia/consensus/default_constants.py +3 -4
  310. chia/consensus/difficulty_adjustment.py +5 -5
  311. chia/consensus/find_fork_point.py +5 -5
  312. chia/consensus/full_block_to_block_record.py +4 -4
  313. chia/consensus/get_block_challenge.py +2 -2
  314. chia/consensus/get_block_generator.py +4 -3
  315. chia/consensus/multiprocess_validation.py +207 -304
  316. chia/consensus/vdf_info_computation.py +3 -3
  317. chia/daemon/client.py +46 -27
  318. chia/daemon/keychain_proxy.py +10 -9
  319. chia/daemon/keychain_server.py +18 -18
  320. chia/daemon/server.py +103 -113
  321. chia/daemon/windows_signal.py +2 -2
  322. chia/data_layer/data_layer.py +64 -76
  323. chia/data_layer/data_layer_api.py +8 -0
  324. chia/data_layer/data_layer_errors.py +3 -3
  325. chia/data_layer/data_layer_server.py +2 -2
  326. chia/data_layer/data_layer_util.py +71 -71
  327. chia/data_layer/data_layer_wallet.py +63 -67
  328. chia/data_layer/data_store.py +72 -72
  329. chia/data_layer/dl_wallet_store.py +10 -10
  330. chia/data_layer/download_data.py +5 -5
  331. chia/data_layer/s3_plugin_service.py +9 -9
  332. chia/data_layer/util/benchmark.py +0 -1
  333. chia/data_layer/util/plugin.py +2 -3
  334. chia/farmer/farmer.py +46 -43
  335. chia/farmer/farmer_api.py +27 -21
  336. chia/full_node/block_height_map.py +6 -6
  337. chia/full_node/block_store.py +41 -35
  338. chia/full_node/coin_store.py +42 -41
  339. chia/full_node/fee_estimate.py +2 -2
  340. chia/full_node/fee_estimation.py +1 -2
  341. chia/full_node/fee_history.py +5 -6
  342. chia/full_node/fee_tracker.py +24 -24
  343. chia/full_node/full_node.py +574 -300
  344. chia/full_node/full_node_api.py +181 -130
  345. chia/full_node/full_node_store.py +43 -43
  346. chia/full_node/hint_management.py +4 -4
  347. chia/full_node/hint_store.py +9 -10
  348. chia/full_node/mempool.py +25 -19
  349. chia/full_node/mempool_check_conditions.py +11 -42
  350. chia/full_node/mempool_manager.py +48 -53
  351. chia/full_node/pending_tx_cache.py +9 -9
  352. chia/full_node/subscriptions.py +23 -24
  353. chia/full_node/sync_store.py +8 -7
  354. chia/full_node/tx_processing_queue.py +3 -3
  355. chia/full_node/util/__init__.py +0 -0
  356. chia/full_node/weight_proof.py +79 -78
  357. chia/harvester/harvester.py +9 -8
  358. chia/harvester/harvester_api.py +19 -13
  359. chia/introducer/introducer.py +7 -5
  360. chia/introducer/introducer_api.py +9 -3
  361. chia/legacy/keyring.py +6 -5
  362. chia/plot_sync/delta.py +8 -8
  363. chia/plot_sync/receiver.py +12 -11
  364. chia/plot_sync/sender.py +15 -12
  365. chia/plotters/bladebit.py +12 -12
  366. chia/plotters/chiapos.py +2 -2
  367. chia/plotters/madmax.py +8 -8
  368. chia/plotters/plotters.py +6 -6
  369. chia/plotters/plotters_util.py +6 -4
  370. chia/plotting/cache.py +8 -7
  371. chia/plotting/check_plots.py +8 -8
  372. chia/plotting/create_plots.py +6 -6
  373. chia/plotting/manager.py +22 -22
  374. chia/plotting/util.py +31 -19
  375. chia/pools/pool_config.py +7 -7
  376. chia/pools/pool_puzzles.py +16 -16
  377. chia/pools/pool_wallet.py +64 -57
  378. chia/pools/pool_wallet_info.py +3 -3
  379. chia/protocols/full_node_protocol.py +3 -3
  380. chia/protocols/harvester_protocol.py +12 -12
  381. chia/protocols/introducer_protocol.py +1 -2
  382. chia/protocols/protocol_message_types.py +4 -4
  383. chia/protocols/protocol_state_machine.py +2 -2
  384. chia/protocols/protocol_timing.py +1 -0
  385. chia/protocols/shared_protocol.py +3 -3
  386. chia/protocols/timelord_protocol.py +2 -2
  387. chia/protocols/wallet_protocol.py +33 -33
  388. chia/rpc/crawler_rpc_api.py +12 -7
  389. chia/rpc/data_layer_rpc_api.py +49 -44
  390. chia/rpc/data_layer_rpc_client.py +41 -41
  391. chia/rpc/data_layer_rpc_util.py +7 -11
  392. chia/rpc/farmer_rpc_api.py +32 -27
  393. chia/rpc/farmer_rpc_client.py +14 -14
  394. chia/rpc/full_node_rpc_api.py +53 -48
  395. chia/rpc/full_node_rpc_client.py +30 -30
  396. chia/rpc/harvester_rpc_api.py +16 -11
  397. chia/rpc/harvester_rpc_client.py +6 -6
  398. chia/rpc/rpc_client.py +34 -14
  399. chia/rpc/rpc_server.py +117 -43
  400. chia/rpc/timelord_rpc_api.py +9 -4
  401. chia/rpc/util.py +11 -211
  402. chia/rpc/wallet_request_types.py +276 -60
  403. chia/rpc/wallet_rpc_api.py +563 -399
  404. chia/rpc/wallet_rpc_client.py +220 -250
  405. chia/seeder/crawl_store.py +6 -8
  406. chia/seeder/crawler.py +23 -36
  407. chia/seeder/crawler_api.py +28 -22
  408. chia/seeder/dns_server.py +99 -50
  409. chia/seeder/start_crawler.py +13 -9
  410. chia/server/address_manager.py +19 -19
  411. chia/server/address_manager_store.py +17 -17
  412. chia/server/api_protocol.py +106 -1
  413. chia/server/capabilities.py +3 -3
  414. chia/server/chia_policy.py +17 -16
  415. chia/server/introducer_peers.py +3 -3
  416. chia/server/node_discovery.py +34 -38
  417. chia/server/rate_limit_numbers.py +26 -16
  418. chia/server/rate_limits.py +67 -27
  419. chia/server/server.py +52 -31
  420. chia/server/signal_handlers.py +6 -3
  421. chia/server/ssl_context.py +5 -5
  422. chia/server/start_data_layer.py +37 -23
  423. chia/server/start_farmer.py +28 -16
  424. chia/server/start_full_node.py +29 -23
  425. chia/server/start_harvester.py +28 -15
  426. chia/server/start_introducer.py +27 -15
  427. chia/server/start_service.py +17 -29
  428. chia/server/start_timelord.py +25 -18
  429. chia/server/start_wallet.py +22 -18
  430. chia/server/upnp.py +4 -3
  431. chia/server/ws_connection.py +68 -54
  432. chia/simulator/add_blocks_in_batches.py +54 -0
  433. chia/simulator/block_tools.py +65 -64
  434. chia/simulator/full_node_simulator.py +66 -74
  435. chia/simulator/setup_services.py +10 -9
  436. chia/simulator/simulator_full_node_rpc_api.py +12 -14
  437. chia/simulator/simulator_full_node_rpc_client.py +3 -5
  438. chia/simulator/simulator_test_tools.py +8 -7
  439. chia/simulator/socket.py +1 -4
  440. chia/simulator/ssl_certs.py +5 -5
  441. chia/simulator/ssl_certs_1.py +2 -4
  442. chia/simulator/ssl_certs_10.py +2 -4
  443. chia/simulator/ssl_certs_2.py +2 -4
  444. chia/simulator/ssl_certs_3.py +2 -4
  445. chia/simulator/ssl_certs_4.py +2 -4
  446. chia/simulator/ssl_certs_5.py +2 -4
  447. chia/simulator/ssl_certs_6.py +2 -4
  448. chia/simulator/ssl_certs_7.py +2 -4
  449. chia/simulator/ssl_certs_8.py +2 -4
  450. chia/simulator/ssl_certs_9.py +2 -4
  451. chia/simulator/start_simulator.py +14 -6
  452. chia/simulator/wallet_tools.py +21 -20
  453. chia/ssl/create_ssl.py +11 -11
  454. chia/timelord/iters_from_block.py +2 -2
  455. chia/timelord/timelord.py +57 -33
  456. chia/timelord/timelord_api.py +12 -6
  457. chia/timelord/timelord_launcher.py +10 -8
  458. chia/timelord/timelord_state.py +5 -5
  459. chia/types/block_protocol.py +2 -2
  460. chia/types/blockchain_format/coin.py +3 -3
  461. chia/types/blockchain_format/program.py +17 -18
  462. chia/types/blockchain_format/tree_hash.py +9 -9
  463. chia/types/coin_spend.py +8 -8
  464. chia/types/condition_with_args.py +1 -2
  465. chia/types/eligible_coin_spends.py +16 -15
  466. chia/types/generator_types.py +1 -2
  467. chia/types/internal_mempool_item.py +1 -2
  468. chia/types/mempool_item.py +7 -7
  469. chia/types/mempool_submission_status.py +2 -2
  470. chia/types/peer_info.py +1 -1
  471. chia/types/spend_bundle.py +1 -2
  472. chia/types/transaction_queue_entry.py +2 -2
  473. chia/types/unfinished_header_block.py +2 -2
  474. chia/types/validation_state.py +14 -0
  475. chia/types/weight_proof.py +5 -6
  476. chia/util/action_scope.py +8 -8
  477. chia/util/async_pool.py +6 -4
  478. chia/util/augmented_chain.py +13 -9
  479. chia/util/batches.py +5 -2
  480. chia/util/bech32m.py +14 -11
  481. chia/util/beta_metrics.py +5 -4
  482. chia/util/block_cache.py +5 -5
  483. chia/util/byte_types.py +2 -0
  484. chia/util/check_fork_next_block.py +3 -2
  485. chia/util/chia_logging.py +41 -21
  486. chia/util/collection.py +3 -3
  487. chia/util/condition_tools.py +18 -18
  488. chia/util/config.py +26 -25
  489. chia/util/cpu.py +2 -0
  490. chia/util/db_synchronous.py +2 -0
  491. chia/util/db_version.py +2 -0
  492. chia/util/db_wrapper.py +13 -10
  493. chia/util/default_root.py +17 -0
  494. chia/util/dump_keyring.py +6 -6
  495. chia/util/errors.py +5 -3
  496. chia/util/file_keyring.py +22 -33
  497. chia/util/files.py +2 -0
  498. chia/util/full_block_utils.py +31 -7
  499. chia/util/generator_tools.py +18 -8
  500. chia/util/hash.py +3 -1
  501. chia/util/initial-config.yaml +19 -0
  502. chia/util/inline_executor.py +2 -0
  503. chia/util/ip_address.py +39 -0
  504. chia/util/json_util.py +0 -4
  505. chia/util/keychain.py +27 -24
  506. chia/util/keyring_wrapper.py +65 -4
  507. chia/util/limited_semaphore.py +3 -1
  508. chia/util/lock.py +4 -2
  509. chia/util/log_exceptions.py +5 -2
  510. chia/util/logging.py +3 -1
  511. chia/util/lru_cache.py +2 -0
  512. chia/util/math.py +4 -4
  513. chia/util/network.py +15 -73
  514. chia/util/paginator.py +3 -1
  515. chia/util/path.py +2 -0
  516. chia/util/permissions.py +3 -2
  517. chia/util/prev_transaction_block.py +1 -3
  518. chia/util/priority_mutex.py +6 -3
  519. chia/util/profiler.py +7 -4
  520. chia/util/recursive_replace.py +2 -0
  521. chia/util/safe_cancel_task.py +2 -0
  522. chia/util/service_groups.py +2 -2
  523. chia/util/setproctitle.py +2 -0
  524. chia/util/significant_bits.py +2 -0
  525. chia/util/ssl_check.py +11 -11
  526. chia/util/streamable.py +44 -56
  527. chia/util/task_referencer.py +59 -0
  528. chia/util/task_timing.py +22 -18
  529. chia/util/timing.py +4 -1
  530. chia/util/vdf_prover.py +2 -3
  531. chia/util/virtual_project_analysis.py +540 -0
  532. chia/util/ws_message.py +6 -6
  533. chia/wallet/cat_wallet/cat_info.py +3 -3
  534. chia/wallet/cat_wallet/cat_outer_puzzle.py +3 -3
  535. chia/wallet/cat_wallet/cat_utils.py +5 -4
  536. chia/wallet/cat_wallet/cat_wallet.py +56 -70
  537. chia/wallet/cat_wallet/dao_cat_info.py +3 -3
  538. chia/wallet/cat_wallet/dao_cat_wallet.py +18 -18
  539. chia/wallet/cat_wallet/lineage_store.py +2 -2
  540. chia/wallet/coin_selection.py +15 -15
  541. chia/wallet/conditions.py +257 -71
  542. chia/wallet/dao_wallet/dao_info.py +4 -4
  543. chia/wallet/dao_wallet/dao_utils.py +43 -42
  544. chia/wallet/dao_wallet/dao_wallet.py +66 -68
  545. chia/wallet/db_wallet/db_wallet_puzzles.py +12 -8
  546. chia/wallet/derive_keys.py +11 -11
  547. chia/wallet/did_wallet/did_info.py +3 -3
  548. chia/wallet/did_wallet/did_wallet.py +56 -47
  549. chia/wallet/did_wallet/did_wallet_puzzles.py +7 -6
  550. chia/wallet/lineage_proof.py +4 -4
  551. chia/wallet/nft_wallet/metadata_outer_puzzle.py +2 -2
  552. chia/wallet/nft_wallet/nft_info.py +4 -4
  553. chia/wallet/nft_wallet/nft_puzzles.py +16 -16
  554. chia/wallet/nft_wallet/nft_wallet.py +90 -89
  555. chia/wallet/nft_wallet/ownership_outer_puzzle.py +2 -2
  556. chia/wallet/nft_wallet/singleton_outer_puzzle.py +2 -2
  557. chia/wallet/nft_wallet/transfer_program_puzzle.py +2 -2
  558. chia/wallet/nft_wallet/uncurry_nft.py +2 -2
  559. chia/wallet/notification_manager.py +5 -5
  560. chia/wallet/notification_store.py +6 -6
  561. chia/wallet/outer_puzzles.py +2 -2
  562. chia/wallet/payment.py +4 -5
  563. chia/wallet/puzzle_drivers.py +4 -4
  564. chia/wallet/puzzles/clawback/drivers.py +5 -5
  565. chia/wallet/puzzles/clawback/puzzle_decorator.py +7 -7
  566. chia/wallet/puzzles/load_clvm.py +2 -3
  567. chia/wallet/puzzles/p2_conditions.py +1 -2
  568. chia/wallet/puzzles/p2_delegated_conditions.py +1 -2
  569. chia/wallet/puzzles/p2_delegated_puzzle.py +2 -3
  570. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +3 -4
  571. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +1 -2
  572. chia/wallet/puzzles/p2_puzzle_hash.py +1 -2
  573. chia/wallet/puzzles/puzzle_utils.py +7 -7
  574. chia/wallet/puzzles/singleton_top_layer.py +6 -5
  575. chia/wallet/puzzles/singleton_top_layer_v1_1.py +6 -5
  576. chia/wallet/puzzles/tails.py +34 -30
  577. chia/wallet/signer_protocol.py +7 -8
  578. chia/wallet/singleton.py +4 -4
  579. chia/wallet/trade_manager.py +155 -141
  580. chia/wallet/trade_record.py +5 -5
  581. chia/wallet/trading/offer.py +100 -101
  582. chia/wallet/trading/trade_store.py +14 -14
  583. chia/wallet/transaction_record.py +31 -16
  584. chia/wallet/util/address_type.py +4 -4
  585. chia/wallet/util/blind_signer_tl.py +8 -12
  586. chia/wallet/util/clvm_streamable.py +15 -15
  587. chia/wallet/util/compute_hints.py +5 -5
  588. chia/wallet/util/compute_memos.py +4 -6
  589. chia/wallet/util/curry_and_treehash.py +3 -2
  590. chia/wallet/util/debug_spend_bundle.py +6 -8
  591. chia/wallet/util/merkle_tree.py +10 -10
  592. chia/wallet/util/merkle_utils.py +10 -10
  593. chia/wallet/util/new_peak_queue.py +3 -3
  594. chia/wallet/util/peer_request_cache.py +8 -8
  595. chia/{util → wallet/util}/pprint.py +2 -3
  596. chia/wallet/util/puzzle_compression.py +3 -4
  597. chia/wallet/util/puzzle_decorator.py +10 -10
  598. chia/wallet/util/query_filter.py +9 -10
  599. chia/wallet/util/tx_config.py +12 -12
  600. chia/wallet/util/wallet_sync_utils.py +24 -21
  601. chia/wallet/util/wallet_types.py +9 -2
  602. chia/wallet/vc_wallet/cr_cat_drivers.py +28 -27
  603. chia/wallet/vc_wallet/cr_cat_wallet.py +42 -40
  604. chia/wallet/vc_wallet/cr_outer_puzzle.py +4 -4
  605. chia/wallet/vc_wallet/vc_drivers.py +16 -16
  606. chia/wallet/vc_wallet/vc_store.py +9 -9
  607. chia/wallet/vc_wallet/vc_wallet.py +35 -35
  608. chia/wallet/wallet.py +54 -54
  609. chia/wallet/wallet_action_scope.py +14 -13
  610. chia/wallet/wallet_blockchain.py +10 -10
  611. chia/wallet/wallet_coin_record.py +2 -2
  612. chia/wallet/wallet_coin_store.py +10 -10
  613. chia/wallet/wallet_info.py +1 -2
  614. chia/wallet/wallet_interested_store.py +5 -5
  615. chia/wallet/wallet_nft_store.py +6 -6
  616. chia/wallet/wallet_node.py +72 -76
  617. chia/wallet/wallet_node_api.py +33 -27
  618. chia/wallet/wallet_pool_store.py +1 -2
  619. chia/wallet/wallet_protocol.py +15 -15
  620. chia/wallet/wallet_puzzle_store.py +35 -4
  621. chia/wallet/wallet_retry_store.py +2 -2
  622. chia/wallet/wallet_singleton_store.py +10 -9
  623. chia/wallet/wallet_spend_bundle.py +4 -20
  624. chia/wallet/wallet_state_manager.py +223 -224
  625. chia/wallet/wallet_transaction_store.py +44 -18
  626. chia/wallet/wallet_user_store.py +2 -2
  627. chia/wallet/wallet_weight_proof_handler.py +2 -2
  628. {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/LICENSE +1 -1
  629. {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/METADATA +67 -72
  630. chia_blockchain-2.5.1rc2.dist-info/RECORD +1042 -0
  631. {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/WHEEL +1 -1
  632. mozilla-ca/cacert.pem +32 -87
  633. chia/_tests/cmds/wallet/test_coins.py +0 -195
  634. chia/consensus/block_root_validation.py +0 -46
  635. chia/util/api_decorators.py +0 -89
  636. chia_blockchain-2.5.0rc2.dist-info/RECORD +0 -1028
  637. {chia_blockchain-2.5.0rc2.dist-info → chia_blockchain-2.5.1rc2.dist-info}/entry_points.txt +0 -0
@@ -1,11 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import asyncio
3
4
  import logging
4
5
  import random
5
6
  import time
7
+ from collections.abc import AsyncIterator, Awaitable
6
8
  from contextlib import asynccontextmanager
7
9
  from dataclasses import replace
8
- from typing import AsyncIterator, Dict, List, Optional
10
+ from typing import Optional
9
11
 
10
12
  import pytest
11
13
  from chia_rs import AugSchemeMPL, G2Element, MerkleSet
@@ -20,6 +22,7 @@ from chia._tests.blockchain.blockchain_test_utils import (
20
22
  )
21
23
  from chia._tests.conftest import ConsensusMode
22
24
  from chia._tests.util.blockchain import create_blockchain
25
+ from chia._tests.util.get_name_puzzle_conditions import get_name_puzzle_conditions
23
26
  from chia.consensus.block_body_validation import ForkInfo
24
27
  from chia.consensus.block_header_validation import validate_finished_header_block
25
28
  from chia.consensus.block_record import BlockRecord
@@ -27,11 +30,11 @@ from chia.consensus.block_rewards import calculate_base_farmer_reward
27
30
  from chia.consensus.blockchain import AddBlockResult, Blockchain
28
31
  from chia.consensus.coinbase import create_farmer_coin
29
32
  from chia.consensus.constants import ConsensusConstants
33
+ from chia.consensus.find_fork_point import lookup_fork_chain
30
34
  from chia.consensus.full_block_to_block_record import block_to_block_record
31
35
  from chia.consensus.get_block_generator import get_block_generator
32
- from chia.consensus.multiprocess_validation import PreValidationResult, pre_validate_blocks_multiprocessing
36
+ from chia.consensus.multiprocess_validation import PreValidationResult, pre_validate_block
33
37
  from chia.consensus.pot_iterations import is_overflow_block
34
- from chia.full_node.mempool_check_conditions import get_name_puzzle_conditions
35
38
  from chia.simulator.block_tools import BlockTools, create_block_tools_async
36
39
  from chia.simulator.keyring import TempKeyring
37
40
  from chia.simulator.wallet_tools import WalletTool
@@ -49,7 +52,8 @@ from chia.types.full_block import FullBlock
49
52
  from chia.types.generator_types import BlockGenerator
50
53
  from chia.types.spend_bundle import SpendBundle
51
54
  from chia.types.unfinished_block import UnfinishedBlock
52
- from chia.util.cpu import available_logical_cores
55
+ from chia.types.validation_state import ValidationState
56
+ from chia.util.augmented_chain import AugmentedBlockchain
53
57
  from chia.util.errors import Err
54
58
  from chia.util.generator_tools import get_block_header
55
59
  from chia.util.hash import std_hash
@@ -72,14 +76,14 @@ async def make_empty_blockchain(constants: ConsensusConstants) -> AsyncIterator[
72
76
  Provides a list of 10 valid blocks, as well as a blockchain with 9 blocks added to it.
73
77
  """
74
78
 
75
- async with create_blockchain(constants, 2) as (bc, db_wrapper):
79
+ async with create_blockchain(constants, 2) as (bc, _):
76
80
  yield bc
77
81
 
78
82
 
79
83
  class TestGenesisBlock:
80
84
  @pytest.mark.anyio
81
85
  async def test_block_tools_proofs_400(
82
- self, default_400_blocks: List[FullBlock], blockchain_constants: ConsensusConstants
86
+ self, default_400_blocks: list[FullBlock], blockchain_constants: ConsensusConstants
83
87
  ) -> None:
84
88
  vdf, proof = get_vdf_info_and_proof(
85
89
  blockchain_constants,
@@ -92,7 +96,7 @@ class TestGenesisBlock:
92
96
 
93
97
  @pytest.mark.anyio
94
98
  async def test_block_tools_proofs_1000(
95
- self, default_1000_blocks: List[FullBlock], blockchain_constants: ConsensusConstants
99
+ self, default_1000_blocks: list[FullBlock], blockchain_constants: ConsensusConstants
96
100
  ) -> None:
97
101
  vdf, proof = get_vdf_info_and_proof(
98
102
  blockchain_constants,
@@ -149,8 +153,9 @@ class TestGenesisBlock:
149
153
  class TestBlockHeaderValidation:
150
154
  @pytest.mark.limit_consensus_modes(reason="save time")
151
155
  @pytest.mark.anyio
152
- async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_blocks: List[FullBlock]) -> None:
156
+ async def test_long_chain(self, empty_blockchain: Blockchain, default_1000_blocks: list[FullBlock]) -> None:
153
157
  blocks = default_1000_blocks
158
+ fork_info = ForkInfo(blocks[0].height - 1, blocks[0].height - 1, blocks[0].prev_header_hash)
154
159
  for block in blocks:
155
160
  if (
156
161
  len(block.finished_sub_slots) > 0
@@ -165,23 +170,21 @@ class TestBlockHeaderValidation:
165
170
  block_bad = recursive_replace(
166
171
  block, "finished_sub_slots", [new_finished_ss] + block.finished_sub_slots[1:]
167
172
  )
168
- header_block_bad = get_block_header(block_bad, [], [])
173
+ header_block_bad = get_block_header(block_bad)
169
174
  # TODO: Inspect these block values as they are currently None
170
175
  expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
171
176
  expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
177
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
172
178
  _, error = validate_finished_header_block(
173
- empty_blockchain.constants,
174
- empty_blockchain,
175
- header_block_bad,
176
- False,
177
- expected_difficulty,
178
- expected_sub_slot_iters,
179
+ empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
179
180
  )
180
181
  assert error is not None
181
182
  assert error.code == Err.INVALID_NEW_SUB_SLOT_ITERS
182
183
 
183
184
  # Also fails calling the outer methods, but potentially with a different error
184
- await _validate_and_add_block(empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK)
185
+ await _validate_and_add_block(
186
+ empty_blockchain, block_bad, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
187
+ )
185
188
 
186
189
  new_finished_ss_2 = recursive_replace(
187
190
  block.finished_sub_slots[0],
@@ -192,24 +195,20 @@ class TestBlockHeaderValidation:
192
195
  block, "finished_sub_slots", [new_finished_ss_2] + block.finished_sub_slots[1:]
193
196
  )
194
197
 
195
- header_block_bad_2 = get_block_header(block_bad_2, [], [])
198
+ header_block_bad_2 = get_block_header(block_bad_2)
196
199
  # TODO: Inspect these block values as they are currently None
197
200
  expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
198
201
  expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
202
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
199
203
  _, error = validate_finished_header_block(
200
- empty_blockchain.constants,
201
- empty_blockchain,
202
- header_block_bad_2,
203
- False,
204
- expected_difficulty,
205
- expected_sub_slot_iters,
204
+ empty_blockchain.constants, empty_blockchain, header_block_bad_2, False, expected_vs
206
205
  )
207
206
  assert error is not None
208
207
  assert error.code == Err.INVALID_NEW_DIFFICULTY
209
208
 
210
209
  # Also fails calling the outer methods, but potentially with a different error
211
210
  await _validate_and_add_block(
212
- empty_blockchain, block_bad_2, expected_result=AddBlockResult.INVALID_BLOCK
211
+ empty_blockchain, block_bad_2, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
213
212
  )
214
213
 
215
214
  # 3c
@@ -226,24 +225,20 @@ class TestBlockHeaderValidation:
226
225
  log.warning(f"Number of slots: {len(block.finished_sub_slots)}")
227
226
  block_bad_3 = recursive_replace(block, "finished_sub_slots", [new_finished_ss_3])
228
227
 
229
- header_block_bad_3 = get_block_header(block_bad_3, [], [])
228
+ header_block_bad_3 = get_block_header(block_bad_3)
230
229
  # TODO: Inspect these block values as they are currently None
231
230
  expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
232
231
  expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
232
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
233
233
  _, error = validate_finished_header_block(
234
- empty_blockchain.constants,
235
- empty_blockchain,
236
- header_block_bad_3,
237
- False,
238
- expected_difficulty,
239
- expected_sub_slot_iters,
234
+ empty_blockchain.constants, empty_blockchain, header_block_bad_3, False, expected_vs
240
235
  )
241
236
  assert error is not None
242
237
  assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY
243
238
 
244
239
  # Also fails calling the outer methods, but potentially with a different error
245
240
  await _validate_and_add_block(
246
- empty_blockchain, block_bad_3, expected_result=AddBlockResult.INVALID_BLOCK
241
+ empty_blockchain, block_bad_3, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
247
242
  )
248
243
 
249
244
  # 3d
@@ -259,26 +254,22 @@ class TestBlockHeaderValidation:
259
254
  )
260
255
  block_bad_4 = recursive_replace(block, "finished_sub_slots", [new_finished_ss_4])
261
256
 
262
- header_block_bad_4 = get_block_header(block_bad_4, [], [])
257
+ header_block_bad_4 = get_block_header(block_bad_4)
263
258
  # TODO: Inspect these block values as they are currently None
264
259
  expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
265
260
  expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
261
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
266
262
  _, error = validate_finished_header_block(
267
- empty_blockchain.constants,
268
- empty_blockchain,
269
- header_block_bad_4,
270
- False,
271
- expected_difficulty,
272
- expected_sub_slot_iters,
263
+ empty_blockchain.constants, empty_blockchain, header_block_bad_4, False, expected_vs
273
264
  )
274
265
  assert error is not None
275
266
  assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY
276
267
 
277
268
  # Also fails calling the outer methods, but potentially with a different error
278
269
  await _validate_and_add_block(
279
- empty_blockchain, block_bad_4, expected_result=AddBlockResult.INVALID_BLOCK
270
+ empty_blockchain, block_bad_4, expected_result=AddBlockResult.INVALID_BLOCK, fork_info=fork_info
280
271
  )
281
- await _validate_and_add_block(empty_blockchain, block)
272
+ await _validate_and_add_block(empty_blockchain, block, fork_info=fork_info)
282
273
  log.info(
283
274
  f"Added block {block.height} total iters {block.total_iters} "
284
275
  f"new slot? {len(block.finished_sub_slots)}"
@@ -370,7 +361,7 @@ class TestBlockHeaderValidation:
370
361
  async def test_one_sb_per_slot(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
371
362
  blockchain = empty_blockchain
372
363
  num_blocks = 20
373
- blocks: List[FullBlock] = []
364
+ blocks: list[FullBlock] = []
374
365
  for _ in range(num_blocks):
375
366
  blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=1)
376
367
  await _validate_and_add_block(empty_blockchain, blocks[-1])
@@ -382,7 +373,7 @@ class TestBlockHeaderValidation:
382
373
  async def test_all_overflow(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
383
374
  blockchain = empty_blockchain
384
375
  num_rounds = 5
385
- blocks: List[FullBlock] = []
376
+ blocks: list[FullBlock] = []
386
377
  num_blocks = 0
387
378
  for i in range(1, num_rounds):
388
379
  num_blocks += i
@@ -399,7 +390,7 @@ class TestBlockHeaderValidation:
399
390
  ) -> None:
400
391
  blockchain = empty_blockchain
401
392
 
402
- blocks: List[FullBlock] = []
393
+ blocks: list[FullBlock] = []
403
394
  while True:
404
395
  # This creates an overflow block, then a normal block, and then an overflow in the next sub-slot
405
396
  # blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, force_overflow=True)
@@ -447,7 +438,7 @@ class TestBlockHeaderValidation:
447
438
  async def test_one_sb_per_two_slots(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
448
439
  blockchain = empty_blockchain
449
440
  num_blocks = 20
450
- blocks: List[FullBlock] = []
441
+ blocks: list[FullBlock] = []
451
442
  for _ in range(num_blocks): # Same thing, but 2 sub-slots per block
452
443
  blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=2)
453
444
  await _validate_and_add_block(blockchain, blocks[-1])
@@ -459,7 +450,7 @@ class TestBlockHeaderValidation:
459
450
  async def test_one_sb_per_five_slots(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
460
451
  blockchain = empty_blockchain
461
452
  num_blocks = 10
462
- blocks: List[FullBlock] = []
453
+ blocks: list[FullBlock] = []
463
454
  for _ in range(num_blocks): # Same thing, but 5 sub-slots per block
464
455
  blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=5)
465
456
  await _validate_and_add_block(blockchain, blocks[-1])
@@ -480,7 +471,7 @@ class TestBlockHeaderValidation:
480
471
  async def test_one_sb_per_two_slots_force_overflow(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
481
472
  blockchain = empty_blockchain
482
473
  num_blocks = 10
483
- blocks: List[FullBlock] = []
474
+ blocks: list[FullBlock] = []
484
475
  for _ in range(num_blocks):
485
476
  blocks = bt.get_consecutive_blocks(1, block_list_input=blocks, skip_slots=2, force_overflow=True)
486
477
  await _validate_and_add_block(blockchain, blocks[-1])
@@ -519,14 +510,12 @@ class TestBlockHeaderValidation:
519
510
  blocks[0], "finished_sub_slots", [new_finished_ss] + blocks[0].finished_sub_slots[1:]
520
511
  )
521
512
 
522
- header_block_bad = get_block_header(block_0_bad, [], [])
513
+ header_block_bad = get_block_header(block_0_bad)
514
+ expected_vs = ValidationState(
515
+ empty_blockchain.constants.SUB_SLOT_ITERS_STARTING, empty_blockchain.constants.DIFFICULTY_STARTING, None
516
+ )
523
517
  _, error = validate_finished_header_block(
524
- empty_blockchain.constants,
525
- empty_blockchain,
526
- header_block_bad,
527
- False,
528
- empty_blockchain.constants.DIFFICULTY_STARTING,
529
- empty_blockchain.constants.SUB_SLOT_ITERS_STARTING,
518
+ empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
530
519
  )
531
520
 
532
521
  assert error is not None
@@ -550,17 +539,13 @@ class TestBlockHeaderValidation:
550
539
  )
551
540
 
552
541
  await _validate_and_add_block(empty_blockchain, blocks[0])
553
- header_block_bad = get_block_header(block_1_bad, [], [])
542
+ header_block_bad = get_block_header(block_1_bad)
554
543
  # TODO: Inspect these block values as they are currently None
555
544
  expected_difficulty = blocks[1].finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
556
545
  expected_sub_slot_iters = blocks[1].finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
546
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
557
547
  _, error = validate_finished_header_block(
558
- empty_blockchain.constants,
559
- empty_blockchain,
560
- header_block_bad,
561
- False,
562
- expected_difficulty,
563
- expected_sub_slot_iters,
548
+ empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
564
549
  )
565
550
  assert error is not None
566
551
  assert error.code == Err.INVALID_PREV_CHALLENGE_SLOT_HASH
@@ -581,17 +566,13 @@ class TestBlockHeaderValidation:
581
566
  )
582
567
  await _validate_and_add_block(empty_blockchain, blocks[0])
583
568
 
584
- header_block_bad = get_block_header(block_1_bad, [], [])
569
+ header_block_bad = get_block_header(block_1_bad)
585
570
  # TODO: Inspect these block values as they are currently None
586
571
  expected_difficulty = blocks[1].finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
587
572
  expected_sub_slot_iters = blocks[1].finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
573
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
588
574
  _, error = validate_finished_header_block(
589
- empty_blockchain.constants,
590
- empty_blockchain,
591
- header_block_bad,
592
- False,
593
- expected_difficulty,
594
- expected_sub_slot_iters,
575
+ empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
595
576
  )
596
577
  assert error is not None
597
578
  assert error.code == Err.INVALID_PREV_CHALLENGE_SLOT_HASH
@@ -606,7 +587,7 @@ class TestBlockHeaderValidation:
606
587
  "infused_challenge_chain",
607
588
  InfusedChallengeChainSubSlot(
608
589
  VDFInfo(
609
- bytes32([0] * 32),
590
+ bytes32.zeros,
610
591
  uint64(1200),
611
592
  ClassgroupElement.get_default_element(),
612
593
  )
@@ -627,7 +608,7 @@ class TestBlockHeaderValidation:
627
608
  ),
628
609
  keychain=keychain,
629
610
  )
630
- async with create_blockchain(bt_high_iters.constants, db_version) as (bc1, db_wrapper):
611
+ async with create_blockchain(bt_high_iters.constants, db_version) as (bc1, _):
631
612
  blocks = bt_high_iters.get_consecutive_blocks(10)
632
613
  for block in blocks:
633
614
  if (
@@ -677,7 +658,7 @@ class TestBlockHeaderValidation:
677
658
  block.finished_sub_slots[
678
659
  -1
679
660
  ].infused_challenge_chain.infused_challenge_chain_end_of_slot_vdf.replace(
680
- challenge=bytes32([0] * 32)
661
+ challenge=bytes32.zeros
681
662
  )
682
663
  ),
683
664
  )
@@ -740,17 +721,13 @@ class TestBlockHeaderValidation:
740
721
  block, "finished_sub_slots", block.finished_sub_slots[:-1] + [new_finished_ss]
741
722
  )
742
723
 
743
- header_block_bad = get_block_header(block_bad, [], [])
724
+ header_block_bad = get_block_header(block_bad)
744
725
  # TODO: Inspect these block values as they are currently None
745
726
  expected_difficulty = block.finished_sub_slots[0].challenge_chain.new_difficulty or uint64(0)
746
727
  expected_sub_slot_iters = block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters or uint64(0)
728
+ expected_vs = ValidationState(expected_sub_slot_iters, expected_difficulty, None)
747
729
  _, error = validate_finished_header_block(
748
- empty_blockchain.constants,
749
- empty_blockchain,
750
- header_block_bad,
751
- False,
752
- expected_difficulty,
753
- expected_sub_slot_iters,
730
+ empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
754
731
  )
755
732
  assert error is not None
756
733
  assert error.code == Err.INVALID_ICC_HASH_CC
@@ -815,14 +792,12 @@ class TestBlockHeaderValidation:
815
792
  blocks[-1], "finished_sub_slots", blocks[-1].finished_sub_slots[:-1] + [new_finished_ss]
816
793
  )
817
794
 
818
- header_block_bad = get_block_header(block_bad, [], [])
795
+ header_block_bad = get_block_header(block_bad)
796
+ expected_vs = ValidationState(
797
+ empty_blockchain.constants.SUB_SLOT_ITERS_STARTING, empty_blockchain.constants.DIFFICULTY_STARTING, None
798
+ )
819
799
  _, error = validate_finished_header_block(
820
- empty_blockchain.constants,
821
- empty_blockchain,
822
- header_block_bad,
823
- False,
824
- empty_blockchain.constants.DIFFICULTY_STARTING,
825
- empty_blockchain.constants.SUB_SLOT_ITERS_STARTING,
800
+ empty_blockchain.constants, empty_blockchain, header_block_bad, False, expected_vs
826
801
  )
827
802
  assert error is not None
828
803
  assert error.code == Err.INVALID_SUB_EPOCH_SUMMARY_HASH
@@ -830,7 +805,7 @@ class TestBlockHeaderValidation:
830
805
 
831
806
  @pytest.mark.anyio
832
807
  async def test_empty_sub_slots_epoch(
833
- self, empty_blockchain: Blockchain, default_400_blocks: List[FullBlock], bt: BlockTools
808
+ self, empty_blockchain: Blockchain, default_400_blocks: list[FullBlock], bt: BlockTools
834
809
  ) -> None:
835
810
  # 2m
836
811
  # Tests adding an empty sub slot after the sub-epoch / epoch.
@@ -871,7 +846,7 @@ class TestBlockHeaderValidation:
871
846
  @pytest.mark.anyio
872
847
  async def test_invalid_cc_sub_slot_vdf(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
873
848
  # 2q
874
- blocks: List[FullBlock] = []
849
+ blocks: list[FullBlock] = []
875
850
  found_overflow_slot: bool = False
876
851
 
877
852
  while not found_overflow_slot:
@@ -969,7 +944,7 @@ class TestBlockHeaderValidation:
969
944
  @pytest.mark.anyio
970
945
  async def test_invalid_rc_sub_slot_vdf(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
971
946
  # 2p
972
- blocks: List[FullBlock] = []
947
+ blocks: list[FullBlock] = []
973
948
  found_block: bool = False
974
949
 
975
950
  while not found_block:
@@ -1099,7 +1074,7 @@ class TestBlockHeaderValidation:
1099
1074
  recursive_replace(
1100
1075
  block.finished_sub_slots[0].challenge_chain,
1101
1076
  "subepoch_summary_hash",
1102
- bytes32([0] * 32),
1077
+ bytes32.zeros,
1103
1078
  ),
1104
1079
  )
1105
1080
 
@@ -1134,7 +1109,7 @@ class TestBlockHeaderValidation:
1134
1109
  recursive_replace(
1135
1110
  blocks[-1].finished_sub_slots[0].challenge_chain,
1136
1111
  "subepoch_summary_hash",
1137
- bytes32([0] * 32),
1112
+ bytes32.zeros,
1138
1113
  ),
1139
1114
  )
1140
1115
 
@@ -1222,7 +1197,7 @@ class TestBlockHeaderValidation:
1222
1197
  @pytest.mark.anyio
1223
1198
  async def test_sp_0_no_sp(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
1224
1199
  # 7
1225
- blocks: List[FullBlock] = []
1200
+ blocks: list[FullBlock] = []
1226
1201
  case_1, case_2 = False, False
1227
1202
  while not case_1 or not case_2:
1228
1203
  blocks = bt.get_consecutive_blocks(1, block_list_input=blocks)
@@ -1819,67 +1794,63 @@ class TestPreValidation:
1819
1794
  block_bad = recursive_replace(
1820
1795
  blocks[-1], "reward_chain_block.total_iters", blocks[-1].reward_chain_block.total_iters + 1
1821
1796
  )
1822
- res = await pre_validate_blocks_multiprocessing(
1823
- empty_blockchain.constants,
1824
- empty_blockchain,
1825
- [blocks[0], block_bad],
1826
- empty_blockchain.pool,
1827
- {},
1828
- sub_slot_iters=ssi,
1829
- difficulty=difficulty,
1830
- prev_ses_block=None,
1831
- validate_signatures=True,
1832
- )
1797
+ futures = []
1798
+ vs = ValidationState(ssi, difficulty, None)
1799
+ chain = AugmentedBlockchain(empty_blockchain)
1800
+ for block in [blocks[0], block_bad]:
1801
+ futures.append(
1802
+ await pre_validate_block(
1803
+ empty_blockchain.constants,
1804
+ chain,
1805
+ block,
1806
+ empty_blockchain.pool,
1807
+ None,
1808
+ vs,
1809
+ )
1810
+ )
1811
+ res: list[PreValidationResult] = list(await asyncio.gather(*futures))
1833
1812
  assert res[0].error is None
1834
1813
  assert res[1].error is not None
1835
1814
 
1836
1815
  @pytest.mark.anyio
1837
1816
  async def test_pre_validation(
1838
- self, empty_blockchain: Blockchain, default_1000_blocks: List[FullBlock], bt: BlockTools
1817
+ self, empty_blockchain: Blockchain, default_1000_blocks: list[FullBlock], bt: BlockTools
1839
1818
  ) -> None:
1840
1819
  blocks = default_1000_blocks[:100]
1841
1820
  start = time.time()
1842
- n_at_a_time = min(available_logical_cores(), 32)
1843
- times_pv = []
1844
- times_rb = []
1845
1821
  ssi = empty_blockchain.constants.SUB_SLOT_ITERS_STARTING
1846
1822
  difficulty = empty_blockchain.constants.DIFFICULTY_STARTING
1847
- for i in range(0, len(blocks), n_at_a_time):
1848
- end_i = min(i + n_at_a_time, len(blocks))
1849
- blocks_to_validate = blocks[i:end_i]
1850
- start_pv = time.time()
1851
- res = await pre_validate_blocks_multiprocessing(
1852
- empty_blockchain.constants,
1853
- empty_blockchain,
1854
- blocks_to_validate,
1855
- empty_blockchain.pool,
1856
- {},
1857
- sub_slot_iters=ssi,
1858
- difficulty=difficulty,
1859
- prev_ses_block=None,
1860
- validate_signatures=True,
1861
- )
1862
- end_pv = time.time()
1863
- times_pv.append(end_pv - start_pv)
1864
- assert res is not None
1865
- for n in range(end_i - i):
1866
- assert res[n] is not None
1867
- assert res[n].error is None
1868
- block = blocks_to_validate[n]
1869
- start_rb = time.time()
1870
- result, err, _ = await empty_blockchain.add_block(block, res[n], None, ssi)
1871
- end_rb = time.time()
1872
- times_rb.append(end_rb - start_rb)
1873
- assert err is None
1874
- assert result == AddBlockResult.NEW_PEAK
1875
- log.info(
1876
- f"Added block {block.height} total iters {block.total_iters} "
1877
- f"new slot? {len(block.finished_sub_slots)}, time {end_rb - start_rb}"
1823
+ blockchain = AugmentedBlockchain(empty_blockchain)
1824
+ vs = ValidationState(ssi, difficulty, None)
1825
+ futures: list[Awaitable[PreValidationResult]] = []
1826
+ start = time.monotonic()
1827
+ for block in blocks:
1828
+ futures.append(
1829
+ await pre_validate_block(
1830
+ bt.constants,
1831
+ blockchain,
1832
+ block,
1833
+ empty_blockchain.pool,
1834
+ None,
1835
+ vs,
1878
1836
  )
1879
- end = time.time()
1837
+ )
1838
+
1839
+ results = await asyncio.gather(*futures)
1840
+ end = time.monotonic()
1841
+ validation_time = start - end
1842
+ db_start = end
1843
+
1844
+ fork_info = ForkInfo(-1, -1, bt.constants.GENESIS_CHALLENGE)
1845
+ for block, res in zip(blocks, results):
1846
+ assert res.error is None
1847
+ result, err, _ = await empty_blockchain.add_block(block, res, ssi, fork_info=fork_info)
1848
+ assert err is None
1849
+ assert result == AddBlockResult.NEW_PEAK
1850
+ end = time.monotonic()
1880
1851
  log.info(f"Total time: {end - start} seconds")
1881
- log.info(f"Average pv: {sum(times_pv)/(len(blocks)/n_at_a_time)}")
1882
- log.info(f"Average rb: {sum(times_rb)/(len(blocks))}")
1852
+ log.info(f"Average validation: {validation_time / len(blocks)}")
1853
+ log.info(f"Average database: {(end - db_start) / (len(blocks))}")
1883
1854
 
1884
1855
 
1885
1856
  class TestBodyValidation:
@@ -1939,7 +1910,7 @@ class TestBodyValidation:
1939
1910
  else:
1940
1911
  assert False
1941
1912
 
1942
- conditions: Dict[ConditionOpcode, List[ConditionWithArgs]] = {
1913
+ conditions: dict[ConditionOpcode, list[ConditionWithArgs]] = {
1943
1914
  opcode: [ConditionWithArgs(opcode, args + ([b"garbage"] if with_garbage else []))]
1944
1915
  }
1945
1916
 
@@ -1956,20 +1927,20 @@ class TestBodyValidation:
1956
1927
  )
1957
1928
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
1958
1929
  diff = b.constants.DIFFICULTY_STARTING
1959
- pre_validation_results: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
1930
+ block = blocks[-1]
1931
+ future = await pre_validate_block(
1960
1932
  b.constants,
1961
- b,
1962
- [blocks[-1]],
1933
+ AugmentedBlockchain(b),
1934
+ block,
1963
1935
  b.pool,
1964
- {},
1965
- sub_slot_iters=ssi,
1966
- difficulty=diff,
1967
- prev_ses_block=None,
1968
- validate_signatures=False,
1936
+ None,
1937
+ ValidationState(ssi, diff, None),
1969
1938
  )
1939
+ pre_validation_result: PreValidationResult = await future
1970
1940
  # Ignore errors from pre-validation, we are testing block_body_validation
1971
- repl_preval_results = replace(pre_validation_results[0], error=None, required_iters=uint64(1))
1972
- code, err, state_change = await b.add_block(blocks[-1], repl_preval_results, None, sub_slot_iters=ssi)
1941
+ repl_preval_results = replace(pre_validation_result, error=None, required_iters=uint64(1))
1942
+ fork_info = ForkInfo(block.height - 1, block.height - 1, block.prev_header_hash)
1943
+ code, err, state_change = await b.add_block(block, repl_preval_results, sub_slot_iters=ssi, fork_info=fork_info)
1973
1944
  assert code == AddBlockResult.NEW_PEAK
1974
1945
  assert err is None
1975
1946
  assert state_change is not None
@@ -2080,19 +2051,20 @@ class TestBodyValidation:
2080
2051
  )
2081
2052
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
2082
2053
  diff = b.constants.DIFFICULTY_STARTING
2083
- pre_validation_results: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
2054
+ block = blocks[-1]
2055
+ future = await pre_validate_block(
2084
2056
  b.constants,
2085
- b,
2086
- [blocks[-1]],
2057
+ AugmentedBlockchain(b),
2058
+ block,
2087
2059
  b.pool,
2088
- {},
2089
- sub_slot_iters=ssi,
2090
- difficulty=diff,
2091
- prev_ses_block=None,
2092
- validate_signatures=True,
2060
+ None,
2061
+ ValidationState(ssi, diff, None),
2093
2062
  )
2094
- assert pre_validation_results is not None
2095
- assert (await b.add_block(blocks[-1], pre_validation_results[0], None, sub_slot_iters=ssi))[0] == expected
2063
+ pre_validation_result: PreValidationResult = await future
2064
+ fork_info = ForkInfo(block.height - 1, block.height - 1, block.prev_header_hash)
2065
+ assert (await b.add_block(block, pre_validation_result, sub_slot_iters=ssi, fork_info=fork_info))[
2066
+ 0
2067
+ ] == expected
2096
2068
 
2097
2069
  if expected == AddBlockResult.NEW_PEAK:
2098
2070
  # ensure coin was in fact spent
@@ -2161,20 +2133,22 @@ class TestBodyValidation:
2161
2133
  )
2162
2134
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
2163
2135
  diff = b.constants.DIFFICULTY_STARTING
2164
- pre_validation_results: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
2136
+ block = blocks[-1]
2137
+ future = await pre_validate_block(
2165
2138
  b.constants,
2166
- b,
2167
- [blocks[-1]],
2139
+ AugmentedBlockchain(b),
2140
+ block,
2168
2141
  b.pool,
2169
- {},
2170
- sub_slot_iters=ssi,
2171
- difficulty=diff,
2172
- prev_ses_block=None,
2173
- validate_signatures=False,
2142
+ None,
2143
+ ValidationState(ssi, diff, None),
2174
2144
  )
2145
+ pre_validation_result: PreValidationResult = await future
2175
2146
  # Ignore errors from pre-validation, we are testing block_body_validation
2176
- repl_preval_results = replace(pre_validation_results[0], error=None, required_iters=uint64(1))
2177
- res, error, state_change = await b.add_block(blocks[-1], repl_preval_results, None, sub_slot_iters=ssi)
2147
+ repl_preval_results = replace(pre_validation_result, error=None, required_iters=uint64(1))
2148
+ fork_info = ForkInfo(block.height - 1, block.height - 1, block.prev_header_hash)
2149
+ res, error, state_change = await b.add_block(
2150
+ block, repl_preval_results, sub_slot_iters=ssi, fork_info=fork_info
2151
+ )
2178
2152
  assert res == AddBlockResult.NEW_PEAK
2179
2153
  assert error is None
2180
2154
  assert state_change is not None and state_change.fork_height == uint32(2)
@@ -2287,19 +2261,20 @@ class TestBodyValidation:
2287
2261
  )
2288
2262
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
2289
2263
  diff = b.constants.DIFFICULTY_STARTING
2290
- pre_validation_results: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
2264
+ block = blocks[-1]
2265
+ future = await pre_validate_block(
2291
2266
  b.constants,
2292
- b,
2293
- [blocks[-1]],
2267
+ AugmentedBlockchain(b),
2268
+ block,
2294
2269
  b.pool,
2295
- {},
2296
- sub_slot_iters=ssi,
2297
- difficulty=diff,
2298
- prev_ses_block=None,
2299
- validate_signatures=True,
2270
+ None,
2271
+ ValidationState(ssi, diff, None),
2300
2272
  )
2301
- assert pre_validation_results is not None
2302
- assert (await b.add_block(blocks[-1], pre_validation_results[0], None, sub_slot_iters=ssi))[0] == expected
2273
+ pre_validation_result: PreValidationResult = await future
2274
+ fork_info = ForkInfo(block.height - 1, block.height - 1, block.prev_header_hash)
2275
+ assert (await b.add_block(block, pre_validation_result, sub_slot_iters=ssi, fork_info=fork_info))[
2276
+ 0
2277
+ ] == expected
2303
2278
 
2304
2279
  if expected == AddBlockResult.NEW_PEAK:
2305
2280
  # ensure coin1 was in fact spent
@@ -2432,8 +2407,9 @@ class TestBodyValidation:
2432
2407
 
2433
2408
  # Too many
2434
2409
  h = std_hash(b"")
2435
- too_many_reward_claims = block.transactions_info.reward_claims_incorporated + [
2436
- Coin(h, h, too_few_reward_claims[0].amount)
2410
+ too_many_reward_claims = [
2411
+ *block.transactions_info.reward_claims_incorporated,
2412
+ Coin(h, h, too_few_reward_claims[0].amount),
2437
2413
  ]
2438
2414
  block_2 = recursive_replace(block, "transactions_info.reward_claims_incorporated", too_many_reward_claims)
2439
2415
  assert block_2.transactions_info is not None
@@ -2452,8 +2428,9 @@ class TestBodyValidation:
2452
2428
  await _validate_and_add_block(b, block_2, expected_error=Err.INVALID_REWARD_COINS, skip_prevalidation=True)
2453
2429
 
2454
2430
  # Duplicates
2455
- duplicate_reward_claims = block.transactions_info.reward_claims_incorporated + [
2456
- block.transactions_info.reward_claims_incorporated[-1]
2431
+ duplicate_reward_claims = [
2432
+ *block.transactions_info.reward_claims_incorporated,
2433
+ block.transactions_info.reward_claims_incorporated[-1],
2457
2434
  ]
2458
2435
  block_2 = recursive_replace(block, "transactions_info.reward_claims_incorporated", duplicate_reward_claims)
2459
2436
  assert block_2.transactions_info is not None
@@ -2615,7 +2592,7 @@ class TestBodyValidation:
2615
2592
 
2616
2593
  wt: WalletTool = bt.get_pool_wallet_tool()
2617
2594
 
2618
- condition_dict: Dict[ConditionOpcode, List[ConditionWithArgs]] = {ConditionOpcode.CREATE_COIN: []}
2595
+ condition_dict: dict[ConditionOpcode, list[ConditionWithArgs]] = {ConditionOpcode.CREATE_COIN: []}
2619
2596
  for i in range(7_000):
2620
2597
  output = ConditionWithArgs(ConditionOpcode.CREATE_COIN, [bt.pool_ph, int_to_bytes(i)])
2621
2598
  condition_dict[ConditionOpcode.CREATE_COIN].append(output)
@@ -2629,6 +2606,7 @@ class TestBodyValidation:
2629
2606
  )
2630
2607
 
2631
2608
  assert blocks[-1].transactions_generator is not None
2609
+ assert blocks[-1].transactions_info is not None
2632
2610
  block_generator = BlockGenerator(blocks[-1].transactions_generator, [])
2633
2611
  npc_result = get_name_puzzle_conditions(
2634
2612
  block_generator,
@@ -2637,30 +2615,30 @@ class TestBodyValidation:
2637
2615
  height=softfork_height,
2638
2616
  constants=bt.constants,
2639
2617
  )
2618
+ assert npc_result.conds is not None
2640
2619
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
2641
2620
  diff = b.constants.DIFFICULTY_STARTING
2621
+ block = blocks[-1]
2622
+ fork_info = ForkInfo(block.height - 1, block.height - 1, block.prev_header_hash)
2642
2623
  err = (
2643
2624
  await b.add_block(
2644
2625
  blocks[-1],
2645
- PreValidationResult(None, uint64(1), npc_result.conds, True, uint32(0)),
2646
- None,
2626
+ PreValidationResult(None, uint64(1), npc_result.conds.replace(validated_signature=True), uint32(0)),
2647
2627
  sub_slot_iters=ssi,
2628
+ fork_info=fork_info,
2648
2629
  )
2649
2630
  )[1]
2650
- assert err in [Err.BLOCK_COST_EXCEEDS_MAX]
2651
- results: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
2631
+ assert err == Err.BLOCK_COST_EXCEEDS_MAX
2632
+ future = await pre_validate_block(
2652
2633
  b.constants,
2653
- b,
2654
- [blocks[-1]],
2634
+ AugmentedBlockchain(b),
2635
+ blocks[-1],
2655
2636
  b.pool,
2656
- {},
2657
- sub_slot_iters=ssi,
2658
- difficulty=diff,
2659
- prev_ses_block=None,
2660
- validate_signatures=False,
2637
+ None,
2638
+ ValidationState(ssi, diff, None),
2661
2639
  )
2662
- assert results is not None
2663
- assert Err(results[0].error) == Err.BLOCK_COST_EXCEEDS_MAX
2640
+ result: PreValidationResult = await future
2641
+ assert Err(result.error) == Err.BLOCK_COST_EXCEEDS_MAX
2664
2642
 
2665
2643
  @pytest.mark.anyio
2666
2644
  async def test_clvm_must_not_fail(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
@@ -2718,9 +2696,14 @@ class TestBodyValidation:
2718
2696
  height=softfork_height,
2719
2697
  constants=bt.constants,
2720
2698
  )
2699
+ assert npc_result.conds is not None
2721
2700
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
2701
+ fork_info = ForkInfo(block_2.height - 1, block_2.height - 1, block_2.prev_header_hash)
2722
2702
  _, err, _ = await b.add_block(
2723
- block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
2703
+ block_2,
2704
+ PreValidationResult(None, uint64(1), npc_result.conds.replace(validated_signature=True), uint32(0)),
2705
+ sub_slot_iters=ssi,
2706
+ fork_info=fork_info,
2724
2707
  )
2725
2708
  assert err == Err.INVALID_BLOCK_COST
2726
2709
 
@@ -2748,8 +2731,13 @@ class TestBodyValidation:
2748
2731
  height=softfork_height,
2749
2732
  constants=bt.constants,
2750
2733
  )
2734
+ assert npc_result.conds is not None
2735
+ fork_info = ForkInfo(block_2.height - 1, block_2.height - 1, block_2.prev_header_hash)
2751
2736
  _, err, _ = await b.add_block(
2752
- block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
2737
+ block_2,
2738
+ PreValidationResult(None, uint64(1), npc_result.conds.replace(validated_signature=True), uint32(0)),
2739
+ sub_slot_iters=ssi,
2740
+ fork_info=fork_info,
2753
2741
  )
2754
2742
  assert err == Err.INVALID_BLOCK_COST
2755
2743
 
@@ -2776,11 +2764,19 @@ class TestBodyValidation:
2776
2764
  else b.constants.MAX_BLOCK_COST_CLVM * 1000
2777
2765
  )
2778
2766
  npc_result = get_name_puzzle_conditions(
2779
- block_generator, max_cost, mempool_mode=False, height=softfork_height, constants=bt.constants
2767
+ block_generator,
2768
+ max_cost,
2769
+ mempool_mode=False,
2770
+ height=softfork_height,
2771
+ constants=bt.constants,
2780
2772
  )
2781
-
2782
- result, err, _ = await b.add_block(
2783
- block_2, PreValidationResult(None, uint64(1), npc_result.conds, False, uint32(0)), None, sub_slot_iters=ssi
2773
+ assert npc_result.conds is not None
2774
+ fork_info = ForkInfo(block_2.height - 1, block_2.height - 1, block_2.prev_header_hash)
2775
+ _result, err, _ = await b.add_block(
2776
+ block_2,
2777
+ PreValidationResult(None, uint64(1), npc_result.conds.replace(validated_signature=True), uint32(0)),
2778
+ sub_slot_iters=ssi,
2779
+ fork_info=fork_info,
2784
2780
  )
2785
2781
  assert err == Err.INVALID_BLOCK_COST
2786
2782
 
@@ -2817,7 +2813,7 @@ class TestBodyValidation:
2817
2813
 
2818
2814
  # wt: WalletTool = bt_2.get_pool_wallet_tool()
2819
2815
 
2820
- # condition_dict: Dict[ConditionOpcode, List[ConditionWithArgs]] = {ConditionOpcode.CREATE_COIN: []}
2816
+ # condition_dict: dict[ConditionOpcode, list[ConditionWithArgs]] = {ConditionOpcode.CREATE_COIN: []}
2821
2817
  # output = ConditionWithArgs(ConditionOpcode.CREATE_COIN, [bt_2.pool_ph, int_to_bytes(2 ** 64)])
2822
2818
  # condition_dict[ConditionOpcode.CREATE_COIN].append(output)
2823
2819
 
@@ -2935,7 +2931,7 @@ class TestBodyValidation:
2935
2931
 
2936
2932
  wt: WalletTool = bt.get_pool_wallet_tool()
2937
2933
 
2938
- condition_dict: Dict[ConditionOpcode, List[ConditionWithArgs]] = {ConditionOpcode.CREATE_COIN: []}
2934
+ condition_dict: dict[ConditionOpcode, list[ConditionWithArgs]] = {ConditionOpcode.CREATE_COIN: []}
2939
2935
  for _ in range(2):
2940
2936
  output = ConditionWithArgs(ConditionOpcode.CREATE_COIN, [bt.pool_ph, int_to_bytes(1)])
2941
2937
  condition_dict[ConditionOpcode.CREATE_COIN].append(output)
@@ -3048,27 +3044,40 @@ class TestBodyValidation:
3048
3044
  await _validate_and_add_block(b, block)
3049
3045
 
3050
3046
  blocks_reorg = bt.get_consecutive_blocks(2, block_list_input=blocks[:-7], guarantee_transaction_block=True)
3051
- await _validate_and_add_block(b, blocks_reorg[-2], expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3052
- await _validate_and_add_block(b, blocks_reorg[-1], expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3047
+ fork_info = ForkInfo(blocks[-8].height, blocks[-8].height, blocks[-8].header_hash)
3048
+ await _validate_and_add_block(
3049
+ b, blocks_reorg[-2], expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3050
+ )
3051
+ await _validate_and_add_block(
3052
+ b, blocks_reorg[-1], expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3053
+ )
3053
3054
 
3054
3055
  # Coin does not exist in reorg
3055
3056
  blocks_reorg = bt.get_consecutive_blocks(
3056
3057
  1, block_list_input=blocks_reorg, guarantee_transaction_block=True, transaction_data=tx_2
3057
3058
  )
3058
-
3059
- await _validate_and_add_block(b, blocks_reorg[-1], expected_error=Err.UNKNOWN_UNSPENT)
3059
+ peak = b.get_peak()
3060
+ assert peak is not None
3061
+ await _validate_and_add_block(b, blocks_reorg[-1], expected_error=Err.UNKNOWN_UNSPENT, fork_info=fork_info)
3060
3062
 
3061
3063
  # Finally add the block to the fork (spending both in same bundle, this is ephemeral)
3062
3064
  agg = SpendBundle.aggregate([tx, tx_2])
3063
3065
  blocks_reorg = bt.get_consecutive_blocks(
3064
3066
  1, block_list_input=blocks_reorg[:-1], guarantee_transaction_block=True, transaction_data=agg
3065
3067
  )
3066
- await _validate_and_add_block(b, blocks_reorg[-1], expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3068
+
3069
+ peak = b.get_peak()
3070
+ assert peak is not None
3071
+ await _validate_and_add_block(
3072
+ b, blocks_reorg[-1], expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3073
+ )
3067
3074
 
3068
3075
  blocks_reorg = bt.get_consecutive_blocks(
3069
3076
  1, block_list_input=blocks_reorg, guarantee_transaction_block=True, transaction_data=tx_2
3070
3077
  )
3071
- await _validate_and_add_block(b, blocks_reorg[-1], expected_error=Err.DOUBLE_SPEND_IN_FORK)
3078
+ peak = b.get_peak()
3079
+ assert peak is not None
3080
+ await _validate_and_add_block(b, blocks_reorg[-1], expected_error=Err.DOUBLE_SPEND_IN_FORK, fork_info=fork_info)
3072
3081
 
3073
3082
  rewards_ph = wt.get_new_puzzlehash()
3074
3083
  blocks_reorg = bt.get_consecutive_blocks(
@@ -3077,9 +3086,12 @@ class TestBodyValidation:
3077
3086
  guarantee_transaction_block=True,
3078
3087
  farmer_reward_puzzle_hash=rewards_ph,
3079
3088
  )
3089
+
3090
+ peak = b.get_peak()
3091
+ assert peak is not None
3080
3092
  for block in blocks_reorg[-10:]:
3081
3093
  await _validate_and_add_block_multi_result(
3082
- b, block, expected_result=[AddBlockResult.ADDED_AS_ORPHAN, AddBlockResult.NEW_PEAK]
3094
+ b, block, expected_result=[AddBlockResult.ADDED_AS_ORPHAN, AddBlockResult.NEW_PEAK], fork_info=fork_info
3083
3095
  )
3084
3096
 
3085
3097
  # ephemeral coin is spent
@@ -3221,25 +3233,20 @@ class TestBodyValidation:
3221
3233
 
3222
3234
  # Bad signature fails during add_block
3223
3235
  await _validate_and_add_block(b, last_block, expected_error=Err.BAD_AGGREGATE_SIGNATURE)
3224
- # Also test the same case but when using BLSCache
3225
- await _validate_and_add_block(b, last_block, expected_error=Err.BAD_AGGREGATE_SIGNATURE, use_bls_cache=True)
3226
3236
 
3227
3237
  # Bad signature also fails in prevalidation
3228
3238
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
3229
3239
  diff = b.constants.DIFFICULTY_STARTING
3230
- preval_results = await pre_validate_blocks_multiprocessing(
3240
+ future = await pre_validate_block(
3231
3241
  b.constants,
3232
- b,
3233
- [last_block],
3242
+ AugmentedBlockchain(b),
3243
+ last_block,
3234
3244
  b.pool,
3235
- {},
3236
- sub_slot_iters=ssi,
3237
- difficulty=diff,
3238
- prev_ses_block=None,
3239
- validate_signatures=True,
3245
+ None,
3246
+ ValidationState(ssi, diff, None),
3240
3247
  )
3241
- assert preval_results is not None
3242
- assert preval_results[0].error == Err.BAD_AGGREGATE_SIGNATURE.value
3248
+ preval_result: PreValidationResult = await future
3249
+ assert preval_result.error == Err.BAD_AGGREGATE_SIGNATURE.value
3243
3250
 
3244
3251
 
3245
3252
  def maybe_header_hash(block: Optional[BlockRecord]) -> Optional[bytes32]:
@@ -3261,13 +3268,18 @@ class TestReorgs:
3261
3268
  assert peak.height == 14
3262
3269
 
3263
3270
  blocks_reorg_chain = bt.get_consecutive_blocks(7, blocks[:10], seed=b"2")
3271
+ fork_info = ForkInfo(-1, -1, bt.constants.GENESIS_CHALLENGE)
3264
3272
  for reorg_block in blocks_reorg_chain:
3265
3273
  if reorg_block.height < 10:
3266
- await _validate_and_add_block(b, reorg_block, expected_result=AddBlockResult.ALREADY_HAVE_BLOCK)
3274
+ await _validate_and_add_block(
3275
+ b, reorg_block, expected_result=AddBlockResult.ALREADY_HAVE_BLOCK, fork_info=fork_info
3276
+ )
3267
3277
  elif reorg_block.height < 15:
3268
- await _validate_and_add_block(b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3278
+ await _validate_and_add_block(
3279
+ b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3280
+ )
3269
3281
  elif reorg_block.height >= 15:
3270
- await _validate_and_add_block(b, reorg_block)
3282
+ await _validate_and_add_block(b, reorg_block, fork_info=fork_info)
3271
3283
  peak = b.get_peak()
3272
3284
  assert peak is not None
3273
3285
  assert peak.height == 16
@@ -3296,16 +3308,19 @@ class TestReorgs:
3296
3308
  assert maybe_header_hash(b.get_tx_peak()) == last_tx_block
3297
3309
 
3298
3310
  reorg_last_tx_block: Optional[bytes32] = None
3299
-
3311
+ fork_block = blocks[9]
3312
+ fork_info = ForkInfo(fork_block.height, fork_block.height, fork_block.header_hash)
3300
3313
  blocks_reorg_chain = bt.get_consecutive_blocks(7, blocks[:10], seed=b"2")
3301
3314
  assert blocks_reorg_chain[reorg_point].is_transaction_block() is False
3302
3315
  for reorg_block in blocks_reorg_chain:
3303
3316
  if reorg_block.height < 10:
3304
3317
  await _validate_and_add_block(b, reorg_block, expected_result=AddBlockResult.ALREADY_HAVE_BLOCK)
3305
3318
  elif reorg_block.height < reorg_point:
3306
- await _validate_and_add_block(b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3319
+ await _validate_and_add_block(
3320
+ b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3321
+ )
3307
3322
  elif reorg_block.height >= reorg_point:
3308
- await _validate_and_add_block(b, reorg_block)
3323
+ await _validate_and_add_block(b, reorg_block, fork_info=fork_info)
3309
3324
 
3310
3325
  if reorg_block.is_transaction_block():
3311
3326
  reorg_last_tx_block = reorg_block.header_hash
@@ -3324,9 +3339,9 @@ class TestReorgs:
3324
3339
  self,
3325
3340
  light_blocks: bool,
3326
3341
  empty_blockchain: Blockchain,
3327
- default_10000_blocks: List[FullBlock],
3328
- test_long_reorg_blocks: List[FullBlock],
3329
- test_long_reorg_blocks_light: List[FullBlock],
3342
+ default_10000_blocks: list[FullBlock],
3343
+ test_long_reorg_blocks: list[FullBlock],
3344
+ test_long_reorg_blocks_light: list[FullBlock],
3330
3345
  ) -> None:
3331
3346
  if light_blocks:
3332
3347
  reorg_blocks = test_long_reorg_blocks_light[:1650]
@@ -3345,17 +3360,21 @@ class TestReorgs:
3345
3360
  print(f"pre-validating {len(blocks)} blocks")
3346
3361
  ssi = b.constants.SUB_SLOT_ITERS_STARTING
3347
3362
  diff = b.constants.DIFFICULTY_STARTING
3348
- pre_validation_results: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
3349
- b.constants,
3350
- b,
3351
- blocks,
3352
- b.pool,
3353
- {},
3354
- sub_slot_iters=ssi,
3355
- difficulty=diff,
3356
- prev_ses_block=None,
3357
- validate_signatures=False,
3358
- )
3363
+ chain = AugmentedBlockchain(b)
3364
+ vs = ValidationState(ssi, diff, None)
3365
+ futures = []
3366
+ for block in blocks:
3367
+ futures.append(
3368
+ await pre_validate_block(
3369
+ b.constants,
3370
+ chain,
3371
+ block,
3372
+ b.pool,
3373
+ None,
3374
+ vs,
3375
+ )
3376
+ )
3377
+ pre_validation_results: list[PreValidationResult] = list(await asyncio.gather(*futures))
3359
3378
  for i, block in enumerate(blocks):
3360
3379
  if block.height != 0 and len(block.finished_sub_slots) > 0:
3361
3380
  if block.finished_sub_slots[0].challenge_chain.new_sub_slot_iters is not None:
@@ -3363,7 +3382,12 @@ class TestReorgs:
3363
3382
  assert pre_validation_results[i].error is None
3364
3383
  if (block.height % 100) == 0:
3365
3384
  print(f"main chain: {block.height:4} weight: {block.weight}")
3366
- (result, err, _) = await b.add_block(block, pre_validation_results[i], None, sub_slot_iters=ssi)
3385
+
3386
+ fork_info: ForkInfo = ForkInfo(block.height - 1, block.height - 1, block.prev_header_hash)
3387
+ assert fork_info is not None
3388
+ (result, err, _) = await b.add_block(
3389
+ block, pre_validation_results[i], sub_slot_iters=ssi, fork_info=fork_info
3390
+ )
3367
3391
  await check_block_store_invariant(b)
3368
3392
  assert err is None
3369
3393
  assert result == AddBlockResult.NEW_PEAK
@@ -3388,7 +3412,7 @@ class TestReorgs:
3388
3412
  b.clean_block_records()
3389
3413
 
3390
3414
  first_peak = b.get_peak()
3391
- fork_info: Optional[ForkInfo] = None
3415
+ fork_info2 = None
3392
3416
  for reorg_block in reorg_blocks:
3393
3417
  if (reorg_block.height % 100) == 0:
3394
3418
  peak = b.get_peak()
@@ -3402,14 +3426,14 @@ class TestReorgs:
3402
3426
  if reorg_block.height < num_blocks_chain_2_start:
3403
3427
  await _validate_and_add_block(b, reorg_block, expected_result=AddBlockResult.ALREADY_HAVE_BLOCK)
3404
3428
  elif reorg_block.weight <= chain_1_weight:
3405
- if fork_info is None:
3406
- fork_info = ForkInfo(reorg_block.height - 1, reorg_block.height - 1, reorg_block.prev_header_hash)
3429
+ if fork_info2 is None:
3430
+ fork_info2 = ForkInfo(reorg_block.height - 1, reorg_block.height - 1, reorg_block.prev_header_hash)
3407
3431
  await _validate_and_add_block(
3408
- b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3432
+ b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info2
3409
3433
  )
3410
3434
  elif reorg_block.weight > chain_1_weight:
3411
3435
  await _validate_and_add_block(
3412
- b, reorg_block, expected_result=AddBlockResult.NEW_PEAK, fork_info=fork_info
3436
+ b, reorg_block, expected_result=AddBlockResult.NEW_PEAK, fork_info=fork_info2
3413
3437
  )
3414
3438
 
3415
3439
  # if these asserts fires, there was no reorg
@@ -3448,7 +3472,7 @@ class TestReorgs:
3448
3472
 
3449
3473
  # start the fork point a few blocks back, to test that the blockchain
3450
3474
  # can catch up
3451
- fork_block = default_10000_blocks[num_blocks_chain_2_start - 200]
3475
+ fork_block = default_10000_blocks[num_blocks_chain_2_start - 101]
3452
3476
  fork_info = ForkInfo(fork_block.height, fork_block.height, fork_block.header_hash)
3453
3477
  await b.warmup(fork_block.height)
3454
3478
  for block in blocks:
@@ -3476,7 +3500,7 @@ class TestReorgs:
3476
3500
 
3477
3501
  @pytest.mark.anyio
3478
3502
  async def test_long_compact_blockchain(
3479
- self, empty_blockchain: Blockchain, default_2000_blocks_compact: List[FullBlock]
3503
+ self, empty_blockchain: Blockchain, default_2000_blocks_compact: list[FullBlock]
3480
3504
  ) -> None:
3481
3505
  b = empty_blockchain
3482
3506
  for block in default_2000_blocks_compact:
@@ -3499,22 +3523,34 @@ class TestReorgs:
3499
3523
 
3500
3524
  # Reorg to alternate chain that is 1 height longer
3501
3525
  blocks_reorg_chain = bt.get_consecutive_blocks(16, [], seed=b"2")
3526
+ fork_info = ForkInfo(-1, -1, bt.constants.GENESIS_CHALLENGE)
3502
3527
  for reorg_block in blocks_reorg_chain:
3503
3528
  if reorg_block.height < 15:
3504
3529
  await _validate_and_add_block_multi_result(
3505
3530
  b,
3506
3531
  reorg_block,
3507
3532
  expected_result=[AddBlockResult.ADDED_AS_ORPHAN, AddBlockResult.ALREADY_HAVE_BLOCK],
3533
+ fork_info=fork_info,
3508
3534
  )
3509
3535
  elif reorg_block.height >= 15:
3510
- await _validate_and_add_block(b, reorg_block)
3536
+ await _validate_and_add_block(b, reorg_block, fork_info=fork_info)
3511
3537
 
3512
3538
  # Back to original chain
3513
3539
  blocks_reorg_chain_2 = bt.get_consecutive_blocks(3, blocks, seed=b"3")
3514
3540
 
3515
- await _validate_and_add_block(b, blocks_reorg_chain_2[-3], expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3516
- await _validate_and_add_block(b, blocks_reorg_chain_2[-2])
3517
- await _validate_and_add_block(b, blocks_reorg_chain_2[-1])
3541
+ # we start from the beginning to make sure fork_info is built correctly
3542
+ fork_info = ForkInfo(-1, -1, bt.constants.GENESIS_CHALLENGE)
3543
+ for reorg_block in blocks_reorg_chain_2:
3544
+ if reorg_block.height < 15:
3545
+ await _validate_and_add_block(
3546
+ b, reorg_block, expected_result=AddBlockResult.ALREADY_HAVE_BLOCK, fork_info=fork_info
3547
+ )
3548
+ elif reorg_block.height < 16:
3549
+ await _validate_and_add_block(
3550
+ b, reorg_block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info
3551
+ )
3552
+ else:
3553
+ await _validate_and_add_block(b, reorg_block, fork_info=fork_info)
3518
3554
 
3519
3555
  peak = b.get_peak()
3520
3556
  assert peak is not None
@@ -3562,9 +3598,10 @@ class TestReorgs:
3562
3598
  )
3563
3599
  for block in blocks:
3564
3600
  await _validate_and_add_block(b, block)
3565
-
3566
- for block in blocks_fork:
3567
- await _validate_and_add_block_no_error(b, block)
3601
+ fork_block = blocks[11]
3602
+ fork_info = ForkInfo(fork_block.height, fork_block.height, fork_block.header_hash)
3603
+ for block in blocks_fork[12:]:
3604
+ await _validate_and_add_block_no_error(b, block, fork_info=fork_info)
3568
3605
 
3569
3606
  @pytest.mark.anyio
3570
3607
  async def test_get_header_blocks_in_range_tx_filter(self, empty_blockchain: Blockchain, bt: BlockTools) -> None:
@@ -3600,7 +3637,7 @@ class TestReorgs:
3600
3637
  assert blocks_with_filter[header_hash].header_hash == blocks_without_filter[header_hash].header_hash
3601
3638
 
3602
3639
  @pytest.mark.anyio
3603
- async def test_get_blocks_at(self, empty_blockchain: Blockchain, default_1000_blocks: List[FullBlock]) -> None:
3640
+ async def test_get_blocks_at(self, empty_blockchain: Blockchain, default_1000_blocks: list[FullBlock]) -> None:
3604
3641
  b = empty_blockchain
3605
3642
  heights = []
3606
3643
  for block in default_1000_blocks[:200]:
@@ -3678,8 +3715,8 @@ async def test_reorg_new_ref(empty_blockchain: Blockchain, bt: BlockTools) -> No
3678
3715
  )
3679
3716
  blocks_reorg_chain = bt.get_consecutive_blocks(4, blocks_reorg_chain, seed=b"2")
3680
3717
 
3718
+ fork_info = ForkInfo(-1, -1, b.constants.GENESIS_CHALLENGE)
3681
3719
  for i, block in enumerate(blocks_reorg_chain):
3682
- fork_info: Optional[ForkInfo] = None
3683
3720
  if i < 10:
3684
3721
  expected = AddBlockResult.ALREADY_HAVE_BLOCK
3685
3722
  elif i < 19:
@@ -3693,8 +3730,6 @@ async def test_reorg_new_ref(empty_blockchain: Blockchain, bt: BlockTools) -> No
3693
3730
  expected = AddBlockResult.NEW_PEAK
3694
3731
  else:
3695
3732
  expected = AddBlockResult.NEW_PEAK
3696
- if fork_info is None:
3697
- fork_info = ForkInfo(blocks[1].height, blocks[1].height, blocks[1].header_hash)
3698
3733
  await _validate_and_add_block(b, block, expected_result=expected, fork_info=fork_info)
3699
3734
  peak = b.get_peak()
3700
3735
  assert peak is not None
@@ -3746,7 +3781,7 @@ async def test_reorg_stale_fork_height(empty_blockchain: Blockchain, bt: BlockTo
3746
3781
  await _validate_and_add_block(b, block, expected_result=AddBlockResult.NEW_PEAK)
3747
3782
 
3748
3783
  # fake the fork_info to make every new block look like a reorg
3749
- fork_info = ForkInfo(blocks[1].height, blocks[1].height, blocks[1].header_hash)
3784
+ fork_info = ForkInfo(blocks[4].height, blocks[4].height, blocks[4].header_hash)
3750
3785
  for block in blocks[5:]:
3751
3786
  await _validate_and_add_block(b, block, expected_result=AddBlockResult.NEW_PEAK, fork_info=fork_info)
3752
3787
  peak = b.get_peak()
@@ -3796,8 +3831,10 @@ async def test_chain_failed_rollback(empty_blockchain: Blockchain, bt: BlockTool
3796
3831
  guarantee_transaction_block=True,
3797
3832
  )
3798
3833
 
3834
+ fork_block = blocks_reorg_chain[9]
3835
+ fork_info = ForkInfo(fork_block.height, fork_block.height, fork_block.header_hash)
3799
3836
  for block in blocks_reorg_chain[10:-1]:
3800
- await _validate_and_add_block(b, block, expected_result=AddBlockResult.ADDED_AS_ORPHAN)
3837
+ await _validate_and_add_block(b, block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info)
3801
3838
 
3802
3839
  # Incorrectly set the height as spent in DB to trigger an error
3803
3840
  print(f"{await b.coin_store.get_coin_record(spend_bundle.coin_spends[0].coin.name())}")
@@ -3806,8 +3843,10 @@ async def test_chain_failed_rollback(empty_blockchain: Blockchain, bt: BlockTool
3806
3843
  await b.coin_store.rollback_to_block(2)
3807
3844
  print(f"{await b.coin_store.get_coin_record(spend_bundle.coin_spends[0].coin.name())}")
3808
3845
 
3846
+ fork_block = blocks_reorg_chain[10 - 1]
3847
+ # fork_info = ForkInfo(fork_block.height, fork_block.height, fork_block.header_hash)
3809
3848
  with pytest.raises(ValueError, match="Invalid operation to set spent"):
3810
- await _validate_and_add_block(b, blocks_reorg_chain[-1])
3849
+ await _validate_and_add_block(b, blocks_reorg_chain[-1], fork_info=fork_info)
3811
3850
 
3812
3851
  peak = b.get_peak()
3813
3852
  assert peak is not None
@@ -3906,31 +3945,37 @@ async def test_reorg_flip_flop(empty_blockchain: Blockchain, bt: BlockTools) ->
3906
3945
  block1, block2 = b1, b2
3907
3946
  counter += 1
3908
3947
 
3909
- preval: List[PreValidationResult] = await pre_validate_blocks_multiprocessing(
3910
- b.constants,
3911
- b,
3912
- [block1],
3913
- b.pool,
3914
- {},
3915
- sub_slot_iters=ssi,
3916
- difficulty=diff,
3917
- prev_ses_block=None,
3918
- validate_signatures=False,
3948
+ preval = await (
3949
+ await pre_validate_block(
3950
+ b.constants,
3951
+ AugmentedBlockchain(b),
3952
+ block1,
3953
+ b.pool,
3954
+ None,
3955
+ ValidationState(ssi, diff, None),
3956
+ )
3919
3957
  )
3920
- _, err, _ = await b.add_block(block1, preval[0], None, sub_slot_iters=ssi)
3958
+ peak = b.get_peak()
3959
+ if peak is None:
3960
+ fork_info = ForkInfo(-1, -1, bt.constants.GENESIS_CHALLENGE)
3961
+ else:
3962
+ fork_info = await get_fork_info(b, block1, peak)
3963
+ _, err, _ = await b.add_block(block1, preval, sub_slot_iters=ssi, fork_info=fork_info)
3921
3964
  assert err is None
3922
- preval = await pre_validate_blocks_multiprocessing(
3923
- b.constants,
3924
- b,
3925
- [block2],
3926
- b.pool,
3927
- {},
3928
- sub_slot_iters=ssi,
3929
- difficulty=diff,
3930
- prev_ses_block=None,
3931
- validate_signatures=False,
3965
+ preval = await (
3966
+ await pre_validate_block(
3967
+ b.constants,
3968
+ AugmentedBlockchain(b),
3969
+ block2,
3970
+ b.pool,
3971
+ None,
3972
+ ValidationState(ssi, diff, None),
3973
+ )
3932
3974
  )
3933
- _, err, _ = await b.add_block(block2, preval[0], None, sub_slot_iters=ssi)
3975
+ peak = b.get_peak()
3976
+ assert peak is not None
3977
+ fork_info = await get_fork_info(b, block2, peak)
3978
+ _, err, _ = await b.add_block(block2, preval, sub_slot_iters=ssi, fork_info=fork_info)
3934
3979
  assert err is None
3935
3980
 
3936
3981
  peak = b.get_peak()
@@ -3949,27 +3994,33 @@ async def test_reorg_flip_flop(empty_blockchain: Blockchain, bt: BlockTools) ->
3949
3994
  await _validate_and_add_block(b, block)
3950
3995
 
3951
3996
 
3952
- async def test_get_tx_peak(default_400_blocks: List[FullBlock], empty_blockchain: Blockchain) -> None:
3997
+ async def test_get_tx_peak(default_400_blocks: list[FullBlock], empty_blockchain: Blockchain) -> None:
3953
3998
  bc = empty_blockchain
3954
3999
  test_blocks = default_400_blocks[:100]
3955
4000
  ssi = bc.constants.SUB_SLOT_ITERS_STARTING
3956
4001
  diff = bc.constants.DIFFICULTY_STARTING
3957
- res = await pre_validate_blocks_multiprocessing(
3958
- bc.constants,
3959
- bc,
3960
- test_blocks,
3961
- bc.pool,
3962
- {},
3963
- sub_slot_iters=ssi,
3964
- difficulty=diff,
3965
- prev_ses_block=None,
3966
- validate_signatures=False,
3967
- )
4002
+ futures: list[Awaitable[PreValidationResult]] = []
4003
+ chain = AugmentedBlockchain(bc)
4004
+ vs = ValidationState(ssi, diff, None)
4005
+ for block in test_blocks:
4006
+ futures.append(
4007
+ await pre_validate_block(
4008
+ bc.constants,
4009
+ chain,
4010
+ block,
4011
+ bc.pool,
4012
+ None,
4013
+ vs,
4014
+ )
4015
+ )
4016
+
4017
+ res: list[PreValidationResult] = list(await asyncio.gather(*futures))
3968
4018
 
3969
4019
  last_tx_block_record = None
3970
4020
  for b, prevalidation_res in zip(test_blocks, res):
3971
4021
  assert bc.get_tx_peak() == last_tx_block_record
3972
- _, err, _ = await bc.add_block(b, prevalidation_res, None, sub_slot_iters=ssi)
4022
+ fork_info = ForkInfo(b.height - 1, b.height - 1, b.prev_header_hash)
4023
+ _, err, _ = await bc.add_block(b, prevalidation_res, sub_slot_iters=ssi, fork_info=fork_info)
3973
4024
  assert err is None
3974
4025
 
3975
4026
  if b.is_transaction_block():
@@ -3995,8 +4046,8 @@ def to_bytes(gen: Optional[SerializedProgram]) -> bytes:
3995
4046
  @pytest.mark.limit_consensus_modes(reason="block heights for generators differ between test chains in different modes")
3996
4047
  @pytest.mark.parametrize("clear_cache", [True, False])
3997
4048
  async def test_lookup_block_generators(
3998
- default_10000_blocks: List[FullBlock],
3999
- test_long_reorg_blocks_light: List[FullBlock],
4049
+ default_10000_blocks: list[FullBlock],
4050
+ test_long_reorg_blocks_light: list[FullBlock],
4000
4051
  bt: BlockTools,
4001
4052
  empty_blockchain: Blockchain,
4002
4053
  clear_cache: bool,
@@ -4020,11 +4071,13 @@ async def test_lookup_block_generators(
4020
4071
  # 507, 516, 527, 535, 539, 543, 547
4021
4072
 
4022
4073
  # start with adding some blocks to test lookups from the mainchain
4074
+ fork_info = ForkInfo(-1, -1, bt.constants.GENESIS_CHALLENGE)
4023
4075
  for block in blocks_2[:550]:
4024
- await _validate_and_add_block(b, block, expected_result=AddBlockResult.NEW_PEAK)
4076
+ await _validate_and_add_block(b, block, expected_result=AddBlockResult.NEW_PEAK, fork_info=fork_info)
4025
4077
 
4078
+ fork_info = ForkInfo(blocks_1[500].height - 1, blocks_1[500].height - 1, blocks_1[500].prev_header_hash)
4026
4079
  for block in blocks_1[500:550]:
4027
- await _validate_and_add_block(b, block, expected_result=AddBlockResult.ADDED_AS_ORPHAN)
4080
+ await _validate_and_add_block(b, block, expected_result=AddBlockResult.ADDED_AS_ORPHAN, fork_info=fork_info)
4028
4081
 
4029
4082
  # now we have a blockchain with two forks, the peak is at blocks_2[550] and
4030
4083
  # the leight weight peak is at blocks_1[550]
@@ -4098,3 +4151,52 @@ async def test_lookup_block_generators(
4098
4151
  b.clean_block_records()
4099
4152
  with pytest.raises(AssertionError):
4100
4153
  await b.lookup_block_generators(blocks_1[600].prev_header_hash, {uint32(3)})
4154
+
4155
+
4156
+ async def get_fork_info(blockchain: Blockchain, block: FullBlock, peak: BlockRecord) -> ForkInfo:
4157
+ fork_chain, fork_hash = await lookup_fork_chain(
4158
+ blockchain,
4159
+ (peak.height, peak.header_hash),
4160
+ (block.height - 1, block.prev_header_hash),
4161
+ blockchain.constants,
4162
+ )
4163
+ # now we know how long the fork is, and can compute the fork
4164
+ # height.
4165
+ fork_height = block.height - len(fork_chain) - 1
4166
+ fork_info = ForkInfo(fork_height, fork_height, fork_hash)
4167
+
4168
+ # now run all the blocks of the fork to compute the additions
4169
+ # and removals. They are recorded in the fork_info object
4170
+ counter = 0
4171
+ start = time.monotonic()
4172
+ for height in range(fork_info.fork_height + 1, block.height):
4173
+ fork_block: Optional[FullBlock] = await blockchain.block_store.get_full_block(fork_chain[uint32(height)])
4174
+ assert fork_block is not None
4175
+ assert fork_block.height - 1 == fork_info.peak_height
4176
+ assert fork_block.height == 0 or fork_block.prev_header_hash == fork_info.peak_hash
4177
+ await blockchain.run_single_block(fork_block, fork_info)
4178
+ counter += 1
4179
+ end = time.monotonic()
4180
+ log.info(
4181
+ f"executed {counter} block generators in {end - start:2f} s. "
4182
+ f"{len(fork_info.additions_since_fork)} additions, "
4183
+ f"{len(fork_info.removals_since_fork)} removals"
4184
+ )
4185
+
4186
+ return fork_info
4187
+
4188
+
4189
+ @pytest.mark.anyio
4190
+ async def test_get_header_blocks_in_range_tx_filter_non_tx_block(empty_blockchain: Blockchain, bt: BlockTools) -> None:
4191
+ """
4192
+ Covers the case of calling `get_header_blocks_in_range`, requesting
4193
+ transactions filter, on a non transaction block.
4194
+ """
4195
+ b = empty_blockchain
4196
+ blocks = bt.get_consecutive_blocks(2)
4197
+ for block in blocks:
4198
+ await _validate_and_add_block(b, block)
4199
+ non_tx_block = next(block for block in blocks if not block.is_transaction_block())
4200
+ blocks_with_filter = await b.get_header_blocks_in_range(0, 42, tx_filter=True)
4201
+ empty_tx_filter = b"\x00"
4202
+ assert blocks_with_filter[non_tx_block.header_hash].transactions_filter == empty_tx_filter