chia-blockchain 2.5.7rc3__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 +12 -7
  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 +16 -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.7rc3.dist-info → chia_blockchain-2.5.8rc1.dist-info}/METADATA +6 -5
  504. {chia_blockchain-2.5.7rc3.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.7rc3.dist-info → chia_blockchain-2.5.8rc1.dist-info}/WHEEL +0 -0
  527. {chia_blockchain-2.5.7rc3.dist-info → chia_blockchain-2.5.8rc1.dist-info}/entry_points.txt +0 -0
  528. {chia_blockchain-2.5.7rc3.dist-info → chia_blockchain-2.5.8rc1.dist-info}/licenses/LICENSE +0 -0
@@ -7,12 +7,13 @@ import traceback
7
7
  from collections.abc import Collection
8
8
  from concurrent.futures import ThreadPoolExecutor
9
9
  from datetime import datetime, timezone
10
- from typing import TYPE_CHECKING, ClassVar, Optional, cast
10
+ from typing import TYPE_CHECKING, ClassVar, cast
11
11
 
12
12
  import anyio
13
13
  from chia_rs import (
14
14
  AugSchemeMPL,
15
15
  BlockRecord,
16
+ CoinRecord,
16
17
  CoinState,
17
18
  EndOfSubSlotBundle,
18
19
  FoliageBlockData,
@@ -24,7 +25,6 @@ from chia_rs import (
24
25
  PoolTarget,
25
26
  RespondToPhUpdates,
26
27
  RewardChainBlockUnfinished,
27
- SpendBundle,
28
28
  SubEpochSummary,
29
29
  UnfinishedBlock,
30
30
  additions_and_removals,
@@ -38,19 +38,20 @@ from chiabip158 import PyBIP158
38
38
  from chia.consensus.block_creation import create_unfinished_block
39
39
  from chia.consensus.blockchain import BlockchainMutexPriority
40
40
  from chia.consensus.generator_tools import get_block_header
41
+ from chia.consensus.get_block_challenge import pre_sp_tx_block_height
41
42
  from chia.consensus.get_block_generator import get_block_generator
42
43
  from chia.consensus.pot_iterations import calculate_ip_iters, calculate_iterations_quality, calculate_sp_iters
43
44
  from chia.consensus.signage_point import SignagePoint
44
45
  from chia.full_node.coin_store import CoinStore
45
46
  from chia.full_node.fee_estimator_interface import FeeEstimatorInterface
46
47
  from chia.full_node.full_block_utils import get_height_and_tx_status_from_block, header_block_from_block
47
- from chia.full_node.tx_processing_queue import TransactionQueueEntry, TransactionQueueFull
48
+ from chia.full_node.tx_processing_queue import PeerWithTx, TransactionQueueEntry, TransactionQueueFull
48
49
  from chia.protocols import farmer_protocol, full_node_protocol, introducer_protocol, timelord_protocol, wallet_protocol
49
50
  from chia.protocols.fee_estimate import FeeEstimate, FeeEstimateGroup, fee_rate_v2_to_v1
50
51
  from chia.protocols.full_node_protocol import RejectBlock, RejectBlocks
51
52
  from chia.protocols.outbound_message import Message, make_msg
52
53
  from chia.protocols.protocol_message_types import ProtocolMessageTypes
53
- from chia.protocols.protocol_timing import RATE_LIMITER_BAN_SECONDS
54
+ from chia.protocols.protocol_timing import CONSENSUS_ERROR_BAN_SECONDS, RATE_LIMITER_BAN_SECONDS
54
55
  from chia.protocols.shared_protocol import Capability
55
56
  from chia.protocols.wallet_protocol import (
56
57
  PuzzleSolutionResponse,
@@ -66,7 +67,6 @@ from chia.server.ws_connection import WSChiaConnection
66
67
  from chia.types.block_protocol import BlockInfo
67
68
  from chia.types.blockchain_format.coin import Coin, hash_coin_ids
68
69
  from chia.types.blockchain_format.proof_of_space import verify_and_get_quality_string
69
- from chia.types.coin_record import CoinRecord
70
70
  from chia.types.generator_types import BlockGenerator, NewBlockGenerator
71
71
  from chia.types.mempool_inclusion_status import MempoolInclusionStatus
72
72
  from chia.types.peer_info import PeerInfo
@@ -83,11 +83,54 @@ else:
83
83
  FullNode = object
84
84
 
85
85
 
86
+ async def tx_request_and_timeout(full_node: FullNode, transaction_id: bytes32, task_id: bytes32) -> None:
87
+ """
88
+ Request a transaction from peers that advertised it, until we either
89
+ receive it or timeout.
90
+ """
91
+ tried_peers: set[bytes32] = set()
92
+ try:
93
+ # Limit to asking a few peers, it's possible that this tx got included on chain already
94
+ # Highly unlikely that the peers that advertised a tx don't respond to a request. Also, if we
95
+ # drop some transactions, we don't want to re-fetch too many times
96
+ for _ in range(5):
97
+ peers_with_tx = full_node.full_node_store.peers_with_tx.get(transaction_id)
98
+ if peers_with_tx is None:
99
+ break
100
+ peers_to_try = set(peers_with_tx) - tried_peers
101
+ if len(peers_to_try) == 0:
102
+ break
103
+ peer_id = peers_to_try.pop()
104
+ tried_peers.add(peer_id)
105
+ assert full_node.server is not None
106
+ if peer_id not in full_node.server.all_connections:
107
+ continue
108
+ random_peer = full_node.server.all_connections[peer_id]
109
+ request_tx = full_node_protocol.RequestTransaction(transaction_id)
110
+ msg = make_msg(ProtocolMessageTypes.request_transaction, request_tx)
111
+ await random_peer.send_message(msg)
112
+ await asyncio.sleep(5)
113
+ if full_node.mempool_manager.seen(transaction_id):
114
+ break
115
+ except asyncio.CancelledError:
116
+ pass
117
+ finally:
118
+ # Always Cleanup
119
+ if transaction_id in full_node.full_node_store.peers_with_tx:
120
+ full_node.full_node_store.peers_with_tx.pop(transaction_id)
121
+ if transaction_id in full_node.full_node_store.pending_tx_request:
122
+ full_node.full_node_store.pending_tx_request.pop(transaction_id)
123
+ if task_id in full_node.full_node_store.tx_fetch_tasks:
124
+ full_node.full_node_store.tx_fetch_tasks.pop(task_id)
125
+
126
+
86
127
  class FullNodeAPI:
87
128
  if TYPE_CHECKING:
88
- from chia.server.api_protocol import ApiProtocol
129
+ from chia.apis.full_node_stub import FullNodeApiStub
89
130
 
90
- _protocol_check: ClassVar[ApiProtocol] = cast("FullNodeAPI", None)
131
+ # Verify this class implements the FullNodeApiStub protocol
132
+ def _protocol_check(self: FullNodeAPI) -> FullNodeApiStub:
133
+ return self
91
134
 
92
135
  log: logging.Logger
93
136
  full_node: FullNode
@@ -108,9 +151,7 @@ class FullNodeAPI:
108
151
  return self.full_node.initialized
109
152
 
110
153
  @metadata.request(peer_required=True, reply_types=[ProtocolMessageTypes.respond_peers])
111
- async def request_peers(
112
- self, _request: full_node_protocol.RequestPeers, peer: WSChiaConnection
113
- ) -> Optional[Message]:
154
+ async def request_peers(self, _request: full_node_protocol.RequestPeers, peer: WSChiaConnection) -> Message | None:
114
155
  if peer.peer_server_port is None:
115
156
  return None
116
157
  peer_info = PeerInfo(peer.peer_info.host, peer.peer_server_port)
@@ -120,9 +161,7 @@ class FullNodeAPI:
120
161
  return None
121
162
 
122
163
  @metadata.request(peer_required=True)
123
- async def respond_peers(
124
- self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection
125
- ) -> Optional[Message]:
164
+ async def respond_peers(self, request: full_node_protocol.RespondPeers, peer: WSChiaConnection) -> Message | None:
126
165
  self.log.debug(f"Received {len(request.peer_list)} peers")
127
166
  if self.full_node.full_node_peers is not None:
128
167
  await self.full_node.full_node_peers.add_peers(request.peer_list, peer.get_peer_info(), True)
@@ -131,7 +170,7 @@ class FullNodeAPI:
131
170
  @metadata.request(peer_required=True)
132
171
  async def respond_peers_introducer(
133
172
  self, request: introducer_protocol.RespondPeersIntroducer, peer: WSChiaConnection
134
- ) -> Optional[Message]:
173
+ ) -> Message | None:
135
174
  self.log.debug(f"Received {len(request.peer_list)} peers from introducer")
136
175
  if self.full_node.full_node_peers is not None:
137
176
  await self.full_node.full_node_peers.add_peers(request.peer_list, peer.get_peer_info(), False)
@@ -159,7 +198,7 @@ class FullNodeAPI:
159
198
  @metadata.request(peer_required=True)
160
199
  async def new_transaction(
161
200
  self, transaction: full_node_protocol.NewTransaction, peer: WSChiaConnection
162
- ) -> Optional[Message]:
201
+ ) -> Message | None:
163
202
  """
164
203
  A peer notifies us of a new transaction.
165
204
  Requests a full transaction if we haven't seen it previously, and if the fees are enough.
@@ -170,66 +209,60 @@ class FullNodeAPI:
170
209
  if not (await self.full_node.synced()):
171
210
  return None
172
211
 
173
- # Ignore if already seen
174
- if self.full_node.mempool_manager.seen(transaction.transaction_id):
212
+ # It's not reasonable to advertise a transaction with zero cost
213
+ if transaction.cost == 0:
214
+ self.log.warning(
215
+ f"Banning peer {peer.peer_node_id}. Sent us a tx {transaction.transaction_id} with zero cost."
216
+ )
217
+ await peer.close(CONSENSUS_ERROR_BAN_SECONDS)
218
+ return None
219
+
220
+ # If already seen, the cost and fee must match, otherwise ban the peer
221
+ mempool_item = self.full_node.mempool_manager.get_mempool_item(transaction.transaction_id, include_pending=True)
222
+ if mempool_item is not None:
223
+ if mempool_item.cost != transaction.cost or mempool_item.fee != transaction.fees:
224
+ self.log.warning(
225
+ f"Banning peer {peer.peer_node_id}. Sent us an already seen tx {transaction.transaction_id} "
226
+ f"with mismatch on cost {transaction.cost} vs validation cost {mempool_item.cost} and/or "
227
+ f"fee {transaction.fees} vs {mempool_item.fee}."
228
+ )
229
+ await peer.close(CONSENSUS_ERROR_BAN_SECONDS)
175
230
  return None
176
231
 
177
232
  if self.full_node.mempool_manager.is_fee_enough(transaction.fees, transaction.cost):
178
233
  # If there's current pending request just add this peer to the set of peers that have this tx
179
234
  if transaction.transaction_id in self.full_node.full_node_store.pending_tx_request:
180
- if transaction.transaction_id in self.full_node.full_node_store.peers_with_tx:
181
- current_set = self.full_node.full_node_store.peers_with_tx[transaction.transaction_id]
182
- if peer.peer_node_id in current_set:
183
- return None
184
- current_set.add(peer.peer_node_id)
235
+ current_map = self.full_node.full_node_store.peers_with_tx.get(transaction.transaction_id)
236
+ if current_map is None:
237
+ self.full_node.full_node_store.peers_with_tx[transaction.transaction_id] = {
238
+ peer.peer_node_id: PeerWithTx(
239
+ peer_host=peer.peer_info.host,
240
+ advertised_fee=transaction.fees,
241
+ advertised_cost=transaction.cost,
242
+ )
243
+ }
185
244
  return None
186
- else:
187
- new_set = set()
188
- new_set.add(peer.peer_node_id)
189
- self.full_node.full_node_store.peers_with_tx[transaction.transaction_id] = new_set
245
+ prev = current_map.get(peer.peer_node_id)
246
+ if prev is not None:
247
+ if prev.advertised_fee != transaction.fees or prev.advertised_cost != transaction.cost:
248
+ self.log.warning(
249
+ f"Banning peer {peer.peer_node_id}. Sent us a new tx {transaction.transaction_id} with "
250
+ f"mismatch on cost {transaction.cost} vs previous advertised cost {prev.advertised_cost} "
251
+ f"and/or fee {transaction.fees} vs previous advertised fee {prev.advertised_fee}."
252
+ )
253
+ await peer.close(CONSENSUS_ERROR_BAN_SECONDS)
190
254
  return None
255
+ current_map[peer.peer_node_id] = PeerWithTx(
256
+ peer_host=peer.peer_info.host, advertised_fee=transaction.fees, advertised_cost=transaction.cost
257
+ )
258
+ return None
191
259
 
192
260
  self.full_node.full_node_store.pending_tx_request[transaction.transaction_id] = peer.peer_node_id
193
- new_set = set()
194
- new_set.add(peer.peer_node_id)
195
- self.full_node.full_node_store.peers_with_tx[transaction.transaction_id] = new_set
196
-
197
- async def tx_request_and_timeout(full_node: FullNode, transaction_id: bytes32, task_id: bytes32) -> None:
198
- counter = 0
199
- try:
200
- while True:
201
- # Limit to asking a few peers, it's possible that this tx got included on chain already
202
- # Highly unlikely that the peers that advertised a tx don't respond to a request. Also, if we
203
- # drop some transactions, we don't want to re-fetch too many times
204
- if counter == 5:
205
- break
206
- if transaction_id not in full_node.full_node_store.peers_with_tx:
207
- break
208
- peers_with_tx: set[bytes32] = full_node.full_node_store.peers_with_tx[transaction_id]
209
- if len(peers_with_tx) == 0:
210
- break
211
- peer_id = peers_with_tx.pop()
212
- assert full_node.server is not None
213
- if peer_id not in full_node.server.all_connections:
214
- continue
215
- random_peer = full_node.server.all_connections[peer_id]
216
- request_tx = full_node_protocol.RequestTransaction(transaction.transaction_id)
217
- msg = make_msg(ProtocolMessageTypes.request_transaction, request_tx)
218
- await random_peer.send_message(msg)
219
- await asyncio.sleep(5)
220
- counter += 1
221
- if full_node.mempool_manager.seen(transaction_id):
222
- break
223
- except asyncio.CancelledError:
224
- pass
225
- finally:
226
- # Always Cleanup
227
- if transaction_id in full_node.full_node_store.peers_with_tx:
228
- full_node.full_node_store.peers_with_tx.pop(transaction_id)
229
- if transaction_id in full_node.full_node_store.pending_tx_request:
230
- full_node.full_node_store.pending_tx_request.pop(transaction_id)
231
- if task_id in full_node.full_node_store.tx_fetch_tasks:
232
- full_node.full_node_store.tx_fetch_tasks.pop(task_id)
261
+ self.full_node.full_node_store.peers_with_tx[transaction.transaction_id] = {
262
+ peer.peer_node_id: PeerWithTx(
263
+ peer_host=peer.peer_info.host, advertised_fee=transaction.fees, advertised_cost=transaction.cost
264
+ )
265
+ }
233
266
 
234
267
  task_id: bytes32 = bytes32.secret()
235
268
  fetch_task = create_referenced_task(
@@ -240,7 +273,7 @@ class FullNodeAPI:
240
273
  return None
241
274
 
242
275
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_transaction])
243
- async def request_transaction(self, request: full_node_protocol.RequestTransaction) -> Optional[Message]:
276
+ async def request_transaction(self, request: full_node_protocol.RequestTransaction) -> Message | None:
244
277
  """Peer has requested a full transaction from us."""
245
278
  # Ignore if syncing
246
279
  if self.full_node.sync_store.get_sync_mode():
@@ -261,7 +294,7 @@ class FullNodeAPI:
261
294
  peer: WSChiaConnection,
262
295
  tx_bytes: bytes = b"",
263
296
  test: bool = False,
264
- ) -> Optional[Message]:
297
+ ) -> Message | None:
265
298
  """
266
299
  Receives a full transaction from peer.
267
300
  If tx is added to mempool, send tx_id to others. (new_transaction)
@@ -270,20 +303,22 @@ class FullNodeAPI:
270
303
  spend_name = std_hash(tx_bytes)
271
304
  if spend_name in self.full_node.full_node_store.pending_tx_request:
272
305
  self.full_node.full_node_store.pending_tx_request.pop(spend_name)
306
+ peers_with_tx = {}
273
307
  if spend_name in self.full_node.full_node_store.peers_with_tx:
274
- self.full_node.full_node_store.peers_with_tx.pop(spend_name)
308
+ peers_with_tx = self.full_node.full_node_store.peers_with_tx.pop(spend_name)
275
309
 
276
310
  # TODO: Use fee in priority calculation, to prioritize high fee TXs
277
311
  try:
278
- await self.full_node.transaction_queue.put(
279
- TransactionQueueEntry(tx.transaction, tx_bytes, spend_name, peer, test), peer.peer_node_id
312
+ self.full_node.transaction_queue.put(
313
+ TransactionQueueEntry(tx.transaction, tx_bytes, spend_name, peer, test, peers_with_tx),
314
+ peer.peer_node_id,
280
315
  )
281
316
  except TransactionQueueFull:
282
317
  pass # we can't do anything here, the tx will be dropped. We might do something in the future.
283
318
  return None
284
319
 
285
320
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_proof_of_weight])
286
- async def request_proof_of_weight(self, request: full_node_protocol.RequestProofOfWeight) -> Optional[Message]:
321
+ async def request_proof_of_weight(self, request: full_node_protocol.RequestProofOfWeight) -> Message | None:
287
322
  if self.full_node.weight_proof_handler is None:
