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