chia-blockchain 2.5.7rc4__py3-none-any.whl → 2.5.8rc1__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 (528) hide show
  1. chia/__init__.py +8 -4
  2. chia/_tests/blockchain/blockchain_test_utils.py +6 -8
  3. chia/_tests/blockchain/test_augmented_chain.py +4 -4
  4. chia/_tests/blockchain/test_blockchain.py +165 -190
  5. chia/_tests/blockchain/test_build_chains.py +2 -4
  6. chia/_tests/blockchain/test_get_block_generator.py +2 -3
  7. chia/_tests/clvm/coin_store.py +4 -7
  8. chia/_tests/clvm/test_clvm_step.py +4 -4
  9. chia/_tests/clvm/test_puzzle_compression.py +2 -1
  10. chia/_tests/clvm/test_puzzle_drivers.py +2 -2
  11. chia/_tests/clvm/test_singletons.py +2 -4
  12. chia/_tests/clvm/test_spend_sim.py +2 -2
  13. chia/_tests/cmds/cmd_test_utils.py +27 -45
  14. chia/_tests/cmds/test_cmd_framework.py +6 -6
  15. chia/_tests/cmds/test_daemon.py +3 -3
  16. chia/_tests/cmds/test_show.py +4 -4
  17. chia/_tests/cmds/test_tx_config_args.py +1 -2
  18. chia/_tests/cmds/testing_classes.py +4 -5
  19. chia/_tests/cmds/wallet/test_did.py +24 -27
  20. chia/_tests/cmds/wallet/test_nft.py +12 -10
  21. chia/_tests/cmds/wallet/test_vcs.py +11 -12
  22. chia/_tests/cmds/wallet/test_wallet.py +134 -89
  23. chia/_tests/conftest.py +59 -30
  24. chia/_tests/connection_utils.py +2 -2
  25. chia/_tests/core/cmds/test_beta.py +4 -4
  26. chia/_tests/core/cmds/test_keys.py +2 -3
  27. chia/_tests/core/cmds/test_wallet.py +15 -15
  28. chia/_tests/core/consensus/test_pot_iterations.py +19 -73
  29. chia/_tests/core/custom_types/test_proof_of_space.py +124 -98
  30. chia/_tests/core/daemon/test_daemon.py +11 -11
  31. chia/_tests/core/data_layer/conftest.py +2 -2
  32. chia/_tests/core/data_layer/test_data_rpc.py +28 -14
  33. chia/_tests/core/data_layer/test_data_store.py +10 -10
  34. chia/_tests/core/data_layer/util.py +11 -11
  35. chia/_tests/core/farmer/test_farmer_api.py +2 -4
  36. chia/_tests/core/full_node/full_sync/test_full_sync.py +8 -7
  37. chia/_tests/core/full_node/stores/test_block_store.py +5 -4
  38. chia/_tests/core/full_node/stores/test_coin_store.py +5 -11
  39. chia/_tests/core/full_node/stores/test_full_node_store.py +8 -8
  40. chia/_tests/core/full_node/stores/test_hint_store.py +2 -2
  41. chia/_tests/core/full_node/test_block_height_map.py +3 -4
  42. chia/_tests/core/full_node/test_conditions.py +21 -23
  43. chia/_tests/core/full_node/test_full_node.py +225 -62
  44. chia/_tests/core/full_node/test_hint_management.py +2 -4
  45. chia/_tests/core/full_node/test_performance.py +0 -1
  46. chia/_tests/core/full_node/test_prev_tx_block.py +88 -11
  47. chia/_tests/core/full_node/test_transactions.py +1 -2
  48. chia/_tests/core/full_node/test_tx_processing_queue.py +109 -25
  49. chia/_tests/core/mempool/test_mempool.py +29 -37
  50. chia/_tests/core/mempool/test_mempool_fee_estimator.py +39 -39
  51. chia/_tests/core/mempool/test_mempool_fee_protocol.py +2 -6
  52. chia/_tests/core/mempool/test_mempool_manager.py +963 -839
  53. chia/_tests/core/mempool/test_singleton_fast_forward.py +6 -6
  54. chia/_tests/core/server/serve.py +7 -7
  55. chia/_tests/core/server/test_dos.py +1 -2
  56. chia/_tests/core/server/test_event_loop.py +12 -4
  57. chia/_tests/core/server/test_loop.py +7 -8
  58. chia/_tests/core/server/test_rate_limits.py +9 -8
  59. chia/_tests/core/server/test_server.py +61 -1
  60. chia/_tests/core/services/test_services.py +2 -2
  61. chia/_tests/core/ssl/test_ssl.py +2 -2
  62. chia/_tests/core/test_cost_calculation.py +2 -6
  63. chia/_tests/core/test_farmer_harvester_rpc.py +3 -5
  64. chia/_tests/core/test_filter.py +0 -1
  65. chia/_tests/core/test_full_node_rpc.py +2 -2
  66. chia/_tests/core/test_merkle_set.py +1 -2
  67. chia/_tests/core/test_seeder.py +4 -4
  68. chia/_tests/core/util/test_config.py +4 -4
  69. chia/_tests/core/util/test_jsonify.py +2 -2
  70. chia/_tests/core/util/test_keychain.py +3 -3
  71. chia/_tests/core/util/test_lockfile.py +2 -1
  72. chia/_tests/core/util/test_log_exceptions.py +1 -2
  73. chia/_tests/core/util/test_streamable.py +17 -17
  74. chia/_tests/db/test_db_wrapper.py +3 -2
  75. chia/_tests/environments/wallet.py +14 -14
  76. chia/_tests/ether.py +4 -3
  77. chia/_tests/farmer_harvester/test_farmer.py +41 -24
  78. chia/_tests/farmer_harvester/test_farmer_harvester.py +50 -17
  79. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +27 -27
  80. chia/_tests/farmer_harvester/test_third_party_harvesters.py +21 -22
  81. chia/_tests/fee_estimation/test_fee_estimation_integration.py +18 -18
  82. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +11 -9
  83. chia/_tests/harvester/test_harvester_api.py +11 -4
  84. chia/_tests/plot_sync/test_plot_sync.py +13 -11
  85. chia/_tests/plot_sync/test_receiver.py +11 -10
  86. chia/_tests/plot_sync/test_sync_simulated.py +2 -2
  87. chia/_tests/plot_sync/util.py +1 -2
  88. chia/_tests/plotting/test_plot_manager.py +7 -6
  89. chia/_tests/plotting/test_prover.py +30 -38
  90. chia/_tests/pools/test_pool_cmdline.py +4 -6
  91. chia/_tests/pools/test_pool_rpc.py +203 -61
  92. chia/_tests/pools/test_pool_wallet.py +3 -3
  93. chia/_tests/pools/test_wallet_pool_store.py +1 -4
  94. chia/_tests/process_junit.py +2 -2
  95. chia/_tests/rpc/test_rpc_client.py +4 -4
  96. chia/_tests/rpc/test_rpc_server.py +3 -3
  97. chia/_tests/simulation/test_simulation.py +12 -25
  98. chia/_tests/solver/test_solver_service.py +13 -4
  99. chia/_tests/testconfig.py +2 -2
  100. chia/_tests/timelord/test_new_peak.py +22 -11
  101. chia/_tests/tools/test_run_block.py +0 -2
  102. chia/_tests/tools/test_virtual_project.py +2 -1
  103. chia/_tests/util/benchmarks.py +1 -0
  104. chia/_tests/util/blockchain.py +38 -36
  105. chia/_tests/util/blockchain_mock.py +11 -11
  106. chia/_tests/util/build_network_protocol_files.py +2 -1
  107. chia/_tests/util/coin_store.py +2 -1
  108. chia/_tests/util/config.py +1 -1
  109. chia/_tests/util/db_connection.py +2 -3
  110. chia/_tests/util/full_sync.py +9 -11
  111. chia/_tests/util/gen_ssl_certs.py +4 -5
  112. chia/_tests/util/get_name_puzzle_conditions.py +2 -0
  113. chia/_tests/util/misc.py +24 -24
  114. chia/_tests/util/network_protocol_data.py +20 -3
  115. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  116. chia/_tests/util/protocol_messages_json.py +292 -3
  117. chia/_tests/util/setup_nodes.py +62 -47
  118. chia/_tests/util/spend_sim.py +57 -57
  119. chia/_tests/util/test_async_pool.py +2 -3
  120. chia/_tests/util/test_chia_version.py +1 -3
  121. chia/_tests/util/test_config.py +3 -3
  122. chia/_tests/util/test_full_block_utils.py +6 -3
  123. chia/_tests/util/test_limited_semaphore.py +1 -2
  124. chia/_tests/util/test_misc.py +2 -2
  125. chia/_tests/util/test_network.py +1 -2
  126. chia/_tests/util/test_priority_mutex.py +3 -3
  127. chia/_tests/util/test_recursive_replace.py +5 -6
  128. chia/_tests/util/test_replace_str_to_bytes.py +8 -10
  129. chia/_tests/util/test_testnet_overrides.py +3 -3
  130. chia/_tests/util/time_out_assert.py +2 -2
  131. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +4 -6
  132. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +2 -4
  133. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +19 -13
  134. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +13 -13
  135. chia/_tests/wallet/cat_wallet/test_trades.py +40 -38
  136. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +2 -4
  137. chia/_tests/wallet/conftest.py +6 -6
  138. chia/_tests/wallet/db_wallet/test_db_graftroot.py +1 -1
  139. chia/_tests/wallet/db_wallet/test_dl_offers.py +34 -34
  140. chia/_tests/wallet/did_wallet/test_did.py +16 -6
  141. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +21 -21
  142. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +20 -6
  143. chia/_tests/wallet/nft_wallet/test_nft_offers.py +19 -21
  144. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +1 -2
  145. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +121 -2
  146. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +6 -9
  147. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +44 -1
  148. chia/_tests/wallet/rpc/test_wallet_rpc.py +1672 -896
  149. chia/_tests/wallet/sync/test_wallet_sync.py +43 -47
  150. chia/_tests/wallet/test_clvm_streamable.py +2 -3
  151. chia/_tests/wallet/test_coin_management.py +2 -2
  152. chia/_tests/wallet/test_conditions.py +45 -51
  153. chia/_tests/wallet/test_debug_spend_bundle.py +2 -2
  154. chia/_tests/wallet/test_new_wallet_protocol.py +4 -6
  155. chia/_tests/wallet/test_notifications.py +14 -14
  156. chia/_tests/wallet/test_signer_protocol.py +5 -5
  157. chia/_tests/wallet/test_singleton_lifecycle_fast.py +4 -3
  158. chia/_tests/wallet/test_transaction_store.py +20 -20
  159. chia/_tests/wallet/test_util.py +2 -2
  160. chia/_tests/wallet/test_wallet.py +380 -228
  161. chia/_tests/wallet/test_wallet_action_scope.py +4 -4
  162. chia/_tests/wallet/test_wallet_blockchain.py +12 -12
  163. chia/_tests/wallet/test_wallet_coin_store.py +3 -4
  164. chia/_tests/wallet/test_wallet_node.py +14 -14
  165. chia/_tests/wallet/test_wallet_test_framework.py +2 -1
  166. chia/_tests/wallet/test_wallet_utils.py +2 -3
  167. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +3 -5
  168. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +14 -15
  169. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +29 -24
  170. chia/_tests/wallet/wallet_block_tools.py +12 -11
  171. chia/_tests/weight_proof/config.py +1 -0
  172. chia/_tests/weight_proof/test_weight_proof.py +5 -4
  173. chia/apis/__init__.py +21 -0
  174. chia/apis/farmer_stub.py +102 -0
  175. chia/apis/full_node_stub.py +372 -0
  176. chia/apis/harvester_stub.py +57 -0
  177. chia/apis/introducer_stub.py +35 -0
  178. chia/apis/solver_stub.py +30 -0
  179. chia/apis/stub_protocol_registry.py +21 -0
  180. chia/apis/timelord_stub.py +39 -0
  181. chia/apis/wallet_stub.py +161 -0
  182. chia/cmds/beta.py +3 -4
  183. chia/cmds/beta_funcs.py +4 -3
  184. chia/cmds/check_wallet_db.py +4 -4
  185. chia/cmds/chia.py +1 -2
  186. chia/cmds/cmd_classes.py +11 -13
  187. chia/cmds/cmd_helpers.py +11 -11
  188. chia/cmds/cmds_util.py +15 -15
  189. chia/cmds/coin_funcs.py +6 -7
  190. chia/cmds/coins.py +2 -3
  191. chia/cmds/configure.py +1 -2
  192. chia/cmds/data.py +42 -42
  193. chia/cmds/data_funcs.py +81 -81
  194. chia/cmds/db.py +4 -5
  195. chia/cmds/db_backup_func.py +2 -2
  196. chia/cmds/db_upgrade_func.py +3 -3
  197. chia/cmds/db_validate_func.py +2 -2
  198. chia/cmds/dev/data.py +4 -4
  199. chia/cmds/dev/gh.py +5 -5
  200. chia/cmds/dev/installers.py +2 -3
  201. chia/cmds/dev/mempool.py +3 -4
  202. chia/cmds/dev/mempool_funcs.py +4 -4
  203. chia/cmds/dev/sim.py +8 -8
  204. chia/cmds/dump_keyring.py +3 -3
  205. chia/cmds/farm.py +6 -8
  206. chia/cmds/farm_funcs.py +25 -24
  207. chia/cmds/init_funcs.py +4 -4
  208. chia/cmds/keys.py +16 -18
  209. chia/cmds/keys_funcs.py +36 -36
  210. chia/cmds/netspace.py +1 -3
  211. chia/cmds/netspace_funcs.py +1 -2
  212. chia/cmds/options.py +3 -2
  213. chia/cmds/param_types.py +17 -16
  214. chia/cmds/passphrase.py +6 -7
  215. chia/cmds/passphrase_funcs.py +11 -13
  216. chia/cmds/peer.py +1 -3
  217. chia/cmds/peer_funcs.py +3 -3
  218. chia/cmds/plotnft.py +6 -7
  219. chia/cmds/plotnft_funcs.py +37 -26
  220. chia/cmds/rpc.py +3 -3
  221. chia/cmds/show.py +3 -5
  222. chia/cmds/show_funcs.py +9 -9
  223. chia/cmds/sim_funcs.py +25 -26
  224. chia/cmds/solver.py +1 -3
  225. chia/cmds/solver_funcs.py +1 -2
  226. chia/cmds/start_funcs.py +2 -2
  227. chia/cmds/wallet.py +76 -81
  228. chia/cmds/wallet_funcs.py +206 -177
  229. chia/consensus/augmented_chain.py +6 -6
  230. chia/consensus/block_body_validation.py +19 -15
  231. chia/consensus/block_creation.py +25 -21
  232. chia/consensus/block_header_validation.py +27 -13
  233. chia/consensus/block_height_map.py +3 -6
  234. chia/consensus/block_height_map_protocol.py +2 -2
  235. chia/consensus/block_record.py +2 -4
  236. chia/consensus/blockchain.py +58 -40
  237. chia/consensus/blockchain_interface.py +7 -7
  238. chia/consensus/coin_store_protocol.py +5 -6
  239. chia/consensus/condition_tools.py +4 -4
  240. chia/consensus/cost_calculator.py +2 -3
  241. chia/consensus/default_constants.py +16 -13
  242. chia/consensus/deficit.py +1 -3
  243. chia/consensus/difficulty_adjustment.py +3 -5
  244. chia/consensus/find_fork_point.py +2 -4
  245. chia/consensus/full_block_to_block_record.py +11 -13
  246. chia/consensus/generator_tools.py +2 -3
  247. chia/consensus/get_block_challenge.py +42 -26
  248. chia/consensus/get_block_generator.py +2 -3
  249. chia/consensus/make_sub_epoch_summary.py +8 -7
  250. chia/consensus/multiprocess_validation.py +31 -20
  251. chia/consensus/pos_quality.py +6 -23
  252. chia/consensus/pot_iterations.py +17 -44
  253. chia/consensus/signage_point.py +4 -5
  254. chia/consensus/vdf_info_computation.py +2 -4
  255. chia/daemon/client.py +8 -8
  256. chia/daemon/keychain_proxy.py +31 -37
  257. chia/daemon/server.py +32 -33
  258. chia/daemon/windows_signal.py +4 -3
  259. chia/data_layer/data_layer.py +86 -77
  260. chia/data_layer/data_layer_rpc_api.py +9 -9
  261. chia/data_layer/data_layer_rpc_client.py +13 -15
  262. chia/data_layer/data_layer_server.py +3 -3
  263. chia/data_layer/data_layer_util.py +14 -14
  264. chia/data_layer/data_layer_wallet.py +94 -101
  265. chia/data_layer/data_store.py +50 -50
  266. chia/data_layer/dl_wallet_store.py +9 -12
  267. chia/data_layer/download_data.py +8 -9
  268. chia/data_layer/s3_plugin_service.py +5 -9
  269. chia/data_layer/start_data_layer.py +5 -5
  270. chia/farmer/farmer.py +31 -31
  271. chia/farmer/farmer_api.py +45 -33
  272. chia/farmer/farmer_rpc_api.py +5 -4
  273. chia/farmer/farmer_rpc_client.py +6 -6
  274. chia/farmer/start_farmer.py +6 -6
  275. chia/full_node/block_store.py +13 -16
  276. chia/full_node/check_fork_next_block.py +1 -2
  277. chia/full_node/coin_store.py +15 -16
  278. chia/full_node/eligible_coin_spends.py +3 -3
  279. chia/full_node/fee_estimate_store.py +2 -3
  280. chia/full_node/fee_tracker.py +1 -2
  281. chia/full_node/full_block_utils.py +4 -4
  282. chia/full_node/full_node.py +238 -224
  283. chia/full_node/full_node_api.py +193 -150
  284. chia/full_node/full_node_rpc_api.py +53 -31
  285. chia/full_node/full_node_rpc_client.py +18 -19
  286. chia/full_node/full_node_store.py +45 -43
  287. chia/full_node/hint_management.py +2 -2
  288. chia/full_node/mempool.py +17 -19
  289. chia/full_node/mempool_manager.py +89 -42
  290. chia/full_node/pending_tx_cache.py +2 -3
  291. chia/full_node/start_full_node.py +5 -5
  292. chia/full_node/sync_store.py +3 -4
  293. chia/full_node/tx_processing_queue.py +34 -13
  294. chia/full_node/weight_proof.py +61 -48
  295. chia/harvester/harvester.py +25 -24
  296. chia/harvester/harvester_api.py +61 -38
  297. chia/harvester/harvester_rpc_api.py +10 -10
  298. chia/harvester/start_harvester.py +4 -4
  299. chia/introducer/introducer.py +3 -3
  300. chia/introducer/introducer_api.py +6 -4
  301. chia/introducer/start_introducer.py +4 -4
  302. chia/legacy/keyring.py +3 -3
  303. chia/plot_sync/delta.py +1 -2
  304. chia/plot_sync/receiver.py +20 -17
  305. chia/plot_sync/sender.py +15 -10
  306. chia/plotters/bladebit.py +7 -7
  307. chia/plotters/chiapos.py +2 -2
  308. chia/plotters/madmax.py +4 -4
  309. chia/plotters/plotters.py +4 -4
  310. chia/plotters/plotters_util.py +3 -3
  311. chia/plotting/cache.py +20 -14
  312. chia/plotting/check_plots.py +26 -35
  313. chia/plotting/create_plots.py +22 -23
  314. chia/plotting/manager.py +21 -14
  315. chia/plotting/prover.py +59 -42
  316. chia/plotting/util.py +16 -16
  317. chia/pools/pool_config.py +2 -1
  318. chia/pools/pool_puzzles.py +11 -12
  319. chia/pools/pool_wallet.py +34 -57
  320. chia/pools/pool_wallet_info.py +39 -10
  321. chia/protocols/farmer_protocol.py +8 -9
  322. chia/protocols/fee_estimate.py +3 -4
  323. chia/protocols/full_node_protocol.py +3 -4
  324. chia/protocols/harvester_protocol.py +27 -15
  325. chia/protocols/outbound_message.py +3 -3
  326. chia/protocols/pool_protocol.py +8 -9
  327. chia/protocols/shared_protocol.py +1 -2
  328. chia/protocols/solver_protocol.py +9 -2
  329. chia/protocols/timelord_protocol.py +4 -7
  330. chia/protocols/wallet_protocol.py +11 -12
  331. chia/rpc/rpc_client.py +9 -9
  332. chia/rpc/rpc_server.py +17 -17
  333. chia/rpc/util.py +2 -2
  334. chia/seeder/crawler.py +8 -8
  335. chia/seeder/crawler_api.py +21 -27
  336. chia/seeder/crawler_rpc_api.py +2 -2
  337. chia/seeder/dns_server.py +21 -21
  338. chia/seeder/start_crawler.py +4 -4
  339. chia/server/address_manager.py +15 -16
  340. chia/server/api_protocol.py +11 -11
  341. chia/server/chia_policy.py +46 -26
  342. chia/server/introducer_peers.py +2 -3
  343. chia/server/node_discovery.py +19 -19
  344. chia/server/rate_limit_numbers.py +4 -5
  345. chia/server/rate_limits.py +4 -4
  346. chia/server/resolve_peer_info.py +4 -4
  347. chia/server/server.py +49 -52
  348. chia/server/signal_handlers.py +6 -6
  349. chia/server/start_service.py +17 -17
  350. chia/server/upnp.py +4 -6
  351. chia/server/ws_connection.py +52 -37
  352. chia/simulator/add_blocks_in_batches.py +1 -3
  353. chia/simulator/block_tools.py +312 -200
  354. chia/simulator/full_node_simulator.py +56 -35
  355. chia/simulator/keyring.py +2 -3
  356. chia/simulator/setup_services.py +15 -15
  357. chia/simulator/simulator_full_node_rpc_api.py +1 -2
  358. chia/simulator/simulator_full_node_rpc_client.py +1 -2
  359. chia/simulator/simulator_protocol.py +1 -2
  360. chia/simulator/simulator_test_tools.py +3 -3
  361. chia/simulator/start_simulator.py +7 -7
  362. chia/simulator/wallet_tools.py +10 -10
  363. chia/solver/solver.py +10 -10
  364. chia/solver/solver_api.py +10 -8
  365. chia/solver/solver_rpc_api.py +2 -2
  366. chia/solver/start_solver.py +4 -4
  367. chia/ssl/cacert.pem +148 -90
  368. chia/ssl/chia_ca.crt +14 -10
  369. chia/ssl/chia_ca_old.crt +19 -0
  370. chia/ssl/create_ssl.py +4 -4
  371. chia/ssl/renewedselfsignedca.conf +4 -0
  372. chia/ssl/ssl_check.py +1 -2
  373. chia/timelord/iters_from_block.py +1 -4
  374. chia/timelord/start_timelord.py +4 -4
  375. chia/timelord/timelord.py +44 -40
  376. chia/timelord/timelord_api.py +6 -4
  377. chia/timelord/timelord_launcher.py +2 -2
  378. chia/timelord/timelord_rpc_api.py +2 -2
  379. chia/timelord/timelord_state.py +11 -12
  380. chia/types/block_protocol.py +1 -3
  381. chia/types/blockchain_format/coin.py +1 -3
  382. chia/types/blockchain_format/program.py +11 -8
  383. chia/types/blockchain_format/proof_of_space.py +123 -76
  384. chia/types/blockchain_format/tree_hash.py +3 -3
  385. chia/types/blockchain_format/vdf.py +1 -2
  386. chia/types/coin_spend.py +3 -3
  387. chia/types/mempool_item.py +5 -5
  388. chia/types/mempool_submission_status.py +2 -3
  389. chia/types/peer_info.py +1 -2
  390. chia/types/unfinished_header_block.py +3 -4
  391. chia/types/validation_state.py +1 -2
  392. chia/util/action_scope.py +8 -8
  393. chia/util/async_pool.py +5 -5
  394. chia/util/bech32m.py +1 -2
  395. chia/util/beta_metrics.py +2 -2
  396. chia/util/block_cache.py +4 -4
  397. chia/util/chia_logging.py +2 -2
  398. chia/util/chia_version.py +1 -2
  399. chia/util/config.py +15 -16
  400. chia/util/db_wrapper.py +26 -27
  401. chia/util/default_root.py +1 -2
  402. chia/util/errors.py +3 -3
  403. chia/util/file_keyring.py +14 -14
  404. chia/util/files.py +2 -3
  405. chia/util/hash.py +4 -4
  406. chia/util/initial-config.yaml +3 -5
  407. chia/util/inline_executor.py +2 -1
  408. chia/util/ip_address.py +1 -2
  409. chia/util/keychain.py +25 -27
  410. chia/util/keyring_wrapper.py +18 -19
  411. chia/util/lock.py +3 -4
  412. chia/util/log_exceptions.py +1 -2
  413. chia/util/lru_cache.py +2 -2
  414. chia/util/network.py +6 -6
  415. chia/util/path.py +2 -3
  416. chia/util/priority_mutex.py +2 -2
  417. chia/util/profiler.py +1 -2
  418. chia/util/safe_cancel_task.py +1 -2
  419. chia/util/streamable.py +22 -8
  420. chia/util/task_referencer.py +1 -1
  421. chia/util/timing.py +3 -3
  422. chia/util/virtual_project_analysis.py +6 -5
  423. chia/util/ws_message.py +2 -2
  424. chia/wallet/cat_wallet/cat_info.py +3 -4
  425. chia/wallet/cat_wallet/cat_outer_puzzle.py +12 -11
  426. chia/wallet/cat_wallet/cat_utils.py +3 -4
  427. chia/wallet/cat_wallet/cat_wallet.py +61 -83
  428. chia/wallet/cat_wallet/lineage_store.py +3 -4
  429. chia/wallet/cat_wallet/r_cat_wallet.py +19 -22
  430. chia/wallet/coin_selection.py +9 -10
  431. chia/wallet/conditions.py +120 -105
  432. chia/wallet/db_wallet/db_wallet_puzzles.py +4 -5
  433. chia/wallet/derivation_record.py +1 -2
  434. chia/wallet/derive_keys.py +2 -4
  435. chia/wallet/did_wallet/did_info.py +10 -11
  436. chia/wallet/did_wallet/did_wallet.py +36 -82
  437. chia/wallet/did_wallet/did_wallet_puzzles.py +7 -8
  438. chia/wallet/driver_protocol.py +5 -7
  439. chia/wallet/lineage_proof.py +4 -4
  440. chia/wallet/nft_wallet/metadata_outer_puzzle.py +11 -11
  441. chia/wallet/nft_wallet/nft_info.py +8 -9
  442. chia/wallet/nft_wallet/nft_puzzle_utils.py +8 -8
  443. chia/wallet/nft_wallet/nft_wallet.py +79 -116
  444. chia/wallet/nft_wallet/ownership_outer_puzzle.py +14 -14
  445. chia/wallet/nft_wallet/singleton_outer_puzzle.py +12 -11
  446. chia/wallet/nft_wallet/transfer_program_puzzle.py +11 -11
  447. chia/wallet/nft_wallet/uncurry_nft.py +10 -11
  448. chia/wallet/notification_manager.py +3 -3
  449. chia/wallet/notification_store.py +44 -61
  450. chia/wallet/outer_puzzles.py +6 -7
  451. chia/wallet/puzzle_drivers.py +34 -6
  452. chia/wallet/puzzles/clawback/drivers.py +6 -6
  453. chia/wallet/puzzles/deployed_puzzle_hashes.json +1 -54
  454. chia/wallet/puzzles/load_clvm.py +1 -1
  455. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +1 -2
  456. chia/wallet/puzzles/singleton_top_layer.py +2 -3
  457. chia/wallet/puzzles/singleton_top_layer_v1_1.py +3 -4
  458. chia/wallet/puzzles/tails.py +3 -3
  459. chia/wallet/singleton.py +5 -7
  460. chia/wallet/singleton_record.py +3 -3
  461. chia/wallet/start_wallet.py +5 -5
  462. chia/wallet/trade_manager.py +37 -58
  463. chia/wallet/trade_record.py +4 -4
  464. chia/wallet/trading/offer.py +59 -46
  465. chia/wallet/trading/trade_store.py +8 -9
  466. chia/wallet/transaction_record.py +8 -8
  467. chia/wallet/uncurried_puzzle.py +1 -2
  468. chia/wallet/util/clvm_streamable.py +12 -12
  469. chia/wallet/util/compute_hints.py +4 -5
  470. chia/wallet/util/curry_and_treehash.py +1 -2
  471. chia/wallet/util/merkle_tree.py +2 -3
  472. chia/wallet/util/peer_request_cache.py +8 -8
  473. chia/wallet/util/signing.py +85 -0
  474. chia/wallet/util/tx_config.py +15 -6
  475. chia/wallet/util/wallet_sync_utils.py +14 -16
  476. chia/wallet/util/wallet_types.py +2 -2
  477. chia/wallet/vc_wallet/cr_cat_drivers.py +10 -11
  478. chia/wallet/vc_wallet/cr_cat_wallet.py +50 -68
  479. chia/wallet/vc_wallet/cr_outer_puzzle.py +14 -13
  480. chia/wallet/vc_wallet/vc_drivers.py +27 -27
  481. chia/wallet/vc_wallet/vc_store.py +5 -6
  482. chia/wallet/vc_wallet/vc_wallet.py +33 -61
  483. chia/wallet/wallet.py +50 -78
  484. chia/wallet/wallet_action_scope.py +11 -11
  485. chia/wallet/wallet_blockchain.py +12 -12
  486. chia/wallet/wallet_coin_record.py +12 -6
  487. chia/wallet/wallet_coin_store.py +24 -25
  488. chia/wallet/wallet_interested_store.py +3 -5
  489. chia/wallet/wallet_nft_store.py +10 -11
  490. chia/wallet/wallet_node.py +53 -61
  491. chia/wallet/wallet_node_api.py +5 -3
  492. chia/wallet/wallet_protocol.py +23 -23
  493. chia/wallet/wallet_puzzle_store.py +15 -18
  494. chia/wallet/wallet_request_types.py +778 -114
  495. chia/wallet/wallet_retry_store.py +1 -3
  496. chia/wallet/wallet_rpc_api.py +572 -909
  497. chia/wallet/wallet_rpc_client.py +87 -279
  498. chia/wallet/wallet_singleton_store.py +3 -4
  499. chia/wallet/wallet_state_manager.py +332 -106
  500. chia/wallet/wallet_transaction_store.py +11 -14
  501. chia/wallet/wallet_user_store.py +4 -6
  502. chia/wallet/wallet_weight_proof_handler.py +4 -4
  503. {chia_blockchain-2.5.7rc4.dist-info → chia_blockchain-2.5.8rc1.dist-info}/METADATA +6 -5
  504. {chia_blockchain-2.5.7rc4.dist-info → chia_blockchain-2.5.8rc1.dist-info}/RECORD +507 -516
  505. chia/apis.py +0 -21
  506. chia/consensus/check_time_locks.py +0 -57
  507. chia/data_layer/puzzles/__init__.py +0 -0
  508. chia/data_layer/puzzles/graftroot_dl_offers.clsp +0 -100
  509. chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +0 -1
  510. chia/types/coin_record.py +0 -44
  511. chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
  512. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +0 -6
  513. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +0 -1
  514. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +0 -6
  515. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +0 -1
  516. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +0 -30
  517. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +0 -1
  518. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +0 -28
  519. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +0 -1
  520. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +0 -100
  521. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +0 -1
  522. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +0 -78
  523. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +0 -1
  524. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +0 -74
  525. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +0 -1
  526. {chia_blockchain-2.5.7rc4.dist-info → chia_blockchain-2.5.8rc1.dist-info}/WHEEL +0 -0
  527. {chia_blockchain-2.5.7rc4.dist-info → chia_blockchain-2.5.8rc1.dist-info}/entry_points.txt +0 -0
  528. {chia_blockchain-2.5.7rc4.dist-info → chia_blockchain-2.5.8rc1.dist-info}/licenses/LICENSE +0 -0