288
323
  return None
289
324
  if self.full_node.blockchain.try_block_record(request.tip) is None:
@@ -323,21 +358,21 @@ class FullNodeAPI:
323
358
  return message
324
359
 
325
360
  @metadata.request()
326
- async def respond_proof_of_weight(self, request: full_node_protocol.RespondProofOfWeight) -> Optional[Message]:
361
+ async def respond_proof_of_weight(self, request: full_node_protocol.RespondProofOfWeight) -> Message | None:
327
362
  self.log.warning("Received proof of weight too late.")
328
363
  return None
329
364
 
330
365
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_block, ProtocolMessageTypes.reject_block])
331
- async def request_block(self, request: full_node_protocol.RequestBlock) -> Optional[Message]:
366
+ async def request_block(self, request: full_node_protocol.RequestBlock) -> Message | None:
332
367
  if not self.full_node.blockchain.contains_height(request.height):
333
368
  reject = RejectBlock(request.height)
334
369
  msg = make_msg(ProtocolMessageTypes.reject_block, reject)
335
370
  return msg
336
- header_hash: Optional[bytes32] = self.full_node.blockchain.height_to_hash(request.height)
371
+ header_hash: bytes32 | None = self.full_node.blockchain.height_to_hash(request.height)
337
372
  if header_hash is None:
338
373
  return make_msg(ProtocolMessageTypes.reject_block, RejectBlock(request.height))
339
374
 
340
- block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(header_hash)
375
+ block: FullBlock | None = await self.full_node.block_store.get_full_block(header_hash)
341
376
  if block is not None:
342
377
  if not request.include_transaction_block and block.transactions_generator is not None:
343
378
  block = block.replace(transactions_generator=None)
@@ -345,7 +380,7 @@ class FullNodeAPI:
345
380
  return make_msg(ProtocolMessageTypes.reject_block, RejectBlock(request.height))
346
381
 
347
382
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_blocks, ProtocolMessageTypes.reject_blocks])
348
- async def request_blocks(self, request: full_node_protocol.RequestBlocks) -> Optional[Message]:
383
+ async def request_blocks(self, request: full_node_protocol.RequestBlocks) -> Message | None:
349
384
  # note that we treat the request range as *inclusive*, but we check the
350
385
  # size before we bump end_height. So MAX_BLOCK_COUNT_PER_REQUESTS is off
351
386
  # by one
@@ -365,12 +400,12 @@ class FullNodeAPI:
365
400
  if not request.include_transaction_block:
366
401
  blocks: list[FullBlock] = []
367
402
  for i in range(request.start_height, request.end_height + 1):
