chia-blockchain 2.5.4rc2__py3-none-any.whl → 2.5.5__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 +529 -69
  63. chia/_tests/core/mempool/test_mempool_performance.py +3 -2
  64. chia/_tests/core/mempool/test_singleton_fast_forward.py +61 -132
  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 +153 -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 +47 -45
  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.5.dist-info}/METADATA +7 -7
  424. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5.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.5.dist-info}/LICENSE +0 -0
  452. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5.dist-info}/WHEEL +0 -0
  453. {chia_blockchain-2.5.4rc2.dist-info → chia_blockchain-2.5.5.dist-info}/entry_points.txt +0 -0
@@ -5,31 +5,31 @@ from dataclasses import dataclass
5
5
  from pathlib import Path
6
6
  from typing import Optional
7
7
 
8
+ import aiosqlite
8
9
  import pytest
10
+ from chia_rs import CoinState, FullBlock, additions_and_removals, get_flags_for_height_and_constants
9
11
  from chia_rs.sized_bytes import bytes32
10
12
  from chia_rs.sized_ints import uint32, uint64
11
- from clvm.casts import int_to_bytes
12
13
 
13
14
  from chia._tests.blockchain.blockchain_test_utils import _validate_and_add_block
15
+ from chia._tests.util.coin_store import add_coin_records_to_db
14
16
  from chia._tests.util.db_connection import DBConnection
15
- from chia._tests.util.get_name_puzzle_conditions import get_name_puzzle_conditions
16
17
  from chia._tests.util.misc import Marks, datacases
17
18
  from chia.consensus.block_body_validation import ForkInfo
18
19
  from chia.consensus.block_rewards import calculate_base_farmer_reward, calculate_pool_reward
19
20
  from chia.consensus.blockchain import AddBlockResult, Blockchain
20
21
  from chia.consensus.coinbase import create_farmer_coin, create_pool_coin
22
+ from chia.full_node.block_height_map import BlockHeightMap
21
23
  from chia.full_node.block_store import BlockStore
22
24
  from chia.full_node.coin_store import CoinStore
23
25
  from chia.full_node.hint_store import HintStore
24
- from chia.protocols.wallet_protocol import CoinState
25
26
  from chia.simulator.block_tools import BlockTools, test_constants
26
27
  from chia.simulator.wallet_tools import WalletTool
27
28
  from chia.types.blockchain_format.coin import Coin
28
29
  from chia.types.coin_record import CoinRecord
29
- from chia.types.eligible_coin_spends import UnspentLineageInfo
30
- from chia.types.full_block import FullBlock
31
- from chia.types.generator_types import BlockGenerator
32
- from chia.util.generator_tools import tx_removals_and_additions
30
+ from chia.types.mempool_item import UnspentLineageInfo
31
+ from chia.util.casts import int_to_bytes
32
+ from chia.util.db_wrapper import DBWrapper2
33
33
  from chia.util.hash import std_hash
34
34
 
35
35
  constants = test_constants
