chia-blockchain 2.5.4rc2__py3-none-any.whl → 2.5.5rc2__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 (453) hide show
  1. chia/_tests/blockchain/blockchain_test_utils.py +2 -3
  2. chia/_tests/blockchain/test_augmented_chain.py +2 -3
  3. chia/_tests/blockchain/test_blockchain.py +261 -44
  4. chia/_tests/blockchain/test_blockchain_transactions.py +4 -3
  5. chia/_tests/blockchain/test_build_chains.py +197 -1
  6. chia/_tests/blockchain/test_get_block_generator.py +1 -1
  7. chia/_tests/blockchain/test_lookup_fork_chain.py +1 -1
  8. chia/_tests/clvm/benchmark_costs.py +1 -1
  9. chia/_tests/clvm/coin_store.py +3 -4
  10. chia/_tests/clvm/test_message_conditions.py +2 -2
  11. chia/_tests/clvm/test_puzzle_compression.py +2 -3
  12. chia/_tests/clvm/test_puzzles.py +1 -2
  13. chia/_tests/clvm/test_singletons.py +2 -3
  14. chia/_tests/clvm/test_spend_sim.py +7 -7
  15. chia/_tests/cmds/cmd_test_utils.py +30 -25
  16. chia/_tests/cmds/test_dev_gh.py +1 -1
  17. chia/_tests/cmds/test_farm_cmd.py +1 -1
  18. chia/_tests/cmds/test_show.py +1 -2
  19. chia/_tests/cmds/wallet/test_did.py +101 -56
  20. chia/_tests/cmds/wallet/test_nft.py +109 -84
  21. chia/_tests/cmds/wallet/test_notifications.py +1 -1
  22. chia/_tests/cmds/wallet/test_offer.toffer +1 -1
  23. chia/_tests/cmds/wallet/test_vcs.py +8 -8
  24. chia/_tests/cmds/wallet/test_wallet.py +100 -46
  25. chia/_tests/conftest.py +31 -20
  26. chia/_tests/connection_utils.py +1 -1
  27. chia/_tests/core/consensus/stores/__init__.py +0 -0
  28. chia/_tests/core/consensus/stores/test_coin_store_protocol.py +40 -0
  29. chia/_tests/core/consensus/test_block_creation.py +2 -31
  30. chia/_tests/core/consensus/test_pot_iterations.py +38 -3
  31. chia/_tests/core/custom_types/test_proof_of_space.py +154 -26
  32. chia/_tests/core/custom_types/test_spend_bundle.py +2 -3
  33. chia/_tests/core/daemon/test_daemon.py +80 -0
  34. chia/_tests/core/data_layer/test_data_layer.py +1 -1
  35. chia/_tests/core/data_layer/test_data_layer_util.py +1 -1
  36. chia/_tests/core/data_layer/test_data_rpc.py +14 -10
  37. chia/_tests/core/data_layer/test_data_store.py +5 -5
  38. chia/_tests/core/farmer/test_farmer_api.py +2 -2
  39. chia/_tests/core/full_node/full_sync/test_full_sync.py +446 -406
  40. chia/_tests/core/full_node/ram_db.py +3 -1
  41. chia/_tests/core/full_node/stores/test_block_store.py +28 -16
  42. chia/_tests/core/full_node/stores/test_coin_store.py +277 -185
  43. chia/_tests/core/full_node/stores/test_full_node_store.py +11 -4
  44. chia/_tests/core/full_node/stores/test_hint_store.py +2 -2
  45. chia/_tests/core/full_node/test_address_manager.py +200 -27
  46. chia/_tests/core/full_node/test_block_height_map.py +2 -2
  47. chia/_tests/core/full_node/test_conditions.py +7 -6
  48. chia/_tests/core/full_node/test_full_node.py +456 -40
  49. chia/_tests/core/full_node/test_generator_tools.py +32 -2
  50. chia/_tests/core/full_node/test_hint_management.py +1 -1
  51. chia/_tests/core/full_node/test_node_load.py +20 -21
  52. chia/_tests/core/full_node/test_performance.py +3 -4
  53. chia/_tests/core/full_node/test_prev_tx_block.py +43 -0
  54. chia/_tests/core/full_node/test_subscriptions.py +1 -2
  55. chia/_tests/core/full_node/test_transactions.py +9 -5
  56. chia/_tests/core/full_node/test_tx_processing_queue.py +1 -2
  57. chia/_tests/core/large_block.py +1 -2
  58. chia/_tests/core/make_block_generator.py +3 -4
  59. chia/_tests/core/mempool/test_mempool.py +36 -86
  60. chia/_tests/core/mempool/test_mempool_fee_estimator.py +1 -1
  61. chia/_tests/core/mempool/test_mempool_item_queries.py +1 -3
  62. chia/_tests/core/mempool/test_mempool_manager.py +421 -69
  63. chia/_tests/core/mempool/test_mempool_performance.py +3 -2
  64. chia/_tests/core/mempool/test_singleton_fast_forward.py +60 -131
  65. chia/_tests/core/server/flood.py +1 -1
  66. chia/_tests/core/server/test_dos.py +1 -1
  67. chia/_tests/core/server/test_node_discovery.py +41 -27
  68. chia/_tests/core/server/test_rate_limits.py +1 -1
  69. chia/_tests/core/server/test_server.py +1 -1
  70. chia/_tests/core/services/test_services.py +5 -5
  71. chia/_tests/core/ssl/test_ssl.py +1 -1
  72. chia/_tests/core/test_cost_calculation.py +6 -6
  73. chia/_tests/core/test_crawler.py +2 -2
  74. chia/_tests/core/test_crawler_rpc.py +1 -1
  75. chia/_tests/core/test_db_conversion.py +3 -1
  76. chia/_tests/core/test_db_validation.py +5 -3
  77. chia/_tests/core/test_farmer_harvester_rpc.py +15 -15
  78. chia/_tests/core/test_filter.py +4 -1
  79. chia/_tests/core/test_full_node_rpc.py +99 -82
  80. chia/_tests/core/test_program.py +2 -2
  81. chia/_tests/core/util/test_block_cache.py +1 -1
  82. chia/_tests/core/util/test_keychain.py +2 -2
  83. chia/_tests/core/util/test_lockfile.py +1 -1
  84. chia/_tests/core/util/test_log_exceptions.py +5 -5
  85. chia/_tests/core/util/test_streamable.py +81 -22
  86. chia/_tests/db/test_db_wrapper.py +1 -3
  87. chia/_tests/environments/wallet.py +5 -5
  88. chia/_tests/farmer_harvester/test_farmer.py +9 -7
  89. chia/_tests/farmer_harvester/test_farmer_harvester.py +11 -4
  90. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +6 -5
  91. chia/_tests/farmer_harvester/test_third_party_harvesters.py +15 -9
  92. chia/_tests/fee_estimation/test_fee_estimation_integration.py +1 -2
  93. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +7 -5
  94. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +1 -1
  95. chia/_tests/generator/test_compression.py +1 -2
  96. chia/_tests/generator/test_rom.py +8 -4
  97. chia/_tests/plot_sync/test_plot_sync.py +3 -3
  98. chia/_tests/plot_sync/test_receiver.py +3 -3
  99. chia/_tests/plot_sync/test_sender.py +1 -1
  100. chia/_tests/plot_sync/test_sync_simulated.py +3 -3
  101. chia/_tests/plot_sync/util.py +2 -2
  102. chia/_tests/pools/test_pool_cmdline.py +48 -21
  103. chia/_tests/pools/test_pool_puzzles_lifecycle.py +2 -3
  104. chia/_tests/pools/test_pool_rpc.py +237 -105
  105. chia/_tests/pools/test_pool_wallet.py +11 -2
  106. chia/_tests/pools/test_wallet_pool_store.py +5 -4
  107. chia/_tests/rpc/test_rpc_client.py +1 -1
  108. chia/_tests/simulation/test_simulation.py +13 -8
  109. chia/_tests/simulation/test_simulator.py +2 -2
  110. chia/_tests/timelord/test_new_peak.py +191 -47
  111. chia/_tests/timelord/test_timelord.py +1 -1
  112. chia/_tests/tools/test_full_sync.py +0 -2
  113. chia/_tests/tools/test_run_block.py +3 -1
  114. chia/_tests/util/benchmark_cost.py +3 -3
  115. chia/_tests/util/benchmarks.py +2 -2
  116. chia/_tests/util/blockchain.py +11 -5
  117. chia/_tests/util/blockchain_mock.py +1 -4
  118. chia/_tests/util/coin_store.py +29 -0
  119. chia/_tests/util/constants.py +2 -18
  120. chia/_tests/util/full_sync.py +3 -3
  121. chia/_tests/util/generator_tools_testing.py +2 -3
  122. chia/_tests/util/key_tool.py +2 -3
  123. chia/_tests/util/misc.py +33 -31
  124. chia/_tests/util/network_protocol_data.py +19 -17
  125. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  126. chia/_tests/util/protocol_messages_json.py +3 -1
  127. chia/_tests/util/run_block.py +2 -2
  128. chia/_tests/util/setup_nodes.py +7 -7
  129. chia/_tests/util/spend_sim.py +47 -55
  130. chia/_tests/util/test_condition_tools.py +5 -4
  131. chia/_tests/util/test_config.py +2 -2
  132. chia/_tests/util/test_dump_keyring.py +1 -1
  133. chia/_tests/util/test_full_block_utils.py +12 -14
  134. chia/_tests/util/test_misc.py +2 -2
  135. chia/_tests/util/test_paginator.py +4 -4
  136. chia/_tests/util/test_priority_mutex.py +2 -2
  137. chia/_tests/util/test_replace_str_to_bytes.py +15 -5
  138. chia/_tests/util/test_ssl_check.py +1 -1
  139. chia/_tests/util/test_testnet_overrides.py +13 -3
  140. chia/_tests/util/time_out_assert.py +4 -2
  141. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +1 -1
  142. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +1 -2
  143. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +352 -432
  144. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +3 -6
  145. chia/_tests/wallet/cat_wallet/test_trades.py +53 -77
  146. chia/_tests/wallet/clawback/test_clawback_decorator.py +3 -1
  147. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +3 -3
  148. chia/_tests/wallet/clawback/test_clawback_metadata.py +4 -2
  149. chia/_tests/wallet/conftest.py +11 -12
  150. chia/_tests/wallet/db_wallet/test_db_graftroot.py +11 -4
  151. chia/_tests/wallet/db_wallet/test_dl_offers.py +433 -130
  152. chia/_tests/wallet/db_wallet/test_dl_wallet.py +3 -3
  153. chia/_tests/wallet/did_wallet/test_did.py +2132 -2000
  154. chia/_tests/wallet/nft_wallet/config.py +1 -1
  155. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1610 -742
  156. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +486 -907
  157. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +4 -4
  158. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +517 -294
  159. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +133 -62
  160. chia/_tests/wallet/rpc/test_wallet_rpc.py +495 -265
  161. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +10 -6
  162. chia/_tests/wallet/sync/test_wallet_sync.py +89 -60
  163. chia/_tests/wallet/test_clvm_casts.py +88 -0
  164. chia/_tests/wallet/test_coin_management.py +1 -1
  165. chia/_tests/wallet/test_coin_selection.py +1 -1
  166. chia/_tests/wallet/test_conditions.py +1 -1
  167. chia/_tests/wallet/test_new_wallet_protocol.py +13 -11
  168. chia/_tests/wallet/test_notifications.py +5 -3
  169. chia/_tests/wallet/test_sign_coin_spends.py +6 -6
  170. chia/_tests/wallet/test_signer_protocol.py +13 -12
  171. chia/_tests/wallet/test_singleton.py +1 -1
  172. chia/_tests/wallet/test_singleton_lifecycle_fast.py +5 -7
  173. chia/_tests/wallet/test_util.py +2 -2
  174. chia/_tests/wallet/test_wallet.py +108 -29
  175. chia/_tests/wallet/test_wallet_action_scope.py +9 -2
  176. chia/_tests/wallet/test_wallet_blockchain.py +2 -3
  177. chia/_tests/wallet/test_wallet_key_val_store.py +1 -2
  178. chia/_tests/wallet/test_wallet_node.py +2 -4
  179. chia/_tests/wallet/test_wallet_retry.py +4 -2
  180. chia/_tests/wallet/test_wallet_state_manager.py +191 -5
  181. chia/_tests/wallet/test_wallet_test_framework.py +1 -1
  182. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +8 -8
  183. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +29 -12
  184. chia/_tests/wallet/wallet_block_tools.py +6 -6
  185. chia/_tests/weight_proof/test_weight_proof.py +10 -48
  186. chia/apis.py +1 -1
  187. chia/cmds/beta.py +1 -1
  188. chia/cmds/chia.py +9 -9
  189. chia/cmds/cmd_classes.py +12 -11
  190. chia/cmds/cmd_helpers.py +1 -1
  191. chia/cmds/cmds_util.py +12 -9
  192. chia/cmds/coin_funcs.py +2 -2
  193. chia/cmds/configure.py +2 -2
  194. chia/cmds/data.py +0 -2
  195. chia/cmds/data_funcs.py +1 -1
  196. chia/cmds/db_validate_func.py +1 -2
  197. chia/cmds/dev/__init__.py +0 -0
  198. chia/cmds/dev/data.py +273 -0
  199. chia/cmds/{gh.py → dev/gh.py} +5 -5
  200. chia/cmds/dev/main.py +22 -0
  201. chia/cmds/dev/mempool.py +78 -0
  202. chia/cmds/dev/mempool_funcs.py +63 -0
  203. chia/cmds/farm_funcs.py +5 -4
  204. chia/cmds/init_funcs.py +11 -11
  205. chia/cmds/keys.py +2 -2
  206. chia/cmds/keys_funcs.py +4 -4
  207. chia/cmds/netspace_funcs.py +1 -1
  208. chia/cmds/peer_funcs.py +2 -2
  209. chia/cmds/plotnft_funcs.py +72 -26
  210. chia/cmds/rpc.py +1 -1
  211. chia/cmds/show_funcs.py +5 -5
  212. chia/cmds/signer.py +8 -7
  213. chia/cmds/sim_funcs.py +8 -9
  214. chia/cmds/wallet.py +2 -2
  215. chia/cmds/wallet_funcs.py +165 -131
  216. chia/{util → consensus}/augmented_chain.py +1 -2
  217. chia/consensus/block_body_validation.py +54 -40
  218. chia/consensus/block_creation.py +42 -76
  219. chia/consensus/block_header_validation.py +32 -26
  220. chia/consensus/block_record.py +0 -3
  221. chia/consensus/blockchain.py +23 -32
  222. chia/consensus/blockchain_interface.py +1 -5
  223. chia/consensus/check_time_locks.py +57 -0
  224. chia/consensus/coin_store_protocol.py +151 -0
  225. chia/consensus/coinbase.py +0 -6
  226. chia/consensus/condition_costs.py +4 -0
  227. chia/{util → consensus}/condition_tools.py +4 -5
  228. chia/consensus/cost_calculator.py +1 -1
  229. chia/consensus/default_constants.py +32 -9
  230. chia/consensus/deficit.py +1 -3
  231. chia/consensus/difficulty_adjustment.py +1 -2
  232. chia/consensus/find_fork_point.py +1 -3
  233. chia/consensus/full_block_to_block_record.py +1 -6
  234. chia/{util → consensus}/generator_tools.py +1 -3
  235. chia/consensus/get_block_challenge.py +30 -7
  236. chia/consensus/make_sub_epoch_summary.py +1 -5
  237. chia/consensus/multiprocess_validation.py +21 -20
  238. chia/consensus/pot_iterations.py +74 -13
  239. chia/{util → consensus}/prev_transaction_block.py +1 -1
  240. chia/consensus/vdf_info_computation.py +1 -3
  241. chia/daemon/keychain_proxy.py +5 -5
  242. chia/daemon/server.py +22 -5
  243. chia/data_layer/data_layer.py +92 -51
  244. chia/{rpc → data_layer}/data_layer_rpc_api.py +1 -1
  245. chia/{rpc → data_layer}/data_layer_rpc_util.py +3 -6
  246. chia/data_layer/data_layer_util.py +4 -6
  247. chia/data_layer/data_layer_wallet.py +42 -69
  248. chia/data_layer/dl_wallet_store.py +12 -6
  249. chia/data_layer/download_data.py +3 -3
  250. chia/data_layer/s3_plugin_service.py +0 -1
  251. chia/farmer/farmer.py +3 -4
  252. chia/farmer/farmer_api.py +11 -7
  253. chia/{rpc → farmer}/farmer_rpc_client.py +1 -1
  254. chia/full_node/block_height_map.py +7 -6
  255. chia/full_node/block_store.py +5 -7
  256. chia/full_node/bundle_tools.py +1 -2
  257. chia/full_node/coin_store.py +143 -124
  258. chia/{types → full_node}/eligible_coin_spends.py +39 -70
  259. chia/full_node/fee_estimator.py +1 -1
  260. chia/full_node/fee_estimator_interface.py +0 -8
  261. chia/full_node/fee_tracker.py +25 -25
  262. chia/full_node/full_node.py +70 -53
  263. chia/full_node/full_node_api.py +57 -40
  264. chia/{rpc → full_node}/full_node_rpc_api.py +87 -8
  265. chia/{rpc → full_node}/full_node_rpc_client.py +7 -6
  266. chia/full_node/full_node_store.py +23 -8
  267. chia/full_node/mempool.py +206 -53
  268. chia/full_node/mempool_check_conditions.py +20 -63
  269. chia/full_node/mempool_manager.py +26 -40
  270. chia/full_node/subscriptions.py +1 -3
  271. chia/full_node/tx_processing_queue.py +50 -3
  272. chia/full_node/weight_proof.py +46 -37
  273. chia/harvester/harvester.py +1 -1
  274. chia/harvester/harvester_api.py +22 -7
  275. chia/introducer/introducer.py +1 -1
  276. chia/introducer/introducer_api.py +1 -1
  277. chia/plot_sync/exceptions.py +1 -1
  278. chia/plot_sync/receiver.py +1 -1
  279. chia/plot_sync/sender.py +2 -2
  280. chia/pools/pool_puzzles.py +13 -18
  281. chia/pools/pool_wallet.py +23 -46
  282. chia/protocols/farmer_protocol.py +11 -3
  283. chia/protocols/full_node_protocol.py +1 -4
  284. chia/protocols/harvester_protocol.py +3 -3
  285. chia/protocols/pool_protocol.py +1 -2
  286. chia/protocols/shared_protocol.py +3 -3
  287. chia/protocols/timelord_protocol.py +1 -3
  288. chia/protocols/wallet_protocol.py +3 -3
  289. chia/rpc/rpc_client.py +7 -8
  290. chia/rpc/rpc_server.py +3 -3
  291. chia/rpc/util.py +3 -1
  292. chia/seeder/crawler.py +1 -1
  293. chia/seeder/crawler_api.py +1 -1
  294. chia/seeder/dns_server.py +2 -0
  295. chia/seeder/start_crawler.py +3 -3
  296. chia/server/address_manager.py +286 -38
  297. chia/server/address_manager_store.py +0 -215
  298. chia/{types → server}/aliases.py +7 -7
  299. chia/server/api_protocol.py +1 -1
  300. chia/server/chia_policy.py +1 -1
  301. chia/server/node_discovery.py +76 -113
  302. chia/server/rate_limits.py +1 -1
  303. chia/server/resolve_peer_info.py +43 -0
  304. chia/server/server.py +5 -5
  305. chia/server/start_data_layer.py +4 -4
  306. chia/server/start_farmer.py +5 -4
  307. chia/server/start_full_node.py +5 -4
  308. chia/server/start_harvester.py +7 -5
  309. chia/server/start_introducer.py +2 -2
  310. chia/server/start_service.py +1 -1
  311. chia/server/start_timelord.py +7 -5
  312. chia/server/start_wallet.py +7 -5
  313. chia/server/ws_connection.py +1 -1
  314. chia/simulator/add_blocks_in_batches.py +2 -2
  315. chia/simulator/block_tools.py +245 -201
  316. chia/simulator/full_node_simulator.py +38 -10
  317. chia/simulator/setup_services.py +12 -12
  318. chia/simulator/simulator_full_node_rpc_api.py +2 -2
  319. chia/simulator/simulator_full_node_rpc_client.py +2 -2
  320. chia/simulator/simulator_test_tools.py +2 -2
  321. chia/simulator/start_simulator.py +1 -1
  322. chia/simulator/wallet_tools.py +10 -18
  323. chia/ssl/create_ssl.py +1 -1
  324. chia/timelord/iters_from_block.py +14 -14
  325. chia/timelord/timelord.py +15 -11
  326. chia/timelord/timelord_api.py +14 -2
  327. chia/timelord/timelord_state.py +20 -14
  328. chia/types/blockchain_format/program.py +53 -10
  329. chia/types/blockchain_format/proof_of_space.py +73 -19
  330. chia/types/coin_spend.py +3 -56
  331. chia/types/generator_types.py +28 -0
  332. chia/types/internal_mempool_item.py +1 -2
  333. chia/types/mempool_item.py +12 -7
  334. chia/types/unfinished_header_block.py +1 -2
  335. chia/types/validation_state.py +1 -2
  336. chia/types/weight_proof.py +1 -3
  337. chia/util/action_scope.py +3 -3
  338. chia/util/block_cache.py +1 -2
  339. chia/util/byte_types.py +1 -1
  340. chia/util/casts.py +21 -0
  341. chia/util/config.py +0 -37
  342. chia/util/db_wrapper.py +8 -1
  343. chia/util/errors.py +3 -2
  344. chia/util/initial-config.yaml +21 -5
  345. chia/util/keychain.py +6 -7
  346. chia/util/keyring_wrapper.py +5 -5
  347. chia/util/limited_semaphore.py +1 -1
  348. chia/util/priority_mutex.py +1 -1
  349. chia/util/streamable.py +63 -5
  350. chia/util/task_timing.py +1 -1
  351. chia/util/virtual_project_analysis.py +1 -1
  352. chia/wallet/cat_wallet/cat_info.py +7 -3
  353. chia/wallet/cat_wallet/cat_outer_puzzle.py +9 -5
  354. chia/wallet/cat_wallet/cat_utils.py +1 -1
  355. chia/wallet/cat_wallet/cat_wallet.py +44 -36
  356. chia/wallet/cat_wallet/lineage_store.py +7 -0
  357. chia/wallet/cat_wallet/r_cat_wallet.py +274 -0
  358. chia/wallet/conditions.py +5 -10
  359. chia/wallet/db_wallet/db_wallet_puzzles.py +4 -4
  360. chia/wallet/derivation_record.py +33 -0
  361. chia/wallet/derive_keys.py +3 -3
  362. chia/wallet/did_wallet/did_info.py +12 -3
  363. chia/wallet/did_wallet/did_wallet.py +132 -101
  364. chia/wallet/did_wallet/did_wallet_puzzles.py +9 -9
  365. chia/wallet/driver_protocol.py +3 -1
  366. chia/{types/spend_bundle.py → wallet/estimate_fees.py} +2 -7
  367. chia/wallet/nft_wallet/metadata_outer_puzzle.py +5 -3
  368. chia/wallet/nft_wallet/nft_puzzle_utils.py +1 -1
  369. chia/wallet/nft_wallet/nft_wallet.py +69 -112
  370. chia/wallet/nft_wallet/ownership_outer_puzzle.py +5 -3
  371. chia/wallet/nft_wallet/singleton_outer_puzzle.py +6 -4
  372. chia/wallet/nft_wallet/transfer_program_puzzle.py +4 -2
  373. chia/wallet/nft_wallet/uncurry_nft.py +4 -6
  374. chia/wallet/notification_manager.py +2 -3
  375. chia/wallet/outer_puzzles.py +7 -2
  376. chia/wallet/puzzle_drivers.py +1 -1
  377. chia/wallet/puzzles/clawback/drivers.py +5 -4
  378. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +1 -1
  379. chia/wallet/puzzles/singleton_top_layer.py +2 -1
  380. chia/wallet/puzzles/singleton_top_layer_v1_1.py +2 -1
  381. chia/wallet/puzzles/tails.py +1 -3
  382. chia/wallet/signer_protocol.py +5 -6
  383. chia/wallet/singleton.py +5 -4
  384. chia/wallet/singleton_record.py +1 -1
  385. chia/wallet/trade_manager.py +18 -20
  386. chia/wallet/trade_record.py +3 -6
  387. chia/wallet/trading/offer.py +12 -13
  388. chia/wallet/uncurried_puzzle.py +2 -2
  389. chia/wallet/util/compute_additions.py +58 -0
  390. chia/wallet/util/compute_hints.py +3 -3
  391. chia/wallet/util/compute_memos.py +4 -4
  392. chia/wallet/util/curry_and_treehash.py +2 -1
  393. chia/wallet/util/debug_spend_bundle.py +1 -1
  394. chia/wallet/util/merkle_tree.py +1 -1
  395. chia/wallet/util/peer_request_cache.py +1 -2
  396. chia/wallet/util/tx_config.py +3 -8
  397. chia/wallet/util/wallet_sync_utils.py +10 -5
  398. chia/wallet/util/wallet_types.py +1 -0
  399. chia/wallet/vc_wallet/cr_cat_drivers.py +17 -18
  400. chia/wallet/vc_wallet/cr_cat_wallet.py +30 -28
  401. chia/wallet/vc_wallet/cr_outer_puzzle.py +5 -3
  402. chia/wallet/vc_wallet/vc_drivers.py +50 -8
  403. chia/wallet/vc_wallet/vc_store.py +3 -5
  404. chia/wallet/vc_wallet/vc_wallet.py +15 -22
  405. chia/wallet/wallet.py +36 -46
  406. chia/wallet/wallet_action_scope.py +73 -4
  407. chia/wallet/wallet_blockchain.py +1 -3
  408. chia/wallet/wallet_interested_store.py +1 -1
  409. chia/wallet/wallet_nft_store.py +3 -3
  410. chia/wallet/wallet_node.py +17 -16
  411. chia/wallet/wallet_node_api.py +4 -5
  412. chia/wallet/wallet_pool_store.py +1 -1
  413. chia/wallet/wallet_protocol.py +2 -0
  414. chia/wallet/wallet_puzzle_store.py +1 -1
  415. chia/{rpc → wallet}/wallet_request_types.py +670 -81
  416. chia/{rpc → wallet}/wallet_rpc_api.py +735 -766
  417. chia/{rpc → wallet}/wallet_rpc_client.py +268 -420
  418. chia/wallet/wallet_singleton_store.py +8 -7
  419. chia/wallet/wallet_spend_bundle.py +4 -3
  420. chia/wallet/wallet_state_manager.py +320 -191
  421. chia/wallet/wallet_weight_proof_handler.py +1 -2
  422. chia/wallet/wsm_apis.py +98 -0
  423. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/METADATA +7 -7
  424. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/RECORD +443 -436
  425. mozilla-ca/cacert.pem +3 -165
  426. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +0 -145
  427. chia/cmds/dev.py +0 -18
  428. chia/types/blockchain_format/slots.py +0 -9
  429. chia/types/blockchain_format/sub_epoch_summary.py +0 -5
  430. chia/types/end_of_slot_bundle.py +0 -5
  431. chia/types/full_block.py +0 -5
  432. chia/types/header_block.py +0 -5
  433. chia/types/spend_bundle_conditions.py +0 -7
  434. chia/types/transaction_queue_entry.py +0 -56
  435. chia/types/unfinished_block.py +0 -5
  436. /chia/cmds/{installers.py → dev/installers.py} +0 -0
  437. /chia/cmds/{sim.py → dev/sim.py} +0 -0
  438. /chia/{util → cmds}/dump_keyring.py +0 -0
  439. /chia/{full_node → consensus}/signage_point.py +0 -0
  440. /chia/{rpc → data_layer}/data_layer_rpc_client.py +0 -0
  441. /chia/{rpc → farmer}/farmer_rpc_api.py +0 -0
  442. /chia/{util → full_node}/full_block_utils.py +0 -0
  443. /chia/{rpc → harvester}/harvester_rpc_api.py +0 -0
  444. /chia/{rpc → harvester}/harvester_rpc_client.py +0 -0
  445. /chia/{full_node → protocols}/fee_estimate.py +0 -0
  446. /chia/{server → protocols}/outbound_message.py +0 -0
  447. /chia/{rpc → seeder}/crawler_rpc_api.py +0 -0
  448. /chia/{util → simulator}/vdf_prover.py +0 -0
  449. /chia/{util → ssl}/ssl_check.py +0 -0
  450. /chia/{rpc → timelord}/timelord_rpc_api.py +0 -0
  451. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/LICENSE +0 -0
  452. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/WHEEL +0 -0
  453. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5rc2.dist-info}/entry_points.txt +0 -0
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import dataclasses
4
4
  import logging