368
- header_hash_i: Optional[bytes32] = self.full_node.blockchain.height_to_hash(uint32(i))
403
+ header_hash_i: bytes32 | None = self.full_node.blockchain.height_to_hash(uint32(i))
369
404
  if header_hash_i is None:
370
405
  reject = RejectBlocks(request.start_height, request.end_height)
371
406
  return make_msg(ProtocolMessageTypes.reject_blocks, reject)
372
407
 
373
- block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(header_hash_i)
408
+ block: FullBlock | None = await self.full_node.block_store.get_full_block(header_hash_i)
374
409
  if block is None:
375
410
  reject = RejectBlocks(request.start_height, request.end_height)
376
411
  return make_msg(ProtocolMessageTypes.reject_blocks, reject)
@@ -387,7 +422,7 @@ class FullNodeAPI:
387
422
  if header_hash_i is None:
388
423
  reject = RejectBlocks(request.start_height, request.end_height)
389
424
  return make_msg(ProtocolMessageTypes.reject_blocks, reject)
390
- block_bytes: Optional[bytes] = await self.full_node.block_store.get_full_block_bytes(header_hash_i)
425
+ block_bytes: bytes | None = await self.full_node.block_store.get_full_block_bytes(header_hash_i)
391
426
  if block_bytes is None:
392
427
  reject = RejectBlocks(request.start_height, request.end_height)
393
428
  msg = make_msg(ProtocolMessageTypes.reject_blocks, reject)
@@ -438,15 +473,13 @@ class FullNodeAPI:
438
473
  self,
439
474
  respond_block: full_node_protocol.RespondBlock,
440
475
  peer: WSChiaConnection,
441
- ) -> Optional[Message]:
476
+ ) -> Message | None:
442
477
  self.log.warning(f"Received unsolicited/late block from peer {peer.get_peer_logging()}")
443
478
  await peer.close(RATE_LIMITER_BAN_SECONDS)
444
479
  return None
445
480
 
446
481
  @metadata.request()
447
- async def new_unfinished_block(
448
- self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock
449
- ) -> Optional[Message]:
482
+ async def new_unfinished_block(self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock) -> Message | None:
450
483
  # Ignore if syncing
451
484
  if self.full_node.sync_store.get_sync_mode():
452
485
  return None
@@ -482,8 +515,8 @@ class FullNodeAPI:
482
515
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_unfinished_block])
483
516
  async def request_unfinished_block(
484
517
  self, request_unfinished_block: full_node_protocol.RequestUnfinishedBlock
485
- ) -> Optional[Message]:
486
- unfinished_block: Optional[UnfinishedBlock] = self.full_node.full_node_store.get_unfinished_block(
518
+ ) -> Message | None:
519
+ unfinished_block: UnfinishedBlock | None = self.full_node.full_node_store.get_unfinished_block(
487
520
  request_unfinished_block.unfinished_reward_hash
488
521
  )
489
522
  if unfinished_block is not None:
@@ -497,7 +530,7 @@ class FullNodeAPI:
497
530
  @metadata.request()
498
531
  async def new_unfinished_block2(
499
532
  self, new_unfinished_block: full_node_protocol.NewUnfinishedBlock2
500
- ) -> Optional[Message]:
533
+ ) -> Message | None:
501
534
  # Ignore if syncing
502
535
  if self.full_node.sync_store.get_sync_mode():
503
536
  return None
@@ -550,8 +583,8 @@ class FullNodeAPI:
550
583
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_unfinished_block])
551
584
  async def request_unfinished_block2(
552
585
  self, request_unfinished_block: full_node_protocol.RequestUnfinishedBlock2
553
- ) -> Optional[Message]:
554
- unfinished_block: Optional[UnfinishedBlock]
586
+ ) -> Message | None:
587
+ unfinished_block: UnfinishedBlock | None
555
588
  unfinished_block, _, _ = self.full_node.full_node_store.get_unfinished_block2(
556
589
  request_unfinished_block.unfinished_reward_hash,
557
590
  request_unfinished_block.foliage_hash,
@@ -569,7 +602,7 @@ class FullNodeAPI:
569
602
  self,
570
603
  respond_unfinished_block: full_node_protocol.RespondUnfinishedBlock,
571
604
  peer: WSChiaConnection,
572
- ) -> Optional[Message]:
605
+ ) -> Message | None:
573
606
  if self.full_node.sync_store.get_sync_mode():
574
607
  return None
575
608
  await self.full_node.add_unfinished_block(respond_unfinished_block.unfinished_block, peer)
@@ -578,7 +611,7 @@ class FullNodeAPI:
578
611
  @metadata.request(peer_required=True)
579
612
  async def new_signage_point_or_end_of_sub_slot(
580
613
  self, new_sp: full_node_protocol.NewSignagePointOrEndOfSubSlot, peer: WSChiaConnection
581
- ) -> Optional[Message]:
614
+ ) -> Message | None:
582
615
  # Ignore if syncing
583
616
  if self.full_node.sync_store.get_sync_mode():