@@ -10,15 +10,16 @@ import random
10
10
  import sqlite3
11
11
  import time
12
12
  import traceback
13
- from collections.abc import AsyncIterator, Awaitable, Sequence
13
+ from collections.abc import AsyncIterator, Awaitable, Callable, Sequence
14
14
  from multiprocessing.context import BaseContext
15
15
  from pathlib import Path
16
- from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, TextIO, Union, cast, final
16
+ from typing import TYPE_CHECKING, Any, ClassVar, TextIO, cast, final
17
17
 
18
18
  from chia_rs import (
19
19
  AugSchemeMPL,
20
20
  BlockRecord,
21
21
  BLSCache,
22
+ CoinRecord,
22
23
  CoinState,
23
24
  ConsensusConstants,
24
25
  EndOfSubSlotBundle,
@@ -61,7 +62,7 @@ from chia.full_node.mempool import MempoolRemoveInfo
61
62
  from chia.full_node.mempool_manager import MempoolManager
62
63
  from chia.full_node.subscriptions import PeerSubscriptions, peers_for_spend_bundle
63
64
  from chia.full_node.sync_store import Peak, SyncStore
64
- from chia.full_node.tx_processing_queue import TransactionQueue, TransactionQueueEntry
65
+ from chia.full_node.tx_processing_queue import PeerWithTx, TransactionQueue, TransactionQueueEntry
65
66
  from chia.full_node.weight_proof import WeightProofHandler
66
67
  from chia.protocols import farmer_protocol, full_node_protocol, timelord_protocol, wallet_protocol
67
68
  from chia.protocols.farmer_protocol import SignagePointSourceData, SPSubSlotSourceData, SPVDFSourceData
@@ -77,7 +78,6 @@ from chia.server.server import ChiaServer
77
78
  from chia.server.ws_connection import WSChiaConnection
78
79
  from chia.types.blockchain_format.classgroup import ClassgroupElement
79
80
  from chia.types.blockchain_format.vdf import CompressibleVDFField, VDFInfo, VDFProof, validate_vdf
80
- from chia.types.coin_record import CoinRecord
81
81
  from chia.types.mempool_inclusion_status import MempoolInclusionStatus
82
82
  from chia.types.mempool_item import MempoolItem
83
83
  from chia.types.peer_info import PeerInfo
@@ -106,7 +106,7 @@ class PeakPostProcessingResult:
106
106
  fns_peak_result: FullNodeStorePeakResult # The result of calling FullNodeStore.new_peak
107
107
  hints: list[tuple[bytes32, bytes]] # The hints added to the DB
108
108
  lookup_coin_ids: list[bytes32] # The coin IDs that we need to look up to notify wallets of changes
109
- signage_points: list[tuple[RespondSignagePoint, WSChiaConnection, Optional[EndOfSubSlotBundle]]]
109
+ signage_points: list[tuple[RespondSignagePoint, WSChiaConnection, EndOfSubSlotBundle | None]]
110
110
 
111
111
 
112
112
  @dataclasses.dataclass(frozen=True)
@@ -135,39 +135,39 @@ class FullNode:
135
135
  wallet_sync_queue: asyncio.Queue[WalletUpdate]
136
136
  _segment_task_list: list[asyncio.Task[None]] = dataclasses.field(default_factory=list)
137
137
  initialized: bool = False
138
- _server: Optional[ChiaServer] = None
138
+ _server: ChiaServer | None = None
139
139
  _shut_down: bool = False
140
140
  pow_creation: dict[bytes32, asyncio.Event] = dataclasses.field(default_factory=dict)
141
- state_changed_callback: Optional[StateChangedProtocol] = None
142
- full_node_peers: Optional[FullNodePeers] = None
141
+ state_changed_callback: StateChangedProtocol | None = None
142
+ full_node_peers: FullNodePeers | None = None
143
143
  sync_store: SyncStore = dataclasses.field(default_factory=SyncStore)
144
- uncompact_task: Optional[asyncio.Task[None]] = None
144
+ uncompact_task: asyncio.Task[None] | None = None
145
145
  compact_vdf_requests: set[bytes32] = dataclasses.field(default_factory=set)
146
146
  # TODO: Logging isn't setup yet so the log entries related to parsing the
147
147
  # config would end up on stdout if handled here.
148
- multiprocessing_context: Optional[BaseContext] = None
148
+ multiprocessing_context: BaseContext | None = None
149
149
  _ui_tasks: set[asyncio.Task[None]] = dataclasses.field(default_factory=set)
150
150
  subscriptions: PeerSubscriptions = dataclasses.field(default_factory=PeerSubscriptions)
151
- _transaction_queue_task: Optional[asyncio.Task[None]] = None
152
- simulator_transaction_callback: Optional[Callable[[bytes32], Awaitable[None]]] = None
151
+ _transaction_queue_task: asyncio.Task[None] | None = None
152
+ simulator_transaction_callback: Callable[[bytes32], Awaitable[None]] | None = None
153
153
  _sync_task_list: list[asyncio.Task[None]] = dataclasses.field(default_factory=list)
154
- _transaction_queue: Optional[TransactionQueue] = None
154
+ _transaction_queue: TransactionQueue | None = None
155
155
  _tx_task_list: list[asyncio.Task[None]] = dataclasses.field(default_factory=list)
156
- _compact_vdf_sem: Optional[LimitedSemaphore] = None
157
- _new_peak_sem: Optional[LimitedSemaphore] = None
158
- _add_transaction_semaphore: Optional[asyncio.Semaphore] = None
159
- _db_wrapper: Optional[DBWrapper2] = None
160
- _hint_store: Optional[HintStore] = None
161
- _block_store: Optional[BlockStore] = None
162
- _coin_store: Optional[CoinStoreProtocol] = None
163
- _mempool_manager: Optional[MempoolManager] = None
164
- _init_weight_proof: Optional[asyncio.Task[None]] = None
165
- _blockchain: Optional[Blockchain] = None
166
- _timelord_lock: Optional[asyncio.Lock] = None
167
- weight_proof_handler: Optional[WeightProofHandler] = None
156
+ _compact_vdf_sem: LimitedSemaphore | None = None
157
+ _new_peak_sem: LimitedSemaphore | None = None
158
+ _add_transaction_semaphore: asyncio.Semaphore | None = None
159
+ _db_wrapper: DBWrapper2 | None = None
160
+ _hint_store: HintStore | None = None
161
+ _block_store: BlockStore | None = None
162
+ _coin_store: CoinStoreProtocol | None = None
163
+ _mempool_manager: MempoolManager | None = None
164
+ _init_weight_proof: asyncio.Task[None] | None = None
165
+ _blockchain: Blockchain | None = None
166
+ _timelord_lock: asyncio.Lock | None = None
167
+ weight_proof_handler: WeightProofHandler | None = None
168
168
  # hashes of peaks that failed long sync on chip13 Validation
169
169
  bad_peak_cache: dict[bytes32, uint32] = dataclasses.field(default_factory=dict)
170
- wallet_sync_task: Optional[asyncio.Task[None]] = None
170
+ wallet_sync_task: asyncio.Task[None] | None = None
171
171
  _bls_cache: BLSCache = dataclasses.field(default_factory=lambda: BLSCache(50000))
172
172
 
173
173
  @property
@@ -215,9 +215,9 @@ class FullNode:
215
215
  # These many respond_transaction tasks can be active at any point in time
216
216
  self._add_transaction_semaphore = asyncio.Semaphore(200)
217
217
 
218
- sql_log_path: Optional[Path] = None
218
+ sql_log_path: Path | None = None
219
219
  with contextlib.ExitStack() as exit_stack:
220
- sql_log_file: Optional[TextIO] = None
220
+ sql_log_file: TextIO | None = None
221
221
  if self.config.get("log_sqlite_cmds", False):
222
222
  sql_log_path = path_from_root(self.root_path, "log/sql.log")
223
223
  self.log.info(f"logging SQL commands to {sql_log_path}")
@@ -279,127 +279,123 @@ class FullNode:
279
279
  log_coins=log_coins,
280
280
  )