@@ -98,75 +98,73 @@ async def test_basic_coin_store(db_version: int, softfork_height: uint32, bt: Bl
98
98
  farmer_coin, pool_coin = get_future_reward_coins(block)
99
99
  should_be_included.add(farmer_coin)
100
100
  should_be_included.add(pool_coin)
101
- if block.is_transaction_block():
102
- if block.transactions_generator is not None:
103
- assert block.transactions_info is not None
104
- block_gen: BlockGenerator = BlockGenerator(block.transactions_generator, [])
105
- npc_result = get_name_puzzle_conditions(
106
- block_gen,
107
- bt.constants.MAX_BLOCK_COST_CLVM,
108
- mempool_mode=False,
109
- height=softfork_height,
110
- constants=bt.constants,
111
- )
112
- tx_removals, tx_additions = tx_removals_and_additions(npc_result.conds)
113
- else:
114
- tx_removals, tx_additions = [], []
115
-
116
- assert set(block.get_included_reward_coins()) == should_be_included_prev
101
+ if not block.is_transaction_block():
102
+ continue
103
+ if block.transactions_generator is not None:
104
+ assert block.transactions_info is not None
105
+ flags = get_flags_for_height_and_constants(block.height, bt.constants)
106
+ additions, removals = additions_and_removals(
107
+ bytes(block.transactions_generator), [], flags, bt.constants
108
+ )
109
+ tx_removals = [name for name, _ in removals]
110
+ tx_additions = [(addition.name(), addition, False) for addition, _ in additions]
111
+ else:
112
+ tx_removals, tx_additions = [], []
113
+
114
+ reward_coins = block.get_included_reward_coins()
115
+ assert set(reward_coins) == should_be_included_prev
116
+
117
+ assert block.foliage_transaction_block is not None
118
+ await coin_store.new_block(
119
+ block.height,
120
+ block.foliage_transaction_block.timestamp,
121
+ reward_coins,
122
+ tx_additions,
123
+ tx_removals,
124
+ )
117
125
 
118
- if block.is_transaction_block():
119
- assert block.foliage_transaction_block is not None
126
+ if block.height != 0:
127
+ with pytest.raises(Exception):
120
128
  await coin_store.new_block(
121
129
  block.height,
122
130
  block.foliage_transaction_block.timestamp,
123
- block.get_included_reward_coins(),
131
+ reward_coins,
124
132
  tx_additions,
125
133
  tx_removals,
126
134
  )
127
135
 
128
- if block.height != 0:
129
- with pytest.raises(Exception):
130
- await coin_store.new_block(
131
- block.height,
132
- block.foliage_transaction_block.timestamp,
133
- block.get_included_reward_coins(),
134
- tx_additions,
135
- tx_removals,
136
- )
137
-
138
- all_records = set()
139
- for expected_coin in should_be_included_prev:
140
- # Check that the coinbase rewards are added
141
- record = await coin_store.get_coin_record(expected_coin.name())
142
- assert record is not None
143
- assert not record.spent
144
- assert record.coin == expected_coin
145
- all_records.add(record)
146
- for coin_name in tx_removals:
147
- # Check that the removed coins are set to spent
148
- record = await coin_store.get_coin_record(coin_name)
149
- assert record is not None
150
- assert record.spent
151
- all_records.add(record)
152
- for coin in tx_additions:
153
- # Check that the added coins are added
154
- record = await coin_store.get_coin_record(coin.name())
155
- assert record is not None
156
- assert not record.spent
157
- assert coin == record.coin
158
- all_records.add(record)
159
-
160
- db_records = await coin_store.get_coin_records(
161
- [c.name() for c in list(should_be_included_prev) + tx_additions] + tx_removals
162
- )
163
- assert len(db_records) == len(should_be_included_prev) + len(tx_removals) + len(tx_additions)
164
- assert len(db_records) == len(all_records)
165
- for record in db_records:
166
- assert record in all_records
136
+ all_records = set()
137
+ for expected_coin in should_be_included_prev:
138
+ # Check that the coinbase rewards are added
139
+ record = await coin_store.get_coin_record(expected_coin.name())
140
+ assert record is not None
141
+ assert not record.spent
142
+ assert record.coin == expected_coin
143
+ all_records.add(record)
144
+ for coin_name in tx_removals:
145
+ # Check that the removed coins are set to spent
146
+ record = await coin_store.get_coin_record(coin_name)
147
+ assert record is not None
148
+ assert record.spent
149
+ all_records.add(record)
150
+ for coin_id, coin, _ in tx_additions:
151
+ # Check that the added coins are added
152
+ record = await coin_store.get_coin_record(coin_id)
153
+ assert record is not None
154
+ assert not record.spent
155
+ assert coin == record.coin
156
+ all_records.add(record)
157
+
158
+ db_records = await coin_store.get_coin_records(
159
+ [c.name() for c in should_be_included_prev] + [coin_id for coin_id, _, _ in tx_additions] + tx_removals
160
+ )
161
+ assert len(db_records) == len(should_be_included_prev) + len(tx_removals) + len(tx_additions)
162
+ assert len(db_records) == len(all_records)
163
+ for record in db_records:
164
+ assert record in all_records
167
165
 
168
- should_be_included_prev = should_be_included.copy()
169
- should_be_included = set()
166
+ should_be_included_prev = should_be_included.copy()
167
+ should_be_included = set()
170
168
 
171
169
 
172
170
  @pytest.mark.limit_consensus_modes(reason="save time")
@@ -179,39 +177,31 @@ async def test_set_spent(db_version: int, bt: BlockTools) -> None:
179
177
 
180
178
  # Save/get block
181
179
  for block in blocks:
182
- if block.is_transaction_block():
183
- removals: list[bytes32] = []
184
- additions: list[Coin] = []
185
- async with db_wrapper.writer():
186
- if block.is_transaction_block():
187
- assert block.foliage_transaction_block is not None
188
- await coin_store.new_block(
189
- block.height,
190
- block.foliage_transaction_block.timestamp,
191
- block.get_included_reward_coins(),
192
- additions,
193
- removals,
194
- )
195
-
196
- coins = block.get_included_reward_coins()
197
- records = [await coin_store.get_coin_record(coin.name()) for coin in coins]
180
+ if not block.is_transaction_block():
181
+ continue
182
+ assert block.foliage_transaction_block is not None
183
+ await coin_store.new_block(
184
+ block.height, block.foliage_transaction_block.timestamp, block.get_included_reward_coins(), [], []
185
+ )
186
+ coins = block.get_included_reward_coins()
187
+ records = [await coin_store.get_coin_record(coin.name()) for coin in coins]
198
188
 
199
- await coin_store._set_spent([r.name for r in records if r is not None], block.height)
189
+ await coin_store._set_spent([r.name for r in records if r is not None], block.height)
200
190
 
201
- if len(records) > 0:
202
- for r in records:
203
- assert r is not None
204
- assert (await coin_store.get_coin_record(r.name)) is not None
191
+ if len(records) > 0:
192
+ for r in records:
193
+ assert r is not None
194
+ assert (await coin_store.get_coin_record(r.name)) is not None
205
195
 
206
- # Check that we can't spend a coin twice in DB
207
- with pytest.raises(ValueError, match="Invalid operation to set spent"):
208
- await coin_store._set_spent([r.name for r in records if r is not None], block.height)
196
+ # Check that we can't spend a coin twice in DB
197
+ with pytest.raises(ValueError, match="Invalid operation to set spent"):
198
+ await coin_store._set_spent([r.name for r in records if r is not None], block.height)
209
199
 
210
- records = [await coin_store.get_coin_record(coin.name()) for coin in coins]
211
- for record in records:
212
- assert record is not None
213
- assert record.spent
214
- assert record.spent_block_index == block.height
200
+ records = [await coin_store.get_coin_record(coin.name()) for coin in coins]
201
+ for record in records:
202
+ assert record is not None
203
+ assert record.spent
204
+ assert record.spent_block_index == block.height
215
205
 
216
206
 
217
207
  @pytest.mark.limit_consensus_modes(reason="save time")
@@ -228,22 +218,12 @@ async def test_num_unspent(bt: BlockTools, db_version: int) -> None:
228
218
  for block in blocks:
229
219
  if not block.is_transaction_block():
230
220
  continue
231
-
232
- if block.is_transaction_block():
233
- assert block.foliage_transaction_block is not None
234
- removals: list[bytes32] = []
235
- additions: list[Coin] = []
236
- await coin_store.new_block(
237
- block.height,
238
- block.foliage_transaction_block.timestamp,
239
- block.get_included_reward_coins(),
240
- additions,
241
- removals,
242
- )
243
-
244
- expect_unspent += len(block.get_included_reward_coins())
245
- assert await coin_store.num_unspent() == expect_unspent
246
- test_excercised = expect_unspent > 0
221
+ assert block.foliage_transaction_block is not None
222
+ reward_coins = block.get_included_reward_coins()
223
+ await coin_store.new_block(block.height, block.foliage_transaction_block.timestamp, reward_coins, [], [])
224
+ expect_unspent += len(reward_coins)
225
+ assert await coin_store.num_unspent() == expect_unspent
226
+ test_excercised = expect_unspent > 0
247
227
 
248
228
  assert test_excercised
249
229
 
@@ -260,48 +240,41 @@ async def test_rollback(db_version: int, bt: BlockTools) -> None:
260
240
  all_coins: list[Coin] = []
261
241
 
262
242
  for block in blocks:
263
- all_coins += list(block.get_included_reward_coins())
264
- if block.is_transaction_block():
265
- removals: list[bytes32] = []
266
- additions: list[Coin] = []
267
- assert block.foliage_transaction_block is not None
268
- await coin_store.new_block(
269
- block.height,
270
- block.foliage_transaction_block.timestamp,
271
- block.get_included_reward_coins(),
272
- additions,
273
- removals,
274
- )
275
- coins = block.get_included_reward_coins()
276
- records = [await coin_store.get_coin_record(coin.name()) for coin in coins]
277
-
278
- spend_selected_coin = selected_coin is not None
279
- if block.height != 0 and selected_coin is None:
280
- # Select the first CoinRecord which will be spent at the next transaction block.
281
- selected_coin = records[0]
282
- await coin_store._set_spent([r.name for r in records[1:] if r is not None], block.height)
283
- else:
284
- await coin_store._set_spent([r.name for r in records if r is not None], block.height)
285
-
286
- if spend_selected_coin:
287
- assert selected_coin is not None
288
- await coin_store._set_spent([selected_coin.name], block.height)
243
+ if not block.is_transaction_block():
244
+ continue
245
+ assert block.foliage_transaction_block is not None
246
+ reward_coins = block.get_included_reward_coins()
247
+ all_coins += reward_coins
248
+ await coin_store.new_block(block.height, block.foliage_transaction_block.timestamp, reward_coins, [], [])
249
+ records = [await coin_store.get_coin_record(coin.name()) for coin in reward_coins]
250
+
251
+ spend_selected_coin = selected_coin is not None
252
+ if block.height != 0 and selected_coin is None:
253
+ # Select the first CoinRecord which will be spent at the next transaction block.
254
+ selected_coin = records[0]
255
+ await coin_store._set_spent([r.name for r in records[1:] if r is not None], block.height)
256
+ else:
257
+ await coin_store._set_spent([r.name for r in records if r is not None], block.height)
289
258
 
290
- records = [await coin_store.get_coin_record(coin.name()) for coin in coins] # update coin records
291
- for record in records:
292
- assert record is not None
293
- if (
294
- selected_coin is not None
295
- and selected_coin.name == record.name
296
- and not selected_coin.confirmed_block_index < block.height
297
- ):
298
- assert not record.spent
299
- else:
300
- assert record.spent
301
- assert record.spent_block_index == block.height
259
+ if spend_selected_coin:
260
+ assert selected_coin is not None
261
+ await coin_store._set_spent([selected_coin.name], block.height)
262
+
263
+ records = [await coin_store.get_coin_record(coin.name()) for coin in reward_coins] # update coin records
264
+ for record in records:
265
+ assert record is not None
266
+ if (
267
+ selected_coin is not None
268
+ and selected_coin.name == record.name
269
+ and not selected_coin.confirmed_block_index < block.height
270
+ ):
271
+ assert not record.spent
272
+ else:
273
+ assert record.spent
274
+ assert record.spent_block_index == block.height
302
275
 
303
- if spend_selected_coin:
304
- break
276
+ if spend_selected_coin:
277
+ break
305
278
 
306
279
  assert selected_coin is not None
307
280
  reorg_index = selected_coin.confirmed_block_index
@@ -311,28 +284,29 @@ async def test_rollback(db_version: int, bt: BlockTools) -> None:
311
284
 
312
285
  # The reorg will revert the creation and spend of many coins. It will also revert the spend (but not the
313
286
  # creation) of the selected coin.
314
- changed_records = await coin_store.rollback_to_block(reorg_index)
315
- changed_coin_records = [cr.coin for cr in changed_records]
316
- assert selected_coin in changed_records
287
+ coin_changes = await coin_store.rollback_to_block(reorg_index)
288
+ changed_coins = {cr.coin for cr in coin_changes.values()}
289
+ assert selected_coin.coin in changed_coins
317
290
  for coin_record in all_records:
318
291
  assert coin_record is not None
319
292
  if coin_record.confirmed_block_index > reorg_index:
320
- assert coin_record.coin in changed_coin_records
293
+ assert coin_record.coin in changed_coins
321
294
  if coin_record.spent_block_index > reorg_index:
322
- assert coin_record.coin in changed_coin_records
295
+ assert coin_record.coin in changed_coins
323
296
 
324
297
  for block in blocks:
325
- if block.is_transaction_block():
326
- coins = block.get_included_reward_coins()
327
- records = [await coin_store.get_coin_record(coin.name()) for coin in coins]
298
+ if not block.is_transaction_block():
299
+ continue
300
+ reward_coins = block.get_included_reward_coins()
301
+ records = [await coin_store.get_coin_record(coin.name()) for coin in reward_coins]
328
302
 
329
- if block.height <= reorg_index:
330
- for record in records:
331
- assert record is not None
332
- assert record.spent == (record.name != selected_coin.name)
333
- else:
334
- for record in records:
335
- assert record is None
303
+ if block.height <= reorg_index:
304
+ for record in records:
305
+ assert record is not None
306
+ assert record.spent == (record.name != selected_coin.name)
307
+ else:
308
+ for record in records:
309
+ assert record is None
336
310
 
337
311
 
338
312
  @pytest.mark.anyio
@@ -343,7 +317,8 @@ async def test_basic_reorg(tmp_dir: Path, db_version: int, bt: BlockTools) -> No
343
317
  blocks = bt.get_consecutive_blocks(initial_block_count)
344
318
  coin_store = await CoinStore.create(db_wrapper)
345
319
  store = await BlockStore.create(db_wrapper)
346
- b: Blockchain = await Blockchain.create(coin_store, store, bt.constants, tmp_dir, 2)
320
+ height_map = await BlockHeightMap.create(tmp_dir, db_wrapper)
321
+ b: Blockchain = await Blockchain.create(coin_store, store, height_map, bt.constants, 2)
347
322
  try:
348
323
  records: list[Optional[CoinRecord]] = []
349
324
 
@@ -409,7 +384,8 @@ async def test_get_puzzle_hash(tmp_dir: Path, db_version: int, bt: BlockTools) -
409
384
  )