584
617
  return None
@@ -664,9 +697,9 @@ class FullNodeAPI:
664
697
  )
665
698
  async def request_signage_point_or_end_of_sub_slot(
666
699
  self, request: full_node_protocol.RequestSignagePointOrEndOfSubSlot
667
- ) -> Optional[Message]:
700
+ ) -> Message | None:
668
701
  if request.index_from_challenge == 0:
669
- sub_slot: Optional[tuple[EndOfSubSlotBundle, int, uint128]] = self.full_node.full_node_store.get_sub_slot(
702
+ sub_slot: tuple[EndOfSubSlotBundle, int, uint128] | None = self.full_node.full_node_store.get_sub_slot(
670
703
  request.challenge_hash
671
704
  )
672
705
  if sub_slot is not None:
@@ -679,7 +712,7 @@ class FullNodeAPI:
679
712
  if request.challenge_hash != self.full_node.constants.GENESIS_CHALLENGE:
680
713
  self.log.info(f"Don't have challenge hash {request.challenge_hash.hex()}")
681
714
 
682
- sp: Optional[SignagePoint] = self.full_node.full_node_store.get_signage_point_by_index(
715
+ sp: SignagePoint | None = self.full_node.full_node_store.get_signage_point_by_index(
683
716
  request.challenge_hash,
684
717
  request.index_from_challenge,
685
718
  request.last_rc_infusion,
@@ -706,7 +739,7 @@ class FullNodeAPI:
706
739
  @metadata.request(peer_required=True)
707
740
  async def respond_signage_point(
708
741
  self, request: full_node_protocol.RespondSignagePoint, peer: WSChiaConnection
709
- ) -> Optional[Message]:
742
+ ) -> Message | None:
710
743
  if self.full_node.sync_store.get_sync_mode():
711
744
  return None
712
745
  async with self.full_node.timelord_lock:
@@ -732,7 +765,7 @@ class FullNodeAPI:
732
765
  )[0]
733
766
  sub_slots_for_peak = await self.full_node.blockchain.get_sp_and_ip_sub_slots(peak.header_hash)
734
767
  assert sub_slots_for_peak is not None
735
- ip_sub_slot: Optional[EndOfSubSlotBundle] = sub_slots_for_peak[1]
768
+ ip_sub_slot: EndOfSubSlotBundle | None = sub_slots_for_peak[1]
736
769
  else:
737
770
  sub_slot_iters = self.full_node.constants.SUB_SLOT_ITERS_STARTING
738
771
  next_sub_slot_iters = sub_slot_iters
@@ -765,7 +798,7 @@ class FullNodeAPI:
765
798
  @metadata.request(peer_required=True)
766
799
  async def respond_end_of_sub_slot(
767
800
  self, request: full_node_protocol.RespondEndOfSubSlot, peer: WSChiaConnection
768
- ) -> Optional[Message]:
801
+ ) -> Message | None:
769
802
  if self.full_node.sync_store.get_sync_mode():
770
803
  return None
771
804
  msg, _ = await self.full_node.add_end_of_sub_slot(request.end_of_slot_bundle, peer)
@@ -776,14 +809,14 @@ class FullNodeAPI:
776
809
  self,
777
810
  request: full_node_protocol.RequestMempoolTransactions,
778
811
  peer: WSChiaConnection,
779
- ) -> Optional[Message]:
812
+ ) -> Message | None:
780
813
  received_filter = PyBIP158(bytearray(request.filter))
781
814
 
782
- items: list[SpendBundle] = self.full_node.mempool_manager.get_items_not_in_filter(received_filter)
815
+ items = self.full_node.mempool_manager.get_items_not_in_filter(received_filter, limit=100)
783
816
 
784
817
  for item in items:
785
- transaction = full_node_protocol.RespondTransaction(item)
786
- msg = make_msg(ProtocolMessageTypes.respond_transaction, transaction)
818
+ transaction = full_node_protocol.NewTransaction(item.name, item.cost, item.fee)
819
+ msg = make_msg(ProtocolMessageTypes.new_transaction, transaction)
787
820
  await peer.send_message(msg)
788
821
  return None
789
822
 
@@ -791,7 +824,7 @@ class FullNodeAPI:
791
824
  @metadata.request(peer_required=True)