281
281
 
282
- self._mempool_manager = MempoolManager(
282
+ async with MempoolManager.managed(
283
283
  get_coin_records=self.coin_store.get_coin_records,
284
284
  get_unspent_lineage_info_for_puzzle_hash=self.coin_store.get_unspent_lineage_info_for_puzzle_hash,
285
285
  consensus_constants=self.constants,
286
286
  single_threaded=single_threaded,
287
- )
288
-
289
- # Transactions go into this queue from the server, and get sent to respond_transaction
290
- self._transaction_queue = TransactionQueue(1000, self.log)
291
- self._transaction_queue_task: asyncio.Task[None] = create_referenced_task(self._handle_transactions())
292
-
293
- self._init_weight_proof = create_referenced_task(self.initialize_weight_proof())
294
-
295
- if self.config.get("enable_profiler", False):
296
- create_referenced_task(profile_task(self.root_path, "node", self.log), known_unreferenced=True)
297
-
298
- self.profile_block_validation = self.config.get("profile_block_validation", False)
299
- if self.profile_block_validation: # pragma: no cover
300
- # this is not covered by any unit tests as it's essentially test code
301
- # itself. It's exercised manually when investigating performance issues
302
- profile_dir = path_from_root(self.root_path, "block-validation-profile")
303
- profile_dir.mkdir(parents=True, exist_ok=True)
304
-
305
- if self.config.get("enable_memory_profiler", False):
306
- create_referenced_task(mem_profile_task(self.root_path, "node", self.log), known_unreferenced=True)
307
-
308
- time_taken = time.monotonic() - start_time
309
- peak: Optional[BlockRecord] = self.blockchain.get_peak()
310
- if peak is None:
311
- self.log.info(f"Initialized with empty blockchain time taken: {int(time_taken)}s")
312
- if not await self.coin_store.is_empty():
313
- self.log.error(
314
- "Inconsistent blockchain DB file! Could not find peak block but found some coins! "
315
- "This is a fatal error. The blockchain database may be corrupt"
316
- )
317
- raise RuntimeError("corrupt blockchain DB")
318
- else:
319
- self.log.info(
320
- f"Blockchain initialized to peak {peak.header_hash} height"
321
- f" {peak.height}, "
322
- f"time taken: {int(time_taken)}s"
323
- )
324
- async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
325
- pending_tx = await self.mempool_manager.new_peak(self.blockchain.get_tx_peak(), None)
326
- # No pending transactions when starting up
327
- assert len(pending_tx.spend_bundle_ids) == 0
328
-
329
- full_peak: Optional[FullBlock] = await self.blockchain.get_full_peak()
330
- assert full_peak is not None
331
- state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [], [])
332
- # Must be called under priority_mutex
333
- ppp_result: PeakPostProcessingResult = await self.peak_post_processing(
334
- full_peak, state_change_summary, None
287
+ ) as self._mempool_manager:
288
+ # Transactions go into this queue from the server, and get sent to respond_transaction
289
+ self._transaction_queue = TransactionQueue(1000, self.log)
290
+ self._transaction_queue_task: asyncio.Task[None] = create_referenced_task(self._handle_transactions())
291
+
292
+ self._init_weight_proof = create_referenced_task(self.initialize_weight_proof())
293
+
294
+ if self.config.get("enable_profiler", False):
295
+ create_referenced_task(profile_task(self.root_path, "node", self.log), known_unreferenced=True)
296
+
297
+ self.profile_block_validation = self.config.get("profile_block_validation", False)
298
+ if self.profile_block_validation: # pragma: no cover
299
+ # this is not covered by any unit tests as it's essentially test code
300
+ # itself. It's exercised manually when investigating performance issues
301
+ profile_dir = path_from_root(self.root_path, "block-validation-profile")
302
+ profile_dir.mkdir(parents=True, exist_ok=True)
303
+
304
+ if self.config.get("enable_memory_profiler", False):
305
+ create_referenced_task(mem_profile_task(self.root_path, "node", self.log), known_unreferenced=True)
306
+
307
+ time_taken = time.monotonic() - start_time
308
+ peak: BlockRecord | None = self.blockchain.get_peak()
309
+ if peak is None:
310
+ self.log.info(f"Initialized with empty blockchain time taken: {int(time_taken)}s")
311
+ if not await self.coin_store.is_empty():
312
+ self.log.error(
313
+ "Inconsistent blockchain DB file! Could not find peak block but found some coins! "
314
+ "This is a fatal error. The blockchain database may be corrupt"
315
+ )
316
+ raise RuntimeError("corrupt blockchain DB")
317
+ else:
318
+ self.log.info(
319
+ f"Blockchain initialized to peak {peak.header_hash} height"
320
+ f" {peak.height}, "
321
+ f"time taken: {int(time_taken)}s"
335
322
  )