410
385
  coin_store = await CoinStore.create(db_wrapper)
411
386
  store = await BlockStore.create(db_wrapper)
412
- b: Blockchain = await Blockchain.create(coin_store, store, bt.constants, tmp_dir, 2)
387
+ height_map = await BlockHeightMap.create(tmp_dir, db_wrapper)
388
+ b: Blockchain = await Blockchain.create(coin_store, store, height_map, bt.constants, 2)
413
389
  for block in blocks:
414
390
  await _validate_and_add_block(b, block)
415
391
  peak = b.get_peak()
@@ -449,7 +425,7 @@ async def test_get_coin_states(db_version: int) -> None:
449
425
  for i in range(1, 301)
450
426
  ]
451
427
  coin_store = await CoinStore.create(db_wrapper)
452
- await coin_store._add_coin_records(crs)
428
+ await add_coin_records_to_db(coin_store, crs)
453
429
 
454
430
  assert len(await coin_store.get_coin_states_by_puzzle_hashes(True, {std_hash(b"2")}, uint32(0))) == 300
455
431
  assert len(await coin_store.get_coin_states_by_puzzle_hashes(False, {std_hash(b"2")}, uint32(0))) == 0
@@ -577,7 +553,7 @@ async def test_coin_state_batches(
577
553
  coin_store = await CoinStore.create(db_wrapper)
578
554
  hint_store = await HintStore.create(db_wrapper)
579
555
 
580
- await coin_store._add_coin_records(random_coin_records.items)
556
+ await add_coin_records_to_db(coin_store, random_coin_records.items)
581
557
  await hint_store.add_hints(random_coin_records.hints)
582
558
 
583
559
  # Make sure all of the coin states are found when batching.
@@ -671,7 +647,7 @@ async def test_batch_many_coin_states(db_version: int, cut_off_middle: bool) ->
671
647
  coin_store = await CoinStore.create(db_wrapper)
672
648
  await HintStore.create(db_wrapper)
673
649
 
674
- await coin_store._add_coin_records(coin_records)
650
+ await add_coin_records_to_db(coin_store, coin_records)
675
651
 
676
652
  # Make sure all of the coin states are found.
677
653
  (all_coin_states, next_height) = await coin_store.batch_coin_states_by_puzzle_hashes([ph])
@@ -684,7 +660,8 @@ async def test_batch_many_coin_states(db_version: int, cut_off_middle: bool) ->
684
660
  assert coin_records[i].coin.name().hex() == all_coin_states[i].coin.name().hex(), i
685
661
 
686
662
  # For the middle case, insert a coin record between the two heights 10 and 12.
687
- await coin_store._add_coin_records(
663
+ await add_coin_records_to_db(
664
+ coin_store,
688
665
  [
689
666
  CoinRecord(
690
667
  coin=Coin(std_hash(b"extra coin"), ph, uint64(0)),
@@ -695,7 +672,7 @@ async def test_batch_many_coin_states(db_version: int, cut_off_middle: bool) ->
695
672
  coinbase=False,
696
673
  timestamp=uint64(0),
697
674
  )
698
- ]
675
+ ],
699
676
  )
700
677
 
701
678
  (all_coin_states, next_height) = await coin_store.batch_coin_states_by_puzzle_hashes([ph])
@@ -732,7 +709,7 @@ async def test_duplicate_by_hint(db_version: int) -> None:
732
709
  uint64(12321312),
733
710
  )