792
825
  async def declare_proof_of_space(
793
826
  self, request: farmer_protocol.DeclareProofOfSpace, peer: WSChiaConnection
794
- ) -> Optional[Message]:
827
+ ) -> Message | None:
795
828
  """
796
829
  Creates a block body and header, with the proof of space, coinbase, and fee targets provided
797
830
  by the farmer, and sends the hash of the header data back to the farmer.
@@ -800,7 +833,7 @@ class FullNodeAPI:
800
833
  return None
801
834
 
802
835
  async with self.full_node.timelord_lock:
803
- sp_vdfs: Optional[SignagePoint] = self.full_node.full_node_store.get_signage_point_by_index_and_cc_output(
836
+ sp_vdfs: SignagePoint | None = self.full_node.full_node_store.get_signage_point_by_index_and_cc_output(
804
837
  request.challenge_chain_sp, request.challenge_hash, request.signage_point_index
805
838
  )
806
839
 
@@ -822,7 +855,7 @@ class FullNodeAPI:
822
855
  assert sp_vdfs.cc_vdf is not None
823
856
  cc_challenge_hash = sp_vdfs.cc_vdf.challenge
824
857
 
825
- pos_sub_slot: Optional[tuple[EndOfSubSlotBundle, int, uint128]] = None
858
+ pos_sub_slot: tuple[EndOfSubSlotBundle, int, uint128] | None = None
826
859
  if request.challenge_hash != self.full_node.constants.GENESIS_CHALLENGE:
827
860
  # Checks that the proof of space is a response to a recent challenge and valid SP
828
861
  pos_sub_slot = self.full_node.full_node_store.get_sub_slot(cc_challenge_hash)
@@ -840,24 +873,31 @@ class FullNodeAPI:
840
873
  # 3. In a future sub-slot that we already know of
841
874
 
842
875
  # Grab best transactions from Mempool for given tip target
843
- new_block_gen: Optional[NewBlockGenerator]
876
+ new_block_gen: NewBlockGenerator | None
844
877
  async with self.full_node.blockchain.priority_mutex.acquire(priority=BlockchainMutexPriority.high):
845
- peak: Optional[BlockRecord] = self.full_node.blockchain.get_peak()
878
+ peak: BlockRecord | None = self.full_node.blockchain.get_peak()
879
+ tx_peak: BlockRecord | None = self.full_node.blockchain.get_tx_peak()
846
880
 
847
881
  # Checks that the proof of space is valid
848
882
  height: uint32
849
- if peak is None:
883
+ tx_height: uint32
884
+ if peak is None or tx_peak is None:
850
885
  height = uint32(0)
886
+ tx_height = uint32(0)
851
887
  else:
852
888
  height = peak.height
853
- quality_string: Optional[bytes32] = verify_and_get_quality_string(
889
+ tx_height = tx_peak.height
890
+ quality_string: bytes32 | None = verify_and_get_quality_string(
854
891
  request.proof_of_space,
855
892
  self.full_node.constants,
856
893
  cc_challenge_hash,
857
894
  request.challenge_chain_sp,
858
895
  height=height,
896
+ prev_transaction_block_height=tx_height,
859
897
  )
860
- assert quality_string is not None and len(quality_string) == 32
898
+ if quality_string is None:
899
+ self.log.warning("Received invalid proof of space in DeclareProofOfSpace from farmer")
900
+ return None
861
901
 
862
902
  if peak is not None:
863
903
  # Finds the last transaction block before this one
@@ -898,10 +938,10 @@ class FullNodeAPI:
898
938
  return request.reward_chain_sp_signature
899
939
  return G2Element()
900
940
 
901
- def get_pool_sig(_1: PoolTarget, _2: Optional[G1Element]) -> Optional[G2Element]:
941
+ def get_pool_sig(_1: PoolTarget, _2: G1Element | None) -> G2Element | None:
902
942
  return request.pool_signature
903
943
 
904
- prev_b: Optional[BlockRecord] = peak
944
+ prev_b: BlockRecord | None = peak
905
945
 
906
946
  # Finds the previous block from the signage point, ensuring that the reward chain VDF is correct
907
947
  if prev_b is not None:
@@ -939,7 +979,7 @@ class FullNodeAPI:
939
979
  return None
940
980
 
941
981
  try:
942
- finished_sub_slots: Optional[list[EndOfSubSlotBundle]] = (
982
+ finished_sub_slots: list[EndOfSubSlotBundle] | None = (
943
983
  self.full_node.full_node_store.get_finished_sub_slots(
944
984
  self.full_node.blockchain, prev_b, cc_challenge_hash
945
985
  )
@@ -987,11 +1027,9 @@ class FullNodeAPI:
987
1027
  required_iters: uint64 = calculate_iterations_quality(
988
1028
  self.full_node.constants,
989
1029
  quality_string,
990
- request.proof_of_space.size(),
1030
+ request.proof_of_space.param(),
991
1031
  difficulty,
992
1032
  request.challenge_chain_sp,
993
- sub_slot_iters,
994
- tx_peak.height if tx_peak is not None else uint32(0),
995
1033
  )
996
1034
  sp_iters: uint64 = calculate_sp_iters(self.full_node.constants, sub_slot_iters, request.signage_point_index)
997
1035
  ip_iters: uint64 = calculate_ip_iters(
@@ -1003,7 +1041,7 @@ class FullNodeAPI:
1003
1041
 
1004
1042
  # The block's timestamp must be greater than the previous transaction block's timestamp
1005
1043
  timestamp = uint64(time.time())
1006
- curr: Optional[BlockRecord] = prev_b
1044
+ curr: BlockRecord | None = prev_b
1007
1045
  while curr is not None and not curr.is_transaction_block and curr.height != 0:
1008
1046
  curr = self.full_node.blockchain.try_block_record(curr.prev_hash)
1009
1047
  if curr is not None:
@@ -1047,9 +1085,9 @@ class FullNodeAPI:
1047
1085
  foliage_transaction_block_hash = bytes32.zeros
1048
1086
  assert foliage_transaction_block_hash is not None
1049
1087
 
1050
- foliage_block_data: Optional[FoliageBlockData] = None
1051
- foliage_transaction_block_data: Optional[FoliageTransactionBlock] = None
1052
- rc_block_unfinished: Optional[RewardChainBlockUnfinished] = None
1088
+ foliage_block_data: FoliageBlockData | None = None
1089
+ foliage_transaction_block_data: FoliageTransactionBlock | None = None
1090
+ rc_block_unfinished: RewardChainBlockUnfinished | None = None
1053
1091
  if request.include_signature_source_data:
1054
1092
  foliage_block_data = unfinished_block.foliage.foliage_block_data
1055
1093
  rc_block_unfinished = unfinished_block.reward_chain_block
@@ -1098,13 +1136,13 @@ class FullNodeAPI:
1098
1136
  @metadata.request(peer_required=True)
1099
1137
  async def signed_values(
1100
1138
  self, farmer_request: farmer_protocol.SignedValues, peer: WSChiaConnection
1101
- ) -> Optional[Message]:
1139
+ ) -> Message | None:
1102
1140
  """
1103
1141
  Signature of header hash, by the harvester. This is enough to create an unfinished
1104
1142
  block, which only needs a Proof of Time to be finished. If the signature is valid,
1105
1143
  we call the unfinished_block routine.