336
- # Can be called outside of priority_mutex
337
- await self.peak_post_processing_2(full_peak, None, state_change_summary, ppp_result)
338
- if self.config["send_uncompact_interval"] != 0:
339
- sanitize_weight_proof_only = False
340
- if "sanitize_weight_proof_only" in self.config:
341
- sanitize_weight_proof_only = self.config["sanitize_weight_proof_only"]
342
- assert self.config["target_uncompact_proofs"] != 0
343
- self.uncompact_task = create_referenced_task(
344
- self.broadcast_uncompact_blocks(
345
- self.config["send_uncompact_interval"],
346
- self.config["target_uncompact_proofs"],
347
- sanitize_weight_proof_only,
323
+ async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
324
+ pending_tx = await self.mempool_manager.new_peak(self.blockchain.get_tx_peak(), None)
325
+ # No pending transactions when starting up
326
+ assert len(pending_tx.spend_bundle_ids) == 0
327
+
328
+ full_peak: FullBlock | None = await self.blockchain.get_full_peak()
329
+ assert full_peak is not None
330
+ state_change_summary = StateChangeSummary(peak, uint32(max(peak.height - 1, 0)), [], [], [], [])
331
+ # Must be called under priority_mutex
332
+ ppp_result: PeakPostProcessingResult = await self.peak_post_processing(
333
+ full_peak, state_change_summary, None
334
+ )
335
+ # Can be called outside of priority_mutex
336
+ await self.peak_post_processing_2(full_peak, None, state_change_summary, ppp_result)
337
+ if self.config["send_uncompact_interval"] != 0:
338
+ sanitize_weight_proof_only = False
339
+ if "sanitize_weight_proof_only" in self.config:
340
+ sanitize_weight_proof_only = self.config["sanitize_weight_proof_only"]
341
+ assert self.config["target_uncompact_proofs"] != 0
342
+ self.uncompact_task = create_referenced_task(
343
+ self.broadcast_uncompact_blocks(
344
+ self.config["send_uncompact_interval"],
345
+ self.config["target_uncompact_proofs"],
346
+ sanitize_weight_proof_only,
347
+ )
348
348
  )
349
- )
350
- if self.wallet_sync_task is None or self.wallet_sync_task.done():
351
- self.wallet_sync_task = create_referenced_task(self._wallets_sync_task_handler())
352
-
353
- self.initialized = True
354
-
355
- try:
356
- async with contextlib.AsyncExitStack() as aexit_stack:
357
- if self.full_node_peers is not None:
358
- await aexit_stack.enter_async_context(self.full_node_peers.manage())
359
- yield
360
- finally:
361
- self._shut_down = True
362
- if self._init_weight_proof is not None:
363
- self._init_weight_proof.cancel()
364
-
365
- # blockchain is created in _start and in certain cases it may not exist here during _close
366
- if self._blockchain is not None:
367
- self.blockchain.shut_down()
368
- # same for mempool_manager
369
- if self._mempool_manager is not None:
370
- self.mempool_manager.shut_down()
371
- if self.uncompact_task is not None:
372
- self.uncompact_task.cancel()
373
- if self._transaction_queue_task is not None:
374
- self._transaction_queue_task.cancel()
375
- cancel_task_safe(task=self.wallet_sync_task, log=self.log)
376
- for one_tx_task in self._tx_task_list:
377
- if not one_tx_task.done():
378
- cancel_task_safe(task=one_tx_task, log=self.log)
379
- for one_sync_task in self._sync_task_list:
380
- if not one_sync_task.done():
381
- cancel_task_safe(task=one_sync_task, log=self.log)
382
- for segment_task in self._segment_task_list:
383
- cancel_task_safe(segment_task, self.log)
384
- for task_id, task in list(self.full_node_store.tx_fetch_tasks.items()):
385
- cancel_task_safe(task, self.log)
386
- if self._init_weight_proof is not None:
387
- await asyncio.wait([self._init_weight_proof])
388
- for one_tx_task in self._tx_task_list:
389
- if one_tx_task.done():
390
- self.log.info(f"TX task {one_tx_task.get_name()} done")
391
- else:
392
- with contextlib.suppress(asyncio.CancelledError):
393
- self.log.info(f"Awaiting TX task {one_tx_task.get_name()}")
394
- await one_tx_task
395
- for one_sync_task in self._sync_task_list:
396
- if one_sync_task.done():
397
- self.log.info(f"Long sync task {one_sync_task.get_name()} done")
398
- else:
399
- with contextlib.suppress(asyncio.CancelledError):
400
- self.log.info(f"Awaiting long sync task {one_sync_task.get_name()}")
401
- await one_sync_task
402
- await asyncio.gather(*self._segment_task_list, return_exceptions=True)
349
+ if self.wallet_sync_task is None or self.wallet_sync_task.done():
350
+ self.wallet_sync_task = create_referenced_task(self._wallets_sync_task_handler())
351
+
352
+ self.initialized = True
353
+
354
+ try:
355
+ async with contextlib.AsyncExitStack() as aexit_stack:
356
+ if self.full_node_peers is not None:
357
+ await aexit_stack.enter_async_context(self.full_node_peers.manage())
358
+ yield
359
+ finally:
360
+ self._shut_down = True
361
+ if self._init_weight_proof is not None:
362
+ self._init_weight_proof.cancel()
363
+
364
+ # blockchain is created in _start and in certain cases it may not exist here during _close
365
+ if self._blockchain is not None:
366
+ self.blockchain.shut_down()
367
+ if self.uncompact_task is not None:
368
+ self.uncompact_task.cancel()
369
+ if self._transaction_queue_task is not None:
370
+ self._transaction_queue_task.cancel()
371
+ cancel_task_safe(task=self.wallet_sync_task, log=self.log)
372
+ for one_tx_task in self._tx_task_list:
373
+ if not one_tx_task.done():
374
+ cancel_task_safe(task=one_tx_task, log=self.log)
375
+ for one_sync_task in self._sync_task_list:
376
+ if not one_sync_task.done():
377
+ cancel_task_safe(task=one_sync_task, log=self.log)
378
+ for segment_task in self._segment_task_list:
379
+ cancel_task_safe(segment_task, self.log)
380
+ for task_id, task in list(self.full_node_store.tx_fetch_tasks.items()):
381
+ cancel_task_safe(task, self.log)
382
+ if self._init_weight_proof is not None:
383
+ await asyncio.wait([self._init_weight_proof])
384
+ for one_tx_task in self._tx_task_list:
385
+ if one_tx_task.done():
386
+ self.log.info(f"TX task {one_tx_task.get_name()} done")
387
+ else:
388
+ with contextlib.suppress(asyncio.CancelledError):
389
+ self.log.info(f"Awaiting TX task {one_tx_task.get_name()}")
390
+ await one_tx_task
391
+ for one_sync_task in self._sync_task_list:
392
+ if one_sync_task.done():
393
+ self.log.info(f"Long sync task {one_sync_task.get_name()} done")
394
+ else:
395
+ with contextlib.suppress(asyncio.CancelledError):
396
+ self.log.info(f"Awaiting long sync task {one_sync_task.get_name()}")
397
+ await one_sync_task
398
+ await asyncio.gather(*self._segment_task_list, return_exceptions=True)
403
399
 
404
400
  @property
405
401
  def block_store(self) -> BlockStore:
@@ -456,7 +452,7 @@ class FullNode:
456
452
  assert self._compact_vdf_sem is not None
457
453
  return self._compact_vdf_sem
458
454
 
459
- def get_connections(self, request_node_type: Optional[NodeType]) -> list[dict[str, Any]]:
455
+ def get_connections(self, request_node_type: NodeType | None) -> list[dict[str, Any]]:
460
456
  connections = self.server.get_connections(request_node_type)
461
457
  con_info: list[dict[str, Any]] = []
462
458
  if self.sync_store is not None:
@@ -498,7 +494,9 @@ class FullNode:
498
494
  async def _handle_one_transaction(self, entry: TransactionQueueEntry) -> None:
499
495
  peer = entry.peer
500
496
  try:
501
- inc_status, err = await self.add_transaction(entry.transaction, entry.spend_name, peer, entry.test)
497
+ inc_status, err = await self.add_transaction(
498
+ entry.transaction, entry.spend_name, peer, entry.test, entry.peers_with_tx
499
+ )
502
500
  entry.done.set((inc_status, err))
503
501
  except asyncio.CancelledError:
504
502
  error_stack = traceback.format_exc()
@@ -572,7 +570,7 @@ class FullNode:
572
570
  self.log.error(f"Exception in peer discovery: {e}")
573
571
  self.log.error(f"Exception Stack: {error_stack}")
574
572
 
575
- def _state_changed(self, change: str, change_data: Optional[dict[str, Any]] = None) -> None:
573
+ def _state_changed(self, change: str, change_data: dict[str, Any] | None = None) -> None:
576
574
  if self.state_changed_callback is not None:
577
575
  self.state_changed_callback(change, change_data)
578
576
 
@@ -639,7 +637,7 @@ class FullNode:
639
637
  if not response:
640
638
  raise ValueError(f"Error short batch syncing, invalid/no response for {height}-{end_height}")
641
639
  async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
642
- state_change_summary: Optional[StateChangeSummary]
640
+ state_change_summary: StateChangeSummary | None
643
641
  prev_b = None
644
642
  if response.blocks[0].height > 0:
645
643
  prev_b = await self.blockchain.get_block_record_from_db(response.blocks[0].prev_header_hash)
@@ -656,7 +654,7 @@ class FullNode:
656
654
  raise ValueError(f"Error short batch syncing, failed to validate blocks {height}-{end_height}")
657
655
  if state_change_summary is not None:
658
656
  try:
659
- peak_fb: Optional[FullBlock] = await self.blockchain.get_full_peak()
657
+ peak_fb: FullBlock | None = await self.blockchain.get_full_peak()
660
658
  assert peak_fb is not None
661
659
  ppp_result: PeakPostProcessingResult = await self.peak_post_processing(
662
660
  peak_fb,
@@ -697,7 +695,7 @@ class FullNode:
697
695
  try:
698
696
  self.sync_store.increment_backtrack_syncing(node_id=peer.peer_node_id)
699
697
 
700
- unfinished_block: Optional[UnfinishedBlock] = self.full_node_store.get_unfinished_block(target_unf_hash)
698
+ unfinished_block: UnfinishedBlock | None = self.full_node_store.get_unfinished_block(target_unf_hash)
701
699
  curr_height: int = target_height
702
700
  found_fork_point = False
703
701
  blocks = []
@@ -773,7 +771,7 @@ class FullNode:
773
771
  return None
774
772
 
775
773
  # Not interested in less heavy peaks
776
- peak: Optional[BlockRecord] = self.blockchain.get_peak()
774
+ peak: BlockRecord | None = self.blockchain.get_peak()
777
775
  curr_peak_height = uint32(0) if peak is None else peak.height
778
776
  if peak is not None and peak.weight > request.weight:
779
777
  return None
@@ -785,7 +783,7 @@ class FullNode:
785
783
  peak_peers: set[bytes32] = self.sync_store.get_peers_that_have_peak([target_peak.header_hash])
786
784
  # Don't ask if we already know this peer has the peak
787
785
  if peer.peer_node_id not in peak_peers:
788
- target_peak_response: Optional[RespondBlock] = await peer.call_api(
786
+ target_peak_response: RespondBlock | None = await peer.call_api(
789
787
  FullNodeAPI.request_block,
790
788
  full_node_protocol.RequestBlock(target_peak.height, False),
791
789
  timeout=10,
@@ -839,7 +837,7 @@ class FullNode:
839
837
  self._sync_task_list.append(create_referenced_task(self._sync()))
840
838
 
841
839
  async def send_peak_to_timelords(
842
- self, peak_block: Optional[FullBlock] = None, peer: Optional[WSChiaConnection] = None
840
+ self, peak_block: FullBlock | None = None, peer: WSChiaConnection | None = None
843
841
  ) -> None:
844
842
  """
845
843
  Sends current peak to timelords
@@ -849,7 +847,7 @@ class FullNode:
849
847
  if peak_block is not None:
850
848
  peak = self.blockchain.block_record(peak_block.header_hash)
851
849
  difficulty = self.blockchain.get_next_sub_slot_iters_and_difficulty(peak.header_hash, False)[1]
852
- ses: Optional[SubEpochSummary] = next_sub_epoch_summary(
850
+ ses: SubEpochSummary | None = next_sub_epoch_summary(
853
851
  self.constants,
854
852
  self.blockchain,
855
853
  peak.required_iters,
@@ -893,12 +891,12 @@ class FullNode:
893
891
  else:
894
892
  await self.server.send_to_specific([msg], peer.peer_node_id)
895
893
 
896
- async def synced(self, block_is_current_at: Optional[uint64] = None) -> bool:
894
+ async def synced(self, block_is_current_at: uint64 | None = None) -> bool:
897
895
  if block_is_current_at is None:
898
896
  block_is_current_at = uint64(time.time() - 60 * 7)
899
897
  if "simulator" in str(self.config.get("selected_network")):
900
898
  return True # sim is always synced because it has no peers
901
- curr: Optional[BlockRecord] = self.blockchain.get_peak()
899
+ curr: BlockRecord | None = self.blockchain.get_peak()
902
900
  if curr is None:
903
901
  return False
904
902
 
@@ -941,7 +939,7 @@ class FullNode:
941
939
  msg = make_msg(ProtocolMessageTypes.request_mempool_transactions, mempool_request)
942
940
  await connection.send_message(msg)
943
941
 
944
- peak_full: Optional[FullBlock] = await self.blockchain.get_full_peak()
942
+ peak_full: FullBlock | None = await self.blockchain.get_full_peak()
945
943
 
946
944
  if peak_full is not None:
947
945
  peak: BlockRecord = self.blockchain.block_record(peak_full.header_hash)
@@ -987,7 +985,7 @@ class FullNode:
987
985
  - Disconnect peers that provide invalid blocks or don't have the blocks
988
986
  """
989
987
  # Ensure we are only syncing once and not double calling this method
990
- fork_point: Optional[uint32] = None
988
+ fork_point: uint32 | None = None
991
989
  if self.sync_store.get_sync_mode():
992
990
  return None
993
991
 
@@ -1087,7 +1085,7 @@ class FullNode:
1087
1085
  self.log.info(
1088
1086
  f"Requesting weight proof from peer {weight_proof_peer.peer_info.host} up to height {peak_height}"
1089
1087
  )
1090
- cur_peak: Optional[BlockRecord] = self.blockchain.get_peak()
1088
+ cur_peak: BlockRecord | None = self.blockchain.get_peak()
1091
1089
  if cur_peak is not None and peak_weight <= cur_peak.weight:
1092
1090
  raise ValueError("Not performing sync, already caught up.")
1093
1091
  wp_timeout = 360
@@ -1187,7 +1185,7 @@ class FullNode:
1187
1185
  blockchain = AugmentedBlockchain(self.blockchain)
1188
1186
  peers_with_peak: list[WSChiaConnection] = self.get_peers_with_peak(peak_hash)
1189
1187
 
1190
- async def fetch_blocks(output_queue: asyncio.Queue[Optional[tuple[WSChiaConnection, list[FullBlock]]]]) -> None:
1188
+ async def fetch_blocks(output_queue: asyncio.Queue[tuple[WSChiaConnection, list[FullBlock]] | None]) -> None:
1191
1189
  # the rate limit for respond_blocks is 100 messages / 60 seconds.
1192
1190
  # But the limit is scaled to 30% for outbound messages, so that's 30
1193
1191
  # messages per 60 seconds.
@@ -1294,11 +1292,9 @@ class FullNode:
1294
1292
  await output_queue.put(None)
1295
1293
 
1296
1294
  async def validate_blocks(
1297
- input_queue: asyncio.Queue[Optional[tuple[WSChiaConnection, list[FullBlock]]]],
1295
+ input_queue: asyncio.Queue[tuple[WSChiaConnection, list[FullBlock]] | None],
1298
1296
  output_queue: asyncio.Queue[
1299
- Optional[
1300
- tuple[WSChiaConnection, ValidationState, list[Awaitable[PreValidationResult]], list[FullBlock]]
1301
- ]
1297
+ tuple[WSChiaConnection, ValidationState, list[Awaitable[PreValidationResult]], list[FullBlock]] | None
1302
1298
  ],
1303
1299
  ) -> None:
1304
1300
  nonlocal blockchain
@@ -1309,7 +1305,7 @@ class FullNode:
1309
1305
 
1310
1306
  try:
1311
1307
  while True:
1312
- res: Optional[tuple[WSChiaConnection, list[FullBlock]]] = await input_queue.get()
1308
+ res: tuple[WSChiaConnection, list[FullBlock]] | None = await input_queue.get()
1313
1309
  if res is None:
1314
1310
  self.log.debug("done fetching blocks")
1315
1311
  return None
@@ -1351,9 +1347,7 @@ class FullNode:
1351
1347
 
1352
1348
  async def ingest_blocks(
1353
1349
  input_queue: asyncio.Queue[
1354
- Optional[
1355
- tuple[WSChiaConnection, ValidationState, list[Awaitable[PreValidationResult]], list[FullBlock]]
1356
- ]
1350
+ tuple[WSChiaConnection, ValidationState, list[Awaitable[PreValidationResult]], list[FullBlock]] | None
1357
1351
  ],
1358
1352
  ) -> None:
1359
1353
  nonlocal fork_info
@@ -1396,7 +1390,7 @@ class FullNode:
1396
1390
  f"Added blocks {start_height} to {end_height} "
1397
1391
  f"({block_rate:.3g} blocks/s) (from: {peer.peer_info.ip})"
1398
1392
  )
1399
- peak: Optional[BlockRecord] = self.blockchain.get_peak()
1393
+ peak: BlockRecord | None = self.blockchain.get_peak()
1400
1394
  if state_change_summary is not None:
1401
1395
  assert peak is not None
1402
1396
  # Hints must be added to the DB. The other post-processing tasks are not required when syncing
@@ -1413,9 +1407,9 @@ class FullNode:
1413
1407
  # height, in that case.
1414
1408
  self.blockchain.clean_block_record(end_height - self.constants.BLOCKS_CACHE_SIZE)
1415
1409
 
1416
- block_queue: asyncio.Queue[Optional[tuple[WSChiaConnection, list[FullBlock]]]] = asyncio.Queue(maxsize=10)
1410
+ block_queue: asyncio.Queue[tuple[WSChiaConnection, list[FullBlock]] | None] = asyncio.Queue(maxsize=10)
1417
1411
  validation_queue: asyncio.Queue[
1418
- Optional[tuple[WSChiaConnection, ValidationState, list[Awaitable[PreValidationResult]], list[FullBlock]]]
1412
+ tuple[WSChiaConnection, ValidationState, list[Awaitable[PreValidationResult]], list[FullBlock]] | None
1419
1413
  ] = asyncio.Queue(maxsize=10)
1420
1414
 
1421
1415
  fetch_task = create_referenced_task(fetch_blocks(block_queue))
@@ -1501,8 +1495,8 @@ class FullNode:
1501
1495
  fork_info: ForkInfo,
1502
1496
  vs: ValidationState, # in-out parameter
1503
1497
  blockchain: AugmentedBlockchain,
1504
- wp_summaries: Optional[list[SubEpochSummary]] = None,
1505
- ) -> tuple[bool, Optional[StateChangeSummary]]:
1498
+ wp_summaries: list[SubEpochSummary] | None = None,
1499
+ ) -> tuple[bool, StateChangeSummary | None]:
1506
1500
  # Precondition: All blocks must be contiguous blocks, index i+1 must be the parent of index i
1507
1501
  # Returns a bool for success, as well as a StateChangeSummary if the peak was advanced
1508
1502
 
@@ -1584,7 +1578,7 @@ class FullNode:
1584
1578
  blockchain: AugmentedBlockchain,
1585
1579
  blocks_to_validate: list[FullBlock],
1586
1580
  vs: ValidationState,
1587
- wp_summaries: Optional[list[SubEpochSummary]] = None,
1581
+ wp_summaries: list[SubEpochSummary] | None = None,
1588
1582
  ) -> Sequence[Awaitable[PreValidationResult]]:
1589
1583
  """
1590
1584
  This is a thin wrapper over pre_validate_block().
@@ -1625,15 +1619,15 @@ class FullNode:
1625
1619
  fork_info: ForkInfo,
1626
1620
  peer_info: PeerInfo,
1627
1621
  vs: ValidationState, # in-out parameter
1628
- ) -> tuple[Optional[StateChangeSummary], Optional[Err]]:
1629
- agg_state_change_summary: Optional[StateChangeSummary] = None
1622
+ ) -> tuple[StateChangeSummary | None, Err | None]:
1623
+ agg_state_change_summary: StateChangeSummary | None = None
1630
1624
  block_record = await self.blockchain.get_block_record_from_db(blocks_to_validate[0].prev_header_hash)
1631
1625
  for i, block in enumerate(blocks_to_validate):
1632
1626
  header_hash = block.header_hash
1633
1627
  assert vs.prev_ses_block is None or vs.prev_ses_block.height < block.height
1634
1628
  assert pre_validation_results[i].error is None
1635
1629
  assert pre_validation_results[i].required_iters is not None
1636
- state_change_summary: Optional[StateChangeSummary]
1630
+ state_change_summary: StateChangeSummary | None
1637
1631
  # when adding blocks in batches, we won't have any overlapping
1638
1632
  # signatures with the mempool. There won't be any cache hits, so
1639
1633
  # there's no need to pass the BLS cache in
@@ -1696,8 +1690,8 @@ class FullNode:
1696
1690
  return agg_state_change_summary, None
1697
1691
 
1698
1692
  async def get_sub_slot_iters_difficulty_ses_block(
1699
- self, block: FullBlock, ssi: Optional[uint64], diff: Optional[uint64]
1700
- ) -> tuple[uint64, uint64, Optional[BlockRecord]]:
1693
+ self, block: FullBlock, ssi: uint64 | None, diff: uint64 | None
1694
+ ) -> tuple[uint64, uint64, BlockRecord | None]:
1701
1695
  prev_ses_block = None
1702
1696
  if ssi is None or diff is None:
1703
1697
  if block.height == 0:
@@ -1734,7 +1728,7 @@ class FullNode:
1734
1728
  assert diff is not None
1735
1729
  return ssi, diff, prev_ses_block
1736
1730
 
1737
- async def _finish_sync(self, fork_point: Optional[uint32]) -> None:
1731
+ async def _finish_sync(self, fork_point: uint32 | None) -> None:
1738
1732
  """