734
711
 
735
- await coin_store._add_coin_records([cr])
712
+ await add_coin_records_to_db(coin_store, [cr])
736
713
  await hint_store.add_hints([(cr.coin.name(), cr.coin.puzzle_hash)])
737
714
 
738
715
  coin_states, height = await coin_store.batch_coin_states_by_puzzle_hashes([cr.coin.puzzle_hash])
@@ -763,7 +740,7 @@ class UnspentLineageInfoTestItem:
763
740
  puzzlehash: bytes
764
741
  amount: int
765
742
  parent_id: bytes
766
- is_spent: bool = False
743
+ spent_index: int = 0
767
744
 
768
745
 
769
746
  @dataclass
@@ -783,7 +760,7 @@ class UnspentLineageInfoCase:
783
760
  UnspentLineageInfoTestItem(TEST_COIN_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_ID),
784
761
  UnspentLineageInfoTestItem(b"2" * 32, b"2" * 32, 2, b"1" * 32),
785
762
  UnspentLineageInfoTestItem(b"3" * 32, b"3" * 32, 3, b"2" * 32),
786
- UnspentLineageInfoTestItem(TEST_PARENT_ID, b"4" * 32, TEST_AMOUNT, TEST_PARENT_PARENT_ID, is_spent=True),
763
+ UnspentLineageInfoTestItem(TEST_PARENT_ID, b"4" * 32, TEST_AMOUNT, TEST_PARENT_PARENT_ID, spent_index=1),
787
764
  ],