1106
1144
  """
1107
- candidate_tuple: Optional[tuple[uint32, UnfinishedBlock]] = self.full_node.full_node_store.get_candidate_block(
1145
+ candidate_tuple: tuple[uint32, UnfinishedBlock] | None = self.full_node.full_node_store.get_candidate_block(
1108
1146
  farmer_request.quality_string
1109
1147
  )
1110
1148
 
@@ -1164,7 +1202,7 @@ class FullNodeAPI:
1164
1202
  @metadata.request(peer_required=True)
1165
1203
  async def new_infusion_point_vdf(
1166
1204
  self, request: timelord_protocol.NewInfusionPointVDF, peer: WSChiaConnection
1167
- ) -> Optional[Message]:
1205
+ ) -> Message | None:
1168
1206
  if self.full_node.sync_store.get_sync_mode():
1169
1207
  return None
1170
1208
  # Lookup unfinished blocks
@@ -1190,7 +1228,7 @@ class FullNodeAPI:
1190
1228
  @metadata.request(peer_required=True)
1191
1229
  async def new_end_of_sub_slot_vdf(
1192
1230
  self, request: timelord_protocol.NewEndOfSubSlotVDF, peer: WSChiaConnection
1193
- ) -> Optional[Message]:
1231
+ ) -> Message | None:
1194
1232
  if self.full_node.sync_store.get_sync_mode():
1195
1233
  return None
1196
1234
  if (
@@ -1212,19 +1250,19 @@ class FullNodeAPI:
1212
1250
  return msg
1213
1251
 
1214
1252
  @metadata.request()
1215
- async def request_block_header(self, request: wallet_protocol.RequestBlockHeader) -> Optional[Message]:
1253
+ async def request_block_header(self, request: wallet_protocol.RequestBlockHeader) -> Message | None:
1216
1254
  header_hash = self.full_node.blockchain.height_to_hash(request.height)
1217
1255
  if header_hash is None:
1218
1256
  msg = make_msg(ProtocolMessageTypes.reject_header_request, RejectHeaderRequest(request.height))
1219
1257
  return msg
1220
- block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(header_hash)
1258
+ block: FullBlock | None = await self.full_node.block_store.get_full_block(header_hash)
1221
1259
  if block is None:
1222
1260
  return None
1223
1261
 
1224
- removals_and_additions: Optional[tuple[Collection[bytes32], Collection[Coin]]] = None
1262
+ removals_and_additions: tuple[Collection[bytes32], Collection[Coin]] | None = None
1225
1263
 
1226
1264
  if block.transactions_generator is not None:
1227
- block_generator: Optional[BlockGenerator] = await get_block_generator(
1265
+ block_generator: BlockGenerator | None = await get_block_generator(
1228
1266
  self.full_node.blockchain.lookup_block_generators, block
1229
1267
  )
1230
1268
  # get_block_generator() returns None in case the block we specify
@@ -1233,7 +1271,14 @@ class FullNodeAPI:
1233
1271
  # transactions_generator, so the block_generator should always be set
1234
1272
  assert block_generator is not None, "failed to get block_generator for tx-block"
1235
1273
 
1236
- flags = get_flags_for_height_and_constants(request.height, self.full_node.constants)
1274
+ prev_tx_height = pre_sp_tx_block_height(
1275
+ constants=self.full_node.constants,
1276
+ blocks=self.full_node.blockchain,
1277
+ prev_b_hash=block.prev_header_hash,
1278
+ sp_index=block.reward_chain_block.signage_point_index,
1279
+ first_in_sub_slot=len(block.finished_sub_slots) > 0,
1280
+ )
1281
+ flags = get_flags_for_height_and_constants(prev_tx_height, self.full_node.constants)
1237
1282
  additions, removals = await asyncio.get_running_loop().run_in_executor(
1238
1283
  self.executor,
1239
1284
  additions_and_removals,
@@ -1257,9 +1302,9 @@ class FullNodeAPI:
1257
1302
  return msg
1258
1303
 
1259
1304
  @metadata.request()
1260
- async def request_additions(self, request: wallet_protocol.RequestAdditions) -> Optional[Message]:
1305
+ async def request_additions(self, request: wallet_protocol.RequestAdditions) -> Message | None:
1261
1306
  if request.header_hash is None:
1262
- header_hash: Optional[bytes32] = self.full_node.blockchain.height_to_hash(request.height)
1307
+ header_hash: bytes32 | None = self.full_node.blockchain.height_to_hash(request.height)
1263
1308
  else:
1264
1309
  header_hash = request.header_hash
1265
1310
  if header_hash is None:
@@ -1279,7 +1324,7 @@ class FullNodeAPI:
1279
1324
  puzzlehash_coins_map[coin_record.coin.puzzle_hash] = [coin_record.coin]
1280
1325
 
1281
1326
  coins_map: list[tuple[bytes32, list[Coin]]] = []
1282
- proofs_map: list[tuple[bytes32, bytes, Optional[bytes]]] = []
1327
+ proofs_map: list[tuple[bytes32, bytes, bytes | None]] = []
1283
1328
 
1284
1329
  if request.puzzle_hashes is None:
1285
1330
  for puzzle_hash, coins in puzzlehash_coins_map.items():
@@ -1314,8 +1359,8 @@ class FullNodeAPI:
1314
1359
  return make_msg(ProtocolMessageTypes.respond_additions, response)
1315
1360
 
1316
1361
  @metadata.request()
1317
- async def request_removals(self, request: wallet_protocol.RequestRemovals) -> Optional[Message]:
1318
- block: Optional[FullBlock] = await self.full_node.block_store.get_full_block(request.header_hash)
1362
+ async def request_removals(self, request: wallet_protocol.RequestRemovals) -> Message | None:
1363
+ block: FullBlock | None = await self.full_node.block_store.get_full_block(request.header_hash)
1319
1364
 
1320
1365
  # We lock so that the coin store does not get modified
1321
1366
  peak_height = self.full_node.blockchain.get_peak_height()
@@ -1342,12 +1387,12 @@ class FullNodeAPI:
1342
1387
  for coin_record in all_removals:
1343
1388
  all_removals_dict[coin_record.coin.name()] = coin_record.coin
1344
1389
 
1345
- coins_map: list[tuple[bytes32, Optional[Coin]]] = []
1390
+ coins_map: list[tuple[bytes32, Coin | None]] = []
1346
1391
  proofs_map: list[tuple[bytes32, bytes]] = []
1347
1392
 
1348
1393
  # If there are no transactions, respond with empty lists
1349
1394
  if block.transactions_generator is None:
1350
- proofs: Optional[list[tuple[bytes32, bytes]]]
1395
+ proofs: list[tuple[bytes32, bytes]] | None
1351
1396
  if request.coin_names is None:
1352
1397
  proofs = None
1353
1398
  else:
@@ -1380,9 +1425,7 @@ class FullNodeAPI:
1380
1425
  return msg
1381
1426
 
1382
1427
  @metadata.request()
1383
- async def send_transaction(
1384
- self, request: wallet_protocol.SendTransaction, *, test: bool = False
1385
- ) -> Optional[Message]:
1428
+ async def send_transaction(self, request: wallet_protocol.SendTransaction, *, test: bool = False) -> Message | None:
1386
1429
  spend_name = request.transaction.name()
1387
1430
  if self.full_node.mempool_manager.get_spendbundle(spend_name) is not None:
1388
1431
  self.full_node.mempool_manager.remove_seen(spend_name)
@@ -1390,7 +1433,7 @@ class FullNodeAPI:
1390
1433
  return make_msg(ProtocolMessageTypes.transaction_ack, response)
1391
1434
 
1392
1435
  queue_entry = TransactionQueueEntry(request.transaction, None, spend_name, None, test)
1393
- await self.full_node.transaction_queue.put(queue_entry, peer_id=None, high_priority=True)
1436
+ self.full_node.transaction_queue.put(queue_entry, peer_id=None, high_priority=True)
1394
1437
  try:
1395
1438
  with anyio.fail_after(delay=45):
1396
1439
  status, error = await queue_entry.done.wait()
@@ -1408,7 +1451,7 @@ class FullNodeAPI:
1408
1451
  return make_msg(ProtocolMessageTypes.transaction_ack, response)
1409
1452
 
1410
1453
  @metadata.request()
1411
- async def request_puzzle_solution(self, request: wallet_protocol.RequestPuzzleSolution) -> Optional[Message]:
1454
+ async def request_puzzle_solution(self, request: wallet_protocol.RequestPuzzleSolution) -> Message | None:
1412
1455
  coin_name = request.coin_name
1413
1456
  height = request.height
1414
1457
  coin_record = await self.full_node.coin_store.get_coin_record(coin_name)
@@ -1417,16 +1460,16 @@ class FullNodeAPI:
1417
1460
  if coin_record is None or coin_record.spent_block_index != height:
1418
1461
  return reject_msg
1419
1462
 
1420
- header_hash: Optional[bytes32] = self.full_node.blockchain.height_to_hash(height)
1463
+ header_hash: bytes32 | None = self.full_node.blockchain.height_to_hash(height)
1421
1464
  if header_hash is None:
1422
1465
  return reject_msg
1423
1466
 
1424
- block: Optional[BlockInfo] = await self.full_node.block_store.get_block_info(header_hash)
1467
+ block: BlockInfo | None = await self.full_node.block_store.get_block_info(header_hash)
1425
1468
 
1426
1469
  if block is None or block.transactions_generator is None:
1427
1470
  return reject_msg
1428
1471
 
1429
- block_generator: Optional[BlockGenerator] = await get_block_generator(
1472
+ block_generator: BlockGenerator | None = await get_block_generator(
1430
1473
  self.full_node.blockchain.lookup_block_generators, block
1431
1474
  )
1432
1475
  assert block_generator is not None
@@ -1448,7 +1491,7 @@ class FullNodeAPI:
1448
1491
  return response_msg
1449
1492
 
1450
1493
  @metadata.request()
1451
- async def request_block_headers(self, request: wallet_protocol.RequestBlockHeaders) -> Optional[Message]:
1494
+ async def request_block_headers(self, request: wallet_protocol.RequestBlockHeaders) -> Message | None:
1452
1495
  """Returns header blocks by directly streaming bytes into Message