1739
1733
  Finalize sync by setting sync mode to False, clearing all sync information, and adding any final
1740
1734
  blocks that we have finalized recently.
@@ -1747,8 +1741,8 @@ class FullNode:
1747
1741
  return None
1748
1742
 
1749
1743
  async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
1750
- peak: Optional[BlockRecord] = self.blockchain.get_peak()
1751
- peak_fb: Optional[FullBlock] = await self.blockchain.get_full_peak()
1744
+ peak: BlockRecord | None = self.blockchain.get_peak()
1745
+ peak_fb: FullBlock | None = await self.blockchain.get_full_peak()
1752
1746
  if peak_fb is not None:
1753
1747
  if fork_point is None:
1754
1748
  fork_point = uint32(max(peak_fb.height - 1, 0))
@@ -1766,7 +1760,7 @@ class FullNode:
1766
1760
  await self.weight_proof_handler.get_proof_of_weight(peak.header_hash)
1767
1761
  self._state_changed("block")
1768
1762
 
1769
- def has_valid_pool_sig(self, block: Union[UnfinishedBlock, FullBlock]) -> bool:
1763
+ def has_valid_pool_sig(self, block: UnfinishedBlock | FullBlock) -> bool:
1770
1764
  if (
1771
1765
  block.foliage.foliage_block_data.pool_target
1772
1766
  == PoolTarget(self.constants.GENESIS_PRE_FARM_POOL_PUZZLE_HASH, uint32(0))
@@ -1786,7 +1780,7 @@ class FullNode:
1786
1780
  self,
1787
1781
  request: full_node_protocol.RespondSignagePoint,
1788
1782
  peer: WSChiaConnection,
1789
- ip_sub_slot: Optional[EndOfSubSlotBundle],
1783
+ ip_sub_slot: EndOfSubSlotBundle | None,
1790
1784
  ) -> None:
1791
1785
  self.log.info(
1792
1786
  f"⏲️ Finished signage point {request.index_from_challenge}/"
@@ -1796,7 +1790,7 @@ class FullNode:
1796
1790
  )
1797
1791
  self.signage_point_times[request.index_from_challenge] = time.time()
1798
1792
  sub_slot_tuple = self.full_node_store.get_sub_slot(request.challenge_chain_vdf.challenge)
1799
- prev_challenge: Optional[bytes32]
1793
+ prev_challenge: bytes32 | None
1800
1794
  if sub_slot_tuple is not None:
1801
1795
  prev_challenge = sub_slot_tuple[0].challenge_chain.challenge_chain_end_of_slot_vdf.challenge
1802
1796
  else:
@@ -1850,7 +1844,7 @@ class FullNode:
1850
1844
  self,
1851
1845
  block: FullBlock,
1852
1846
  state_change_summary: StateChangeSummary,
1853
- peer: Optional[WSChiaConnection],
1847
+ peer: WSChiaConnection | None,
1854
1848
  ) -> PeakPostProcessingResult:
1855
1849
  """
1856
1850
  Must be called under self.blockchain.priority_mutex. This updates the internal state of the full node with the
@@ -1889,10 +1883,10 @@ class FullNode:
1889
1883
  if not self.sync_store.get_sync_mode():
1890
1884
  self.blockchain.clean_block_records()
1891
1885
 
1892
- fork_block: Optional[BlockRecord] = None
1886
+ fork_block: BlockRecord | None = None
1893
1887
  if state_change_summary.fork_height != block.height - 1 and block.height != 0:
1894
1888
  # This is a reorg
1895
- fork_hash: Optional[bytes32] = self.blockchain.height_to_hash(state_change_summary.fork_height)
1889
+ fork_hash: bytes32 | None = self.blockchain.height_to_hash(state_change_summary.fork_height)
1896
1890
  assert fork_hash is not None
1897
1891
  fork_block = await self.blockchain.get_block_record_from_db(fork_hash)
1898
1892
 
@@ -1907,7 +1901,7 @@ class FullNode:
1907
1901
  difficulty,
1908
1902
  )
1909
1903
 
1910
- signage_points: list[tuple[RespondSignagePoint, WSChiaConnection, Optional[EndOfSubSlotBundle]]] = []
1904
+ signage_points: list[tuple[RespondSignagePoint, WSChiaConnection, EndOfSubSlotBundle | None]] = []
1911
1905
  if fns_peak_result.new_signage_points is not None and peer is not None:
1912
1906
  for index, sp in fns_peak_result.new_signage_points:
1913
1907
  assert (
@@ -1958,7 +1952,7 @@ class FullNode:
1958
1952
  async def peak_post_processing_2(
1959
1953
  self,
1960
1954
  block: FullBlock,
1961
- peer: Optional[WSChiaConnection],
1955
+ peer: WSChiaConnection | None,
1962
1956
  state_change_summary: StateChangeSummary,
1963
1957
  ppp_result: PeakPostProcessingResult,
1964
1958
  ) -> None:
@@ -2037,11 +2031,11 @@ class FullNode:
2037
2031
  async def add_block(
2038
2032
  self,
2039
2033
  block: FullBlock,
2040
- peer: Optional[WSChiaConnection] = None,
2041
- bls_cache: Optional[BLSCache] = None,
2034
+ peer: WSChiaConnection | None = None,
2035
+ bls_cache: BLSCache | None = None,
2042
2036
  raise_on_disconnected: bool = False,
2043
- fork_info: Optional[ForkInfo] = None,
2044
- ) -> Optional[Message]:
2037
+ fork_info: ForkInfo | None = None,
2038
+ ) -> Message | None:
2045
2039
  """
2046
2040
  Add a full block from a peer full node (or ourselves).
2047
2041
  """
@@ -2055,7 +2049,7 @@ class FullNode:
2055
2049
  await self.blockchain.run_single_block(block, fork_info)
2056
2050
  return None
2057
2051
 
2058
- pre_validation_result: Optional[PreValidationResult] = None
2052
+ pre_validation_result: PreValidationResult | None = None
2059
2053
  if (
2060
2054
  block.is_transaction_block()
2061
2055
  and block.transactions_info is not None
@@ -2065,9 +2059,9 @@ class FullNode:
2065
2059
  # This is the case where we already had the unfinished block, and asked for this block without
2066
2060
  # the transactions (since we already had them). Therefore, here we add the transactions.
2067
2061
  unfinished_rh: bytes32 = block.reward_chain_block.get_unfinished().get_hash()
2068
- foliage_hash: Optional[bytes32] = block.foliage.foliage_transaction_block_hash
2062
+ foliage_hash: bytes32 | None = block.foliage.foliage_transaction_block_hash
2069
2063
  assert foliage_hash is not None
2070
- unf_entry: Optional[UnfinishedBlockEntry] = self.full_node_store.get_unfinished_block_result(
2064
+ unf_entry: UnfinishedBlockEntry | None = self.full_node_store.get_unfinished_block_result(
2071
2065
  unfinished_rh, foliage_hash
2072
2066
  )
2073
2067
  assert unf_entry is None or unf_entry.result is None or unf_entry.result.validated_signature is True
@@ -2094,7 +2088,7 @@ class FullNode:
2094
2088
  if peer is None:
2095
2089
  return None
2096
2090
 
2097
- block_response: Optional[Any] = await peer.call_api(
2091
+ block_response: Any | None = await peer.call_api(
2098
2092
  FullNodeAPI.request_block, full_node_protocol.RequestBlock(block.height, True)
2099
2093
  )
2100
2094
  if block_response is None or not isinstance(block_response, full_node_protocol.RespondBlock):
@@ -2117,8 +2111,8 @@ class FullNode:
2117
2111
  )
2118
2112
  # This recursion ends here, we cannot recurse again because transactions_generator is not None
2119
2113
  return await self.add_block(new_block, peer, bls_cache)
2120
- state_change_summary: Optional[StateChangeSummary] = None
2121
- ppp_result: Optional[PeakPostProcessingResult] = None
2114
+ state_change_summary: StateChangeSummary | None = None
2115
+ ppp_result: PeakPostProcessingResult | None = None
2122
2116
  async with (
2123
2117
  self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high),
2124
2118
  enable_profiler(self.profile_block_validation) as pr,
@@ -2156,14 +2150,14 @@ class FullNode:
2156
2150
  ValidationState(ssi, diff, prev_ses_block),
2157
2151
  )
2158
2152
  pre_validation_result = await future
2159
- added: Optional[AddBlockResult] = None
2153
+ added: AddBlockResult | None = None
2160
2154
  add_block_start = time.monotonic()
2161
2155
  pre_validation_time = add_block_start - validation_start
2162
2156
  try:
2163
2157
  if pre_validation_result.error is not None:
2164
2158
  if Err(pre_validation_result.error) == Err.INVALID_PREV_BLOCK_HASH:
2165
2159
  added = AddBlockResult.DISCONNECTED_BLOCK
2166
- error_code: Optional[Err] = Err.INVALID_PREV_BLOCK_HASH
2160
+ error_code: Err | None = Err.INVALID_PREV_BLOCK_HASH
2167
2161
  elif Err(pre_validation_result.error) == Err.TIMESTAMP_TOO_FAR_IN_FUTURE:
2168
2162
  raise TimestampError
2169
2163
  else:
@@ -2267,8 +2261,8 @@ class FullNode:
2267
2261
 
2268
2262
  state_changed_data: dict[str, Any] = {
2269
2263
  "transaction_block": False,
2270
- "k_size": block.reward_chain_block.proof_of_space.size().size_v1,
2271
- "k_size2": block.reward_chain_block.proof_of_space.size().size_v2,
2264
+ "k_size": block.reward_chain_block.proof_of_space.param().size_v1,
2265
+ "strength": block.reward_chain_block.proof_of_space.param().strength_v2,
2272
2266
  "header_hash": block.header_hash,
2273
2267
  "fork_height": None,
2274
2268
  "rolled_back_records": None,
@@ -2311,7 +2305,7 @@ class FullNode:
2311
2305
  async def add_unfinished_block(
2312
2306
  self,
2313
2307
  block: UnfinishedBlock,
2314
- peer: Optional[WSChiaConnection],
2308
+ peer: WSChiaConnection | None,
2315
2309
  farmed_block: bool = False,
2316
2310
  ) -> None:
2317
2311
  """