788
765
  expected_success=False,
789
766
  ),
@@ -798,11 +775,11 @@ class UnspentLineageInfoCase:
798
775
  TEST_PUZZLEHASH,
799
776
  TEST_PARENT_DIFFERENT_AMOUNT,
800
777
  TEST_PARENT_PARENT_ID,
801
- is_spent=True,
778
+ spent_index=1,
802
779
  ),
803
780
  ],
804
781
  parent_with_diff_amount=True,
805
- expected_success=True,
782
+ expected_success=False,
806
783
  ),
807
784
  UnspentLineageInfoCase(
808
785
  id="Unspent with parent that has same puzzlehash and amount but is also unspent",
@@ -821,7 +798,7 @@ class UnspentLineageInfoCase:
821
798
  UnspentLineageInfoTestItem(b"2" * 32, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_ID),
822
799
  UnspentLineageInfoTestItem(b"3" * 32, b"3" * 32, 3, b"2" * 32),
823
800
  UnspentLineageInfoTestItem(
824
- TEST_PARENT_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_PARENT_ID, is_spent=True
801
+ TEST_PARENT_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_PARENT_ID, spent_index=1
825
802
  ),
826
803
  ],
827
804
  expected_success=False,
@@ -829,11 +806,11 @@ class UnspentLineageInfoCase:
829
806
  UnspentLineageInfoCase(
830
807
  id="Unspent with parent that has same puzzlehash and amount",
831
808
  items=[
832
- UnspentLineageInfoTestItem(TEST_COIN_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_ID),
809
+ UnspentLineageInfoTestItem(TEST_COIN_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_ID, spent_index=-1),
833
810
  UnspentLineageInfoTestItem(b"2" * 32, b"2" * 32, 2, b"1" * 32),
834
811
  UnspentLineageInfoTestItem(b"3" * 32, b"3" * 32, 3, b"2" * 32),
835
812
  UnspentLineageInfoTestItem(
836
- TEST_PARENT_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_PARENT_ID, is_spent=True
813
+ TEST_PARENT_ID, TEST_PUZZLEHASH, TEST_AMOUNT, TEST_PARENT_PARENT_ID, spent_index=1
837
814
  ),
838
815
  ],
839
816
  expected_success=True,
@@ -858,7 +835,7 @@ async def test_get_unspent_lineage_info_for_puzzle_hash(case: UnspentLineageInfo
858
835
  (
859
836
  item.coin_id,
860
837
  0,
861
- 1 if item.is_spent else 0,
838
+ item.spent_index,
862
839
  0,
863
840
  item.puzzlehash,
864
841
  item.parent_id,
@@ -884,14 +861,129 @@ async def test_get_unspent_lineage_info_for_puzzle_hash(case: UnspentLineageInfo
884
861
  if case.expected_success:
885
862
  assert result == UnspentLineageInfo(
886
863
  coin_id=bytes32(TEST_COIN_ID),
887
- coin_amount=TEST_AMOUNT,
888
864
  parent_id=(
889
865
  bytes32(TEST_PARENT_ID_DIFFERENT_AMOUNT)
890
866
  if case.parent_with_diff_amount
891
867
  else bytes32(TEST_PARENT_ID)
892
868
  ),
893
- parent_amount=TEST_PARENT_DIFFERENT_AMOUNT if case.parent_with_diff_amount else TEST_AMOUNT,
894
869
  parent_parent_id=bytes32(TEST_PARENT_PARENT_ID),
895
870
  )
896
871
  else:
897
872
  assert result is None
873
+
874
+
875
+ @pytest.mark.anyio
876
+ async def test_add_coin_records_to_db() -> None:
877
+ async with DBConnection(2) as db_wrapper:
878
+ coin_store = await CoinStore.create(db_wrapper)
879
+ test_records = [
880
+ CoinRecord(
881
+ coin=Coin(bytes32([i * 2] * 32), bytes32([i * 2 + 1] * 32), uint64(i)),
882
+ confirmed_block_index=uint32(i + 1),
883
+ spent_block_index=uint32(i),
884
+ coinbase=i % 2 == 0,
885
+ timestamp=uint64(i),
886
+ )
887
+ for i in range(5)
888
+ ]
889
+ await add_coin_records_to_db(coin_store, test_records)
890
+ # Verify all records got inserted correctly
891
+ for record in test_records:
892
+ resulting_record = await coin_store.get_coin_record(record.coin.name())
893
+ assert resulting_record is not None
894
+ assert resulting_record == record
895
+
896
+
897
+ async def get_spent_index(conn: aiosqlite.Connection, coin_name: bytes32) -> int:
898
+ cursor = await conn.execute("SELECT spent_index FROM coin_record WHERE coin_name = ?", (coin_name,))
899
+ row = await cursor.fetchone()
900
+ assert row is not None
901
+ return int(row[0])
902
+
903
+
904
+ @pytest.mark.anyio
905
+ async def test_new_block_tx_additions() -> None:
906
+ """
907
+ Covers properly adding coin records for normal unspent coins and potential
908
+ fast forward singleton unspent coins. That means giving them spent index 0
909
+ and -1 respectively.
910
+ """
911
+ async with DBConnection(2) as db_wrapper:
912
+ coin_store = await CoinStore.create(db_wrapper)
913
+ normal_coin = Coin(bytes32([0] * 32), bytes32([0] * 32), uint64(1))
914
+ normal_coin_id = normal_coin.name()
915
+ same_as_parent_coin = Coin(bytes32([0] * 32), bytes32([0] * 32), uint64(1337))
916
+ same_as_parent_coin_id = same_as_parent_coin.name()
917
+ await coin_store.new_block(
918
+ height=uint32(0),
919
+ timestamp=uint64(1),
920
+ included_reward_coins=[],
921
+ tx_additions=[
922
+ (normal_coin_id, normal_coin, False),
923
+ (same_as_parent_coin_id, same_as_parent_coin, True),
924
+ ],
925
+ tx_removals=[],
926
+ )
927
+ async with db_wrapper.reader_no_transaction() as conn:
928
+ # Normal coin should have spent_index 0
929
+ assert await get_spent_index(conn, normal_coin_id) == 0
930
+ # Potential ff singleton should have spent_index -1
931
+ assert await get_spent_index(conn, same_as_parent_coin_id) == -1
932
+
933
+
934
+ @pytest.mark.anyio
935
+ async def test_rollback_to_block_spent_index_update() -> None:
936
+ """
937
+ Covers properly marking coins as unspent on rollback. Reward coins and
938
+ normal coins get `spent_index` set to `0`, potential ff singleton ones get
939
+ `spent_index` set to `-1`.
940
+ """
941
+
942
+ async def insert_coins(db_wrapper: DBWrapper2, coins: list[tuple[Coin, int, bool]]) -> None:
943
+ values_to_insert = [
944
+ (
945
+ coin.name(),
946
+ 0,
947
+ spent_index,
948
+ int(coinbase),
949
+ coin.puzzle_hash,
950
+ coin.parent_coin_info,
951
+ coin.amount.stream_to_bytes(),
952
+ 0,
953
+ )
954
+ for coin, spent_index, coinbase in coins
955
+ ]
956
+ async with db_wrapper.writer() as conn:
957
+ await conn.executemany("INSERT INTO coin_record VALUES (?, ?, ?, ?, ?, ?, ?, ?)", values_to_insert)
958
+
959
+ async with DBConnection(2) as db_wrapper:
960
+ coin_store = await CoinStore.create(db_wrapper)
961
+ # Let's set things up for roll back. All coins are confirmed at height
962
+ # 0, parent coin gets spent at height 2 and the other test coins get
963
+ # spent at height 3.
964
+ parent_coin = Coin(bytes32([0] * 32), bytes32([1] * 32), uint64(1337))
965
+ parent_coin_id = parent_coin.name()
966
+ normal_child = Coin(parent_coin_id, bytes32([2] * 32), uint64(42))
967
+ same_as_parent_child = Coin(parent_coin_id, parent_coin.puzzle_hash, parent_coin.amount)
968
+ reward_coin = Coin(bytes32([0] * 32), bytes32([0] * 32), uint64(1))
969
+ await insert_coins(
970
+ db_wrapper,
971
+ # List of (coin, spent_index, coinbase) values
972
+ [
973
+ (parent_coin, 2, False),
974
+ (normal_child, 3, False),
975
+ (same_as_parent_child, 3, False),
976
+ (reward_coin, 3, True),
977
+ ],
978
+ )
979
+ # Let's roll back
980
+ await coin_store.rollback_to_block(2)
981
+ async with db_wrapper.reader_no_transaction() as conn:
982
+ # Parent should still be spent
983
+ assert await get_spent_index(conn, parent_coin_id) == 2
984
+ # Normal child should be unspent with spent_index 0
985
+ assert await get_spent_index(conn, normal_child.name()) == 0
986
+ # Same for the reward coin
987
+ assert await get_spent_index(conn, reward_coin.name()) == 0
988
+ # The potential ff singleton child should be marked with -1
989
+ assert await get_spent_index(conn, same_as_parent_child.name()) == -1