chia-blockchain 2.5.1rc1__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 (1042) hide show
  1. chia/__init__.py +10 -0
  2. chia/__main__.py +5 -0
  3. chia/_tests/README.md +53 -0
  4. chia/_tests/__init__.py +0 -0
  5. chia/_tests/blockchain/__init__.py +0 -0
  6. chia/_tests/blockchain/blockchain_test_utils.py +195 -0
  7. chia/_tests/blockchain/config.py +4 -0
  8. chia/_tests/blockchain/test_augmented_chain.py +145 -0
  9. chia/_tests/blockchain/test_blockchain.py +4202 -0
  10. chia/_tests/blockchain/test_blockchain_transactions.py +1031 -0
  11. chia/_tests/blockchain/test_build_chains.py +59 -0
  12. chia/_tests/blockchain/test_get_block_generator.py +72 -0
  13. chia/_tests/blockchain/test_lookup_fork_chain.py +194 -0
  14. chia/_tests/build-init-files.py +92 -0
  15. chia/_tests/build-job-matrix.py +204 -0
  16. chia/_tests/check_pytest_monitor_output.py +34 -0
  17. chia/_tests/check_sql_statements.py +72 -0
  18. chia/_tests/chia-start-sim +42 -0
  19. chia/_tests/clvm/__init__.py +0 -0
  20. chia/_tests/clvm/benchmark_costs.py +23 -0
  21. chia/_tests/clvm/coin_store.py +149 -0
  22. chia/_tests/clvm/test_chialisp_deserialization.py +101 -0
  23. chia/_tests/clvm/test_clvm_step.py +37 -0
  24. chia/_tests/clvm/test_condition_codes.py +13 -0
  25. chia/_tests/clvm/test_curry_and_treehash.py +55 -0
  26. chia/_tests/clvm/test_message_conditions.py +184 -0
  27. chia/_tests/clvm/test_program.py +150 -0
  28. chia/_tests/clvm/test_puzzle_compression.py +143 -0
  29. chia/_tests/clvm/test_puzzle_drivers.py +45 -0
  30. chia/_tests/clvm/test_puzzles.py +242 -0
  31. chia/_tests/clvm/test_singletons.py +540 -0
  32. chia/_tests/clvm/test_spend_sim.py +181 -0
  33. chia/_tests/cmds/__init__.py +0 -0
  34. chia/_tests/cmds/cmd_test_utils.py +469 -0
  35. chia/_tests/cmds/config.py +3 -0
  36. chia/_tests/cmds/conftest.py +23 -0
  37. chia/_tests/cmds/test_click_types.py +200 -0
  38. chia/_tests/cmds/test_cmd_framework.py +620 -0
  39. chia/_tests/cmds/test_cmds_util.py +97 -0
  40. chia/_tests/cmds/test_daemon.py +92 -0
  41. chia/_tests/cmds/test_dev_gh.py +131 -0
  42. chia/_tests/cmds/test_farm_cmd.py +66 -0
  43. chia/_tests/cmds/test_show.py +116 -0
  44. chia/_tests/cmds/test_sim.py +207 -0
  45. chia/_tests/cmds/test_timelock_args.py +75 -0
  46. chia/_tests/cmds/test_tx_config_args.py +154 -0
  47. chia/_tests/cmds/testing_classes.py +59 -0
  48. chia/_tests/cmds/wallet/__init__.py +0 -0
  49. chia/_tests/cmds/wallet/test_consts.py +47 -0
  50. chia/_tests/cmds/wallet/test_dao.py +565 -0
  51. chia/_tests/cmds/wallet/test_did.py +403 -0
  52. chia/_tests/cmds/wallet/test_nft.py +471 -0
  53. chia/_tests/cmds/wallet/test_notifications.py +124 -0
  54. chia/_tests/cmds/wallet/test_offer.toffer +1 -0
  55. chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
  56. chia/_tests/cmds/wallet/test_vcs.py +400 -0
  57. chia/_tests/cmds/wallet/test_wallet.py +1125 -0
  58. chia/_tests/cmds/wallet/test_wallet_check.py +109 -0
  59. chia/_tests/conftest.py +1419 -0
  60. chia/_tests/connection_utils.py +125 -0
  61. chia/_tests/core/__init__.py +0 -0
  62. chia/_tests/core/cmds/__init__.py +0 -0
  63. chia/_tests/core/cmds/test_beta.py +382 -0
  64. chia/_tests/core/cmds/test_keys.py +1734 -0
  65. chia/_tests/core/cmds/test_wallet.py +126 -0
  66. chia/_tests/core/config.py +3 -0
  67. chia/_tests/core/consensus/__init__.py +0 -0
  68. chia/_tests/core/consensus/test_block_creation.py +54 -0
  69. chia/_tests/core/consensus/test_pot_iterations.py +117 -0
  70. chia/_tests/core/custom_types/__init__.py +0 -0
  71. chia/_tests/core/custom_types/test_coin.py +107 -0
  72. chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
  73. chia/_tests/core/custom_types/test_spend_bundle.py +70 -0
  74. chia/_tests/core/daemon/__init__.py +0 -0
  75. chia/_tests/core/daemon/config.py +4 -0
  76. chia/_tests/core/daemon/test_daemon.py +2128 -0
  77. chia/_tests/core/daemon/test_daemon_register.py +109 -0
  78. chia/_tests/core/daemon/test_keychain_proxy.py +101 -0
  79. chia/_tests/core/data_layer/__init__.py +0 -0
  80. chia/_tests/core/data_layer/config.py +5 -0
  81. chia/_tests/core/data_layer/conftest.py +106 -0
  82. chia/_tests/core/data_layer/test_data_cli.py +56 -0
  83. chia/_tests/core/data_layer/test_data_layer.py +83 -0
  84. chia/_tests/core/data_layer/test_data_layer_util.py +218 -0
  85. chia/_tests/core/data_layer/test_data_rpc.py +3847 -0
  86. chia/_tests/core/data_layer/test_data_store.py +2424 -0
  87. chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
  88. chia/_tests/core/data_layer/test_plugin.py +91 -0
  89. chia/_tests/core/data_layer/util.py +233 -0
  90. chia/_tests/core/farmer/__init__.py +0 -0
  91. chia/_tests/core/farmer/config.py +3 -0
  92. chia/_tests/core/farmer/test_farmer_api.py +103 -0
  93. chia/_tests/core/full_node/__init__.py +0 -0
  94. chia/_tests/core/full_node/config.py +4 -0
  95. chia/_tests/core/full_node/dos/__init__.py +0 -0
  96. chia/_tests/core/full_node/dos/config.py +3 -0
  97. chia/_tests/core/full_node/full_sync/__init__.py +0 -0
  98. chia/_tests/core/full_node/full_sync/config.py +4 -0
  99. chia/_tests/core/full_node/full_sync/test_full_sync.py +443 -0
  100. chia/_tests/core/full_node/ram_db.py +27 -0
  101. chia/_tests/core/full_node/stores/__init__.py +0 -0
  102. chia/_tests/core/full_node/stores/config.py +4 -0
  103. chia/_tests/core/full_node/stores/test_block_store.py +590 -0
  104. chia/_tests/core/full_node/stores/test_coin_store.py +897 -0
  105. chia/_tests/core/full_node/stores/test_full_node_store.py +1219 -0
  106. chia/_tests/core/full_node/stores/test_hint_store.py +229 -0
  107. chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
  108. chia/_tests/core/full_node/test_address_manager.py +588 -0
  109. chia/_tests/core/full_node/test_block_height_map.py +556 -0
  110. chia/_tests/core/full_node/test_conditions.py +556 -0
  111. chia/_tests/core/full_node/test_full_node.py +2700 -0
  112. chia/_tests/core/full_node/test_generator_tools.py +82 -0
  113. chia/_tests/core/full_node/test_hint_management.py +104 -0
  114. chia/_tests/core/full_node/test_node_load.py +34 -0
  115. chia/_tests/core/full_node/test_performance.py +179 -0
  116. chia/_tests/core/full_node/test_subscriptions.py +492 -0
  117. chia/_tests/core/full_node/test_transactions.py +203 -0
  118. chia/_tests/core/full_node/test_tx_processing_queue.py +155 -0
  119. chia/_tests/core/large_block.py +2388 -0
  120. chia/_tests/core/make_block_generator.py +70 -0
  121. chia/_tests/core/mempool/__init__.py +0 -0
  122. chia/_tests/core/mempool/config.py +4 -0
  123. chia/_tests/core/mempool/test_mempool.py +3255 -0
  124. chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
  125. chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
  126. chia/_tests/core/mempool/test_mempool_item_queries.py +190 -0
  127. chia/_tests/core/mempool/test_mempool_manager.py +2084 -0
  128. chia/_tests/core/mempool/test_mempool_performance.py +64 -0
  129. chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
  130. chia/_tests/core/node_height.py +28 -0
  131. chia/_tests/core/server/__init__.py +0 -0
  132. chia/_tests/core/server/config.py +3 -0
  133. chia/_tests/core/server/flood.py +84 -0
  134. chia/_tests/core/server/serve.py +135 -0
  135. chia/_tests/core/server/test_api_protocol.py +21 -0
  136. chia/_tests/core/server/test_capabilities.py +66 -0
  137. chia/_tests/core/server/test_dos.py +319 -0
  138. chia/_tests/core/server/test_event_loop.py +109 -0
  139. chia/_tests/core/server/test_loop.py +294 -0
  140. chia/_tests/core/server/test_node_discovery.py +73 -0
  141. chia/_tests/core/server/test_rate_limits.py +482 -0
  142. chia/_tests/core/server/test_server.py +226 -0
  143. chia/_tests/core/server/test_upnp.py +8 -0
  144. chia/_tests/core/services/__init__.py +0 -0
  145. chia/_tests/core/services/config.py +3 -0
  146. chia/_tests/core/services/test_services.py +188 -0
  147. chia/_tests/core/ssl/__init__.py +0 -0
  148. chia/_tests/core/ssl/config.py +3 -0
  149. chia/_tests/core/ssl/test_ssl.py +202 -0
  150. chia/_tests/core/test_coins.py +33 -0
  151. chia/_tests/core/test_cost_calculation.py +313 -0
  152. chia/_tests/core/test_crawler.py +175 -0
  153. chia/_tests/core/test_crawler_rpc.py +53 -0
  154. chia/_tests/core/test_daemon_rpc.py +24 -0
  155. chia/_tests/core/test_db_conversion.py +130 -0
  156. chia/_tests/core/test_db_validation.py +162 -0
  157. chia/_tests/core/test_farmer_harvester_rpc.py +505 -0
  158. chia/_tests/core/test_filter.py +35 -0
  159. chia/_tests/core/test_full_node_rpc.py +768 -0
  160. chia/_tests/core/test_merkle_set.py +343 -0
  161. chia/_tests/core/test_program.py +47 -0
  162. chia/_tests/core/test_rpc_util.py +86 -0
  163. chia/_tests/core/test_seeder.py +420 -0
  164. chia/_tests/core/test_setproctitle.py +13 -0
  165. chia/_tests/core/util/__init__.py +0 -0
  166. chia/_tests/core/util/config.py +4 -0
  167. chia/_tests/core/util/test_block_cache.py +44 -0
  168. chia/_tests/core/util/test_cached_bls.py +57 -0
  169. chia/_tests/core/util/test_config.py +337 -0
  170. chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
  171. chia/_tests/core/util/test_files.py +391 -0
  172. chia/_tests/core/util/test_jsonify.py +146 -0
  173. chia/_tests/core/util/test_keychain.py +522 -0
  174. chia/_tests/core/util/test_keyring_wrapper.py +491 -0
  175. chia/_tests/core/util/test_lockfile.py +380 -0
  176. chia/_tests/core/util/test_log_exceptions.py +187 -0
  177. chia/_tests/core/util/test_lru_cache.py +56 -0
  178. chia/_tests/core/util/test_significant_bits.py +40 -0
  179. chia/_tests/core/util/test_streamable.py +883 -0
  180. chia/_tests/db/__init__.py +0 -0
  181. chia/_tests/db/test_db_wrapper.py +566 -0
  182. chia/_tests/environments/__init__.py +0 -0
  183. chia/_tests/environments/common.py +35 -0
  184. chia/_tests/environments/full_node.py +47 -0
  185. chia/_tests/environments/wallet.py +429 -0
  186. chia/_tests/ether.py +19 -0
  187. chia/_tests/farmer_harvester/__init__.py +0 -0
  188. chia/_tests/farmer_harvester/config.py +3 -0
  189. chia/_tests/farmer_harvester/test_farmer.py +1264 -0
  190. chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
  191. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +131 -0
  192. chia/_tests/farmer_harvester/test_third_party_harvesters.py +528 -0
  193. chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
  194. chia/_tests/fee_estimation/__init__.py +0 -0
  195. chia/_tests/fee_estimation/config.py +3 -0
  196. chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
  197. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
  198. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +144 -0
  199. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
  200. chia/_tests/generator/__init__.py +0 -0
  201. chia/_tests/generator/puzzles/__init__.py +0 -0
  202. chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
  203. chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
  204. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
  205. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
  206. chia/_tests/generator/test_compression.py +201 -0
  207. chia/_tests/generator/test_generator_types.py +44 -0
  208. chia/_tests/generator/test_rom.py +180 -0
  209. chia/_tests/plot_sync/__init__.py +0 -0
  210. chia/_tests/plot_sync/config.py +3 -0
  211. chia/_tests/plot_sync/test_delta.py +101 -0
  212. chia/_tests/plot_sync/test_plot_sync.py +618 -0
  213. chia/_tests/plot_sync/test_receiver.py +451 -0
  214. chia/_tests/plot_sync/test_sender.py +116 -0
  215. chia/_tests/plot_sync/test_sync_simulated.py +451 -0
  216. chia/_tests/plot_sync/util.py +68 -0
  217. chia/_tests/plotting/__init__.py +0 -0
  218. chia/_tests/plotting/config.py +3 -0
  219. chia/_tests/plotting/test_plot_manager.py +781 -0
  220. chia/_tests/plotting/util.py +12 -0
  221. chia/_tests/pools/__init__.py +0 -0
  222. chia/_tests/pools/config.py +5 -0
  223. chia/_tests/pools/test_pool_cli_parsing.py +128 -0
  224. chia/_tests/pools/test_pool_cmdline.py +1001 -0
  225. chia/_tests/pools/test_pool_config.py +42 -0
  226. chia/_tests/pools/test_pool_puzzles_lifecycle.py +397 -0
  227. chia/_tests/pools/test_pool_rpc.py +1123 -0
  228. chia/_tests/pools/test_pool_wallet.py +205 -0
  229. chia/_tests/pools/test_wallet_pool_store.py +161 -0
  230. chia/_tests/process_junit.py +348 -0
  231. chia/_tests/rpc/__init__.py +0 -0
  232. chia/_tests/rpc/test_rpc_client.py +138 -0
  233. chia/_tests/rpc/test_rpc_server.py +183 -0
  234. chia/_tests/simulation/__init__.py +0 -0
  235. chia/_tests/simulation/config.py +6 -0
  236. chia/_tests/simulation/test_simulation.py +501 -0
  237. chia/_tests/simulation/test_simulator.py +232 -0
  238. chia/_tests/simulation/test_start_simulator.py +107 -0
  239. chia/_tests/testconfig.py +13 -0
  240. chia/_tests/timelord/__init__.py +0 -0
  241. chia/_tests/timelord/config.py +3 -0
  242. chia/_tests/timelord/test_new_peak.py +437 -0
  243. chia/_tests/timelord/test_timelord.py +11 -0
  244. chia/_tests/tools/1315537.json +170 -0
  245. chia/_tests/tools/1315544.json +160 -0
  246. chia/_tests/tools/1315630.json +150 -0
  247. chia/_tests/tools/300000.json +105 -0
  248. chia/_tests/tools/442734.json +140 -0
  249. chia/_tests/tools/466212.json +130 -0
  250. chia/_tests/tools/__init__.py +0 -0
  251. chia/_tests/tools/config.py +5 -0
  252. chia/_tests/tools/test-blockchain-db.sqlite +0 -0
  253. chia/_tests/tools/test_full_sync.py +30 -0
  254. chia/_tests/tools/test_legacy_keyring.py +82 -0
  255. chia/_tests/tools/test_run_block.py +128 -0
  256. chia/_tests/tools/test_virtual_project.py +591 -0
  257. chia/_tests/util/__init__.py +0 -0
  258. chia/_tests/util/benchmark_cost.py +170 -0
  259. chia/_tests/util/benchmarks.py +153 -0
  260. chia/_tests/util/bip39_test_vectors.json +148 -0
  261. chia/_tests/util/blockchain.py +134 -0
  262. chia/_tests/util/blockchain_mock.py +132 -0
  263. chia/_tests/util/build_network_protocol_files.py +302 -0
  264. chia/_tests/util/clvm_generator.bin +0 -0
  265. chia/_tests/util/config.py +3 -0
  266. chia/_tests/util/constants.py +20 -0
  267. chia/_tests/util/db_connection.py +37 -0
  268. chia/_tests/util/full_sync.py +253 -0
  269. chia/_tests/util/gen_ssl_certs.py +114 -0
  270. chia/_tests/util/generator_tools_testing.py +45 -0
  271. chia/_tests/util/get_name_puzzle_conditions.py +52 -0
  272. chia/_tests/util/key_tool.py +36 -0
  273. chia/_tests/util/misc.py +675 -0
  274. chia/_tests/util/network_protocol_data.py +1072 -0
  275. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  276. chia/_tests/util/protocol_messages_json.py +2701 -0
  277. chia/_tests/util/rpc.py +26 -0
  278. chia/_tests/util/run_block.py +163 -0
  279. chia/_tests/util/setup_nodes.py +481 -0
  280. chia/_tests/util/spend_sim.py +492 -0
  281. chia/_tests/util/split_managers.py +102 -0
  282. chia/_tests/util/temp_file.py +14 -0
  283. chia/_tests/util/test_action_scope.py +144 -0
  284. chia/_tests/util/test_async_pool.py +366 -0
  285. chia/_tests/util/test_build_job_matrix.py +42 -0
  286. chia/_tests/util/test_build_network_protocol_files.py +7 -0
  287. chia/_tests/util/test_chia_version.py +50 -0
  288. chia/_tests/util/test_collection.py +11 -0
  289. chia/_tests/util/test_condition_tools.py +229 -0
  290. chia/_tests/util/test_config.py +426 -0
  291. chia/_tests/util/test_dump_keyring.py +60 -0
  292. chia/_tests/util/test_errors.py +10 -0
  293. chia/_tests/util/test_full_block_utils.py +279 -0
  294. chia/_tests/util/test_installed.py +20 -0
  295. chia/_tests/util/test_limited_semaphore.py +53 -0
  296. chia/_tests/util/test_logging_filter.py +42 -0
  297. chia/_tests/util/test_misc.py +445 -0
  298. chia/_tests/util/test_network.py +73 -0
  299. chia/_tests/util/test_network_protocol_files.py +578 -0
  300. chia/_tests/util/test_network_protocol_json.py +267 -0
  301. chia/_tests/util/test_network_protocol_test.py +256 -0
  302. chia/_tests/util/test_paginator.py +71 -0
  303. chia/_tests/util/test_pprint.py +17 -0
  304. chia/_tests/util/test_priority_mutex.py +488 -0
  305. chia/_tests/util/test_recursive_replace.py +116 -0
  306. chia/_tests/util/test_replace_str_to_bytes.py +137 -0
  307. chia/_tests/util/test_service_groups.py +15 -0
  308. chia/_tests/util/test_ssl_check.py +31 -0
  309. chia/_tests/util/test_testnet_overrides.py +19 -0
  310. chia/_tests/util/test_tests_misc.py +38 -0
  311. chia/_tests/util/test_timing.py +37 -0
  312. chia/_tests/util/test_trusted_peer.py +51 -0
  313. chia/_tests/util/time_out_assert.py +191 -0
  314. chia/_tests/wallet/__init__.py +0 -0
  315. chia/_tests/wallet/cat_wallet/__init__.py +0 -0
  316. chia/_tests/wallet/cat_wallet/config.py +4 -0
  317. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
  318. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
  319. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1826 -0
  320. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
  321. chia/_tests/wallet/cat_wallet/test_trades.py +2600 -0
  322. chia/_tests/wallet/clawback/__init__.py +0 -0
  323. chia/_tests/wallet/clawback/config.py +3 -0
  324. chia/_tests/wallet/clawback/test_clawback_decorator.py +78 -0
  325. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
  326. chia/_tests/wallet/clawback/test_clawback_metadata.py +50 -0
  327. chia/_tests/wallet/config.py +4 -0
  328. chia/_tests/wallet/conftest.py +278 -0
  329. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  330. chia/_tests/wallet/dao_wallet/config.py +3 -0
  331. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1330 -0
  332. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
  333. chia/_tests/wallet/db_wallet/__init__.py +0 -0
  334. chia/_tests/wallet/db_wallet/config.py +3 -0
  335. chia/_tests/wallet/db_wallet/test_db_graftroot.py +141 -0
  336. chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
  337. chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
  338. chia/_tests/wallet/did_wallet/__init__.py +0 -0
  339. chia/_tests/wallet/did_wallet/config.py +4 -0
  340. chia/_tests/wallet/did_wallet/test_did.py +2284 -0
  341. chia/_tests/wallet/nft_wallet/__init__.py +0 -0
  342. chia/_tests/wallet/nft_wallet/config.py +4 -0
  343. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1493 -0
  344. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1024 -0
  345. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +375 -0
  346. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
  347. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
  348. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2584 -0
  349. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
  350. chia/_tests/wallet/rpc/__init__.py +0 -0
  351. chia/_tests/wallet/rpc/config.py +4 -0
  352. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +285 -0
  353. chia/_tests/wallet/rpc/test_wallet_rpc.py +3153 -0
  354. chia/_tests/wallet/simple_sync/__init__.py +0 -0
  355. chia/_tests/wallet/simple_sync/config.py +3 -0
  356. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +718 -0
  357. chia/_tests/wallet/sync/__init__.py +0 -0
  358. chia/_tests/wallet/sync/config.py +4 -0
  359. chia/_tests/wallet/sync/test_wallet_sync.py +1692 -0
  360. chia/_tests/wallet/test_address_type.py +189 -0
  361. chia/_tests/wallet/test_bech32m.py +45 -0
  362. chia/_tests/wallet/test_clvm_streamable.py +244 -0
  363. chia/_tests/wallet/test_coin_management.py +354 -0
  364. chia/_tests/wallet/test_coin_selection.py +588 -0
  365. chia/_tests/wallet/test_conditions.py +400 -0
  366. chia/_tests/wallet/test_debug_spend_bundle.py +218 -0
  367. chia/_tests/wallet/test_new_wallet_protocol.py +1174 -0
  368. chia/_tests/wallet/test_nft_store.py +192 -0
  369. chia/_tests/wallet/test_notifications.py +196 -0
  370. chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
  371. chia/_tests/wallet/test_puzzle_store.py +132 -0
  372. chia/_tests/wallet/test_sign_coin_spends.py +159 -0
  373. chia/_tests/wallet/test_signer_protocol.py +947 -0
  374. chia/_tests/wallet/test_singleton.py +122 -0
  375. chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
  376. chia/_tests/wallet/test_singleton_store.py +152 -0
  377. chia/_tests/wallet/test_taproot.py +19 -0
  378. chia/_tests/wallet/test_transaction_store.py +945 -0
  379. chia/_tests/wallet/test_util.py +185 -0
  380. chia/_tests/wallet/test_wallet.py +2139 -0
  381. chia/_tests/wallet/test_wallet_action_scope.py +85 -0
  382. chia/_tests/wallet/test_wallet_blockchain.py +111 -0
  383. chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
  384. chia/_tests/wallet/test_wallet_interested_store.py +43 -0
  385. chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
  386. chia/_tests/wallet/test_wallet_node.py +780 -0
  387. chia/_tests/wallet/test_wallet_retry.py +95 -0
  388. chia/_tests/wallet/test_wallet_state_manager.py +259 -0
  389. chia/_tests/wallet/test_wallet_test_framework.py +275 -0
  390. chia/_tests/wallet/test_wallet_trade_store.py +218 -0
  391. chia/_tests/wallet/test_wallet_user_store.py +34 -0
  392. chia/_tests/wallet/test_wallet_utils.py +156 -0
  393. chia/_tests/wallet/vc_wallet/__init__.py +0 -0
  394. chia/_tests/wallet/vc_wallet/config.py +3 -0
  395. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
  396. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
  397. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +830 -0
  398. chia/_tests/wallet/wallet_block_tools.py +327 -0
  399. chia/_tests/weight_proof/__init__.py +0 -0
  400. chia/_tests/weight_proof/config.py +3 -0
  401. chia/_tests/weight_proof/test_weight_proof.py +528 -0
  402. chia/apis.py +19 -0
  403. chia/clvm/__init__.py +0 -0
  404. chia/cmds/__init__.py +0 -0
  405. chia/cmds/beta.py +184 -0
  406. chia/cmds/beta_funcs.py +137 -0
  407. chia/cmds/check_wallet_db.py +420 -0
  408. chia/cmds/chia.py +151 -0
  409. chia/cmds/cmd_classes.py +323 -0
  410. chia/cmds/cmd_helpers.py +242 -0
  411. chia/cmds/cmds_util.py +488 -0
  412. chia/cmds/coin_funcs.py +275 -0
  413. chia/cmds/coins.py +182 -0
  414. chia/cmds/completion.py +49 -0
  415. chia/cmds/configure.py +332 -0
  416. chia/cmds/dao.py +1064 -0
  417. chia/cmds/dao_funcs.py +598 -0
  418. chia/cmds/data.py +708 -0
  419. chia/cmds/data_funcs.py +385 -0
  420. chia/cmds/db.py +87 -0
  421. chia/cmds/db_backup_func.py +77 -0
  422. chia/cmds/db_upgrade_func.py +452 -0
  423. chia/cmds/db_validate_func.py +184 -0
  424. chia/cmds/dev.py +18 -0
  425. chia/cmds/farm.py +100 -0
  426. chia/cmds/farm_funcs.py +200 -0
  427. chia/cmds/gh.py +275 -0
  428. chia/cmds/init.py +63 -0
  429. chia/cmds/init_funcs.py +367 -0
  430. chia/cmds/installers.py +131 -0
  431. chia/cmds/keys.py +527 -0
  432. chia/cmds/keys_funcs.py +863 -0
  433. chia/cmds/netspace.py +50 -0
  434. chia/cmds/netspace_funcs.py +54 -0
  435. chia/cmds/options.py +32 -0
  436. chia/cmds/param_types.py +238 -0
  437. chia/cmds/passphrase.py +131 -0
  438. chia/cmds/passphrase_funcs.py +292 -0
  439. chia/cmds/peer.py +51 -0
  440. chia/cmds/peer_funcs.py +129 -0
  441. chia/cmds/plotnft.py +260 -0
  442. chia/cmds/plotnft_funcs.py +405 -0
  443. chia/cmds/plots.py +230 -0
  444. chia/cmds/plotters.py +18 -0
  445. chia/cmds/rpc.py +208 -0
  446. chia/cmds/show.py +72 -0
  447. chia/cmds/show_funcs.py +215 -0
  448. chia/cmds/signer.py +296 -0
  449. chia/cmds/sim.py +225 -0
  450. chia/cmds/sim_funcs.py +509 -0
  451. chia/cmds/start.py +24 -0
  452. chia/cmds/start_funcs.py +109 -0
  453. chia/cmds/stop.py +62 -0
  454. chia/cmds/units.py +9 -0
  455. chia/cmds/wallet.py +1901 -0
  456. chia/cmds/wallet_funcs.py +1874 -0
  457. chia/consensus/__init__.py +0 -0
  458. chia/consensus/block_body_validation.py +562 -0
  459. chia/consensus/block_creation.py +546 -0
  460. chia/consensus/block_header_validation.py +1059 -0
  461. chia/consensus/block_record.py +31 -0
  462. chia/consensus/block_rewards.py +53 -0
  463. chia/consensus/blockchain.py +1087 -0
  464. chia/consensus/blockchain_interface.py +56 -0
  465. chia/consensus/coinbase.py +30 -0
  466. chia/consensus/condition_costs.py +9 -0
  467. chia/consensus/constants.py +49 -0
  468. chia/consensus/cost_calculator.py +15 -0
  469. chia/consensus/default_constants.py +89 -0
  470. chia/consensus/deficit.py +55 -0
  471. chia/consensus/difficulty_adjustment.py +412 -0
  472. chia/consensus/find_fork_point.py +111 -0
  473. chia/consensus/full_block_to_block_record.py +167 -0
  474. chia/consensus/get_block_challenge.py +106 -0
  475. chia/consensus/get_block_generator.py +27 -0
  476. chia/consensus/make_sub_epoch_summary.py +210 -0
  477. chia/consensus/multiprocess_validation.py +268 -0
  478. chia/consensus/pos_quality.py +19 -0
  479. chia/consensus/pot_iterations.py +67 -0
  480. chia/consensus/puzzles/__init__.py +0 -0
  481. chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
  482. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
  483. chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
  484. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
  485. chia/consensus/vdf_info_computation.py +156 -0
  486. chia/daemon/__init__.py +0 -0
  487. chia/daemon/client.py +252 -0
  488. chia/daemon/keychain_proxy.py +502 -0
  489. chia/daemon/keychain_server.py +365 -0
  490. chia/daemon/server.py +1606 -0
  491. chia/daemon/windows_signal.py +56 -0
  492. chia/data_layer/__init__.py +0 -0
  493. chia/data_layer/data_layer.py +1291 -0
  494. chia/data_layer/data_layer_api.py +33 -0
  495. chia/data_layer/data_layer_errors.py +50 -0
  496. chia/data_layer/data_layer_server.py +170 -0
  497. chia/data_layer/data_layer_util.py +985 -0
  498. chia/data_layer/data_layer_wallet.py +1311 -0
  499. chia/data_layer/data_store.py +2267 -0
  500. chia/data_layer/dl_wallet_store.py +407 -0
  501. chia/data_layer/download_data.py +389 -0
  502. chia/data_layer/puzzles/__init__.py +0 -0
  503. chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
  504. chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
  505. chia/data_layer/s3_plugin_config.yml +33 -0
  506. chia/data_layer/s3_plugin_service.py +468 -0
  507. chia/data_layer/util/__init__.py +0 -0
  508. chia/data_layer/util/benchmark.py +107 -0
  509. chia/data_layer/util/plugin.py +40 -0
  510. chia/farmer/__init__.py +0 -0
  511. chia/farmer/farmer.py +923 -0
  512. chia/farmer/farmer_api.py +820 -0
  513. chia/full_node/__init__.py +0 -0
  514. chia/full_node/bitcoin_fee_estimator.py +85 -0
  515. chia/full_node/block_height_map.py +271 -0
  516. chia/full_node/block_store.py +576 -0
  517. chia/full_node/bundle_tools.py +19 -0
  518. chia/full_node/coin_store.py +647 -0
  519. chia/full_node/fee_estimate.py +54 -0
  520. chia/full_node/fee_estimate_store.py +24 -0
  521. chia/full_node/fee_estimation.py +92 -0
  522. chia/full_node/fee_estimator.py +90 -0
  523. chia/full_node/fee_estimator_constants.py +38 -0
  524. chia/full_node/fee_estimator_interface.py +42 -0
  525. chia/full_node/fee_history.py +25 -0
  526. chia/full_node/fee_tracker.py +564 -0
  527. chia/full_node/full_node.py +3327 -0
  528. chia/full_node/full_node_api.py +2025 -0
  529. chia/full_node/full_node_store.py +1033 -0
  530. chia/full_node/hint_management.py +56 -0
  531. chia/full_node/hint_store.py +93 -0
  532. chia/full_node/mempool.py +589 -0
  533. chia/full_node/mempool_check_conditions.py +146 -0
  534. chia/full_node/mempool_manager.py +853 -0
  535. chia/full_node/pending_tx_cache.py +112 -0
  536. chia/full_node/puzzles/__init__.py +0 -0
  537. chia/full_node/puzzles/block_program_zero.clsp +14 -0
  538. chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
  539. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
  540. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
  541. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
  542. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
  543. chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
  544. chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
  545. chia/full_node/signage_point.py +16 -0
  546. chia/full_node/subscriptions.py +247 -0
  547. chia/full_node/sync_store.py +146 -0
  548. chia/full_node/tx_processing_queue.py +78 -0
  549. chia/full_node/util/__init__.py +0 -0
  550. chia/full_node/weight_proof.py +1720 -0
  551. chia/harvester/__init__.py +0 -0
  552. chia/harvester/harvester.py +272 -0
  553. chia/harvester/harvester_api.py +380 -0
  554. chia/introducer/__init__.py +0 -0
  555. chia/introducer/introducer.py +122 -0
  556. chia/introducer/introducer_api.py +70 -0
  557. chia/legacy/__init__.py +0 -0
  558. chia/legacy/keyring.py +155 -0
  559. chia/plot_sync/__init__.py +0 -0
  560. chia/plot_sync/delta.py +61 -0
  561. chia/plot_sync/exceptions.py +56 -0
  562. chia/plot_sync/receiver.py +386 -0
  563. chia/plot_sync/sender.py +340 -0
  564. chia/plot_sync/util.py +43 -0
  565. chia/plotters/__init__.py +0 -0
  566. chia/plotters/bladebit.py +388 -0
  567. chia/plotters/chiapos.py +63 -0
  568. chia/plotters/madmax.py +224 -0
  569. chia/plotters/plotters.py +577 -0
  570. chia/plotters/plotters_util.py +133 -0
  571. chia/plotting/__init__.py +0 -0
  572. chia/plotting/cache.py +213 -0
  573. chia/plotting/check_plots.py +283 -0
  574. chia/plotting/create_plots.py +278 -0
  575. chia/plotting/manager.py +436 -0
  576. chia/plotting/util.py +336 -0
  577. chia/pools/__init__.py +0 -0
  578. chia/pools/pool_config.py +110 -0
  579. chia/pools/pool_puzzles.py +459 -0
  580. chia/pools/pool_wallet.py +933 -0
  581. chia/pools/pool_wallet_info.py +118 -0
  582. chia/pools/puzzles/__init__.py +0 -0
  583. chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
  584. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
  585. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
  586. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
  587. chia/protocols/__init__.py +0 -0
  588. chia/protocols/farmer_protocol.py +102 -0
  589. chia/protocols/full_node_protocol.py +219 -0
  590. chia/protocols/harvester_protocol.py +216 -0
  591. chia/protocols/introducer_protocol.py +25 -0
  592. chia/protocols/pool_protocol.py +177 -0
  593. chia/protocols/protocol_message_types.py +139 -0
  594. chia/protocols/protocol_state_machine.py +87 -0
  595. chia/protocols/protocol_timing.py +8 -0
  596. chia/protocols/shared_protocol.py +86 -0
  597. chia/protocols/timelord_protocol.py +93 -0
  598. chia/protocols/wallet_protocol.py +401 -0
  599. chia/py.typed +0 -0
  600. chia/rpc/__init__.py +0 -0
  601. chia/rpc/crawler_rpc_api.py +80 -0
  602. chia/rpc/data_layer_rpc_api.py +644 -0
  603. chia/rpc/data_layer_rpc_client.py +188 -0
  604. chia/rpc/data_layer_rpc_util.py +58 -0
  605. chia/rpc/farmer_rpc_api.py +365 -0
  606. chia/rpc/farmer_rpc_client.py +86 -0
  607. chia/rpc/full_node_rpc_api.py +959 -0
  608. chia/rpc/full_node_rpc_client.py +292 -0
  609. chia/rpc/harvester_rpc_api.py +141 -0
  610. chia/rpc/harvester_rpc_client.py +54 -0
  611. chia/rpc/rpc_client.py +164 -0
  612. chia/rpc/rpc_server.py +521 -0
  613. chia/rpc/timelord_rpc_api.py +32 -0
  614. chia/rpc/util.py +93 -0
  615. chia/rpc/wallet_request_types.py +904 -0
  616. chia/rpc/wallet_rpc_api.py +4943 -0
  617. chia/rpc/wallet_rpc_client.py +1814 -0
  618. chia/seeder/__init__.py +0 -0
  619. chia/seeder/crawl_store.py +425 -0
  620. chia/seeder/crawler.py +410 -0
  621. chia/seeder/crawler_api.py +135 -0
  622. chia/seeder/dns_server.py +593 -0
  623. chia/seeder/peer_record.py +146 -0
  624. chia/seeder/start_crawler.py +92 -0
  625. chia/server/__init__.py +0 -0
  626. chia/server/address_manager.py +658 -0
  627. chia/server/address_manager_store.py +237 -0
  628. chia/server/api_protocol.py +116 -0
  629. chia/server/capabilities.py +24 -0
  630. chia/server/chia_policy.py +346 -0
  631. chia/server/introducer_peers.py +76 -0
  632. chia/server/node_discovery.py +714 -0
  633. chia/server/outbound_message.py +33 -0
  634. chia/server/rate_limit_numbers.py +214 -0
  635. chia/server/rate_limits.py +153 -0
  636. chia/server/server.py +741 -0
  637. chia/server/signal_handlers.py +120 -0
  638. chia/server/ssl_context.py +32 -0
  639. chia/server/start_data_layer.py +151 -0
  640. chia/server/start_farmer.py +98 -0
  641. chia/server/start_full_node.py +112 -0
  642. chia/server/start_harvester.py +93 -0
  643. chia/server/start_introducer.py +81 -0
  644. chia/server/start_service.py +316 -0
  645. chia/server/start_timelord.py +89 -0
  646. chia/server/start_wallet.py +113 -0
  647. chia/server/upnp.py +118 -0
  648. chia/server/ws_connection.py +766 -0
  649. chia/simulator/__init__.py +0 -0
  650. chia/simulator/add_blocks_in_batches.py +54 -0
  651. chia/simulator/block_tools.py +2054 -0
  652. chia/simulator/full_node_simulator.py +794 -0
  653. chia/simulator/keyring.py +128 -0
  654. chia/simulator/setup_services.py +506 -0
  655. chia/simulator/simulator_constants.py +13 -0
  656. chia/simulator/simulator_full_node_rpc_api.py +99 -0
  657. chia/simulator/simulator_full_node_rpc_client.py +60 -0
  658. chia/simulator/simulator_protocol.py +29 -0
  659. chia/simulator/simulator_test_tools.py +164 -0
  660. chia/simulator/socket.py +24 -0
  661. chia/simulator/ssl_certs.py +114 -0
  662. chia/simulator/ssl_certs_1.py +697 -0
  663. chia/simulator/ssl_certs_10.py +697 -0
  664. chia/simulator/ssl_certs_2.py +697 -0
  665. chia/simulator/ssl_certs_3.py +697 -0
  666. chia/simulator/ssl_certs_4.py +697 -0
  667. chia/simulator/ssl_certs_5.py +697 -0
  668. chia/simulator/ssl_certs_6.py +697 -0
  669. chia/simulator/ssl_certs_7.py +697 -0
  670. chia/simulator/ssl_certs_8.py +697 -0
  671. chia/simulator/ssl_certs_9.py +697 -0
  672. chia/simulator/start_simulator.py +143 -0
  673. chia/simulator/wallet_tools.py +246 -0
  674. chia/ssl/__init__.py +0 -0
  675. chia/ssl/chia_ca.crt +19 -0
  676. chia/ssl/chia_ca.key +28 -0
  677. chia/ssl/create_ssl.py +249 -0
  678. chia/ssl/dst_root_ca.pem +20 -0
  679. chia/timelord/__init__.py +0 -0
  680. chia/timelord/iters_from_block.py +50 -0
  681. chia/timelord/timelord.py +1226 -0
  682. chia/timelord/timelord_api.py +138 -0
  683. chia/timelord/timelord_launcher.py +190 -0
  684. chia/timelord/timelord_state.py +244 -0
  685. chia/timelord/types.py +22 -0
  686. chia/types/__init__.py +0 -0
  687. chia/types/aliases.py +35 -0
  688. chia/types/block_protocol.py +20 -0
  689. chia/types/blockchain_format/__init__.py +0 -0
  690. chia/types/blockchain_format/classgroup.py +5 -0
  691. chia/types/blockchain_format/coin.py +28 -0
  692. chia/types/blockchain_format/foliage.py +8 -0
  693. chia/types/blockchain_format/pool_target.py +5 -0
  694. chia/types/blockchain_format/program.py +269 -0
  695. chia/types/blockchain_format/proof_of_space.py +135 -0
  696. chia/types/blockchain_format/reward_chain_block.py +6 -0
  697. chia/types/blockchain_format/serialized_program.py +5 -0
  698. chia/types/blockchain_format/sized_bytes.py +11 -0
  699. chia/types/blockchain_format/slots.py +9 -0
  700. chia/types/blockchain_format/sub_epoch_summary.py +5 -0
  701. chia/types/blockchain_format/tree_hash.py +72 -0
  702. chia/types/blockchain_format/vdf.py +86 -0
  703. chia/types/clvm_cost.py +13 -0
  704. chia/types/coin_record.py +43 -0
  705. chia/types/coin_spend.py +115 -0
  706. chia/types/condition_opcodes.py +73 -0
  707. chia/types/condition_with_args.py +16 -0
  708. chia/types/eligible_coin_spends.py +365 -0
  709. chia/types/end_of_slot_bundle.py +5 -0
  710. chia/types/fee_rate.py +38 -0
  711. chia/types/full_block.py +5 -0
  712. chia/types/generator_types.py +13 -0
  713. chia/types/header_block.py +5 -0
  714. chia/types/internal_mempool_item.py +18 -0
  715. chia/types/mempool_inclusion_status.py +9 -0
  716. chia/types/mempool_item.py +85 -0
  717. chia/types/mempool_submission_status.py +30 -0
  718. chia/types/mojos.py +7 -0
  719. chia/types/peer_info.py +64 -0
  720. chia/types/signing_mode.py +29 -0
  721. chia/types/spend_bundle.py +30 -0
  722. chia/types/spend_bundle_conditions.py +7 -0
  723. chia/types/transaction_queue_entry.py +55 -0
  724. chia/types/unfinished_block.py +5 -0
  725. chia/types/unfinished_header_block.py +37 -0
  726. chia/types/validation_state.py +14 -0
  727. chia/types/weight_proof.py +49 -0
  728. chia/util/__init__.py +0 -0
  729. chia/util/action_scope.py +168 -0
  730. chia/util/async_pool.py +226 -0
  731. chia/util/augmented_chain.py +134 -0
  732. chia/util/batches.py +42 -0
  733. chia/util/bech32m.py +126 -0
  734. chia/util/beta_metrics.py +119 -0
  735. chia/util/block_cache.py +56 -0
  736. chia/util/byte_types.py +12 -0
  737. chia/util/check_fork_next_block.py +33 -0
  738. chia/util/chia_logging.py +144 -0
  739. chia/util/chia_version.py +33 -0
  740. chia/util/collection.py +17 -0
  741. chia/util/condition_tools.py +201 -0
  742. chia/util/config.py +367 -0
  743. chia/util/cpu.py +22 -0
  744. chia/util/db_synchronous.py +23 -0
  745. chia/util/db_version.py +32 -0
  746. chia/util/db_wrapper.py +430 -0
  747. chia/util/default_root.py +27 -0
  748. chia/util/dump_keyring.py +93 -0
  749. chia/util/english.txt +2048 -0
  750. chia/util/errors.py +353 -0
  751. chia/util/file_keyring.py +469 -0
  752. chia/util/files.py +97 -0
  753. chia/util/full_block_utils.py +345 -0
  754. chia/util/generator_tools.py +72 -0
  755. chia/util/hash.py +31 -0
  756. chia/util/initial-config.yaml +694 -0
  757. chia/util/inline_executor.py +26 -0
  758. chia/util/ints.py +19 -0
  759. chia/util/ip_address.py +39 -0
  760. chia/util/json_util.py +37 -0
  761. chia/util/keychain.py +676 -0
  762. chia/util/keyring_wrapper.py +327 -0
  763. chia/util/limited_semaphore.py +41 -0
  764. chia/util/lock.py +49 -0
  765. chia/util/log_exceptions.py +32 -0
  766. chia/util/logging.py +36 -0
  767. chia/util/lru_cache.py +31 -0
  768. chia/util/math.py +20 -0
  769. chia/util/network.py +182 -0
  770. chia/util/paginator.py +48 -0
  771. chia/util/path.py +31 -0
  772. chia/util/permissions.py +20 -0
  773. chia/util/prev_transaction_block.py +21 -0
  774. chia/util/priority_mutex.py +95 -0
  775. chia/util/profiler.py +197 -0
  776. chia/util/recursive_replace.py +24 -0
  777. chia/util/safe_cancel_task.py +16 -0
  778. chia/util/service_groups.py +47 -0
  779. chia/util/setproctitle.py +22 -0
  780. chia/util/significant_bits.py +32 -0
  781. chia/util/ssl_check.py +213 -0
  782. chia/util/streamable.py +642 -0
  783. chia/util/task_referencer.py +59 -0
  784. chia/util/task_timing.py +382 -0
  785. chia/util/timing.py +67 -0
  786. chia/util/vdf_prover.py +30 -0
  787. chia/util/virtual_project_analysis.py +540 -0
  788. chia/util/ws_message.py +66 -0
  789. chia/wallet/__init__.py +0 -0
  790. chia/wallet/cat_wallet/__init__.py +0 -0
  791. chia/wallet/cat_wallet/cat_constants.py +75 -0
  792. chia/wallet/cat_wallet/cat_info.py +47 -0
  793. chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
  794. chia/wallet/cat_wallet/cat_utils.py +164 -0
  795. chia/wallet/cat_wallet/cat_wallet.py +855 -0
  796. chia/wallet/cat_wallet/dao_cat_info.py +28 -0
  797. chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
  798. chia/wallet/cat_wallet/lineage_store.py +74 -0
  799. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  800. chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
  801. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
  802. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
  803. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
  804. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
  805. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
  806. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
  807. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
  808. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
  809. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
  810. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
  811. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
  812. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
  813. chia/wallet/coin_selection.py +188 -0
  814. chia/wallet/conditions.py +1512 -0
  815. chia/wallet/dao_wallet/__init__.py +0 -0
  816. chia/wallet/dao_wallet/dao_info.py +61 -0
  817. chia/wallet/dao_wallet/dao_utils.py +811 -0
  818. chia/wallet/dao_wallet/dao_wallet.py +2119 -0
  819. chia/wallet/db_wallet/__init__.py +0 -0
  820. chia/wallet/db_wallet/db_wallet_puzzles.py +111 -0
  821. chia/wallet/derivation_record.py +30 -0
  822. chia/wallet/derive_keys.py +146 -0
  823. chia/wallet/did_wallet/__init__.py +0 -0
  824. chia/wallet/did_wallet/did_info.py +39 -0
  825. chia/wallet/did_wallet/did_wallet.py +1494 -0
  826. chia/wallet/did_wallet/did_wallet_puzzles.py +221 -0
  827. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  828. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
  829. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
  830. chia/wallet/driver_protocol.py +26 -0
  831. chia/wallet/key_val_store.py +55 -0
  832. chia/wallet/lineage_proof.py +58 -0
  833. chia/wallet/nft_wallet/__init__.py +0 -0
  834. chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
  835. chia/wallet/nft_wallet/nft_info.py +120 -0
  836. chia/wallet/nft_wallet/nft_puzzles.py +305 -0
  837. chia/wallet/nft_wallet/nft_wallet.py +1687 -0
  838. chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
  839. chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
  840. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
  841. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
  842. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
  843. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
  844. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
  845. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
  846. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
  847. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
  848. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
  849. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
  850. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
  851. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
  852. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
  853. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
  854. chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
  855. chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
  856. chia/wallet/nft_wallet/uncurry_nft.py +217 -0
  857. chia/wallet/notification_manager.py +117 -0
  858. chia/wallet/notification_store.py +178 -0
  859. chia/wallet/outer_puzzles.py +84 -0
  860. chia/wallet/payment.py +33 -0
  861. chia/wallet/puzzle_drivers.py +118 -0
  862. chia/wallet/puzzles/__init__.py +0 -0
  863. chia/wallet/puzzles/augmented_condition.clsp +13 -0
  864. chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
  865. chia/wallet/puzzles/clawback/__init__.py +0 -0
  866. chia/wallet/puzzles/clawback/drivers.py +188 -0
  867. chia/wallet/puzzles/clawback/metadata.py +38 -0
  868. chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
  869. chia/wallet/puzzles/condition_codes.clib +77 -0
  870. chia/wallet/puzzles/curry-and-treehash.clib +102 -0
  871. chia/wallet/puzzles/curry.clib +135 -0
  872. chia/wallet/puzzles/curry_by_index.clib +16 -0
  873. chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
  874. chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
  875. chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
  876. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
  877. chia/wallet/puzzles/dao_finished_state.clsp +35 -0
  878. chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
  879. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
  880. chia/wallet/puzzles/dao_lockup.clsp +288 -0
  881. chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
  882. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
  883. chia/wallet/puzzles/dao_proposal.clsp +377 -0
  884. chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
  885. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
  886. chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
  887. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
  888. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
  889. chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
  890. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
  891. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
  892. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
  893. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
  894. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
  895. chia/wallet/puzzles/dao_treasury.clsp +115 -0
  896. chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
  897. chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
  898. chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
  899. chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
  900. chia/wallet/puzzles/json.clib +25 -0
  901. chia/wallet/puzzles/load_clvm.py +161 -0
  902. chia/wallet/puzzles/merkle_utils.clib +18 -0
  903. chia/wallet/puzzles/notification.clsp +7 -0
  904. chia/wallet/puzzles/notification.clsp.hex +1 -0
  905. chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
  906. chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
  907. chia/wallet/puzzles/p2_conditions.clsp +3 -0
  908. chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
  909. chia/wallet/puzzles/p2_conditions.py +26 -0
  910. chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
  911. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
  912. chia/wallet/puzzles/p2_delegated_conditions.py +21 -0
  913. chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
  914. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
  915. chia/wallet/puzzles/p2_delegated_puzzle.py +34 -0
  916. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
  917. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
  918. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +160 -0
  919. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
  920. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
  921. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +21 -0
  922. chia/wallet/puzzles/p2_parent.clsp +19 -0
  923. chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
  924. chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
  925. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
  926. chia/wallet/puzzles/p2_puzzle_hash.py +27 -0
  927. chia/wallet/puzzles/p2_singleton.clsp +30 -0
  928. chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
  929. chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
  930. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
  931. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
  932. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
  933. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
  934. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
  935. chia/wallet/puzzles/puzzle_utils.py +34 -0
  936. chia/wallet/puzzles/settlement_payments.clsp +49 -0
  937. chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
  938. chia/wallet/puzzles/sha256tree.clib +11 -0
  939. chia/wallet/puzzles/singleton_launcher.clsp +16 -0
  940. chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
  941. chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
  942. chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
  943. chia/wallet/puzzles/singleton_top_layer.py +296 -0
  944. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
  945. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
  946. chia/wallet/puzzles/singleton_top_layer_v1_1.py +345 -0
  947. chia/wallet/puzzles/singleton_truths.clib +21 -0
  948. chia/wallet/puzzles/tails.py +348 -0
  949. chia/wallet/puzzles/utility_macros.clib +48 -0
  950. chia/wallet/signer_protocol.py +125 -0
  951. chia/wallet/singleton.py +106 -0
  952. chia/wallet/singleton_record.py +30 -0
  953. chia/wallet/trade_manager.py +1102 -0
  954. chia/wallet/trade_record.py +67 -0
  955. chia/wallet/trading/__init__.py +0 -0
  956. chia/wallet/trading/offer.py +702 -0
  957. chia/wallet/trading/trade_status.py +13 -0
  958. chia/wallet/trading/trade_store.py +526 -0
  959. chia/wallet/transaction_record.py +158 -0
  960. chia/wallet/transaction_sorting.py +14 -0
  961. chia/wallet/uncurried_puzzle.py +17 -0
  962. chia/wallet/util/__init__.py +0 -0
  963. chia/wallet/util/address_type.py +55 -0
  964. chia/wallet/util/blind_signer_tl.py +164 -0
  965. chia/wallet/util/clvm_streamable.py +203 -0
  966. chia/wallet/util/compute_hints.py +66 -0
  967. chia/wallet/util/compute_memos.py +43 -0
  968. chia/wallet/util/curry_and_treehash.py +91 -0
  969. chia/wallet/util/debug_spend_bundle.py +232 -0
  970. chia/wallet/util/merkle_tree.py +100 -0
  971. chia/wallet/util/merkle_utils.py +102 -0
  972. chia/wallet/util/new_peak_queue.py +82 -0
  973. chia/wallet/util/notifications.py +12 -0
  974. chia/wallet/util/peer_request_cache.py +174 -0
  975. chia/wallet/util/pprint.py +39 -0
  976. chia/wallet/util/puzzle_compression.py +95 -0
  977. chia/wallet/util/puzzle_decorator.py +100 -0
  978. chia/wallet/util/puzzle_decorator_type.py +7 -0
  979. chia/wallet/util/query_filter.py +59 -0
  980. chia/wallet/util/transaction_type.py +23 -0
  981. chia/wallet/util/tx_config.py +158 -0
  982. chia/wallet/util/wallet_sync_utils.py +351 -0
  983. chia/wallet/util/wallet_types.py +72 -0
  984. chia/wallet/vc_wallet/__init__.py +0 -0
  985. chia/wallet/vc_wallet/cr_cat_drivers.py +664 -0
  986. chia/wallet/vc_wallet/cr_cat_wallet.py +877 -0
  987. chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
  988. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  989. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
  990. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
  991. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
  992. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
  993. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
  994. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
  995. chia/wallet/vc_wallet/vc_drivers.py +838 -0
  996. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  997. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
  998. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
  999. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
  1000. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
  1001. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
  1002. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
  1003. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
  1004. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
  1005. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
  1006. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
  1007. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
  1008. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
  1009. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
  1010. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
  1011. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
  1012. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
  1013. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
  1014. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
  1015. chia/wallet/vc_wallet/vc_store.py +263 -0
  1016. chia/wallet/vc_wallet/vc_wallet.py +638 -0
  1017. chia/wallet/wallet.py +698 -0
  1018. chia/wallet/wallet_action_scope.py +96 -0
  1019. chia/wallet/wallet_blockchain.py +244 -0
  1020. chia/wallet/wallet_coin_record.py +72 -0
  1021. chia/wallet/wallet_coin_store.py +351 -0
  1022. chia/wallet/wallet_info.py +35 -0
  1023. chia/wallet/wallet_interested_store.py +188 -0
  1024. chia/wallet/wallet_nft_store.py +279 -0
  1025. chia/wallet/wallet_node.py +1765 -0
  1026. chia/wallet/wallet_node_api.py +207 -0
  1027. chia/wallet/wallet_pool_store.py +119 -0
  1028. chia/wallet/wallet_protocol.py +90 -0
  1029. chia/wallet/wallet_puzzle_store.py +396 -0
  1030. chia/wallet/wallet_retry_store.py +70 -0
  1031. chia/wallet/wallet_singleton_store.py +259 -0
  1032. chia/wallet/wallet_spend_bundle.py +25 -0
  1033. chia/wallet/wallet_state_manager.py +2819 -0
  1034. chia/wallet/wallet_transaction_store.py +496 -0
  1035. chia/wallet/wallet_user_store.py +110 -0
  1036. chia/wallet/wallet_weight_proof_handler.py +126 -0
  1037. chia_blockchain-2.5.1rc1.dist-info/LICENSE +201 -0
  1038. chia_blockchain-2.5.1rc1.dist-info/METADATA +156 -0
  1039. chia_blockchain-2.5.1rc1.dist-info/RECORD +1042 -0
  1040. chia_blockchain-2.5.1rc1.dist-info/WHEEL +4 -0
  1041. chia_blockchain-2.5.1rc1.dist-info/entry_points.txt +17 -0
  1042. mozilla-ca/cacert.pem +3611 -0