@@ -2344,7 +2338,7 @@ class FullNode:
2344
2338
  if self.full_node_store.get_unfinished_block2(block_hash, foliage_tx_hash)[0] is not None:
2345
2339
  return None
2346
2340
 
2347
- peak: Optional[BlockRecord] = self.blockchain.get_peak()
2341
+ peak: BlockRecord | None = self.blockchain.get_peak()
2348
2342
  if peak is not None:
2349
2343
  if block.total_iters < peak.sp_total_iters(self.constants):
2350
2344
  # This means this unfinished block is pretty far behind, it will not add weight to our chain
@@ -2372,7 +2366,7 @@ class FullNode:
2372
2366
 
2373
2367
  # The clvm generator and aggregate signature are validated outside of the lock, to allow other blocks and
2374
2368
  # transactions to get validated
2375
- npc_result: Optional[NPCResult] = None
2369
+ npc_result: NPCResult | None = None
2376
2370
  pre_validation_time = None
2377
2371
 
2378
2372
  async with self.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
@@ -2450,7 +2444,7 @@ class FullNode:
2450
2444
  else:
2451
2445
  height = uint32(self.blockchain.block_record(block.prev_header_hash).height + 1)
2452
2446
 
2453
- ses: Optional[SubEpochSummary] = next_sub_epoch_summary(
2447
+ ses: SubEpochSummary | None = next_sub_epoch_summary(
2454
2448
  self.constants,
2455
2449
  self.blockchain,
2456
2450
  validate_result.required_iters,
@@ -2542,7 +2536,7 @@ class FullNode:
2542
2536
  # don't send this to peers with old clients
2543
2537
  return conn.protocol_version > Version("0.0.35")
2544
2538
 
2545
- peer_id: Optional[bytes32] = None if peer is None else peer.peer_node_id
2539
+ peer_id: bytes32 | None = None if peer is None else peer.peer_node_id
2546
2540
  await self.server.send_to_all_if([msg], NodeType.FULL_NODE, old_clients, peer_id)
2547
2541
  await self.server.send_to_all_if([msg2], NodeType.FULL_NODE, new_clients, peer_id)
2548
2542
 
@@ -2557,10 +2551,10 @@ class FullNode:
2557
2551
  )
2558
2552
 
2559
2553
  async def new_infusion_point_vdf(
2560
- self, request: timelord_protocol.NewInfusionPointVDF, timelord_peer: Optional[WSChiaConnection] = None
2561
- ) -> Optional[Message]:
2554
+ self, request: timelord_protocol.NewInfusionPointVDF, timelord_peer: WSChiaConnection | None = None
2555
+ ) -> Message | None:
2562
2556
  # Lookup unfinished blocks
2563
- unfinished_block: Optional[UnfinishedBlock] = self.full_node_store.get_unfinished_block(
2557
+ unfinished_block: UnfinishedBlock | None = self.full_node_store.get_unfinished_block(
2564
2558
  request.unfinished_reward_hash
2565
2559
  )
2566
2560
 
@@ -2570,7 +2564,7 @@ class FullNode:
2570
2564
  )
2571
2565
  return None
2572
2566
 
2573
- prev_b: Optional[BlockRecord] = None
2567
+ prev_b: BlockRecord | None = None
2574
2568
 
2575
2569
  target_rc_hash = request.reward_chain_ip_vdf.challenge
2576
2570
  last_slot_cc_hash = request.challenge_chain_ip_vdf.challenge
@@ -2584,7 +2578,7 @@ class FullNode:
2584
2578
  else:
2585
2579
  # Find the prev block, starts looking backwards from the peak. target_rc_hash must be the hash of a block
2586
2580
  # and not an end of slot (since we just looked through the slots and backtracked)
2587
- curr: Optional[BlockRecord] = self.blockchain.get_peak()
2581
+ curr: BlockRecord | None = self.blockchain.get_peak()
2588
2582
 
2589
2583
  for _ in range(10):
2590
2584
  if curr is None:
@@ -2603,7 +2597,7 @@ class FullNode:
2603
2597
  )
2604
2598
  return None
2605
2599
 
2606
- finished_sub_slots: Optional[list[EndOfSubSlotBundle]] = self.full_node_store.get_finished_sub_slots(
2600
+ finished_sub_slots: list[EndOfSubSlotBundle] | None = self.full_node_store.get_finished_sub_slots(
2607
2601
  self.blockchain,
2608
2602
  prev_b,
2609
2603
  last_slot_cc_hash,
@@ -2663,7 +2657,7 @@ class FullNode:
2663
2657
 
2664
2658
  async def add_end_of_sub_slot(
2665
2659
  self, end_of_slot_bundle: EndOfSubSlotBundle, peer: WSChiaConnection
2666
- ) -> tuple[Optional[Message], bool]:
2660
+ ) -> tuple[Message | None, bool]:
2667
2661
  fetched_ss = self.full_node_store.get_sub_slot(end_of_slot_bundle.challenge_chain.get_hash())
2668
2662
 
2669
2663
  # We are not interested in sub-slots which have the same challenge chain but different reward chain. If there
@@ -2761,8 +2755,15 @@ class FullNode:
2761
2755
  return None, False
2762
2756
 
2763
2757
  async def add_transaction(
2764
- self, transaction: SpendBundle, spend_name: bytes32, peer: Optional[WSChiaConnection] = None, test: bool = False
2765
- ) -> tuple[MempoolInclusionStatus, Optional[Err]]:
2758
+ self,
2759
+ transaction: SpendBundle,
2760
+ spend_name: bytes32,
2761
+ peer: WSChiaConnection | None = None,
2762
+ test: bool = False,
2763
+ # Map of peer ID to its hostname, the fee and the cost it advertised
2764
+ # for this transaction.
2765
+ peers_with_tx: dict[bytes32, PeerWithTx] = {},
2766
+ ) -> tuple[MempoolInclusionStatus, Err | None]:
2766
2767
  if self.sync_store.get_sync_mode():
2767
2768
  return MempoolInclusionStatus.FAILED, Err.NO_TRANSACTIONS_WHILE_SYNCING
2768
2769
  if not test and not (await self.synced()):
@@ -2810,10 +2811,25 @@ class FullNode:
2810
2811
  f"{self.mempool_manager.mempool.total_mempool_cost() / 5000000}"
2811
2812
  )
2812
2813
 
2813
- # Only broadcast successful transactions, not pending ones. Otherwise it's a DOS
2814
- # vector.
2815
2814
  mempool_item = self.mempool_manager.get_mempool_item(spend_name)
2816
2815
  assert mempool_item is not None
2816
+ # Now that we validated this transaction, check what fees and
2817
+ # costs the peers have advertised for it.
2818
+ for peer_id, entry in peers_with_tx.items():
2819
+ if entry.advertised_fee == mempool_item.fee and entry.advertised_cost == mempool_item.cost:
2820
+ continue
2821
+ self.log.warning(
2822
+ f"Banning peer {peer_id}. Sent us a new tx {spend_name} with mismatch "
2823
+ f"on cost {entry.advertised_cost} vs validation cost {mempool_item.cost} and/or "
2824
+ f"fee {entry.advertised_fee} vs {mempool_item.fee}."
2825
+ )
2826
+ peer = self.server.all_connections.get(peer_id)
2827
+ if peer is None:
2828
+ self.server.ban_peer(entry.peer_host, CONSENSUS_ERROR_BAN_SECONDS)
2829
+ else:
2830
+ await peer.close(CONSENSUS_ERROR_BAN_SECONDS)
2831
+ # Only broadcast successful transactions, not pending ones. Otherwise it's a DOS
2832
+ # vector.
2817
2833
  await self.broadcast_removed_tx(info.removals)
2818
2834
  await self.broadcast_added_tx(mempool_item, current_peer=peer)
2819
2835
 
@@ -2825,9 +2841,7 @@ class FullNode:
2825
2841
  self.log.debug(f"Wasn't able to add transaction with id {spend_name}, status {status} error: {error}")
2826
2842
  return status, error
2827
2843
 
2828
- async def broadcast_added_tx(
2829
- self, mempool_item: MempoolItem, current_peer: Optional[WSChiaConnection] = None
2830
- ) -> None:
2844
+ async def broadcast_added_tx(self, mempool_item: MempoolItem, current_peer: WSChiaConnection | None = None) -> None:
2831
2845
  assert mempool_item.fee >= 0
2832
2846
  assert mempool_item.cost is not None
2833
2847
 
@@ -3136,7 +3150,7 @@ class FullNode:
3136
3150
  )
3137
3151
  if header_block is None:
3138
3152
  return None
3139
- vdf_proof: Optional[VDFProof] = None
3153
+ vdf_proof: VDFProof | None = None
3140
3154
  field_vdf = CompressibleVDFField(int(request.field_vdf))
3141
3155
  if field_vdf == CompressibleVDFField.CC_EOS_VDF:
3142
3156
  for sub_slot in header_block.finished_sub_slots:
@@ -3356,7 +3370,7 @@ class FullNode:
3356
3370
  async def node_next_block_check(
3357
3371
  peer: WSChiaConnection, potential_peek: uint32, blockchain: BlockchainInterface
3358
3372
  ) -> bool:
3359
- block_response: Optional[Any] = await peer.call_api(
3373
+ block_response: Any | None = await peer.call_api(
3360
3374
  FullNodeAPI.request_block, full_node_protocol.RequestBlock(potential_peek, True)
3361
3375
  )
3362
3376
  if block_response is not None and isinstance(block_response, full_node_protocol.RespondBlock):