1453
1496
 
1454
1497
  This method should be used instead of RequestHeaderBlocks
@@ -1501,7 +1544,7 @@ class FullNodeAPI:
1501
1544
  return make_msg(ProtocolMessageTypes.respond_block_headers, respond_header_blocks_manually_streamed)
1502
1545
 
1503
1546
  @metadata.request()
1504
- async def request_header_blocks(self, request: wallet_protocol.RequestHeaderBlocks) -> Optional[Message]:
1547
+ async def request_header_blocks(self, request: wallet_protocol.RequestHeaderBlocks) -> Message | None:
1505
1548
  """DEPRECATED: please use RequestBlockHeaders"""
1506
1549
  if (
1507
1550
  request.end_height < request.start_height
@@ -1511,7 +1554,7 @@ class FullNodeAPI:
1511
1554
  height_to_hash = self.full_node.blockchain.height_to_hash
1512
1555
  header_hashes: list[bytes32] = []
1513
1556
  for i in range(request.start_height, request.end_height + 1):
1514
- header_hash: Optional[bytes32] = height_to_hash(uint32(i))
1557
+ header_hash: bytes32 | None = height_to_hash(uint32(i))
1515
1558
  if header_hash is None:
1516
1559
  reject = RejectHeaderBlocks(request.start_height, request.end_height)
1517
1560
  msg = make_msg(ProtocolMessageTypes.reject_header_blocks, reject)
@@ -1688,7 +1731,7 @@ class FullNodeAPI:
1688
1731
  return msg
1689
1732
 
1690
1733
  @metadata.request()
1691
- async def request_children(self, request: wallet_protocol.RequestChildren) -> Optional[Message]:
1734
+ async def request_children(self, request: wallet_protocol.RequestChildren) -> Message | None:
1692
1735
  coin_records: list[CoinRecord] = await self.full_node.coin_store.get_coin_records_by_parent_ids(
1693
1736
  True, [request.coin_name]
1694
1737
  )
@@ -1820,7 +1863,7 @@ class FullNodeAPI:
1820
1863
  return msg
1821
1864
 
1822
1865
  # Check if the request would exceed the subscription limit now.
1823
- def check_subscription_limit() -> Optional[Message]:
1866
+ def check_subscription_limit() -> Message | None:
1824
1867
  new_subscription_count = len(puzzle_hashes) + subs.peer_subscription_count(peer.peer_node_id)
1825
1868
 
1826
1869
  if request.subscribe_when_finished and new_subscription_count > max_subscriptions:
@@ -1892,7 +1935,7 @@ class FullNodeAPI:
1892
1935
  return msg
1893
1936
 
1894
1937
  # Check if the request would exceed the subscription limit now.
1895
- def check_subscription_limit() -> Optional[Message]:
1938
+ def check_subscription_limit() -> Message | None:
1896
1939
  new_subscription_count = len(coin_ids) + subs.peer_subscription_count(peer.peer_node_id)
1897
1940
 
1898
1941
  if request.subscribe and new_subscription_count > max_subscriptions:
@@ -1929,7 +1972,7 @@ class FullNodeAPI:
1929
1972
  return msg
1930
1973
 
1931
1974
  @metadata.request(reply_types=[ProtocolMessageTypes.respond_cost_info])
1932
- async def request_cost_info(self, _request: wallet_protocol.RequestCostInfo) -> Optional[Message]:
1975
+ async def request_cost_info(self, _request: wallet_protocol.RequestCostInfo) -> Message | None:
1933
1976
  mempool_manager = self.full_node.mempool_manager
1934
1977
  response = wallet_protocol.RespondCostInfo(
1935
1978
  max_transaction_cost=mempool_manager.max_tx_clvm_cost,