@@ -0,0 +1,1826 @@
1
+ from __future__ import annotations
2
+
3
+ import tempfile
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+
8
+ from chia._tests.conftest import ConsensusMode
9
+ from chia._tests.environments.wallet import (
10
+ NewPuzzleHashError,
11
+ WalletEnvironment,
12
+ WalletStateTransition,
13
+ WalletTestFramework,
14
+ )
15
+ from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_not_none
16
+ from chia.protocols.wallet_protocol import CoinState
17
+ from chia.rpc.wallet_request_types import GetTransactionMemo, PushTX
18
+ from chia.simulator.simulator_protocol import ReorgProtocol
19
+ from chia.types.blockchain_format.coin import Coin, coin_as_list
20
+ from chia.types.blockchain_format.program import Program
21
+ from chia.types.blockchain_format.sized_bytes import bytes32
22
+ from chia.types.coin_spend import make_spend
23
+ from chia.util.bech32m import encode_puzzle_hash
24
+ from chia.util.db_wrapper import DBWrapper2
25
+ from chia.util.ints import uint32, uint64
26
+ from chia.wallet.cat_wallet.cat_constants import DEFAULT_CATS
27
+ from chia.wallet.cat_wallet.cat_info import LegacyCATInfo
28
+ from chia.wallet.cat_wallet.cat_utils import CAT_MOD, construct_cat_puzzle
29
+ from chia.wallet.cat_wallet.cat_wallet import CATWallet
30
+ from chia.wallet.derivation_record import DerivationRecord
31
+ from chia.wallet.derive_keys import master_pk_to_wallet_pk_unhardened
32
+ from chia.wallet.lineage_proof import LineageProof
33
+ from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import puzzle_hash_for_pk
34
+ from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
35
+ from chia.wallet.util.wallet_types import WalletType
36
+ from chia.wallet.wallet_info import WalletInfo
37
+ from chia.wallet.wallet_interested_store import WalletInterestedStore
38
+ from chia.wallet.wallet_node import WalletNode
39
+ from chia.wallet.wallet_state_manager import WalletStateManager
40
+
41
+
42
+ def check_wallets(node: WalletNode) -> int:
43
+ return len(node.wallet_state_manager.wallets.keys())
44
+
45
+
46
+ @pytest.mark.parametrize(
47
+ "wallet_environments",
48
+ [
49
+ {
50
+ "num_environments": 1,
51
+ "blocks_needed": [1],
52
+ }
53
+ ],
54
+ indirect=True,
55
+ )
56
+ @pytest.mark.limit_consensus_modes([ConsensusMode.PLAIN], reason="irrelevant")
57
+ @pytest.mark.anyio
58
+ async def test_cat_creation(wallet_environments: WalletTestFramework) -> None:
59
+ full_node_api = wallet_environments.full_node
60
+ wsm = wallet_environments.environments[0].wallet_state_manager
61
+ wallet = wallet_environments.environments[0].xch_wallet
62
+ wallet_node = wallet_environments.environments[0].node
63
+ wallet_environments.environments[0].wallet_aliases = {
64
+ "xch": 1,
65
+ "cat": 2,
66
+ }
67
+ test_amount = 100
68
+ test_fee = 10
69
+ async with wallet.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
70
+ cat_wallet = await CATWallet.create_new_cat_wallet(
71
+ wsm,
72
+ wallet,
73
+ {"identifier": "genesis_by_id"},
74
+ uint64(test_amount),
75
+ action_scope,
76
+ fee=uint64(test_fee),
77
+ )
78
+ # The next 2 lines are basically a noop, it just adds test coverage
79
+ cat_wallet = await CATWallet.create(wsm, wallet, cat_wallet.wallet_info)
80
+ await wsm.add_new_wallet(cat_wallet)
81
+
82
+ await wallet_environments.process_pending_states(
83
+ [
84
+ WalletStateTransition(
85
+ pre_block_balance_updates={
86
+ "xch": {
87
+ "confirmed_wallet_balance": 0,
88
+ "unconfirmed_wallet_balance": -test_amount + -test_fee,
89
+ "<=#spendable_balance": -test_amount + -test_fee,
90
+ "<=#max_send_amount": -test_amount + -test_fee,
91
+ ">=#pending_change": 1, # any amount increase
92
+ "pending_coin_removal_count": 1,
93
+ },
94
+ "cat": {
95
+ "init": True,
96
+ "confirmed_wallet_balance": 0,
97
+ "unconfirmed_wallet_balance": test_amount,
98
+ "spendable_balance": 0,
99
+ "max_send_amount": 0,
100
+ "pending_change": test_amount,
101
+ "pending_coin_removal_count": 1,
102
+ },
103
+ },
104
+ post_block_balance_updates={
105
+ "xch": {
106
+ "confirmed_wallet_balance": -test_amount + -test_fee,
107
+ "unconfirmed_wallet_balance": 0,
108
+ ">=#spendable_balance": 0,
109
+ ">=#max_send_amount": 0,
110
+ "<=#pending_change": 1, # any amount decrease
111
+ "pending_coin_removal_count": -1,
112
+ },
113
+ "cat": {
114
+ "confirmed_wallet_balance": test_amount,
115
+ "unconfirmed_wallet_balance": 0,
116
+ "spendable_balance": test_amount,
117
+ "max_send_amount": test_amount,
118
+ "pending_change": -test_amount,
119
+ "pending_coin_removal_count": -1,
120
+ "unspent_coin_count": 1,
121
+ },
122
+ },
123
+ )
124
+ ]
125
+ )
126
+
127
+ # Test migration
128
+ all_lineage = await cat_wallet.lineage_store.get_all_lineage_proofs()
129
+ current_info = cat_wallet.wallet_info
130
+ data_str = bytes(
131
+ LegacyCATInfo(
132
+ cat_wallet.cat_info.limitations_program_hash, cat_wallet.cat_info.my_tail, list(all_lineage.items())
133
+ )
134
+ ).hex()
135
+ wallet_info = WalletInfo(current_info.id, current_info.name, current_info.type, data_str)
136
+ new_cat_wallet = await CATWallet.create(wsm, wallet, wallet_info)
137
+ assert new_cat_wallet.cat_info.limitations_program_hash == cat_wallet.cat_info.limitations_program_hash
138
+ assert new_cat_wallet.cat_info.my_tail == cat_wallet.cat_info.my_tail
139
+ assert await cat_wallet.lineage_store.get_all_lineage_proofs() == all_lineage
140
+
141
+ height = full_node_api.full_node.blockchain.get_peak_height()
142
+ assert height is not None
143
+ await full_node_api.reorg_from_index_to_new_index(
144
+ ReorgProtocol(uint32(height - 1), uint32(height + 1), bytes32(32 * b"1"), None)
145
+ )
146
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, peak_height=uint32(height + 1))
147
+ # The "set_remainder" sections here are due to a peculiarity with how the creation method creates an incoming TX
148
+ # The creation method is for testing purposes only so we're not going to bother fixing it for any real reason
149
+ await wallet_environments.process_pending_states(
150
+ [
151
+ WalletStateTransition(
152
+ pre_block_balance_updates={
153
+ "xch": {
154
+ "confirmed_wallet_balance": test_amount + test_fee,
155
+ "unconfirmed_wallet_balance": 0,
156
+ "<=#spendable_balance": 1,
157
+ "<=#max_send_amount": 1,
158
+ ">=#pending_change": 1, # any amount increase
159
+ "pending_coin_removal_count": 1,
160
+ },
161
+ "cat": {
162
+ "confirmed_wallet_balance": -test_amount,
163
+ "spendable_balance": -test_amount,
164
+ "max_send_amount": -test_amount,
165
+ "unspent_coin_count": -1,
166
+ "set_remainder": True,
167
+ },
168
+ },
169
+ post_block_balance_updates={
170
+ "xch": {
171
+ "confirmed_wallet_balance": -test_amount + -test_fee,
172
+ "unconfirmed_wallet_balance": 0,
173
+ ">=#spendable_balance": 0,
174
+ ">=#max_send_amount": 0,
175
+ "<=#pending_change": 1, # any amount decrease
176
+ "pending_coin_removal_count": -1,
177
+ },
178
+ "cat": {
179
+ "confirmed_wallet_balance": test_amount,
180
+ "spendable_balance": test_amount,
181
+ "max_send_amount": test_amount,
182
+ "unspent_coin_count": 1,
183
+ "set_remainder": True,
184
+ },
185
+ },
186
+ ),
187
+ ]
188
+ )
189
+
190
+
191
+ @pytest.mark.parametrize(
192
+ "wallet_environments",
193
+ [
194
+ {
195
+ "num_environments": 1,
196
+ "blocks_needed": [1],
197
+ "reuse_puzhash": True, # irrelevant
198
+ "trusted": True, # irrelevant
199
+ }
200
+ ],
201
+ indirect=True,
202
+ )
203
+ @pytest.mark.limit_consensus_modes([ConsensusMode.PLAIN], reason="irrelevant")
204
+ @pytest.mark.anyio
205
+ async def test_cat_creation_unique_lineage_store(wallet_environments: WalletTestFramework) -> None:
206
+ wsm = wallet_environments.environments[0].wallet_state_manager
207
+ wallet = wallet_environments.environments[0].xch_wallet
208
+
209
+ async with wsm.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
210
+ cat_wallet_1 = await CATWallet.create_new_cat_wallet(
211
+ wsm,
212
+ wallet,
213
+ {"identifier": "genesis_by_id"},
214
+ uint64(100),
215
+ action_scope,
216
+ )
217
+ async with wsm.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
218
+ cat_wallet_2 = await CATWallet.create_new_cat_wallet(
219
+ wsm,
220
+ wallet,
221
+ {"identifier": "genesis_by_id"},
222
+ uint64(200),
223
+ action_scope,
224
+ )
225
+
226
+ proofs_1 = await cat_wallet_1.lineage_store.get_all_lineage_proofs()
227
+ proofs_2 = await cat_wallet_2.lineage_store.get_all_lineage_proofs()
228
+ assert len(proofs_1) == len(proofs_2)
229
+ assert proofs_1 != proofs_2
230
+ assert cat_wallet_1.lineage_store.table_name != cat_wallet_2.lineage_store.table_name
231
+
232
+
233
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
234
+ @pytest.mark.parametrize(
235
+ "wallet_environments",
236
+ [
237
+ {
238
+ "num_environments": 2,
239
+ "blocks_needed": [1, 1],
240
+ }
241
+ ],
242
+ indirect=True,
243
+ )
244
+ @pytest.mark.anyio
245
+ async def test_cat_spend(wallet_environments: WalletTestFramework) -> None:
246
+ # Setup
247
+ env_1: WalletEnvironment = wallet_environments.environments[0]
248
+ env_2: WalletEnvironment = wallet_environments.environments[1]
249
+ wallet_node = env_1.node
250
+ wallet_node_2 = env_2.node
251
+ wallet = env_1.xch_wallet
252
+ wallet2 = env_2.xch_wallet
253
+ full_node_api = wallet_environments.full_node
254
+
255
+ env_1.wallet_aliases = {
256
+ "xch": 1,
257
+ "cat": 2,
258
+ }
259
+ env_2.wallet_aliases = {
260
+ "xch": 1,
261
+ "cat": 2,
262
+ }
263
+
264
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
265
+ cat_wallet = await CATWallet.create_new_cat_wallet(
266
+ wallet_node.wallet_state_manager,
267
+ wallet,
268
+ {"identifier": "genesis_by_id"},
269
+ uint64(100),
270
+ action_scope,
271
+ )
272
+
273
+ await wallet_environments.process_pending_states(
274
+ [
275
+ WalletStateTransition(
276
+ pre_block_balance_updates={
277
+ "xch": {
278
+ "unconfirmed_wallet_balance": -100,
279
+ "<=#spendable_balance": -100,
280
+ "<=#max_send_amount": -100,
281
+ ">=#pending_change": 1, # any amount increase
282
+ "unspent_coin_count": 0,
283
+ "pending_coin_removal_count": 1,
284
+ },
285
+ "cat": {
286
+ "init": True,
287
+ "confirmed_wallet_balance": 0,
288
+ "unconfirmed_wallet_balance": 100,
289
+ "spendable_balance": 0,
290
+ "pending_change": 100, # A little weird but technically correct
291
+ "max_send_amount": 0,
292
+ "unspent_coin_count": 0,
293
+ "pending_coin_removal_count": 1, # The ephemeral eve spend
294
+ },
295
+ },
296
+ post_block_balance_updates={
297
+ "xch": {
298
+ "confirmed_wallet_balance": -100,
299
+ ">=#spendable_balance": 1, # any amount increase
300
+ ">=#max_send_amount": 1, # any amount increase
301
+ "<=#pending_change": -1, # any amount decrease
302
+ "unspent_coin_count": 0,
303
+ "pending_coin_removal_count": -1,
304
+ },
305
+ "cat": {
306
+ "confirmed_wallet_balance": 100,
307
+ "spendable_balance": 100,
308
+ "pending_change": -100,
309
+ "max_send_amount": 100,
310
+ "unspent_coin_count": 1,
311
+ "pending_coin_removal_count": -1,
312
+ },
313
+ },
314
+ ),
315
+ WalletStateTransition(),
316
+ ]
317
+ )
318
+
319
+ assert cat_wallet.cat_info.limitations_program_hash is not None
320
+ asset_id = cat_wallet.get_asset_id()
321
+
322
+ cat_wallet_2 = await CATWallet.get_or_create_wallet_for_cat(wallet_node_2.wallet_state_manager, wallet2, asset_id)
323
+
324
+ assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
325
+
326
+ cat_2_hash = await cat_wallet_2.standard_wallet.get_puzzle_hash(new=False)
327
+ async with cat_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
328
+ await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], action_scope, fee=uint64(1))
329
+ tx_id = None
330
+ for tx_record in action_scope.side_effects.transactions:
331
+ if tx_record.wallet_id == cat_wallet.id():
332
+ assert tx_record.to_puzzle_hash == cat_2_hash
333
+ if tx_record.spend_bundle is not None:
334
+ tx_id = tx_record.name
335
+ assert tx_id is not None
336
+ memos = await env_1.rpc_client.get_transaction_memo(GetTransactionMemo(transaction_id=tx_id))
337
+ assert len(memos.coins_with_memos) == 2
338
+ assert memos.coins_with_memos[1].memos[0] == cat_2_hash
339
+
340
+ await wallet_environments.process_pending_states(
341
+ [
342
+ WalletStateTransition(
343
+ pre_block_balance_updates={
344
+ "xch": {
345
+ "unconfirmed_wallet_balance": -1,
346
+ "<=#spendable_balance": -1,
347
+ "<=#max_send_amount": -1,
348
+ ">=#pending_change": 1, # any amount increase
349
+ "unspent_coin_count": 0,
350
+ "pending_coin_removal_count": 1,
351
+ },
352
+ "cat": {
353
+ "unconfirmed_wallet_balance": -60,
354
+ "spendable_balance": -100,
355
+ "max_send_amount": -100,
356
+ "pending_change": 40,
357
+ "unspent_coin_count": 0,
358
+ "pending_coin_removal_count": 1,
359
+ },
360
+ },
361
+ post_block_balance_updates={
362
+ "xch": {
363
+ "confirmed_wallet_balance": -1,
364
+ ">=#spendable_balance": 1, # any amount increase
365
+ ">=#max_send_amount": 1, # any amount increase
366
+ "<=#pending_change": -1, # any amount decrease
367
+ "unspent_coin_count": 0,
368
+ "pending_coin_removal_count": -1,
369
+ },
370
+ "cat": {
371
+ "confirmed_wallet_balance": -60,
372
+ "spendable_balance": 40,
373
+ "max_send_amount": 40,
374
+ "pending_change": -40,
375
+ "unspent_coin_count": 0,
376
+ "pending_coin_removal_count": -1,
377
+ },
378
+ },
379
+ ),
380
+ WalletStateTransition(
381
+ pre_block_balance_updates={
382
+ "cat": {
383
+ "init": True,
384
+ "confirmed_wallet_balance": 0,
385
+ "unconfirmed_wallet_balance": 0,
386
+ "spendable_balance": 0,
387
+ "pending_change": 0,
388
+ "max_send_amount": 0,
389
+ "unspent_coin_count": 0,
390
+ "pending_coin_removal_count": 0,
391
+ },
392
+ },
393
+ post_block_balance_updates={
394
+ "cat": {
395
+ "confirmed_wallet_balance": 60,
396
+ "unconfirmed_wallet_balance": 60,
397
+ "spendable_balance": 60,
398
+ "max_send_amount": 60,
399
+ "pending_change": 0,
400
+ "unspent_coin_count": 1,
401
+ "pending_coin_removal_count": 0,
402
+ },
403
+ },
404
+ ),
405
+ ]
406
+ )
407
+
408
+ async with cat_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
409
+ coins = await cat_wallet_2.select_coins(uint64(60), action_scope)
410
+ assert len(coins) == 1
411
+ coin = coins.pop()
412
+ tx_id = coin.name()
413
+ memos = await env_2.rpc_client.get_transaction_memo(GetTransactionMemo(transaction_id=tx_id))
414
+ assert len(memos.coins_with_memos) == 2
415
+ assert memos.coins_with_memos[1].memos[0] == cat_2_hash
416
+ cat_hash = await cat_wallet.standard_wallet.get_puzzle_hash(new=False)
417
+ async with cat_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
418
+ await cat_wallet_2.generate_signed_transaction([uint64(15)], [cat_hash], action_scope)
419
+
420
+ await wallet_environments.process_pending_states(
421
+ [
422
+ WalletStateTransition(
423
+ pre_block_balance_updates={},
424
+ post_block_balance_updates={
425
+ "cat": {
426
+ "confirmed_wallet_balance": 15,
427
+ "unconfirmed_wallet_balance": 15,
428
+ "pending_coin_removal_count": 0,
429
+ "spendable_balance": 15,
430
+ "max_send_amount": 15,
431
+ "pending_change": 0,
432
+ "unspent_coin_count": 1,
433
+ },
434
+ },
435
+ ),
436
+ WalletStateTransition(
437
+ pre_block_balance_updates={
438
+ "cat": {
439
+ "unconfirmed_wallet_balance": -15,
440
+ "spendable_balance": -60,
441
+ "pending_change": 45,
442
+ "max_send_amount": -60,
443
+ "unspent_coin_count": 0,
444
+ "pending_coin_removal_count": 1,
445
+ },
446
+ },
447
+ post_block_balance_updates={
448
+ "cat": {
449
+ "confirmed_wallet_balance": -15,
450
+ "pending_coin_removal_count": -1,
451
+ "spendable_balance": 45,
452
+ "max_send_amount": 45,
453
+ "pending_change": -45,
454
+ "unspent_coin_count": 0,
455
+ },
456
+ },
457
+ ),
458
+ ]
459
+ )
460
+
461
+ height = full_node_api.full_node.blockchain.get_peak_height()
462
+ assert height is not None
463
+ await full_node_api.reorg_from_index_to_new_index(
464
+ ReorgProtocol(uint32(height - 1), uint32(height + 1), bytes32(32 * b"1"), None)
465
+ )
466
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, peak_height=uint32(height + 1))
467
+ await env_1.change_balances(
468
+ {
469
+ "cat": {
470
+ "confirmed_wallet_balance": -15,
471
+ "unconfirmed_wallet_balance": -15,
472
+ "pending_coin_removal_count": 0,
473
+ "spendable_balance": -15,
474
+ "max_send_amount": -15,
475
+ "pending_change": 0,
476
+ "unspent_coin_count": -1,
477
+ },
478
+ }
479
+ )
480
+ await env_1.check_balances()
481
+
482
+
483
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
484
+ @pytest.mark.parametrize(
485
+ "wallet_environments",
486
+ [
487
+ {
488
+ "num_environments": 1,
489
+ "blocks_needed": [1],
490
+ "reuse_puzhash": True, # irrelevant
491
+ "trusted": True, # irrelevant
492
+ }
493
+ ],
494
+ indirect=True,
495
+ )
496
+ @pytest.mark.anyio
497
+ async def test_get_wallet_for_asset_id(wallet_environments: WalletTestFramework) -> None:
498
+ wsm = wallet_environments.environments[0].wallet_state_manager
499
+ wallet = wallet_environments.environments[0].xch_wallet
500
+
501
+ wallet_environments.environments[0].wallet_aliases = {
502
+ "xch": 1,
503
+ "cat": 2,
504
+ }
505
+
506
+ async with wsm.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
507
+ cat_wallet = await CATWallet.create_new_cat_wallet(
508
+ wsm,
509
+ wallet,
510
+ {"identifier": "genesis_by_id"},
511
+ uint64(100),
512
+ action_scope,
513
+ )
514
+
515
+ await wallet_environments.process_pending_states(
516
+ [
517
+ WalletStateTransition(
518
+ pre_block_balance_updates={
519
+ "xch": {"set_remainder": True},
520
+ "cat": {"init": True, "set_remainder": True},
521
+ },
522
+ post_block_balance_updates={
523
+ "xch": {"set_remainder": True},
524
+ "cat": {"set_remainder": True},
525
+ },
526
+ ),
527
+ ]
528
+ )
529
+
530
+ asset_id = cat_wallet.get_asset_id()
531
+ assert cat_wallet.cat_info.my_tail is not None
532
+ await cat_wallet.set_tail_program(bytes(cat_wallet.cat_info.my_tail).hex())
533
+ assert await wsm.get_wallet_for_asset_id(asset_id) == cat_wallet
534
+
535
+ # Test that the a default CAT will initialize correctly
536
+ asset = DEFAULT_CATS[next(iter(DEFAULT_CATS))]
537
+ asset_id = asset["asset_id"]
538
+ cat_wallet_2 = await CATWallet.get_or_create_wallet_for_cat(wsm, wallet, asset_id)
539
+ assert cat_wallet_2.get_name() == asset["name"]
540
+ await cat_wallet_2.set_name("Test Name")
541
+ assert cat_wallet_2.get_name() == "Test Name"
542
+
543
+
544
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
545
+ @pytest.mark.parametrize(
546
+ "wallet_environments",
547
+ [
548
+ {
549
+ "num_environments": 2,
550
+ "blocks_needed": [1, 1],
551
+ "reuse_puzhash": True,
552
+ }
553
+ ],
554
+ indirect=True,
555
+ )
556
+ @pytest.mark.anyio
557
+ async def test_cat_doesnt_see_eve(wallet_environments: WalletTestFramework) -> None:
558
+ # Setup
559
+ env_1: WalletEnvironment = wallet_environments.environments[0]
560
+ env_2: WalletEnvironment = wallet_environments.environments[1]
561
+ wallet_node = env_1.node
562
+ wallet_node_2 = env_2.node
563
+ wallet = env_1.xch_wallet
564
+ wallet2 = env_2.xch_wallet
565
+
566
+ env_1.wallet_aliases = {
567
+ "xch": 1,
568
+ "cat": 2,
569
+ }
570
+ env_2.wallet_aliases = {
571
+ "xch": 1,
572
+ "cat": 2,
573
+ }
574
+
575
+ async with wallet.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
576
+ cat_wallet = await CATWallet.create_new_cat_wallet(
577
+ wallet_node.wallet_state_manager,
578
+ wallet,
579
+ {"identifier": "genesis_by_id"},
580
+ uint64(100),
581
+ action_scope,
582
+ )
583
+
584
+ await wallet_environments.process_pending_states(
585
+ [
586
+ WalletStateTransition(
587
+ pre_block_balance_updates={
588
+ "xch": {"set_remainder": True},
589
+ "cat": {"init": True, "set_remainder": True},
590
+ },
591
+ post_block_balance_updates={
592
+ "xch": {"set_remainder": True},
593
+ "cat": {
594
+ "confirmed_wallet_balance": 100,
595
+ "unconfirmed_wallet_balance": 0,
596
+ "spendable_balance": 100,
597
+ "max_send_amount": 100,
598
+ "pending_change": -100,
599
+ "pending_coin_removal_count": -1,
600
+ "unspent_coin_count": 1,
601
+ },
602
+ },
603
+ ),
604
+ WalletStateTransition(
605
+ pre_block_balance_updates={},
606
+ post_block_balance_updates={},
607
+ ),
608
+ ]
609
+ )
610
+
611
+ assert cat_wallet.cat_info.limitations_program_hash is not None
612
+ asset_id = cat_wallet.get_asset_id()
613
+
614
+ cat_wallet_2 = await CATWallet.get_or_create_wallet_for_cat(wallet_node_2.wallet_state_manager, wallet2, asset_id)
615
+
616
+ assert cat_wallet.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
617
+
618
+ cat_2_hash = await cat_wallet_2.standard_wallet.get_puzzle_hash(new=False)
619
+ async with cat_wallet.wallet_state_manager.new_action_scope(
620
+ wallet_environments.tx_config, push=True
621
+ ) as action_scope:
622
+ await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], action_scope, fee=uint64(1))
623
+
624
+ await wallet_environments.process_pending_states(
625
+ [
626
+ WalletStateTransition(
627
+ pre_block_balance_updates={
628
+ "xch": {
629
+ "unconfirmed_wallet_balance": -1,
630
+ "<=#spendable_balance": -1,
631
+ "<=#max_send_amount": -1,
632
+ ">=#pending_change": 1, # any amount increase
633
+ "unspent_coin_count": 0,
634
+ "pending_coin_removal_count": 1,
635
+ },
636
+ "cat": {
637
+ "unconfirmed_wallet_balance": -60,
638
+ "spendable_balance": -100,
639
+ "max_send_amount": -100,
640
+ "pending_change": 40,
641
+ "unspent_coin_count": 0,
642
+ "pending_coin_removal_count": 1,
643
+ },
644
+ },
645
+ post_block_balance_updates={
646
+ "xch": {
647
+ "confirmed_wallet_balance": -1,
648
+ ">=#spendable_balance": 1, # any amount increase
649
+ ">=#max_send_amount": 1, # any amount increase
650
+ "<=#pending_change": -1, # any amount decrease
651
+ "unspent_coin_count": 0,
652
+ "pending_coin_removal_count": -1,
653
+ },
654
+ "cat": {
655
+ "confirmed_wallet_balance": -60,
656
+ "spendable_balance": 40,
657
+ "max_send_amount": 40,
658
+ "pending_change": -40,
659
+ "unspent_coin_count": 0,
660
+ "pending_coin_removal_count": -1,
661
+ },
662
+ },
663
+ ),
664
+ WalletStateTransition(
665
+ pre_block_balance_updates={
666
+ "cat": {
667
+ "init": True,
668
+ "confirmed_wallet_balance": 0,
669
+ "unconfirmed_wallet_balance": 0,
670
+ "spendable_balance": 0,
671
+ "pending_change": 0,
672
+ "max_send_amount": 0,
673
+ "unspent_coin_count": 0,
674
+ "pending_coin_removal_count": 0,
675
+ },
676
+ },
677
+ post_block_balance_updates={
678
+ "cat": {
679
+ "confirmed_wallet_balance": 60,
680
+ "unconfirmed_wallet_balance": 60,
681
+ "spendable_balance": 60,
682
+ "max_send_amount": 60,
683
+ "pending_change": 0,
684
+ "unspent_coin_count": 1,
685
+ "pending_coin_removal_count": 0,
686
+ },
687
+ },
688
+ ),
689
+ ]
690
+ )
691
+
692
+ cc2_ph = await cat_wallet_2.get_cat_puzzle_hash(new=False)
693
+ async with wallet.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
694
+ await wallet.wallet_state_manager.main_wallet.generate_signed_transaction(uint64(10), cc2_ph, action_scope)
695
+
696
+ await wallet_environments.process_pending_states(
697
+ [
698
+ WalletStateTransition(
699
+ pre_block_balance_updates={
700
+ "xch": {
701
+ "unconfirmed_wallet_balance": -10,
702
+ "<=#spendable_balance": -10,
703
+ "<=#max_send_amount": -10,
704
+ ">=#pending_change": 1, # any amount increase
705
+ "unspent_coin_count": 0,
706
+ "pending_coin_removal_count": 1,
707
+ },
708
+ },
709
+ post_block_balance_updates={
710
+ "xch": {
711
+ "confirmed_wallet_balance": -10,
712
+ ">=#spendable_balance": 1, # any amount increase
713
+ ">=#max_send_amount": 1, # any amount increase
714
+ "<=#pending_change": -1, # any amount decrease
715
+ "unspent_coin_count": 0,
716
+ "pending_coin_removal_count": -1,
717
+ },
718
+ },
719
+ ),
720
+ # No state changes should occur since this was an unspent eve CAT
721
+ WalletStateTransition(
722
+ pre_block_balance_updates={},
723
+ post_block_balance_updates={},
724
+ ),
725
+ ]
726
+ )
727
+
728
+ id = cat_wallet_2.id()
729
+ wsm = cat_wallet_2.wallet_state_manager
730
+
731
+ async def query_and_assert_transactions(wsm: WalletStateManager, id: uint32) -> int:
732
+ all_txs = await wsm.tx_store.get_all_transactions_for_wallet(id)
733
+ return len(list(filter(lambda tx: tx.amount == 10, all_txs)))
734
+
735
+ await time_out_assert(20, query_and_assert_transactions, 0, wsm, id)
736
+
737
+
738
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
739
+ @pytest.mark.parametrize(
740
+ "wallet_environments",
741
+ [
742
+ {
743
+ "num_environments": 3,
744
+ "blocks_needed": [1, 1, 1],
745
+ }
746
+ ],
747
+ indirect=True,
748
+ )
749
+ @pytest.mark.anyio
750
+ async def test_cat_spend_multiple(wallet_environments: WalletTestFramework) -> None:
751
+ # Setup
752
+ env_0: WalletEnvironment = wallet_environments.environments[0]
753
+ env_1: WalletEnvironment = wallet_environments.environments[1]
754
+ env_2: WalletEnvironment = wallet_environments.environments[2]
755
+ wallet_node_0 = env_0.node
756
+ wallet_node_1 = env_1.node
757
+ wallet_node_2 = env_2.node
758
+ wallet_0 = env_0.xch_wallet
759
+ wallet_1 = env_1.xch_wallet
760
+ wallet_2 = env_2.xch_wallet
761
+
762
+ env_0.wallet_aliases = {
763
+ "xch": 1,
764
+ "cat": 2,
765
+ }
766
+ env_1.wallet_aliases = {
767
+ "xch": 1,
768
+ "cat": 2,
769
+ }
770
+ env_2.wallet_aliases = {
771
+ "xch": 1,
772
+ "cat": 2,
773
+ }
774
+
775
+ async with wallet_0.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
776
+ cat_wallet_0 = await CATWallet.create_new_cat_wallet(
777
+ wallet_node_0.wallet_state_manager,
778
+ wallet_0,
779
+ {"identifier": "genesis_by_id"},
780
+ uint64(100),
781
+ action_scope,
782
+ )
783
+
784
+ await wallet_environments.process_pending_states(
785
+ [
786
+ WalletStateTransition(
787
+ pre_block_balance_updates={
788
+ "xch": {"set_remainder": True},
789
+ "cat": {"init": True, "set_remainder": True},
790
+ },
791
+ post_block_balance_updates={
792
+ "xch": {"set_remainder": True},
793
+ "cat": {
794
+ "confirmed_wallet_balance": 100,
795
+ "unconfirmed_wallet_balance": 0,
796
+ "spendable_balance": 100,
797
+ "max_send_amount": 100,
798
+ "pending_change": -100,
799
+ "pending_coin_removal_count": -1,
800
+ "unspent_coin_count": 1,
801
+ },
802
+ },
803
+ ),
804
+ WalletStateTransition(
805
+ pre_block_balance_updates={},
806
+ post_block_balance_updates={},
807
+ ),
808
+ WalletStateTransition(
809
+ pre_block_balance_updates={},
810
+ post_block_balance_updates={},
811
+ ),
812
+ ]
813
+ )
814
+
815
+ assert cat_wallet_0.cat_info.limitations_program_hash is not None
816
+ asset_id = cat_wallet_0.get_asset_id()
817
+
818
+ cat_wallet_1 = await CATWallet.get_or_create_wallet_for_cat(wallet_node_1.wallet_state_manager, wallet_1, asset_id)
819
+
820
+ cat_wallet_2 = await CATWallet.get_or_create_wallet_for_cat(wallet_node_2.wallet_state_manager, wallet_2, asset_id)
821
+
822
+ assert cat_wallet_0.cat_info.limitations_program_hash == cat_wallet_1.cat_info.limitations_program_hash
823
+ assert cat_wallet_0.cat_info.limitations_program_hash == cat_wallet_2.cat_info.limitations_program_hash
824
+
825
+ cat_1_hash = await cat_wallet_1.standard_wallet.get_puzzle_hash(new=False)
826
+ cat_2_hash = await cat_wallet_2.standard_wallet.get_puzzle_hash(new=False)
827
+
828
+ async with cat_wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
829
+ await cat_wallet_0.generate_signed_transaction([uint64(60), uint64(20)], [cat_1_hash, cat_2_hash], action_scope)
830
+
831
+ await wallet_environments.process_pending_states(
832
+ [
833
+ WalletStateTransition(
834
+ pre_block_balance_updates={
835
+ "cat": {
836
+ "unconfirmed_wallet_balance": -80,
837
+ "spendable_balance": -100,
838
+ "max_send_amount": -100,
839
+ "pending_change": 20,
840
+ "unspent_coin_count": 0,
841
+ "pending_coin_removal_count": 1,
842
+ },
843
+ },
844
+ post_block_balance_updates={
845
+ "cat": {
846
+ "confirmed_wallet_balance": -80,
847
+ "spendable_balance": 20,
848
+ "max_send_amount": 20,
849
+ "pending_change": -20,
850
+ "unspent_coin_count": 0,
851
+ "pending_coin_removal_count": -1,
852
+ },
853
+ },
854
+ ),
855
+ WalletStateTransition(
856
+ pre_block_balance_updates={
857
+ "cat": {
858
+ "init": True,
859
+ "confirmed_wallet_balance": 0,
860
+ "unconfirmed_wallet_balance": 0,
861
+ "spendable_balance": 0,
862
+ "pending_change": 0,
863
+ "max_send_amount": 0,
864
+ "unspent_coin_count": 0,
865
+ "pending_coin_removal_count": 0,
866
+ },
867
+ },
868
+ post_block_balance_updates={
869
+ "cat": {
870
+ "confirmed_wallet_balance": 60,
871
+ "unconfirmed_wallet_balance": 60,
872
+ "spendable_balance": 60,
873
+ "max_send_amount": 60,
874
+ "pending_change": 0,
875
+ "unspent_coin_count": 1,
876
+ "pending_coin_removal_count": 0,
877
+ },
878
+ },
879
+ ),
880
+ WalletStateTransition(
881
+ pre_block_balance_updates={
882
+ "cat": {
883
+ "init": True,
884
+ "confirmed_wallet_balance": 0,
885
+ "unconfirmed_wallet_balance": 0,
886
+ "spendable_balance": 0,
887
+ "pending_change": 0,
888
+ "max_send_amount": 0,
889
+ "unspent_coin_count": 0,
890
+ "pending_coin_removal_count": 0,
891
+ },
892
+ },
893
+ post_block_balance_updates={
894
+ "cat": {
895
+ "confirmed_wallet_balance": 20,
896
+ "unconfirmed_wallet_balance": 20,
897
+ "spendable_balance": 20,
898
+ "max_send_amount": 20,
899
+ "pending_change": 0,
900
+ "unspent_coin_count": 1,
901
+ "pending_coin_removal_count": 0,
902
+ },
903
+ },
904
+ ),
905
+ ]
906
+ )
907
+
908
+ cat_hash = await cat_wallet_0.standard_wallet.get_puzzle_hash(new=False)
909
+
910
+ async with cat_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
911
+ await cat_wallet_1.generate_signed_transaction([uint64(15)], [cat_hash], action_scope)
912
+
913
+ async with cat_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope_2:
914
+ await cat_wallet_2.generate_signed_transaction([uint64(20)], [cat_hash], action_scope_2)
915
+
916
+ await wallet_environments.process_pending_states(
917
+ [
918
+ WalletStateTransition(
919
+ pre_block_balance_updates={
920
+ "cat": {},
921
+ },
922
+ post_block_balance_updates={
923
+ "cat": {
924
+ "confirmed_wallet_balance": 35,
925
+ "unconfirmed_wallet_balance": 35,
926
+ "spendable_balance": 35,
927
+ "max_send_amount": 35,
928
+ "pending_change": 0,
929
+ "unspent_coin_count": 2,
930
+ "pending_coin_removal_count": 0,
931
+ },
932
+ },
933
+ ),
934
+ WalletStateTransition(
935
+ pre_block_balance_updates={
936
+ "cat": {
937
+ "unconfirmed_wallet_balance": -15,
938
+ "spendable_balance": -60,
939
+ "pending_change": 45,
940
+ "max_send_amount": -60,
941
+ "unspent_coin_count": 0,
942
+ "pending_coin_removal_count": 1,
943
+ },
944
+ },
945
+ post_block_balance_updates={
946
+ "cat": {
947
+ "confirmed_wallet_balance": -15,
948
+ "spendable_balance": 45,
949
+ "pending_change": -45,
950
+ "max_send_amount": 45,
951
+ "unspent_coin_count": 0,
952
+ "pending_coin_removal_count": -1,
953
+ },
954
+ },
955
+ ),
956
+ WalletStateTransition(
957
+ pre_block_balance_updates={
958
+ "cat": {
959
+ "unconfirmed_wallet_balance": -20,
960
+ "spendable_balance": -20,
961
+ "pending_change": 0,
962
+ "max_send_amount": -20,
963
+ "unspent_coin_count": 0,
964
+ "pending_coin_removal_count": 1,
965
+ },
966
+ },
967
+ post_block_balance_updates={
968
+ "cat": {
969
+ "confirmed_wallet_balance": -20,
970
+ "spendable_balance": 0,
971
+ "pending_change": 0,
972
+ "max_send_amount": 0,
973
+ "unspent_coin_count": -1,
974
+ "pending_coin_removal_count": -1,
975
+ },
976
+ },
977
+ ),
978
+ ]
979
+ )
980
+
981
+ # Test with Memo
982
+ async with cat_wallet_1.wallet_state_manager.new_action_scope(
983
+ wallet_environments.tx_config, push=True
984
+ ) as action_scope:
985
+ await cat_wallet_1.generate_signed_transaction(
986
+ [uint64(30)], [cat_hash], action_scope, memos=[[b"Markus Walburg"]]
987
+ )
988
+ with pytest.raises(ValueError):
989
+ async with cat_wallet_1.wallet_state_manager.new_action_scope(
990
+ DEFAULT_TX_CONFIG, push=False
991
+ ) as failed_action_scope:
992
+ await cat_wallet_1.generate_signed_transaction(
993
+ [uint64(30)],
994
+ [cat_hash],
995
+ failed_action_scope,
996
+ memos=[[b"too"], [b"many"], [b"memos"]],
997
+ )
998
+
999
+ await wallet_environments.process_pending_states(
1000
+ [
1001
+ WalletStateTransition(
1002
+ pre_block_balance_updates={
1003
+ "cat": {},
1004
+ },
1005
+ post_block_balance_updates={
1006
+ "cat": {
1007
+ "confirmed_wallet_balance": 30,
1008
+ "unconfirmed_wallet_balance": 30,
1009
+ "spendable_balance": 30,
1010
+ "max_send_amount": 30,
1011
+ "pending_change": 0,
1012
+ "unspent_coin_count": 1,
1013
+ "pending_coin_removal_count": 0,
1014
+ },
1015
+ },
1016
+ ),
1017
+ WalletStateTransition(
1018
+ pre_block_balance_updates={
1019
+ "cat": {
1020
+ "unconfirmed_wallet_balance": -30,
1021
+ "spendable_balance": -45,
1022
+ "pending_change": 15,
1023
+ "max_send_amount": -45,
1024
+ "unspent_coin_count": 0,
1025
+ "pending_coin_removal_count": 1,
1026
+ },
1027
+ },
1028
+ post_block_balance_updates={
1029
+ "cat": {
1030
+ "confirmed_wallet_balance": -30,
1031
+ "spendable_balance": 15,
1032
+ "pending_change": -15,
1033
+ "max_send_amount": 15,
1034
+ "unspent_coin_count": 0,
1035
+ "pending_coin_removal_count": -1,
1036
+ },
1037
+ },
1038
+ ),
1039
+ WalletStateTransition(
1040
+ pre_block_balance_updates={},
1041
+ post_block_balance_updates={},
1042
+ ),
1043
+ ]
1044
+ )
1045
+
1046
+ txs = await wallet_1.wallet_state_manager.tx_store.get_transactions_between(cat_wallet_1.id(), 0, 100000)
1047
+ for tx in txs:
1048
+ if tx.amount == 30:
1049
+ memos = tx.get_memos()
1050
+ assert len(memos) == 2 # One for tx, one for change
1051
+ assert b"Markus Walburg" in [v for v_list in memos.values() for v in v_list]
1052
+ assert tx.spend_bundle is not None
1053
+ assert next(iter(memos.keys())) in [a.name() for a in tx.spend_bundle.additions()]
1054
+
1055
+
1056
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1057
+ @pytest.mark.parametrize(
1058
+ "wallet_environments",
1059
+ [
1060
+ {
1061
+ "num_environments": 1,
1062
+ "blocks_needed": [1],
1063
+ "reuse_puzhash": True, # irrelevant
1064
+ "trusted": True, # irrelevant
1065
+ }
1066
+ ],
1067
+ indirect=True,
1068
+ )
1069
+ @pytest.mark.anyio
1070
+ async def test_cat_max_amount_send(wallet_environments: WalletTestFramework) -> None:
1071
+ # Setup
1072
+ env: WalletEnvironment = wallet_environments.environments[0]
1073
+ wallet_node = env.node
1074
+ wallet = env.xch_wallet
1075
+
1076
+ env.wallet_aliases = {
1077
+ "xch": 1,
1078
+ "cat": 2,
1079
+ }
1080
+
1081
+ async with wallet.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
1082
+ cat_wallet = await CATWallet.create_new_cat_wallet(
1083
+ wallet_node.wallet_state_manager,
1084
+ wallet,
1085
+ {"identifier": "genesis_by_id"},
1086
+ uint64(100000),
1087
+ action_scope,
1088
+ )
1089
+
1090
+ await wallet_environments.process_pending_states(
1091
+ [
1092
+ WalletStateTransition(
1093
+ pre_block_balance_updates={
1094
+ "xch": {"set_remainder": True},
1095
+ "cat": {"init": True, "set_remainder": True},
1096
+ },
1097
+ post_block_balance_updates={
1098
+ "xch": {"set_remainder": True},
1099
+ "cat": {
1100
+ "confirmed_wallet_balance": 100000,
1101
+ "unconfirmed_wallet_balance": 0,
1102
+ "spendable_balance": 100000,
1103
+ "max_send_amount": 100000,
1104
+ "pending_change": -100000,
1105
+ "pending_coin_removal_count": -1,
1106
+ "unspent_coin_count": 1,
1107
+ },
1108
+ },
1109
+ )
1110
+ ]
1111
+ )
1112
+
1113
+ assert cat_wallet.cat_info.limitations_program_hash is not None
1114
+
1115
+ cat_2 = await cat_wallet.standard_wallet.get_puzzle(new=False)
1116
+ cat_2_hash = cat_2.get_tree_hash()
1117
+ amounts = []
1118
+ puzzle_hashes = []
1119
+ for i in range(1, 50):
1120
+ amounts.append(uint64(i))
1121
+ puzzle_hashes.append(cat_2_hash)
1122
+ spent_coin = (await cat_wallet.get_cat_spendable_coins())[0].coin
1123
+ async with cat_wallet.wallet_state_manager.new_action_scope(
1124
+ wallet_environments.tx_config, push=True
1125
+ ) as action_scope:
1126
+ await cat_wallet.generate_signed_transaction(amounts, puzzle_hashes, action_scope, coins={spent_coin})
1127
+
1128
+ await wallet_environments.process_pending_states(
1129
+ [
1130
+ WalletStateTransition(
1131
+ pre_block_balance_updates={
1132
+ "cat": {
1133
+ "unconfirmed_wallet_balance": 0,
1134
+ "spendable_balance": -100000,
1135
+ "max_send_amount": -100000,
1136
+ "pending_change": 100000,
1137
+ "pending_coin_removal_count": 1,
1138
+ "unspent_coin_count": 0,
1139
+ },
1140
+ },
1141
+ post_block_balance_updates={
1142
+ "cat": {
1143
+ "confirmed_wallet_balance": 0,
1144
+ "spendable_balance": 100000,
1145
+ "max_send_amount": 100000,
1146
+ "pending_change": -100000,
1147
+ "pending_coin_removal_count": -1,
1148
+ "unspent_coin_count": 49,
1149
+ },
1150
+ },
1151
+ )
1152
+ ]
1153
+ )
1154
+
1155
+ async def check_all_there() -> bool:
1156
+ spendable = await cat_wallet.get_cat_spendable_coins()
1157
+ spendable_name_set = set()
1158
+ for record in spendable:
1159
+ spendable_name_set.add(record.coin.name())
1160
+ puzzle_hash = construct_cat_puzzle(CAT_MOD, cat_wallet.cat_info.limitations_program_hash, cat_2).get_tree_hash()
1161
+ for i in range(1, 50):
1162
+ coin = Coin(spent_coin.name(), puzzle_hash, uint64(i))
1163
+ if coin.name() not in spendable_name_set:
1164
+ return False
1165
+ return True
1166
+
1167
+ await time_out_assert(20, check_all_there, True)
1168
+ max_sent_amount = await cat_wallet.get_max_send_amount()
1169
+
1170
+ # 1) Generate transaction that is under the limit
1171
+ async with cat_wallet.wallet_state_manager.new_action_scope(
1172
+ wallet_environments.tx_config, push=False
1173
+ ) as action_scope:
1174
+ await cat_wallet.generate_signed_transaction([uint64(max_sent_amount - 1)], [bytes32.zeros], action_scope)
1175
+ assert action_scope.side_effects.transactions[0].amount == uint64(max_sent_amount - 1)
1176
+
1177
+ # 2) Generate transaction that is equal to limit
1178
+ async with cat_wallet.wallet_state_manager.new_action_scope(
1179
+ wallet_environments.tx_config, push=False
1180
+ ) as action_scope:
1181
+ await cat_wallet.generate_signed_transaction([uint64(max_sent_amount)], [bytes32.zeros], action_scope)
1182
+ assert action_scope.side_effects.transactions[0].amount == uint64(max_sent_amount)
1183
+
1184
+ # 3) Generate transaction that is greater than limit
1185
+ with pytest.raises(ValueError, match="Can't select amount higher than our spendable balance."):
1186
+ async with cat_wallet.wallet_state_manager.new_action_scope(
1187
+ wallet_environments.tx_config, push=False
1188
+ ) as action_scope:
1189
+ await cat_wallet.generate_signed_transaction([uint64(max_sent_amount + 1)], [bytes32.zeros], action_scope)
1190
+
1191
+
1192
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1193
+ @pytest.mark.parametrize(
1194
+ "wallet_environments",
1195
+ [
1196
+ {
1197
+ "num_environments": 2,
1198
+ "blocks_needed": [1, 1],
1199
+ "config_overrides": {"automatically_add_unknown_cats": True},
1200
+ },
1201
+ {
1202
+ "num_environments": 2,
1203
+ "blocks_needed": [1, 1],
1204
+ "config_overrides": {"automatically_add_unknown_cats": False},
1205
+ },
1206
+ ],
1207
+ indirect=True,
1208
+ )
1209
+ @pytest.mark.anyio
1210
+ async def test_cat_hint(wallet_environments: WalletTestFramework) -> None:
1211
+ # Setup
1212
+ env_1: WalletEnvironment = wallet_environments.environments[0]
1213
+ env_2: WalletEnvironment = wallet_environments.environments[1]
1214
+ wallet_node_1 = env_1.node
1215
+ wallet_node_2 = env_2.node
1216
+ wallet_1 = env_1.xch_wallet
1217
+ wallet_2 = env_2.xch_wallet
1218
+
1219
+ env_1.wallet_aliases = {
1220
+ "xch": 1,
1221
+ "cat": 2,
1222
+ }
1223
+ env_2.wallet_aliases = {
1224
+ "xch": 1,
1225
+ "cat": 2,
1226
+ }
1227
+
1228
+ autodiscovery = wallet_node_1.config["automatically_add_unknown_cats"]
1229
+
1230
+ async with wallet_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
1231
+ cat_wallet = await CATWallet.create_new_cat_wallet(
1232
+ wallet_node_1.wallet_state_manager,
1233
+ wallet_1,
1234
+ {"identifier": "genesis_by_id"},
1235
+ uint64(100),
1236
+ action_scope,
1237
+ )
1238
+
1239
+ await wallet_environments.process_pending_states(
1240
+ [
1241
+ WalletStateTransition(
1242
+ pre_block_balance_updates={
1243
+ "xch": {"set_remainder": True},
1244
+ "cat": {"init": True, "set_remainder": True},
1245
+ },
1246
+ post_block_balance_updates={
1247
+ "xch": {"set_remainder": True},
1248
+ "cat": {
1249
+ "confirmed_wallet_balance": 100,
1250
+ "unconfirmed_wallet_balance": 0,
1251
+ "spendable_balance": 100,
1252
+ "max_send_amount": 100,
1253
+ "pending_change": -100,
1254
+ "pending_coin_removal_count": -1,
1255
+ "unspent_coin_count": 1,
1256
+ },
1257
+ },
1258
+ ),
1259
+ WalletStateTransition(
1260
+ pre_block_balance_updates={},
1261
+ post_block_balance_updates={},
1262
+ ),
1263
+ ]
1264
+ )
1265
+
1266
+ assert cat_wallet.cat_info.limitations_program_hash is not None
1267
+
1268
+ cat_2_hash = await wallet_2.get_new_puzzlehash()
1269
+ async with wallet_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
1270
+ await cat_wallet.generate_signed_transaction([uint64(60)], [cat_2_hash], action_scope, memos=[[cat_2_hash]])
1271
+
1272
+ await wallet_environments.process_pending_states(
1273
+ [
1274
+ WalletStateTransition(
1275
+ pre_block_balance_updates={
1276
+ "cat": {
1277
+ "unconfirmed_wallet_balance": -60,
1278
+ "spendable_balance": -100,
1279
+ "max_send_amount": -100,
1280
+ "pending_change": 40,
1281
+ "unspent_coin_count": 0,
1282
+ "pending_coin_removal_count": 1,
1283
+ },
1284
+ },
1285
+ post_block_balance_updates={
1286
+ "cat": {
1287
+ "confirmed_wallet_balance": -60,
1288
+ "spendable_balance": 40,
1289
+ "max_send_amount": 40,
1290
+ "pending_change": -40,
1291
+ "unspent_coin_count": 0,
1292
+ "pending_coin_removal_count": -1,
1293
+ },
1294
+ },
1295
+ ),
1296
+ WalletStateTransition(
1297
+ pre_block_balance_updates={},
1298
+ post_block_balance_updates=(
1299
+ {
1300
+ "cat": {
1301
+ "init": True,
1302
+ "confirmed_wallet_balance": 60,
1303
+ "unconfirmed_wallet_balance": 60,
1304
+ "spendable_balance": 60,
1305
+ "max_send_amount": 60,
1306
+ "pending_change": 0,
1307
+ "unspent_coin_count": 1,
1308
+ "pending_coin_removal_count": 0,
1309
+ },
1310
+ }
1311
+ if autodiscovery
1312
+ else {}
1313
+ ),
1314
+ ),
1315
+ ]
1316
+ )
1317
+
1318
+ # Then we update the wallet's default CATs
1319
+ wallet_node_2.wallet_state_manager.default_cats = {
1320
+ cat_wallet.cat_info.limitations_program_hash.hex(): {
1321
+ "asset_id": cat_wallet.cat_info.limitations_program_hash.hex(),
1322
+ "name": "Test",
1323
+ "symbol": "TST",
1324
+ }
1325
+ }
1326
+
1327
+ # Then we send another transaction
1328
+ async with wallet_1.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
1329
+ await cat_wallet.generate_signed_transaction([uint64(10)], [cat_2_hash], action_scope, memos=[[cat_2_hash]])
1330
+
1331
+ await wallet_environments.process_pending_states(
1332
+ [
1333
+ WalletStateTransition(
1334
+ pre_block_balance_updates={
1335
+ "cat": {
1336
+ "unconfirmed_wallet_balance": -10,
1337
+ "spendable_balance": -40,
1338
+ "max_send_amount": -40,
1339
+ "pending_change": 30,
1340
+ "unspent_coin_count": 0,
1341
+ "pending_coin_removal_count": 1,
1342
+ },
1343
+ },
1344
+ post_block_balance_updates={
1345
+ "cat": {
1346
+ "confirmed_wallet_balance": -10,
1347
+ "spendable_balance": 30,
1348
+ "max_send_amount": 30,
1349
+ "pending_change": -30,
1350
+ "unspent_coin_count": 0,
1351
+ "pending_coin_removal_count": -1,
1352
+ },
1353
+ },
1354
+ ),
1355
+ WalletStateTransition(
1356
+ pre_block_balance_updates={},
1357
+ post_block_balance_updates=(
1358
+ {
1359
+ "cat": {
1360
+ "confirmed_wallet_balance": 10,
1361
+ "unconfirmed_wallet_balance": 10,
1362
+ "spendable_balance": 10,
1363
+ "max_send_amount": 10,
1364
+ "pending_change": 0,
1365
+ "unspent_coin_count": 1,
1366
+ "pending_coin_removal_count": 0,
1367
+ },
1368
+ }
1369
+ if autodiscovery
1370
+ else {
1371
+ "cat": {
1372
+ "init": True,
1373
+ "confirmed_wallet_balance": 70,
1374
+ "unconfirmed_wallet_balance": 70,
1375
+ "spendable_balance": 70,
1376
+ "max_send_amount": 70,
1377
+ "pending_change": 0,
1378
+ "unspent_coin_count": 2,
1379
+ "pending_coin_removal_count": 0,
1380
+ }
1381
+ }
1382
+ ),
1383
+ ),
1384
+ ]
1385
+ )
1386
+
1387
+ cat_wallet_2 = wallet_node_2.wallet_state_manager.wallets[uint32(2)]
1388
+ assert isinstance(cat_wallet_2, CATWallet)
1389
+
1390
+ cat_hash = await cat_wallet.standard_wallet.get_puzzle_hash(new=False)
1391
+ async with cat_wallet_2.wallet_state_manager.new_action_scope(
1392
+ wallet_environments.tx_config, push=True
1393
+ ) as action_scope:
1394
+ await cat_wallet_2.generate_signed_transaction([uint64(5)], [cat_hash], action_scope)
1395
+
1396
+ await wallet_environments.process_pending_states(
1397
+ [
1398
+ WalletStateTransition(
1399
+ pre_block_balance_updates={
1400
+ "cat": {},
1401
+ },
1402
+ post_block_balance_updates={
1403
+ "cat": {
1404
+ "confirmed_wallet_balance": 5,
1405
+ "unconfirmed_wallet_balance": 5,
1406
+ "spendable_balance": 5,
1407
+ "max_send_amount": 5,
1408
+ "pending_change": 0,
1409
+ "unspent_coin_count": 1,
1410
+ "pending_coin_removal_count": 0,
1411
+ },
1412
+ },
1413
+ ),
1414
+ WalletStateTransition(
1415
+ pre_block_balance_updates={
1416
+ "cat": {
1417
+ "unconfirmed_wallet_balance": -5,
1418
+ "<=#spendable_balance": -5,
1419
+ "<=#max_send_amount": -5,
1420
+ ">=#pending_change": 1,
1421
+ "unspent_coin_count": 0,
1422
+ "pending_coin_removal_count": 1,
1423
+ },
1424
+ },
1425
+ post_block_balance_updates={
1426
+ "cat": {
1427
+ "confirmed_wallet_balance": -5,
1428
+ ">=#spendable_balance": 1,
1429
+ ">=#max_send_amount": 1,
1430
+ "<=#pending_change": -1,
1431
+ "unspent_coin_count": 0,
1432
+ "pending_coin_removal_count": -1,
1433
+ },
1434
+ },
1435
+ ),
1436
+ ]
1437
+ )
1438
+
1439
+
1440
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1441
+ @pytest.mark.parametrize(
1442
+ "wallet_environments",
1443
+ [
1444
+ {
1445
+ "num_environments": 1,
1446
+ "blocks_needed": [1],
1447
+ "config_overrides": {"automatically_add_unknown_cats": True},
1448
+ },
1449
+ ],
1450
+ indirect=True,
1451
+ )
1452
+ @pytest.mark.anyio
1453
+ async def test_cat_change_detection(wallet_environments: WalletTestFramework) -> None:
1454
+ full_node_api = wallet_environments.full_node
1455
+ env = wallet_environments.environments[0]
1456
+ wsm = env.wallet_state_manager
1457
+ wallet = env.xch_wallet
1458
+
1459
+ env.wallet_aliases = {
1460
+ "xch": 1,
1461
+ "cat": 2,
1462
+ }
1463
+
1464
+ # Mint CAT to ourselves, immediately spend it to an unhinted puzzle hash that we have manually added to the DB
1465
+ # We should pick up this coin as balance even though it is unhinted because it is "change"
1466
+ pubkey_unhardened = master_pk_to_wallet_pk_unhardened(wsm.root_pubkey, uint32(100000000))
1467
+ inner_puzhash = puzzle_hash_for_pk(pubkey_unhardened)
1468
+ puzzlehash_unhardened = construct_cat_puzzle(
1469
+ CAT_MOD, Program.to(None).get_tree_hash(), inner_puzhash
1470
+ ).get_tree_hash_precalc(inner_puzhash)
1471
+ change_derivation = DerivationRecord(
1472
+ uint32(0), puzzlehash_unhardened, pubkey_unhardened, WalletType.CAT, uint32(2), False
1473
+ )
1474
+ # Insert the derivation record before the wallet exists so that it is not subscribed to
1475
+ await wsm.puzzle_store.add_derivation_paths([change_derivation])
1476
+ our_puzzle = await wallet.get_new_puzzle()
1477
+ cat_puzzle = construct_cat_puzzle(
1478
+ CAT_MOD,
1479
+ Program.to(None).get_tree_hash(),
1480
+ Program.to(1),
1481
+ )
1482
+ addr = encode_puzzle_hash(cat_puzzle.get_tree_hash(), "txch")
1483
+ cat_amount_0 = uint64(100)
1484
+ cat_amount_1 = uint64(5)
1485
+
1486
+ tx = (await env.rpc_client.send_transaction(1, cat_amount_0, addr, wallet_environments.tx_config)).transaction
1487
+ spend_bundle = tx.spend_bundle
1488
+ assert spend_bundle is not None
1489
+
1490
+ await wallet_environments.process_pending_states(
1491
+ [
1492
+ WalletStateTransition(
1493
+ pre_block_balance_updates={"xch": {"set_remainder": True}},
1494
+ post_block_balance_updates={"xch": {"set_remainder": True}},
1495
+ )
1496
+ ]
1497
+ )
1498
+
1499
+ # Do the eve spend back to our wallet and add the CR layer
1500
+ cat_coin = next(c for c in spend_bundle.additions() if c.amount == cat_amount_0)
1501
+ next_coin = Coin(
1502
+ cat_coin.name(),
1503
+ construct_cat_puzzle(CAT_MOD, Program.to(None).get_tree_hash(), our_puzzle).get_tree_hash(),
1504
+ cat_amount_0,
1505
+ )
1506
+ eve_spend, _ = await wsm.sign_bundle(
1507
+ [
1508
+ make_spend(
1509
+ cat_coin,
1510
+ cat_puzzle,
1511
+ Program.to(
1512
+ [
1513
+ Program.to(
1514
+ [
1515
+ [51, our_puzzle.get_tree_hash(), cat_amount_0, [our_puzzle.get_tree_hash()]],
1516
+ [51, None, -113, None, None],
1517
+ ]
1518
+ ),
1519
+ None,
1520
+ cat_coin.name(),
1521
+ coin_as_list(cat_coin),
1522
+ [cat_coin.parent_coin_info, Program.to(1).get_tree_hash(), cat_coin.amount],
1523
+ 0,
1524
+ 0,
1525
+ ]
1526
+ ),
1527
+ ),
1528
+ make_spend(
1529
+ next_coin,
1530
+ construct_cat_puzzle(CAT_MOD, Program.to(None).get_tree_hash(), our_puzzle),
1531
+ Program.to(
1532
+ [
1533
+ [
1534
+ None,
1535
+ (
1536
+ 1,
1537
+ [
1538
+ [51, inner_puzhash, cat_amount_1],
1539
+ [51, bytes32.zeros, cat_amount_0 - cat_amount_1],
1540
+ ],
1541
+ ),
1542
+ None,
1543
+ ],
1544
+ LineageProof(
1545
+ cat_coin.parent_coin_info, Program.to(1).get_tree_hash(), cat_amount_0
1546
+ ).to_program(),
1547
+ next_coin.name(),
1548
+ coin_as_list(next_coin),
1549
+ [next_coin.parent_coin_info, our_puzzle.get_tree_hash(), next_coin.amount],
1550
+ 0,
1551
+ 0,
1552
+ ]
1553
+ ),
1554
+ ),
1555
+ ],
1556
+ )
1557
+ await env.rpc_client.push_tx(PushTX(eve_spend))
1558
+ await time_out_assert_not_none(5, full_node_api.full_node.mempool_manager.get_spendbundle, eve_spend.name())
1559
+ await wallet_environments.process_pending_states(
1560
+ [
1561
+ WalletStateTransition(
1562
+ pre_block_balance_updates={},
1563
+ post_block_balance_updates={
1564
+ "cat": {
1565
+ "init": True,
1566
+ "confirmed_wallet_balance": 5,
1567
+ "unconfirmed_wallet_balance": 5,
1568
+ "spendable_balance": 5,
1569
+ "max_send_amount": 5,
1570
+ "unspent_coin_count": 1,
1571
+ }
1572
+ },
1573
+ )
1574
+ ]
1575
+ )
1576
+
1577
+ assert not full_node_api.full_node.subscriptions.has_puzzle_subscription(puzzlehash_unhardened)
1578
+
1579
+
1580
+ @pytest.mark.anyio
1581
+ async def test_unacknowledged_cat_table() -> None:
1582
+ with tempfile.TemporaryDirectory() as temporary_directory:
1583
+ db_name = Path(temporary_directory).joinpath("test.sqlite")
1584
+ db_name.parent.mkdir(parents=True, exist_ok=True)
1585
+ async with DBWrapper2.managed(database=db_name) as db_wrapper:
1586
+ interested_store = await WalletInterestedStore.create(db_wrapper)
1587
+
1588
+ def asset_id(i: int) -> bytes32:
1589
+ return bytes32([i] * 32)
1590
+
1591
+ def coin_state(i: int) -> CoinState:
1592
+ return CoinState(Coin(bytes32.zeros, bytes32.zeros, uint64(i)), None, None)
1593
+
1594
+ await interested_store.add_unacknowledged_coin_state(asset_id(0), coin_state(0), None)
1595
+ await interested_store.add_unacknowledged_coin_state(asset_id(1), coin_state(1), 100)
1596
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(0)) == [(coin_state(0), 0)]
1597
+ await interested_store.add_unacknowledged_coin_state(asset_id(0), coin_state(0), None)
1598
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(0)) == [(coin_state(0), 0)]
1599
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(1)) == [(coin_state(1), 100)]
1600
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(2)) == []
1601
+ await interested_store.rollback_to_block(50)
1602
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(1)) == []
1603
+ await interested_store.delete_unacknowledged_states_for_asset_id(asset_id(1))
1604
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(0)) == [(coin_state(0), 0)]
1605
+ await interested_store.delete_unacknowledged_states_for_asset_id(asset_id(0))
1606
+ assert await interested_store.get_unacknowledged_states_for_asset_id(asset_id(0)) == []
1607
+
1608
+
1609
+ @pytest.mark.parametrize(
1610
+ "wallet_environments",
1611
+ [
1612
+ {
1613
+ "num_environments": 1,
1614
+ "blocks_needed": [1],
1615
+ "reuse_puzhash": True, # Parameter doesn't matter for this test
1616
+ "config_overrides": {"automatically_add_unknown_cats": True},
1617
+ }
1618
+ ],
1619
+ indirect=True,
1620
+ )
1621
+ @pytest.mark.limit_consensus_modes([ConsensusMode.PLAIN], reason="irrelevant")
1622
+ @pytest.mark.anyio
1623
+ async def test_cat_melt_balance(wallet_environments: WalletTestFramework) -> None:
1624
+ # We push spend bundles direct to full node in this test because
1625
+ # we are testing correct observance independent of local state
1626
+ env = wallet_environments.environments[0]
1627
+ wallet = env.xch_wallet
1628
+ simulator = wallet_environments.full_node
1629
+ wallet_ph = await wallet.get_puzzle_hash(new=False)
1630
+
1631
+ env.wallet_aliases = {
1632
+ "xch": 1,
1633
+ "cat": 2,
1634
+ }
1635
+
1636
+ ACS = Program.to(1)
1637
+ ACS_TAIL = Program.to([])
1638
+ ACS_TAIL_HASH = ACS_TAIL.get_tree_hash()
1639
+ CAT_w_ACS = construct_cat_puzzle(CAT_MOD, ACS_TAIL_HASH, ACS)
1640
+ CAT_w_ACS_HASH = CAT_w_ACS.get_tree_hash()
1641
+
1642
+ from chia.simulator.simulator_protocol import GetAllCoinsProtocol
1643
+ from chia.wallet.cat_wallet.cat_utils import SpendableCAT, unsigned_spend_bundle_for_spendable_cats
1644
+ from chia.wallet.conditions import UnknownCondition
1645
+ from chia.wallet.payment import Payment
1646
+
1647
+ await simulator.farm_blocks_to_puzzlehash(count=1, farm_to=CAT_w_ACS_HASH, guarantee_transaction_blocks=True)
1648
+ await simulator.farm_blocks_to_puzzlehash(count=1)
1649
+ cat_coin = next(
1650
+ c.coin
1651
+ for c in await simulator.get_all_coins(GetAllCoinsProtocol(include_spent_coins=False))
1652
+ if c.coin.puzzle_hash == CAT_w_ACS_HASH
1653
+ )
1654
+
1655
+ tx_amount = 10
1656
+
1657
+ spend_to_wallet = unsigned_spend_bundle_for_spendable_cats(
1658
+ CAT_MOD,
1659
+ [
1660
+ SpendableCAT(
1661
+ coin=cat_coin,
1662
+ limitations_program_hash=ACS_TAIL_HASH,
1663
+ inner_puzzle=ACS,
1664
+ inner_solution=Program.to([[51, wallet_ph, tx_amount, [wallet_ph]], [51, None, -113, ACS_TAIL, None]]),
1665
+ extra_delta=tx_amount - cat_coin.amount,
1666
+ )
1667
+ ],
1668
+ )
1669
+ await env.rpc_client.push_tx(PushTX(spend_to_wallet))
1670
+ await time_out_assert(10, simulator.tx_id_in_mempool, True, spend_to_wallet.name())
1671
+
1672
+ await wallet_environments.process_pending_states(
1673
+ [
1674
+ WalletStateTransition(
1675
+ pre_block_balance_updates={},
1676
+ post_block_balance_updates={
1677
+ "xch": {},
1678
+ "cat": {
1679
+ "init": True,
1680
+ "confirmed_wallet_balance": tx_amount,
1681
+ "unconfirmed_wallet_balance": tx_amount,
1682
+ "spendable_balance": tx_amount,
1683
+ "max_send_amount": tx_amount,
1684
+ "unspent_coin_count": 1,
1685
+ },
1686
+ },
1687
+ )
1688
+ ]
1689
+ )
1690
+
1691
+ cat_wallet = env.wallet_state_manager.wallets[uint32(2)]
1692
+ assert isinstance(cat_wallet, CATWallet)
1693
+
1694
+ # Let's test that continuing to melt this CAT results in the correct balance changes
1695
+ for _ in range(0, 5):
1696
+ tx_amount -= 1
1697
+ new_coin = (await cat_wallet.get_cat_spendable_coins())[0].coin
1698
+ new_spend = unsigned_spend_bundle_for_spendable_cats(
1699
+ CAT_MOD,
1700
+ [
1701
+ SpendableCAT(
1702
+ coin=new_coin,
1703
+ limitations_program_hash=ACS_TAIL_HASH,
1704
+ inner_puzzle=await cat_wallet.inner_puzzle_for_cat_puzhash(new_coin.puzzle_hash),
1705
+ inner_solution=wallet.make_solution(
1706
+ primaries=[Payment(wallet_ph, uint64(tx_amount), [wallet_ph])],
1707
+ conditions=(
1708
+ UnknownCondition(
1709
+ opcode=Program.to(51),
1710
+ args=[Program.to(None), Program.to(-113), Program.to(ACS_TAIL), Program.to(None)],
1711
+ ),
1712
+ ),
1713
+ ),
1714
+ extra_delta=-1,
1715
+ )
1716
+ ],
1717
+ )
1718
+ signed_spend, _ = await env.wallet_state_manager.sign_bundle(new_spend.coin_spends)
1719
+ await env.rpc_client.push_tx(PushTX(signed_spend))
1720
+ await time_out_assert(10, simulator.tx_id_in_mempool, True, signed_spend.name())
1721
+
1722
+ await wallet_environments.process_pending_states(
1723
+ [
1724
+ WalletStateTransition(
1725
+ pre_block_balance_updates={},
1726
+ post_block_balance_updates={
1727
+ "xch": {},
1728
+ "cat": {
1729
+ "confirmed_wallet_balance": -1,
1730
+ "unconfirmed_wallet_balance": -1,
1731
+ "spendable_balance": -1,
1732
+ "max_send_amount": -1,
1733
+ },
1734
+ },
1735
+ )
1736
+ ]
1737
+ )
1738
+
1739
+
1740
+ @pytest.mark.parametrize(
1741
+ "wallet_environments",
1742
+ [
1743
+ {
1744
+ "num_environments": 1,
1745
+ "blocks_needed": [1],
1746
+ "trusted": True, # Parameter doesn't matter for this test
1747
+ "reuse_puzhash": True, # Important to test this is ignored in the duplicate change scenario
1748
+ }
1749
+ ],
1750
+ indirect=True,
1751
+ )
1752
+ @pytest.mark.limit_consensus_modes([ConsensusMode.PLAIN], reason="irrelevant")
1753
+ @pytest.mark.anyio
1754
+ async def test_cat_puzzle_hashes(wallet_environments: WalletTestFramework) -> None:
1755
+ env = wallet_environments.environments[0]
1756
+ wallet = env.xch_wallet
1757
+
1758
+ env.wallet_aliases = {
1759
+ "xch": 1,
1760
+ "cat": 2,
1761
+ }
1762
+
1763
+ async with env.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
1764
+ cat_wallet = await CATWallet.create_new_cat_wallet(
1765
+ env.node.wallet_state_manager,
1766
+ wallet,
1767
+ {"identifier": "genesis_by_id"},
1768
+ uint64(100),
1769
+ action_scope,
1770
+ )
1771
+
1772
+ await wallet_environments.process_pending_states(
1773
+ [
1774
+ WalletStateTransition(
1775
+ pre_block_balance_updates={
1776
+ "xch": {"set_remainder": True},
1777
+ "cat": {"init": True, "set_remainder": True},
1778
+ },
1779
+ post_block_balance_updates={
1780
+ "xch": {"set_remainder": True},
1781
+ "cat": {
1782
+ "confirmed_wallet_balance": 100,
1783
+ "unconfirmed_wallet_balance": 0,
1784
+ "spendable_balance": 100,
1785
+ "max_send_amount": 100,
1786
+ "pending_change": -100,
1787
+ "pending_coin_removal_count": -1,
1788
+ "unspent_coin_count": 1,
1789
+ },
1790
+ },
1791
+ ),
1792
+ ]
1793
+ )
1794
+
1795
+ # Test that we attempt a new puzzle hash here even though everything says we shouldn't
1796
+ with pytest.raises(NewPuzzleHashError):
1797
+ async with env.wallet_state_manager.new_action_scope(wallet_environments.tx_config, push=True) as action_scope:
1798
+ await cat_wallet.generate_signed_transaction(
1799
+ [uint64(50)], [await cat_wallet.standard_wallet.get_puzzle_hash(new=False)], action_scope
1800
+ )
1801
+
1802
+ # Test new puzzle hash getting
1803
+ current_derivation_index = await env.wallet_state_manager.puzzle_store.get_current_derivation_record_for_wallet(
1804
+ uint32(env.wallet_aliases["cat"])
1805
+ )
1806
+ assert current_derivation_index is not None
1807
+ await cat_wallet.get_cat_puzzle_hash(new=True)
1808
+ next_derivation_index = await env.wallet_state_manager.puzzle_store.get_current_derivation_record_for_wallet(
1809
+ uint32(env.wallet_aliases["cat"])
1810
+ )
1811
+ assert next_derivation_index is not None
1812
+ assert current_derivation_index.index < next_derivation_index.index
1813
+
1814
+ # Test a weird edge case where a new puzzle hash needs to get generated
1815
+ # First, we reset the used status of all puzzle hashes by re-adding them
1816
+ for puzhash in await env.wallet_state_manager.puzzle_store.get_all_puzzle_hashes():
1817
+ dr = await env.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(puzhash)
1818
+ assert dr is not None
1819
+ await env.wallet_state_manager.puzzle_store.add_derivation_paths([dr])
1820
+
1821
+ # Then we make sure that even though we asked for a used puzzle hash, it still gives us an unused one
1822
+ unused_count = await env.wallet_state_manager.puzzle_store.get_unused_count(uint32(env.wallet_aliases["cat"]))
1823
+ await cat_wallet.get_cat_puzzle_hash(new=False)
1824
+ assert unused_count < await env.wallet_state_manager.puzzle_store.get_unused_count(
1825
+ uint32(env.wallet_aliases["cat"])
1826
+ )