5
+ import random
5
6
  from collections.abc import Awaitable, Collection, Sequence
6
7
  from typing import Any, Callable, ClassVar, Optional, Union
7
8
 
@@ -10,9 +11,14 @@ from chia_rs import (
10
11
  ELIGIBLE_FOR_DEDUP,
11
12
  ELIGIBLE_FOR_FF,
12
13
  AugSchemeMPL,
14
+ CoinSpend,
13
15
  ConsensusConstants,
14
16
  G2Element,
17
+ SpendBundle,
18
+ SpendBundleConditions,
19
+ SpendConditions,
15
20
  get_conditions_from_spendbundle,
21
+ run_block_generator2,
16
22
  )
17
23
  from chia_rs.sized_bytes import bytes32
18
24
  from chia_rs.sized_ints import uint8, uint32, uint64
@@ -21,10 +27,17 @@ from chiabip158 import PyBIP158
21
27
  from chia._tests.conftest import ConsensusMode
22
28
  from chia._tests.util.misc import Marks, datacases, invariant_check_mempool
23
29
  from chia._tests.util.setup_nodes import OldSimulatorsAndWallets, setup_simulators_and_wallets
30
+ from chia.consensus.check_time_locks import check_time_locks
24
31
  from chia.consensus.condition_costs import ConditionCost
25
32
  from chia.consensus.default_constants import DEFAULT_CONSTANTS
33
+ from chia.full_node.eligible_coin_spends import (
34
+ DedupCoinSpend,
35
+ EligibilityAndAdditions,
36
+ IdenticalSpendDedup,
37
+ SkipDedup,
38
+ run_for_cost,
39
+ )
26
40
  from chia.full_node.mempool import MAX_SKIPPED_ITEMS, PRIORITY_TX_THRESHOLD
27
- from chia.full_node.mempool_check_conditions import mempool_check_time_locks
28
41
  from chia.full_node.mempool_manager import (
29
42
  MEMPOOL_MIN_FEE_INCREASE,
30
43
  QUOTE_BYTES,
@@ -44,28 +57,26 @@ from chia.protocols.full_node_protocol import RequestBlock, RespondBlock
44
57
  from chia.protocols.protocol_message_types import ProtocolMessageTypes
45
58
  from chia.simulator.full_node_simulator import FullNodeSimulator
46
59
  from chia.simulator.simulator_protocol import FarmNewBlockProtocol
60
+ from chia.simulator.wallet_tools import WalletTool
47
61
  from chia.types.blockchain_format.coin import Coin
48
- from chia.types.blockchain_format.program import INFINITE_COST, Program
62
+ from chia.types.blockchain_format.program import DEFAULT_FLAGS, INFINITE_COST, Program
49
63
  from chia.types.blockchain_format.serialized_program import SerializedProgram
50
64
  from chia.types.clvm_cost import CLVMCost
51
65
  from chia.types.coin_record import CoinRecord
52
- from chia.types.coin_spend import CoinSpend, make_spend
66
+ from chia.types.coin_spend import make_spend
53
67
  from chia.types.condition_opcodes import ConditionOpcode
54
- from chia.types.eligible_coin_spends import (
55
- DedupCoinSpend,
56
- EligibilityAndAdditions,
57
- EligibleCoinSpends,
58
- SkipDedup,
59
- UnspentLineageInfo,
60
- run_for_cost,
61
- )
68
+ from chia.types.condition_with_args import ConditionWithArgs
62
69
  from chia.types.mempool_inclusion_status import MempoolInclusionStatus
63
- from chia.types.mempool_item import BundleCoinSpend, MempoolItem
70
+ from chia.types.mempool_item import BundleCoinSpend, MempoolItem, UnspentLineageInfo
64
71
  from chia.types.peer_info import PeerInfo
65
- from chia.types.spend_bundle import SpendBundle
66
- from chia.types.spend_bundle_conditions import SpendBundleConditions, SpendConditions
72
+ from chia.util.casts import int_to_bytes
73
+ from chia.util.default_root import DEFAULT_ROOT_PATH
67
74
  from chia.util.errors import Err, ValidationError
68
75
  from chia.wallet.conditions import AssertCoinAnnouncement
76
+ from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import (
77
+ DEFAULT_HIDDEN_PUZZLE_HASH,
78
+ calculate_synthetic_secret_key,
79
+ )
69
80
  from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
70
81
  from chia.wallet.wallet import Wallet
71
82
  from chia.wallet.wallet_coin_record import WalletCoinRecord
@@ -90,6 +101,28 @@ TEST_COIN_RECORD3 = CoinRecord(TEST_COIN3, uint32(0), uint32(0), False, TEST_TIM
90
101
  TEST_HEIGHT = uint32(5)
91
102
 
92
103
 
104
+ @pytest.fixture(name="test_bundles")
105
+ def test_bundles_fixture() -> list[SpendBundle]:
106
+ ret: list[SpendBundle] = []
107
+
108
+ bundle_path_dir = DEFAULT_ROOT_PATH.parent.joinpath("test-bundles")
109
+ for p in bundle_path_dir.iterdir():
110
+ if not p.is_file(): # pragma: no cover
111
+ continue
112
+ if p.suffix != ".bundle": # pragma: no cover
113
+ continue
114
+ if len(p.name) != 64 + 7: # pragma: no cover
115
+ continue
116
+
117
+ sb = SpendBundle.from_bytes(p.read_bytes())
118
+ ret.append(sb)
119
+
120
+ print(f"loaded {len(ret)} spend bundles from disk")
121
+
122
+ ret.sort(key=lambda x: x.name())
123
+ return ret
124
+
125
+
93
126
  @pytest.mark.parametrize("clvm_hex", ["80", "ff8080", "ff7f03", "ffff8080ff8080"])
94
127
  def test_clvm_canonical(clvm_hex: str) -> None:
95
128
  clvm_buf = bytes.fromhex(clvm_hex)
@@ -158,6 +191,14 @@ def test_atom_canonical(clvm_hex: str, expect: int) -> None:
158
191
  assert is_canonical
159
192
 
160
193
 
194
+ @pytest.mark.anyio
195
+ async def test_bundles_are_canonical(test_bundles: list[SpendBundle]) -> None:
196
+ for sb in test_bundles:
197
+ for spend in sb.coin_spends:
198
+ assert is_clvm_canonical(bytes(spend.puzzle_reveal))
199
+ assert is_clvm_canonical(bytes(spend.solution))
200
+
201
+
161
202
  @dataclasses.dataclass(frozen=True)
162
203
  class TestBlockRecord:
163
204
  """
@@ -318,6 +359,8 @@ def make_test_conds(
318
359
  [],
319
360
  [],
320
361
  flags,
362
+ execution_cost=0,
363
+ condition_cost=0,
321
364
  )
322
365
  for coin_id, parent_id, puzzle_hash, amount, flags, create_coin in spend_info
323
366
  ],
@@ -390,7 +433,7 @@ class TestCheckTimeLocks:
390
433
  expected: Optional[Err],
391
434
  ) -> None:
392
435
  assert (
393
- mempool_check_time_locks(
436
+ check_time_locks(
394
437
  dict(self.REMOVALS),
395
438
  conds,
396
439
  self.PREV_BLOCK_HEIGHT,
@@ -541,6 +584,9 @@ def make_bundle_spends_map_and_fee(
541
584
  eligible_for_dedup=eligibility_info.is_eligible_for_dedup,
542
585
  eligible_for_fast_forward=eligibility_info.ff_puzzle_hash is not None,
543
586
  additions=eligibility_info.spend_additions,
587
+ latest_singleton_lineage=UnspentLineageInfo(coin_id, coin_spend.coin.parent_coin_info, bytes32([0] * 32))
588
+ if eligibility_info.ff_puzzle_hash is not None
589
+ else None,
544
590
  )
545
591
  fee = uint64(removals_amount - additions_amount)
546
592
  return bundle_coin_spends, fee
@@ -1161,7 +1207,7 @@ async def test_total_mempool_fees() -> None:
1161
1207
  async def test_create_bundle_from_mempool(reverse_tx_order: bool) -> None:
1162
1208
  async def make_coin_spends(coins: list[Coin], *, high_fees: bool = True) -> list[CoinSpend]:
1163
1209
  spends_list = []
1164
- for i in range(0, len(coins)):
1210
+ for i in range(len(coins)):
1165
1211
  coin_spend = make_spend(
1166
1212
  coins[i],
1167
1213
  IDENTITY_PUZZLE,
@@ -1185,7 +1231,7 @@ async def test_create_bundle_from_mempool(reverse_tx_order: bool) -> None:
1185
1231
  spends = low_rate_spends + high_rate_spends if reverse_tx_order else high_rate_spends + low_rate_spends
1186
1232
  await send_spends_to_mempool(spends)
1187
1233
  assert mempool_manager.peak is not None
1188
- result = await mempool_manager.create_bundle_from_mempool(mempool_manager.peak.header_hash)
1234
+ result = mempool_manager.create_bundle_from_mempool(mempool_manager.peak.header_hash)
1189
1235
  assert result is not None
1190
1236
  # Make sure we filled the block with only high rate spends
1191
1237
  assert len([s for s in high_rate_spends if s in result[0].coin_spends]) == len(result[0].coin_spends)
@@ -1282,7 +1328,7 @@ async def test_create_bundle_from_mempool_on_max_cost(num_skipped_items: int, ca
1282
1328
 
1283
1329
  assert mempool_manager.peak is not None
1284
1330
  caplog.set_level(logging.DEBUG)
1285
- result = await mempool_manager.create_bundle_from_mempool(mempool_manager.peak.header_hash)
1331
+ result = mempool_manager.create_bundle_from_mempool(mempool_manager.peak.header_hash)
1286
1332
  assert result is not None
1287
1333
  agg, additions = result
1288
1334
  skipped_due_to_eligible_coins = sum(
@@ -1565,14 +1611,14 @@ def test_dedup_info_nothing_to_do() -> None:
1565
1611
  ]
1566
1612
  sb = spend_bundle_from_conditions(conditions, TEST_COIN, sig)
1567
1613
  mempool_item = mempool_item_from_spendbundle(sb)
1568
- eligible_coin_spends = EligibleCoinSpends()
1569
- unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
1614
+ dedup_coin_spends = IdenticalSpendDedup()
1615
+ unique_coin_spends, cost_saving, unique_additions = dedup_coin_spends.get_deduplication_info(
1570
1616
  bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
1571
1617
  )
1572
1618
  assert unique_coin_spends == sb.coin_spends
1573
1619
  assert cost_saving == 0
1574
1620
  assert unique_additions == [Coin(TEST_COIN_ID, IDENTITY_PUZZLE_HASH, uint64(1))]
1575
- assert eligible_coin_spends == EligibleCoinSpends()
1621
+ assert dedup_coin_spends == IdenticalSpendDedup()
1576
1622
 
1577
1623
 
1578
1624
  def test_dedup_info_eligible_1st_time() -> None:
@@ -1584,9 +1630,9 @@ def test_dedup_info_eligible_1st_time() -> None:
1584
1630
  sb = spend_bundle_from_conditions(conditions, TEST_COIN)
1585
1631
  mempool_item = mempool_item_from_spendbundle(sb)
1586
1632
  assert mempool_item.conds is not None
1587
- eligible_coin_spends = EligibleCoinSpends()
1633
+ dedup_coin_spends = IdenticalSpendDedup()
1588
1634
  solution = SerializedProgram.to(conditions)
1589
- unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
1635
+ unique_coin_spends, cost_saving, unique_additions = dedup_coin_spends.get_deduplication_info(
1590
1636
  bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
1591
1637
  )
1592
1638
  assert unique_coin_spends == sb.coin_spends
@@ -1595,7 +1641,7 @@ def test_dedup_info_eligible_1st_time() -> None:
1595
1641
  Coin(TEST_COIN_ID, IDENTITY_PUZZLE_HASH, uint64(1)),
1596
1642
  Coin(TEST_COIN_ID, IDENTITY_PUZZLE_HASH, uint64(TEST_COIN_AMOUNT - 1)),
1597
1643
  }
1598
- assert eligible_coin_spends == EligibleCoinSpends({TEST_COIN_ID: DedupCoinSpend(solution=solution, cost=None)})
1644
+ assert dedup_coin_spends == IdenticalSpendDedup({TEST_COIN_ID: DedupCoinSpend(solution=solution, cost=None)})
1599
1645
 
1600
1646
 
1601
1647
  def test_dedup_info_eligible_but_different_solution() -> None:
@@ -1605,12 +1651,12 @@ def test_dedup_info_eligible_but_different_solution() -> None:
1605
1651
  [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT],
1606
1652
  ]
1607
1653
  initial_solution = SerializedProgram.to(initial_conditions)
1608
- eligible_coin_spends = EligibleCoinSpends({TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=None)})
1654
+ dedup_coin_spends = IdenticalSpendDedup({TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=None)})
1609
1655
  conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT]]
1610
1656
  sb = spend_bundle_from_conditions(conditions, TEST_COIN)
1611
1657
  mempool_item = mempool_item_from_spendbundle(sb)
1612
1658
  with pytest.raises(SkipDedup, match="Solution is different from what we're deduplicating on"):
1613
- eligible_coin_spends.get_deduplication_info(
1659
+ dedup_coin_spends.get_deduplication_info(
1614
1660
  bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
1615
1661
  )
1616
1662
 
@@ -1622,7 +1668,7 @@ def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None:
1622
1668
  [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT - 1],
1623
1669
  ]
1624
1670
  initial_solution = SerializedProgram.to(initial_conditions)
1625
- eligible_coin_spends = EligibleCoinSpends({TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=None)})
1671
+ dedup_coin_spends = IdenticalSpendDedup({TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=None)})
1626
1672
  sb1 = spend_bundle_from_conditions(initial_conditions, TEST_COIN)
1627
1673
  second_conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT2]]
1628
1674
  second_solution = SerializedProgram.to(second_conditions)
@@ -1630,7 +1676,7 @@ def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None:
1630
1676
  sb = SpendBundle.aggregate([sb1, sb2])
1631
1677
  mempool_item = mempool_item_from_spendbundle(sb)
1632
1678
  assert mempool_item.conds is not None
1633
- unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
1679
+ unique_coin_spends, cost_saving, unique_additions = dedup_coin_spends.get_deduplication_info(
1634
1680
  bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
1635
1681
  )
1636
1682
  # Only the eligible one that we encountered more than once gets deduplicated
@@ -1640,13 +1686,13 @@ def test_dedup_info_eligible_2nd_time_and_another_1st_time() -> None:
1640
1686
  assert unique_additions == [Coin(TEST_COIN_ID2, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT2)]
1641
1687
  # The coin we encountered a second time has its cost and additions properly updated
1642
1688
  # The coin we encountered for the first time gets cost None and an empty set of additions
1643
- expected_eligible_spends = EligibleCoinSpends(
1689
+ expected_dedup_coin_spends = IdenticalSpendDedup(
1644
1690
  {
1645
1691
  TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=saved_cost),
1646
1692
  TEST_COIN_ID2: DedupCoinSpend(solution=second_solution, cost=None),
1647
1693
  }
1648
1694
  )
1649
- assert eligible_coin_spends == expected_eligible_spends
1695
+ assert dedup_coin_spends == expected_dedup_coin_spends
1650
1696
 
1651
1697
 
1652
1698
  def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() -> None:
@@ -1659,7 +1705,7 @@ def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() ->
1659
1705
  second_conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT2]]
1660
1706
  second_solution = SerializedProgram.to(second_conditions)
1661
1707
  saved_cost = uint64(3600044)
1662
- eligible_coin_spends = EligibleCoinSpends(
1708
+ dedup_coin_spends = IdenticalSpendDedup(
1663
1709
  {
1664
1710
  TEST_COIN_ID: DedupCoinSpend(solution=initial_solution, cost=saved_cost),
1665
1711
  TEST_COIN_ID2: DedupCoinSpend(solution=second_solution, cost=None),
@@ -1678,20 +1724,20 @@ def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() ->
1678
1724
  sb = SpendBundle.aggregate([sb1, sb2, sb3])
1679
1725
  mempool_item = mempool_item_from_spendbundle(sb)
1680
1726
  assert mempool_item.conds is not None
1681
- unique_coin_spends, cost_saving, unique_additions = eligible_coin_spends.get_deduplication_info(
1727
+ unique_coin_spends, cost_saving, unique_additions = dedup_coin_spends.get_deduplication_info(
1682
1728
  bundle_coin_spends=mempool_item.bundle_coin_spends, max_cost=mempool_item.conds.cost
1683
1729
  )
1684
1730
  assert unique_coin_spends == sb3.coin_spends
1685
1731
  saved_cost2 = uint64(1800044)
1686
1732
  assert cost_saving == saved_cost + saved_cost2
1687
1733
  assert unique_additions == [Coin(TEST_COIN_ID3, IDENTITY_PUZZLE_HASH, TEST_COIN_AMOUNT3)]
1688
- expected_eligible_spends = EligibleCoinSpends(
1734
+ expected_dedup_coin_spends = IdenticalSpendDedup(
1689
1735
  {
1690
1736
  TEST_COIN_ID: DedupCoinSpend(initial_solution, saved_cost),
1691
1737
  TEST_COIN_ID2: DedupCoinSpend(second_solution, saved_cost2),
1692
1738
  }
1693
1739
  )
1694
- assert eligible_coin_spends == expected_eligible_spends
1740
+ assert dedup_coin_spends == expected_dedup_coin_spends
1695
1741
 
1696
1742
 
1697
1743
  @pytest.mark.anyio
@@ -1806,8 +1852,9 @@ async def test_identical_spend_aggregation_e2e(
1806
1852
  full_node_api: FullNodeSimulator, wallet_node: WalletNode
1807
1853
  ) -> tuple[Wallet, list[WalletCoinRecord], bytes32]:
1808
1854
  wallet = wallet_node.wallet_state_manager.main_wallet
1809
- ph = await wallet.get_new_puzzlehash()
1810
- phs = [await wallet.get_new_puzzlehash() for _ in range(3)]
1855
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1856
+ ph = await action_scope.get_puzzle_hash(wallet.wallet_state_manager)
1857
+ phs = [await action_scope.get_puzzle_hash(wallet.wallet_state_manager) for _ in range(3)]
1811
1858
  for _ in range(2):
1812
1859
  await farm_a_block(full_node_api, wallet_node, ph)
1813
1860
  async with wallet.wallet_state_manager.new_action_scope(
@@ -2298,9 +2345,7 @@ class TestCoins:
2298
2345
  self.coin_records[c.name()] = CoinRecord(c, uint32(0), uint32(0), False, TEST_TIMESTAMP)
2299
2346
  self.lineage_info = {}
2300
2347
  for ph, c in lineage.items():
2301
- self.lineage_info[ph] = UnspentLineageInfo(
2302
- c.name(), c.amount, c.parent_coin_info, uint64(1337), bytes32([42] * 32)
2303
- )
2348
+ self.lineage_info[ph] = UnspentLineageInfo(c.name(), c.parent_coin_info, bytes32([42] * 32))
2304
2349
 
2305
2350
  def spend_coin(self, coin_id: bytes32, height: uint32 = uint32(10)) -> None:
2306
2351
  self.coin_records[coin_id] = dataclasses.replace(self.coin_records[coin_id], spent_block_index=height)
@@ -2311,9 +2356,7 @@ class TestCoins:
2311
2356
  else:
2312
2357
  assert coin.puzzle_hash == puzzle_hash
2313
2358
  prev = self.lineage_info[puzzle_hash]
2314
- self.lineage_info[puzzle_hash] = UnspentLineageInfo(
2315
- coin.name(), coin.amount, coin.parent_coin_info, prev.coin_amount, prev.coin_id
2316
- )
2359
+ self.lineage_info[puzzle_hash] = UnspentLineageInfo(coin.name(), coin.parent_coin_info, prev.coin_id)
2317
2360
 
2318
2361
  async def get_coin_records(self, coin_ids: Collection[bytes32]) -> list[CoinRecord]:
2319
2362
  ret = []
@@ -2329,26 +2372,23 @@ class TestCoins:
2329
2372
 
2330
2373
 
2331
2374
  # creates a CoinSpend of a made up
2332
- def make_singleton_spend(launcher_id: bytes32, parent_parent_id: bytes32 = bytes32([3] * 32)) -> CoinSpend:
2375
+ def make_singleton_spend(
2376
+ launcher_id: bytes32, parent_parent_id: bytes32 = bytes32([3] * 32), child_amount: int = 1
2377
+ ) -> CoinSpend:
2333
2378
  from chia_rs import supports_fast_forward
2334
2379
 
2335
2380
  from chia.wallet.lineage_proof import LineageProof
2336
- from chia.wallet.puzzles.singleton_top_layer_v1_1 import (
2337
- puzzle_for_singleton,
2338
- solution_for_singleton,
2339
- )
2381
+ from chia.wallet.puzzles.singleton_top_layer_v1_1 import puzzle_for_singleton, solution_for_singleton
2340
2382
 
2341
- singleton_puzzle = SerializedProgram.from_program(puzzle_for_singleton(launcher_id, Program.to(1)))
2383
+ singleton_puzzle = puzzle_for_singleton(launcher_id, Program.to(1)).to_serialized()
2342
2384
 
2343
2385
  PARENT_COIN = Coin(parent_parent_id, singleton_puzzle.get_tree_hash(), uint64(1))
2344
2386
  COIN = Coin(PARENT_COIN.name(), singleton_puzzle.get_tree_hash(), uint64(1))
2345
2387
 
2346
2388
  lineage_proof = LineageProof(parent_parent_id, IDENTITY_PUZZLE_HASH, uint64(1))
2347
2389
 
2348
- inner_solution = Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, uint64(1)]])
2349
- singleton_solution = SerializedProgram.from_program(
2350
- solution_for_singleton(lineage_proof, uint64(1), inner_solution)
2351
- )
2390
+ inner_solution = Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, uint64(child_amount)]])
2391
+ singleton_solution = solution_for_singleton(lineage_proof, uint64(1), inner_solution).to_serialized()
2352
2392
 
2353
2393
  ret = CoinSpend(COIN, singleton_puzzle, singleton_solution)
2354
2394
 
@@ -2364,7 +2404,7 @@ async def setup_mempool(coins: TestCoins) -> MempoolManager:
2364
2404
  coins.get_unspent_lineage_info,
2365
2405
  DEFAULT_CONSTANTS,
2366
2406
  )
2367
- test_block_record = create_test_block_record(height=uint32(10), timestamp=uint64(12345678))
2407
+ test_block_record = create_test_block_record(height=uint32(5000000), timestamp=uint64(12345678))
2368
2408
  await mempool_manager.new_peak(test_block_record, None)
2369
2409
  return mempool_manager
2370
2410
 
@@ -2426,8 +2466,11 @@ async def test_new_peak_ff_eviction(
2426
2466
  assert bundle_add_info.status == MempoolInclusionStatus.SUCCESS
2427
2467
  item = mempool_manager.get_mempool_item(bundle.name())
2428
2468
  assert item is not None
2429
- assert item.bundle_coin_spends[singleton_spend.coin.name()].eligible_for_fast_forward
2430
- assert item.bundle_coin_spends[singleton_spend.coin.name()].latest_singleton_coin == singleton_spend.coin.name()
2469
+ singleton_name = singleton_spend.coin.name()
2470
+ assert item.bundle_coin_spends[singleton_name].eligible_for_fast_forward
2471
+ latest_singleton_lineage = item.bundle_coin_spends[singleton_name].latest_singleton_lineage
2472
+ assert latest_singleton_lineage is not None
2473
+ assert latest_singleton_lineage.coin_id == singleton_name
2431
2474
 
2432
2475
  spent_coins: list[bytes32] = []
2433
2476
 
@@ -2457,7 +2500,9 @@ async def test_new_peak_ff_eviction(
2457
2500
  item = mempool_manager.get_mempool_item(bundle.name())
2458
2501
  assert item is not None
2459
2502
  assert item.bundle_coin_spends[singleton_spend.coin.name()].eligible_for_fast_forward
2460
- assert item.bundle_coin_spends[singleton_spend.coin.name()].latest_singleton_coin == singleton_spend.coin.name()
2503
+ latest_singleton_lineage = item.bundle_coin_spends[singleton_spend.coin.name()].latest_singleton_lineage
2504
+ assert latest_singleton_lineage is not None
2505
+ assert latest_singleton_lineage.coin_id == singleton_spend.coin.name()
2461
2506
 
2462
2507
 
2463
2508
  @pytest.mark.anyio
@@ -2525,9 +2570,11 @@ async def test_multiple_ff(use_optimization: bool) -> None:
2525
2570
  item = mempool_manager.get_mempool_item(bundle.name())
2526
2571
  assert item is not None
2527
2572
  spend = item.bundle_coin_spends[singleton_spend1.coin.name()]
2528
- assert spend.latest_singleton_coin == singleton_spend3.coin.name()
2573
+ assert spend.latest_singleton_lineage is not None
2574
+ assert spend.latest_singleton_lineage.coin_id == singleton_spend3.coin.name()
2529
2575
  spend = item.bundle_coin_spends[singleton_spend2.coin.name()]
2530
- assert spend.latest_singleton_coin == singleton_spend3.coin.name()
2576
+ assert spend.latest_singleton_lineage is not None
2577
+ assert spend.latest_singleton_lineage.coin_id == singleton_spend3.coin.name()
2531
2578
 
2532
2579
 
2533
2580
  @pytest.mark.anyio
@@ -2574,7 +2621,8 @@ async def test_advancing_ff(use_optimization: bool) -> None:
2574
2621
  assert item is not None
2575
2622
  spend = item.bundle_coin_spends[spend_a.coin.name()]
2576
2623
  assert spend.eligible_for_fast_forward
2577
- assert spend.latest_singleton_coin == spend_a.coin.name()
2624
+ assert spend.latest_singleton_lineage is not None
2625
+ assert spend.latest_singleton_lineage.coin_id == spend_a.coin.name()
2578
2626
 
2579
2627
  coins.update_lineage(singleton_ph, spend_b.coin)
2580
2628
  coins.spend_coin(spend_a.coin.name(), uint32(11))
@@ -2585,7 +2633,8 @@ async def test_advancing_ff(use_optimization: bool) -> None:
2585
2633
  assert item is not None
2586
2634
  spend = item.bundle_coin_spends[spend_a.coin.name()]
2587
2635
  assert spend.eligible_for_fast_forward
2588
- assert spend.latest_singleton_coin == spend_b.coin.name()
2636
+ assert spend.latest_singleton_lineage is not None
2637
+ assert spend.latest_singleton_lineage.coin_id == spend_b.coin.name()
2589
2638
 
2590
2639
  coins.update_lineage(singleton_ph, spend_c.coin)
2591
2640
  coins.spend_coin(spend_b.coin.name(), uint32(12))
@@ -2596,12 +2645,313 @@ async def test_advancing_ff(use_optimization: bool) -> None:
2596
2645
  assert item is not None
2597
2646
  spend = item.bundle_coin_spends[spend_a.coin.name()]
2598
2647
  assert spend.eligible_for_fast_forward
2599
- assert spend.latest_singleton_coin == spend_c.coin.name()
2648
+ assert spend.latest_singleton_lineage is not None
2649
+ assert spend.latest_singleton_lineage.coin_id == spend_c.coin.name()
2650
+
2651
+
2652
+ @pytest.mark.parametrize("old", [True, False])
2653
+ def test_no_peak(old: bool, transactions_1000: list[SpendBundle]) -> None:
2654
+ bundles = transactions_1000[:10]
2655
+ all_coins = [s.coin for b in bundles for s in b.coin_spends]
2656
+ coins = TestCoins(all_coins, {})
2657
+
2658
+ mempool_manager = MempoolManager(
2659
+ coins.get_coin_records,
2660
+ coins.get_unspent_lineage_info,
2661
+ DEFAULT_CONSTANTS,
2662
+ )
2663
+
2664
+ create_block = mempool_manager.create_block_generator if old else mempool_manager.create_block_generator2
2665
+
2666
+ assert create_block(bytes32([1] * 32), 10.0) is None
2667
+
2668
+
2669
+ @pytest.fixture(name="test_wallet")
2670
+ def test_wallet_fixture() -> WalletTool:
2671
+ return WalletTool(DEFAULT_CONSTANTS)
2672
+
2673
+
2674
+ @pytest.fixture(name="transactions_1000")
2675
+ def transactions_1000_fixture(test_wallet: WalletTool, seeded_random: random.Random) -> list[SpendBundle]:
2676
+ op = ConditionOpcode
2677
+ bundles: list[SpendBundle] = []
2678
+
2679
+ test_conditions = [
2680
+ op.AGG_SIG_PARENT,
2681
+ op.AGG_SIG_PUZZLE,
2682
+ op.AGG_SIG_AMOUNT,
2683
+ op.AGG_SIG_PUZZLE_AMOUNT,
2684
+ op.AGG_SIG_PARENT_AMOUNT,
2685
+ op.AGG_SIG_PARENT_PUZZLE,
2686
+ op.AGG_SIG_UNSAFE,
2687
+ op.AGG_SIG_ME,
2688
+ op.CREATE_COIN,
2689
+ op.CREATE_COIN_ANNOUNCEMENT,
2690
+ op.CREATE_PUZZLE_ANNOUNCEMENT,
2691
+ op.ASSERT_MY_COIN_ID,
2692
+ op.ASSERT_MY_PARENT_ID,
2693
+ op.ASSERT_MY_PUZZLEHASH,
2694
+ op.ASSERT_MY_AMOUNT,
2695
+ ]
2696
+
2697
+ print("generating 1000 coins and spend bundles")
2698
+ for i in range(1000):
2699
+ # generate a coin with a dummy parent coin ID
2700
+ puzzle = test_wallet.get_new_puzzle()
2701
+ coin = Coin(bytes32(i.to_bytes(32, byteorder="big")), puzzle.get_tree_hash(), uint64(100 * i))
2702
+
2703
+ conditions: dict[ConditionOpcode, list[ConditionWithArgs]] = {
2704
+ ConditionOpcode.CREATE_COIN: [
2705
+ ConditionWithArgs(
2706
+ ConditionOpcode.CREATE_COIN, [test_wallet.get_new_puzzle().get_tree_hash(), int_to_bytes(25 * i)]
2707
+ )
2708
+ ]
2709
+ }
2710
+ # generate a somewhat arbitrarty set of conditions for the spend, just
2711
+ # to have some diversity and make the block interesting
2712
+ num_conditions = seeded_random.randint(0, 10)
2713
+ for c in seeded_random.sample(test_conditions, num_conditions):
2714
+ if c in set(
2715
+ [
2716
+ op.AGG_SIG_PARENT,
2717
+ op.AGG_SIG_PUZZLE,
2718
+ op.AGG_SIG_AMOUNT,
2719
+ op.AGG_SIG_PUZZLE_AMOUNT,
2720
+ op.AGG_SIG_PARENT_AMOUNT,
2721
+ op.AGG_SIG_PARENT_PUZZLE,
2722
+ op.AGG_SIG_UNSAFE,
2723
+ op.AGG_SIG_ME,
2724
+ ]
2725
+ ):
2726
+ secret_key = test_wallet.get_private_key_for_puzzle_hash(coin.puzzle_hash)
2727
+ synthetic_secret_key = calculate_synthetic_secret_key(secret_key, DEFAULT_HIDDEN_PUZZLE_HASH)
2728
+ cond = ConditionWithArgs(c, [bytes(synthetic_secret_key.get_g1()), b"foobar"])
2729
+ elif c == op.CREATE_COIN:
2730
+ cond = ConditionWithArgs(c, [test_wallet.get_new_puzzle().get_tree_hash(), int_to_bytes(i)])
2731
+ elif c in set([op.CREATE_COIN_ANNOUNCEMENT, op.CREATE_PUZZLE_ANNOUNCEMENT]):
2732
+ cond = ConditionWithArgs(c, [b"foobar"])
2733
+ elif c == op.ASSERT_MY_COIN_ID:
2734
+ cond = ConditionWithArgs(c, [coin.name()])
2735
+ elif c == op.ASSERT_MY_PARENT_ID:
2736
+ cond = ConditionWithArgs(c, [coin.parent_coin_info])
2737
+ elif c == op.ASSERT_MY_PUZZLEHASH:
2738
+ cond = ConditionWithArgs(c, [coin.puzzle_hash])
2739
+ elif c == op.ASSERT_MY_AMOUNT:
2740
+ cond = ConditionWithArgs(c, [int_to_bytes(coin.amount)])
2741
+ conditions.setdefault(c, []).append(cond)
2742
+
2743
+ # generate a spend of that coin
2744
+ bundle = test_wallet.generate_signed_transaction(
2745
+ uint64(50 * i), test_wallet.get_new_puzzle().get_tree_hash(), coin, conditions
2746
+ )
2747
+ bundles.append(bundle)
2748
+ return bundles
2749
+
2750
+
2751
+ # if we try to fill the mempool with more than 550, all spends won't
2752
+ # necessarily fit in the block, which the test assumes
2753
+ @pytest.mark.anyio
2754
+ @pytest.mark.parametrize("mempool_size", [1, 2, 100, 300, 400, 550, 730])
2755
+ @pytest.mark.parametrize("seed", [0, 1, 2, 3, 4])
2756
+ @pytest.mark.parametrize("old", [True, False])
2757
+ async def test_create_block_generator(
2758
+ mempool_size: int, seed: int, old: bool, transactions_1000: list[SpendBundle]
2759
+ ) -> None:
2760
+ # the old way of creating bloks doesn't fit this many transactions, so we
2761
+ # expect it to fail
2762
+ expect_failure = mempool_size == 730 and old
2763
+
2764
+ bundles = transactions_1000
2765
+ all_coins = [s.coin for b in bundles for s in b.coin_spends]
2766
+ coins = TestCoins(all_coins, {})
2767
+
2768
+ rng = random.Random(seed)
2769
+
2770
+ # run the test multiple times, generating different combinations of mempools
2771
+ mempool_manager = await setup_mempool(coins)
2772
+
2773
+ included_bundles = rng.sample(bundles, mempool_size)
2774
+ expected_additions: set[Coin] = set()
2775
+ expected_removals: set[Coin] = set()
2776
+ expected_signature = G2Element()
2777
+ for sb in included_bundles:
2778
+ pre_validation = await mempool_manager.pre_validate_spendbundle(sb)
2779
+ bundle_add_info = await mempool_manager.add_spend_bundle(
2780
+ sb, pre_validation, sb.name(), first_added_height=uint32(1)
2781
+ )
2782
+ expected_additions.update(sb.additions())
2783
+ expected_removals.update(sb.removals())
2784
+
2785
+ expected_signature += sb.aggregated_signature
2786
+ assert bundle_add_info.status == MempoolInclusionStatus.SUCCESS
2787
+ item = mempool_manager.get_mempool_item(sb.name())
2788
+ assert item is not None
2789
+ all_items = mempool_manager.mempool.all_items()
2790
+ assert len(list(all_items)) == len(included_bundles)
2791
+
2792
+ invariant_check_mempool(mempool_manager.mempool)
2793
+
2794
+ assert mempool_manager.peak is not None
2795
+ create_block = mempool_manager.create_block_generator if old else mempool_manager.create_block_generator2
2796
+ new_block_gen = create_block(mempool_manager.peak.header_hash, 10.0)
2797
+ assert new_block_gen is not None
2798
+
2799
+ # now, make sure the generator we got is valid
2800
+
2801
+ if expect_failure:
2802
+ assert len(expected_additions) != len(new_block_gen.additions)
2803
+ assert expected_additions != set(new_block_gen.additions)
2804
+ assert len(expected_removals) != len(new_block_gen.removals)
2805
+ assert expected_removals != set(new_block_gen.removals)
2806
+ assert expected_signature != new_block_gen.signature
2807
+ else:
2808
+ assert len(expected_additions) == len(new_block_gen.additions)
2809
+ assert expected_additions == set(new_block_gen.additions)
2810
+ assert len(expected_removals) == len(new_block_gen.removals)
2811
+ assert expected_removals == set(new_block_gen.removals)
2812
+ assert expected_signature == new_block_gen.signature
2813
+
2814
+ err, conds = run_block_generator2(
2815
+ bytes(new_block_gen.program),
2816
+ new_block_gen.generator_refs,
2817
+ DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM,
2818
+ DEFAULT_FLAGS,
2819
+ new_block_gen.signature,
2820
+ None,
2821
+ DEFAULT_CONSTANTS,
2822
+ )
2823
+
2824
+ assert err is None
2825
+ assert conds is not None
2826
+
2827
+ if expect_failure:
2828
+ assert len(conds.spends) != len(expected_removals)
2829
+ else:
2830
+ assert len(conds.spends) == len(expected_removals)
2831
+ assert conds.cost < DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM
2832
+ assert new_block_gen.cost == conds.cost
2833
+
2834
+ num_additions = 0
2835
+ for spend in conds.spends:
2836
+ assert Coin(spend.parent_id, spend.puzzle_hash, uint64(spend.coin_amount)) in expected_removals
2837
+ for add2 in spend.create_coin:
2838
+ assert Coin(spend.coin_id, add2[0], uint64(add2[1])) in expected_additions
2839
+ num_additions += 1
2840
+
2841
+ assert num_additions == len(new_block_gen.additions)
2842
+
2843
+
2844
+ # if we try to fill the mempool with more than 550, all spends won't
2845
+ # necessarily fit in the block, which the test assumes
2846
+ @pytest.mark.anyio
2847
+ @pytest.mark.parametrize("seed", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20])
2848
+ @pytest.mark.parametrize("old", [True, False])
2849
+ async def test_create_block_generator_real_bundles(seed: int, old: bool, test_bundles: list[SpendBundle]) -> None:
2850
+ all_coins = [s.coin for b in test_bundles for s in b.coin_spends]
2851
+ coins = TestCoins(all_coins, {})
2852
+
2853
+ rng = random.Random(seed)
2854
+
2855
+ mempool_manager = await setup_mempool(coins)
2856
+
2857
+ included_bundles = rng.sample(test_bundles, len(test_bundles) // 5)
2858
+ for sb in included_bundles:
2859
+ pre_validation = await mempool_manager.pre_validate_spendbundle(sb)
2860
+ bundle_add_info = await mempool_manager.add_spend_bundle(
2861
+ sb, pre_validation, sb.name(), first_added_height=uint32(1)
2862
+ )
2863
+
2864
+ # in the test bundles, we have some duplicate spends
2865
+ # just ignore them for now
2866
+ if bundle_add_info.status == MempoolInclusionStatus.FAILED:
2867
+ assert bundle_add_info.error == Err.DOUBLE_SPEND
2868
+ continue
2869
+ assert bundle_add_info.status == MempoolInclusionStatus.SUCCESS
2870
+ item = mempool_manager.get_mempool_item(sb.name())
2871
+ assert item is not None
2872
+
2873
+ invariant_check_mempool(mempool_manager.mempool)
2874
+
2875
+ assert mempool_manager.peak is not None
2876
+ create_block = mempool_manager.create_block_generator if old else mempool_manager.create_block_generator2
2877
+ new_block_gen = create_block(mempool_manager.peak.header_hash, 10.0)
2878
+ assert new_block_gen is not None
2879
+
2880
+ # now, make sure the generator we got is valid
2881
+
2882
+ err, conds = run_block_generator2(
2883
+ bytes(new_block_gen.program),
2884
+ new_block_gen.generator_refs,
2885
+ DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM,
2886
+ DEFAULT_FLAGS,
2887
+ new_block_gen.signature,
2888
+ None,
2889
+ DEFAULT_CONSTANTS,
2890
+ )
2891
+
2892
+ assert err is None
2893
+ assert conds is not None
2894
+
2895
+ assert conds.cost == new_block_gen.cost
2896
+
2897
+ removals: set[Coin] = set()
2898
+ additions: set[Coin] = set()
2899
+
2900
+ for spend in conds.spends:
2901
+ removals.add(Coin(spend.parent_id, spend.puzzle_hash, uint64(spend.coin_amount)))
2902
+ for add in spend.create_coin:
2903
+ additions.add(Coin(spend.coin_id, add[0], uint64(add[1])))
2904
+
2905
+ assert removals == set(new_block_gen.removals)
2906
+ assert additions == set(new_block_gen.additions)
2907
+
2908
+
2909
+ @pytest.mark.anyio
2910
+ async def test_spending_singleton_to_invalidate_existing_ff_spends() -> None:
2911
+ """
2912
+ This test covers the scenario where we attempt to add a transaction to the
2913
+ mempool that contains a singleton that is spent in a way that tries to
2914
+ invalidate existing fast forward spends from existing items in the mempool.
2915
+ """
2916
+ LAUNCHER_ID = bytes32([1] * 32)
2917
+ PARENT_PARENT = bytes32([2] * 32)
2918
+ singleton_spend1 = make_singleton_spend(LAUNCHER_ID, PARENT_PARENT)
2919
+ # This differs in the child amount
2920
+ singleton_spend2 = make_singleton_spend(LAUNCHER_ID, PARENT_PARENT, child_amount=3)
2921
+ coins = TestCoins(
2922
+ coins=[singleton_spend1.coin, singleton_spend2.coin, TEST_COIN, TEST_COIN2],
2923
+ lineage={singleton_spend2.coin.puzzle_hash: singleton_spend2.coin},
2924
+ )
2925
+ mempool_manager = await setup_mempool(coins)
2926
+ coin_spend1 = make_spend(
2927
+ TEST_COIN, IDENTITY_PUZZLE, Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 42]])
2928
+ )
2929
+ sb1 = SpendBundle([singleton_spend1, coin_spend1], G2Element())
2930
+ sb1_conds = make_test_conds(spend_ids=[(singleton_spend1.coin, ELIGIBLE_FOR_FF), (TEST_COIN, 0)], cost=100_000_000)
2931
+ bundle_add_info1 = await mempool_manager.add_spend_bundle(sb1, sb1_conds, sb1.name(), uint32(1))
2932
+ assert bundle_add_info1.status == MempoolInclusionStatus.SUCCESS
2933
+ invariant_check_mempool(mempool_manager.mempool)
2934
+ # Trying to spend the same singleton with a different child amount should
2935
+ # trigger a conflict on any replace by fee attempt.
2936
+ coin_spend2 = make_spend(
2937
+ TEST_COIN2, IDENTITY_PUZZLE, Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 42]])
2938
+ )
2939
+ sb2 = SpendBundle([singleton_spend2, coin_spend1, coin_spend2], G2Element())
2940
+ # This singleton spend is not eligible for fast forward as its next
2941
+ # iteration has a different amount.
2942
+ sb2_conds = make_test_conds(spend_ids=[(singleton_spend2.coin, 0), (TEST_COIN, 0), (TEST_COIN2, 0)], cost=1337)
2943
+ # This transaction conflicts with the previous one no matter what fee you
2944
+ # pay, because we're changing the fast forward eligibility flag for the
2945
+ # singleton spend.
2946
+ bundle_add_info2 = await mempool_manager.add_spend_bundle(sb2, sb2_conds, sb2.name(), uint32(1))
2947
+ assert bundle_add_info2.error == Err.MEMPOOL_CONFLICT
2948
+ assert bundle_add_info2.status == MempoolInclusionStatus.PENDING
2600
2949
 
2601
2950
 
2602
2951
  @pytest.mark.parametrize("flags", [ELIGIBLE_FOR_DEDUP, ELIGIBLE_FOR_FF, ELIGIBLE_FOR_FF | ELIGIBLE_FOR_DEDUP])
2952
+ @pytest.mark.parametrize("old", [True, False])
2603
2953
  @pytest.mark.anyio
2604
- async def test_check_removals_with_block_creation(flags: int) -> None:
2954
+ async def test_check_removals_with_block_creation(flags: int, old: bool) -> None:
2605
2955
  LAUNCHER_ID = bytes32([1] * 32)
2606
2956
  PARENT_PARENT = bytes32([2] * 32)
2607
2957
  singleton_spend = make_singleton_spend(LAUNCHER_ID, PARENT_PARENT)
@@ -2630,13 +2980,15 @@ async def test_check_removals_with_block_creation(flags: int) -> None:
2630
2980
  bundle_add_info2 = await mempool_manager.add_spend_bundle(sb2, sb2_conds, sb2.name(), uint32(1))
2631
2981
  assert bundle_add_info2.status == MempoolInclusionStatus.SUCCESS
2632
2982
  assert mempool_manager.peak is not None
2633
- block_generator = await mempool_manager.create_block_generator(mempool_manager.peak.header_hash)
2634
- assert block_generator is not None
2635
- _, _, additions, removals = block_generator
2636
- assert len(additions) == 1
2637
- assert set(additions) == {Coin(singleton_spend.coin.name(), singleton_spend.coin.puzzle_hash, uint64(1))}
2638
- assert len(removals) == 2
2639
- assert set(removals) == {singleton_spend.coin, TEST_COIN}
2983
+ create_block = mempool_manager.create_block_generator if old else mempool_manager.create_block_generator2
2984
+ new_block_gen = create_block(mempool_manager.peak.header_hash, 10.0)
2985
+ assert new_block_gen is not None
2986
+ assert len(new_block_gen.additions) == 1
2987
+ assert set(new_block_gen.additions) == {
2988
+ Coin(singleton_spend.coin.name(), singleton_spend.coin.puzzle_hash, uint64(1))
2989
+ }
2990
+ assert len(new_block_gen.removals) == 2
2991
+ assert set(new_block_gen.removals) == {singleton_spend.coin, TEST_COIN}
2640
2992
 
2641
2993
 
2642
2994
  @pytest.mark.anyio