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,2284 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import json
5
+
6
+ import pytest
7
+ from chia_rs import AugSchemeMPL, G1Element, G2Element
8
+
9
+ from chia._tests.conftest import ConsensusMode
10
+ from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework
11
+ from chia._tests.util.setup_nodes import OldSimulatorsAndWallets
12
+ from chia._tests.util.time_out_assert import time_out_assert
13
+ from chia.rpc.wallet_request_types import DIDGetCurrentCoinInfo, DIDGetRecoveryInfo
14
+ from chia.rpc.wallet_rpc_api import WalletRpcApi
15
+ from chia.server.server import ChiaServer
16
+ from chia.simulator.block_tools import BlockTools
17
+ from chia.simulator.full_node_simulator import FullNodeSimulator
18
+ from chia.simulator.simulator_protocol import FarmNewBlockProtocol
19
+ from chia.types.blockchain_format.program import Program
20
+ from chia.types.blockchain_format.sized_bytes import bytes32
21
+ from chia.types.condition_opcodes import ConditionOpcode
22
+ from chia.types.peer_info import PeerInfo
23
+ from chia.types.signing_mode import CHIP_0002_SIGN_MESSAGE_PREFIX
24
+ from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash
25
+ from chia.util.condition_tools import conditions_dict_for_solution
26
+ from chia.util.ints import uint16, uint32, uint64
27
+ from chia.wallet.did_wallet.did_wallet import DIDWallet
28
+ from chia.wallet.singleton import create_singleton_puzzle
29
+ from chia.wallet.util.address_type import AddressType
30
+ from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
31
+ from chia.wallet.util.wallet_types import WalletType
32
+ from chia.wallet.wallet_node import WalletNode
33
+ from chia.wallet.wallet_spend_bundle import WalletSpendBundle
34
+
35
+
36
+ async def get_wallet_num(wallet_manager):
37
+ return len(await wallet_manager.get_all_wallet_info_entries())
38
+
39
+
40
+ def get_parent_num(did_wallet: DIDWallet):
41
+ return len(did_wallet.did_info.parent_info)
42
+
43
+
44
+ class TestDIDWallet:
45
+ # TODO: See Issue CHIA-1544
46
+ # This test should be ported to WalletTestFramework once we can replace keys in the wallet node
47
+ @pytest.mark.parametrize(
48
+ "trusted",
49
+ [True, False],
50
+ )
51
+ @pytest.mark.anyio
52
+ async def test_creation_from_coin_spend(
53
+ self, self_hostname: str, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted: bool
54
+ ) -> None:
55
+ """
56
+ Verify that DIDWallet.create_new_did_wallet_from_coin_spend() is called after Singleton creation on
57
+ the blockchain, and that the wallet is created in the second wallet node.
58
+ """
59
+ full_nodes, wallets, _ = two_nodes_two_wallets_with_same_keys
60
+ full_node_api = full_nodes[0]
61
+ full_node_server = full_node_api.server
62
+ wallet_node_0, server_0 = wallets[0]
63
+ wallet_node_1, server_1 = wallets[1]
64
+
65
+ wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
66
+ wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
67
+
68
+ ph0 = await wallet_0.get_new_puzzlehash()
69
+ ph1 = await wallet_1.get_new_puzzlehash()
70
+
71
+ sk0 = await wallet_node_0.wallet_state_manager.get_private_key(ph0)
72
+ sk1 = await wallet_node_1.wallet_state_manager.get_private_key(ph1)
73
+ assert sk0 == sk1
74
+
75
+ if trusted:
76
+ wallet_node_0.config["trusted_peers"] = {
77
+ full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
78
+ }
79
+ wallet_node_1.config["trusted_peers"] = {
80
+ full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
81
+ }
82
+
83
+ else:
84
+ wallet_node_0.config["trusted_peers"] = {}
85
+ wallet_node_1.config["trusted_peers"] = {}
86
+ await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
87
+ await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
88
+
89
+ await full_node_api.farm_blocks_to_wallet(1, wallet_0)
90
+ await full_node_api.farm_blocks_to_wallet(1, wallet_1)
91
+
92
+ # Wallet1 sets up DIDWallet1 without any backup set
93
+ async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
94
+ did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet(
95
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
96
+ )
97
+
98
+ with pytest.raises(RuntimeError):
99
+ assert await did_wallet_0.get_coin() == set()
100
+ assert await did_wallet_0.get_info_for_recovery() is None
101
+
102
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
103
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0, wallet_node_1])
104
+
105
+ await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101)
106
+ await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101)
107
+ await time_out_assert(15, did_wallet_0.get_pending_change_balance, 0)
108
+
109
+ await full_node_api.farm_blocks_to_wallet(1, wallet_0)
110
+
111
+ #######################
112
+ all_node_0_wallets = await wallet_node_0.wallet_state_manager.user_store.get_all_wallet_info_entries()
113
+ all_node_1_wallets = await wallet_node_1.wallet_state_manager.user_store.get_all_wallet_info_entries()
114
+ assert (
115
+ json.loads(all_node_0_wallets[1].data)["current_inner"]
116
+ == json.loads(all_node_1_wallets[1].data)["current_inner"]
117
+ )
118
+
119
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
120
+ @pytest.mark.parametrize(
121
+ "wallet_environments",
122
+ [
123
+ {
124
+ "num_environments": 3,
125
+ "blocks_needed": [1, 1, 1],
126
+ }
127
+ ],
128
+ indirect=True,
129
+ )
130
+ @pytest.mark.anyio
131
+ @pytest.mark.limit_consensus_modes(reason="irrelevant")
132
+ async def test_creation_from_backup_file(self, wallet_environments: WalletTestFramework) -> None:
133
+ env_0 = wallet_environments.environments[0]
134
+ env_1 = wallet_environments.environments[1]
135
+ env_2 = wallet_environments.environments[2]
136
+
137
+ env_0.wallet_aliases = {
138
+ "xch": 1,
139
+ "did": 2,
140
+ }
141
+ env_1.wallet_aliases = {
142
+ "xch": 1,
143
+ "did": 2,
144
+ }
145
+ env_2.wallet_aliases = {
146
+ "xch": 1,
147
+ "did": 2,
148
+ }
149
+
150
+ # Wallet1 sets up DIDWallet1 without any backup set
151
+ async with env_0.wallet_state_manager.new_action_scope(
152
+ wallet_environments.tx_config, push=True
153
+ ) as action_scope:
154
+ did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet(
155
+ env_0.wallet_state_manager, env_0.xch_wallet, uint64(101), action_scope
156
+ )
157
+
158
+ await wallet_environments.process_pending_states(
159
+ [
160
+ WalletStateTransition(
161
+ pre_block_balance_updates={
162
+ "xch": {
163
+ "unconfirmed_wallet_balance": -101,
164
+ "<=#spendable_balance": -101,
165
+ "<=#max_send_amount": -101,
166
+ ">=#pending_change": 1,
167
+ "pending_coin_removal_count": 1,
168
+ },
169
+ "did": {
170
+ "init": True,
171
+ "unconfirmed_wallet_balance": 101,
172
+ "pending_change": 101,
173
+ "pending_coin_removal_count": 1,
174
+ },
175
+ },
176
+ post_block_balance_updates={
177
+ "xch": {
178
+ "confirmed_wallet_balance": -101,
179
+ ">=#spendable_balance": 1,
180
+ ">=#max_send_amount": 1,
181
+ "<=#pending_change": -1,
182
+ "pending_coin_removal_count": -1,
183
+ },
184
+ "did": {
185
+ "confirmed_wallet_balance": 101,
186
+ "spendable_balance": 101,
187
+ "max_send_amount": 101,
188
+ "unspent_coin_count": 1,
189
+ "pending_change": -101,
190
+ "pending_coin_removal_count": -1,
191
+ },
192
+ },
193
+ ),
194
+ WalletStateTransition(
195
+ pre_block_balance_updates={},
196
+ post_block_balance_updates={},
197
+ ),
198
+ WalletStateTransition(
199
+ pre_block_balance_updates={},
200
+ post_block_balance_updates={},
201
+ ),
202
+ ]
203
+ )
204
+
205
+ # Wallet1 sets up DIDWallet_1 with DIDWallet_0 as backup
206
+ backup_ids = [bytes32.from_hexstr(did_wallet_0.get_my_DID())]
207
+
208
+ async with env_1.wallet_state_manager.new_action_scope(
209
+ wallet_environments.tx_config, push=True
210
+ ) as action_scope:
211
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
212
+ env_1.wallet_state_manager, env_1.xch_wallet, uint64(201), action_scope, backup_ids
213
+ )
214
+
215
+ await wallet_environments.process_pending_states(
216
+ [
217
+ WalletStateTransition(
218
+ pre_block_balance_updates={},
219
+ post_block_balance_updates={},
220
+ ),
221
+ WalletStateTransition(
222
+ pre_block_balance_updates={
223
+ "xch": {
224
+ "unconfirmed_wallet_balance": -201,
225
+ "<=#spendable_balance": -201,
226
+ "<=#max_send_amount": -201,
227
+ ">=#pending_change": 1,
228
+ "pending_coin_removal_count": 1,
229
+ },
230
+ "did": {
231
+ "init": True,
232
+ "unconfirmed_wallet_balance": 201,
233
+ "pending_change": 201,
234
+ "pending_coin_removal_count": 1,
235
+ },
236
+ },
237
+ post_block_balance_updates={
238
+ "xch": {
239
+ "confirmed_wallet_balance": -201,
240
+ ">=#spendable_balance": 1,
241
+ ">=#max_send_amount": 1,
242
+ "<=#pending_change": -1,
243
+ "pending_coin_removal_count": -1,
244
+ },
245
+ "did": {
246
+ "confirmed_wallet_balance": 201,
247
+ "spendable_balance": 201,
248
+ "max_send_amount": 201,
249
+ "unspent_coin_count": 1,
250
+ "pending_change": -201,
251
+ "pending_coin_removal_count": -1,
252
+ },
253
+ },
254
+ ),
255
+ WalletStateTransition(
256
+ pre_block_balance_updates={},
257
+ post_block_balance_updates={},
258
+ ),
259
+ ]
260
+ )
261
+
262
+ backup_data = did_wallet_1.create_backup()
263
+
264
+ # Wallet2 recovers DIDWallet2 to a new set of keys
265
+ await env_2.rpc_client.create_new_did_wallet(
266
+ uint64(1),
267
+ DEFAULT_TX_CONFIG,
268
+ type="recovery",
269
+ backup_data=backup_data,
270
+ )
271
+ did_wallet_2 = env_2.wallet_state_manager.get_wallet(id=uint32(2), required_type=DIDWallet)
272
+ recovery_info = await env_2.rpc_client.did_get_recovery_info(
273
+ DIDGetRecoveryInfo(uint32(env_2.wallet_aliases["did"]))
274
+ )
275
+ assert recovery_info.wallet_id == env_2.wallet_aliases["did"]
276
+ assert recovery_info.backup_dids == backup_ids
277
+ current_coin_info_response = await env_0.rpc_client.did_get_current_coin_info(
278
+ DIDGetCurrentCoinInfo(uint32(env_0.wallet_aliases["did"]))
279
+ )
280
+ # TODO: this check is kind of weak, we should research when this endpoint might actually be useful
281
+ assert current_coin_info_response.wallet_id == env_0.wallet_aliases["did"]
282
+ async with env_0.wallet_state_manager.new_action_scope(
283
+ wallet_environments.tx_config, push=True
284
+ ) as action_scope:
285
+ message_spend_bundle, attest_data = await did_wallet_0.create_attestment(
286
+ recovery_info.coin_name, recovery_info.newpuzhash, recovery_info.pubkey, action_scope
287
+ )
288
+
289
+ await wallet_environments.process_pending_states(
290
+ [
291
+ WalletStateTransition(
292
+ pre_block_balance_updates={
293
+ "did": {
294
+ "spendable_balance": -101,
295
+ "pending_change": 101,
296
+ "pending_coin_removal_count": 1,
297
+ "max_send_amount": -101,
298
+ }
299
+ },
300
+ post_block_balance_updates={
301
+ "did": {
302
+ "spendable_balance": 101,
303
+ "pending_change": -101,
304
+ "pending_coin_removal_count": -1,
305
+ "max_send_amount": 101,
306
+ }
307
+ },
308
+ ),
309
+ WalletStateTransition(
310
+ pre_block_balance_updates={},
311
+ post_block_balance_updates={},
312
+ ),
313
+ WalletStateTransition(
314
+ pre_block_balance_updates={
315
+ "did": {
316
+ "init": True,
317
+ }
318
+ },
319
+ post_block_balance_updates={},
320
+ ),
321
+ ]
322
+ )
323
+
324
+ (
325
+ test_info_list,
326
+ test_message_spend_bundle,
327
+ ) = await did_wallet_2.load_attest_files_for_recovery_spend([attest_data])
328
+ assert message_spend_bundle == test_message_spend_bundle
329
+
330
+ async with env_2.wallet_state_manager.new_action_scope(
331
+ wallet_environments.tx_config, push=True
332
+ ) as action_scope:
333
+ assert did_wallet_2.did_info.temp_coin is not None
334
+ await did_wallet_2.recovery_spend(
335
+ did_wallet_2.did_info.temp_coin,
336
+ recovery_info.newpuzhash,
337
+ test_info_list,
338
+ recovery_info.pubkey,
339
+ test_message_spend_bundle,
340
+ action_scope,
341
+ )
342
+
343
+ await wallet_environments.process_pending_states(
344
+ [
345
+ WalletStateTransition(
346
+ pre_block_balance_updates={},
347
+ post_block_balance_updates={},
348
+ ),
349
+ WalletStateTransition(
350
+ pre_block_balance_updates={},
351
+ post_block_balance_updates={
352
+ "did": {
353
+ "confirmed_wallet_balance": -201,
354
+ "unconfirmed_wallet_balance": -201,
355
+ "spendable_balance": -201,
356
+ "max_send_amount": -201,
357
+ "unspent_coin_count": -1,
358
+ }
359
+ },
360
+ ),
361
+ WalletStateTransition(
362
+ pre_block_balance_updates={
363
+ "did": {
364
+ "unconfirmed_wallet_balance": 201,
365
+ "pending_coin_removal_count": 2,
366
+ }
367
+ },
368
+ post_block_balance_updates={
369
+ "did": {
370
+ "confirmed_wallet_balance": 201,
371
+ "spendable_balance": 201,
372
+ "max_send_amount": 201,
373
+ "unspent_coin_count": 1,
374
+ "pending_coin_removal_count": -2,
375
+ }
376
+ },
377
+ ),
378
+ ]
379
+ )
380
+
381
+ for wallet in [did_wallet_0, did_wallet_1, did_wallet_2]:
382
+ assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
383
+
384
+ some_ph = bytes32(32 * b"\2")
385
+ async with env_2.wallet_state_manager.new_action_scope(
386
+ wallet_environments.tx_config, push=True
387
+ ) as action_scope:
388
+ await did_wallet_2.create_exit_spend(some_ph, action_scope)
389
+
390
+ await wallet_environments.process_pending_states(
391
+ [
392
+ WalletStateTransition(
393
+ pre_block_balance_updates={},
394
+ post_block_balance_updates={},
395
+ ),
396
+ WalletStateTransition(
397
+ pre_block_balance_updates={},
398
+ post_block_balance_updates={},
399
+ ),
400
+ WalletStateTransition(
401
+ pre_block_balance_updates={
402
+ "did": {
403
+ "unconfirmed_wallet_balance": -201,
404
+ "spendable_balance": -201,
405
+ "max_send_amount": -201,
406
+ "pending_coin_removal_count": 1,
407
+ }
408
+ },
409
+ post_block_balance_updates={
410
+ "did": {
411
+ "confirmed_wallet_balance": -201,
412
+ "unspent_coin_count": -1,
413
+ "pending_coin_removal_count": -1,
414
+ }
415
+ },
416
+ ),
417
+ ]
418
+ )
419
+
420
+ async def get_coins_with_ph() -> bool:
421
+ coins = await wallet_environments.full_node.full_node.coin_store.get_coin_records_by_puzzle_hash(
422
+ True, some_ph
423
+ )
424
+ return len(coins) == 1
425
+
426
+ await time_out_assert(15, get_coins_with_ph, True)
427
+
428
+ for wallet in [did_wallet_0, did_wallet_1]:
429
+ assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
430
+
431
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
432
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
433
+ @pytest.mark.anyio
434
+ async def test_did_recovery_with_multiple_backup_dids(self, wallet_environments: WalletTestFramework):
435
+ env_0 = wallet_environments.environments[0]
436
+ env_1 = wallet_environments.environments[1]
437
+ wallet_node_0 = env_0.node
438
+ wallet_node_1 = env_1.node
439
+ wallet_0 = env_0.xch_wallet
440
+ wallet_1 = env_1.xch_wallet
441
+
442
+ env_0.wallet_aliases = {
443
+ "xch": 1,
444
+ "did": 2,
445
+ }
446
+ env_1.wallet_aliases = {
447
+ "xch": 1,
448
+ "did": 2,
449
+ }
450
+
451
+ async with wallet_0.wallet_state_manager.new_action_scope(
452
+ wallet_environments.tx_config, push=True
453
+ ) as action_scope:
454
+ did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
455
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
456
+ )
457
+ assert did_wallet.get_name() == "Profile 1"
458
+ recovery_list = [bytes32.from_hexstr(did_wallet.get_my_DID())]
459
+
460
+ async with wallet_1.wallet_state_manager.new_action_scope(
461
+ wallet_environments.tx_config, push=True
462
+ ) as action_scope:
463
+ did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet(
464
+ wallet_node_1.wallet_state_manager, wallet_1, uint64(101), action_scope, recovery_list
465
+ )
466
+
467
+ await wallet_environments.process_pending_states(
468
+ [
469
+ WalletStateTransition(
470
+ pre_block_balance_updates={
471
+ "xch": {
472
+ "set_remainder": True,
473
+ },
474
+ "did": {
475
+ "init": True,
476
+ "unconfirmed_wallet_balance": 101,
477
+ "pending_change": 101,
478
+ "pending_coin_removal_count": 1,
479
+ },
480
+ },
481
+ post_block_balance_updates={
482
+ "xch": {
483
+ "set_remainder": True,
484
+ },
485
+ "did": {
486
+ "confirmed_wallet_balance": 101,
487
+ "spendable_balance": 101,
488
+ "max_send_amount": 101,
489
+ "unspent_coin_count": 1,
490
+ "pending_change": -101,
491
+ "pending_coin_removal_count": -1,
492
+ },
493
+ },
494
+ ),
495
+ WalletStateTransition(
496
+ pre_block_balance_updates={
497
+ "xch": {
498
+ "set_remainder": True,
499
+ },
500
+ "did": {
501
+ "init": True,
502
+ "unconfirmed_wallet_balance": 101,
503
+ "pending_change": 101,
504
+ "pending_coin_removal_count": 1,
505
+ },
506
+ },
507
+ post_block_balance_updates={
508
+ "xch": {
509
+ "set_remainder": True,
510
+ },
511
+ "did": {
512
+ "confirmed_wallet_balance": 101,
513
+ "spendable_balance": 101,
514
+ "max_send_amount": 101,
515
+ "unspent_coin_count": 1,
516
+ "pending_change": -101,
517
+ "pending_coin_removal_count": -1,
518
+ },
519
+ },
520
+ ),
521
+ ]
522
+ )
523
+ assert did_wallet_2.did_info.backup_ids == recovery_list
524
+
525
+ recovery_list.append(bytes32.from_hexstr(did_wallet_2.get_my_DID()))
526
+
527
+ async with wallet_1.wallet_state_manager.new_action_scope(
528
+ wallet_environments.tx_config, push=True
529
+ ) as action_scope:
530
+ did_wallet_3: DIDWallet = await DIDWallet.create_new_did_wallet(
531
+ wallet_node_1.wallet_state_manager, wallet_1, uint64(201), action_scope, recovery_list
532
+ )
533
+
534
+ env_1.wallet_aliases["did_2"] = 3
535
+
536
+ await wallet_environments.process_pending_states(
537
+ [
538
+ WalletStateTransition(
539
+ pre_block_balance_updates={},
540
+ post_block_balance_updates={},
541
+ ),
542
+ WalletStateTransition(
543
+ pre_block_balance_updates={
544
+ "xch": {
545
+ "set_remainder": True,
546
+ },
547
+ "did": {
548
+ "set_remainder": True,
549
+ },
550
+ "did_2": {
551
+ "init": True,
552
+ "unconfirmed_wallet_balance": 201,
553
+ "pending_change": 201,
554
+ "pending_coin_removal_count": 1,
555
+ },
556
+ },
557
+ post_block_balance_updates={
558
+ "xch": {
559
+ "set_remainder": True,
560
+ },
561
+ "did": {
562
+ "set_remainder": True,
563
+ },
564
+ "did_2": {
565
+ "confirmed_wallet_balance": 201,
566
+ "spendable_balance": 201,
567
+ "max_send_amount": 201,
568
+ "unspent_coin_count": 1,
569
+ "pending_change": -201,
570
+ "pending_coin_removal_count": -1,
571
+ },
572
+ },
573
+ ),
574
+ ]
575
+ )
576
+ coin = await did_wallet_3.get_coin()
577
+
578
+ backup_data = did_wallet_3.create_backup()
579
+
580
+ async with wallet_node_0.wallet_state_manager.lock:
581
+ did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery(
582
+ wallet_node_0.wallet_state_manager,
583
+ wallet_0,
584
+ backup_data,
585
+ )
586
+ assert did_wallet_4.get_name() == "Profile 2"
587
+ env_0.wallet_aliases["did_2"] = 3
588
+
589
+ pubkey = (
590
+ await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)
591
+ ).pubkey
592
+ new_ph = did_wallet_4.did_info.temp_puzhash
593
+ async with did_wallet.wallet_state_manager.new_action_scope(
594
+ wallet_environments.tx_config, push=True
595
+ ) as action_scope:
596
+ message_spend_bundle, attest1 = await did_wallet.create_attestment(
597
+ coin.name(), new_ph, pubkey, action_scope
598
+ )
599
+
600
+ async with did_wallet_2.wallet_state_manager.new_action_scope(
601
+ wallet_environments.tx_config, push=True
602
+ ) as action_scope_2:
603
+ message_spend_bundle2, attest2 = await did_wallet_2.create_attestment(
604
+ coin.name(), new_ph, pubkey, action_scope_2
605
+ )
606
+
607
+ message_spend_bundle = message_spend_bundle.aggregate([message_spend_bundle, message_spend_bundle2])
608
+
609
+ (
610
+ test_info_list,
611
+ test_message_spend_bundle,
612
+ ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1, attest2])
613
+ assert message_spend_bundle == test_message_spend_bundle
614
+
615
+ await wallet_environments.process_pending_states(
616
+ [
617
+ WalletStateTransition(
618
+ pre_block_balance_updates={
619
+ "did": {
620
+ "spendable_balance": -101,
621
+ "pending_change": 101,
622
+ "max_send_amount": -101,
623
+ "pending_coin_removal_count": 1,
624
+ "set_remainder": True,
625
+ },
626
+ "did_2": {
627
+ "init": True,
628
+ "unconfirmed_wallet_balance": 0,
629
+ "pending_change": 0,
630
+ "pending_coin_removal_count": 0,
631
+ },
632
+ },
633
+ post_block_balance_updates={
634
+ "did": {
635
+ "spendable_balance": 101,
636
+ "pending_change": -101,
637
+ "max_send_amount": 101,
638
+ "pending_coin_removal_count": -1,
639
+ },
640
+ "did_2": {
641
+ "confirmed_wallet_balance": 0,
642
+ "spendable_balance": 0,
643
+ "max_send_amount": 0,
644
+ "unspent_coin_count": 0,
645
+ "pending_change": 0,
646
+ "pending_coin_removal_count": 0,
647
+ },
648
+ },
649
+ ),
650
+ WalletStateTransition(
651
+ pre_block_balance_updates={
652
+ "did": {
653
+ "spendable_balance": -101,
654
+ "pending_change": 101,
655
+ "max_send_amount": -101,
656
+ "pending_coin_removal_count": 1,
657
+ "set_remainder": True,
658
+ },
659
+ },
660
+ post_block_balance_updates={
661
+ "did": {
662
+ "spendable_balance": 101,
663
+ "pending_change": -101,
664
+ "max_send_amount": 101,
665
+ "pending_coin_removal_count": -1,
666
+ },
667
+ },
668
+ ),
669
+ ]
670
+ )
671
+
672
+ async with did_wallet_4.wallet_state_manager.new_action_scope(
673
+ wallet_environments.tx_config, push=True
674
+ ) as action_scope:
675
+ await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, message_spend_bundle, action_scope)
676
+
677
+ await wallet_environments.process_pending_states(
678
+ [
679
+ WalletStateTransition(
680
+ pre_block_balance_updates={
681
+ "did_2": {
682
+ "unconfirmed_wallet_balance": 201,
683
+ "pending_change": 0,
684
+ "pending_coin_removal_count": 3,
685
+ },
686
+ },
687
+ post_block_balance_updates={
688
+ "did_2": {
689
+ "confirmed_wallet_balance": 201,
690
+ "spendable_balance": 201,
691
+ "max_send_amount": 201,
692
+ "unspent_coin_count": 1,
693
+ "pending_change": 0,
694
+ "pending_coin_removal_count": -3,
695
+ },
696
+ },
697
+ ),
698
+ WalletStateTransition(
699
+ pre_block_balance_updates={
700
+ "did_2": {
701
+ "unconfirmed_wallet_balance": 0, # TODO: fix pre-block balances for recovery
702
+ "spendable_balance": 0,
703
+ "pending_change": 0,
704
+ "max_send_amount": 0,
705
+ "pending_coin_removal_count": 0,
706
+ "set_remainder": True,
707
+ },
708
+ },
709
+ post_block_balance_updates={
710
+ "did_2": {
711
+ "confirmed_wallet_balance": -201,
712
+ "spendable_balance": -201,
713
+ "max_send_amount": -201,
714
+ "unspent_coin_count": -1,
715
+ "set_remainder": True,
716
+ },
717
+ },
718
+ ),
719
+ ]
720
+ )
721
+
722
+ for wallet in [did_wallet, did_wallet_2, did_wallet_3, did_wallet_4]:
723
+ assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
724
+
725
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
726
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
727
+ @pytest.mark.anyio
728
+ async def test_did_recovery_with_empty_set(self, wallet_environments: WalletTestFramework):
729
+ env_0 = wallet_environments.environments[0]
730
+ wallet_node_0 = env_0.node
731
+ wallet_0 = env_0.xch_wallet
732
+
733
+ env_0.wallet_aliases = {
734
+ "xch": 1,
735
+ "did": 2,
736
+ }
737
+
738
+ ph = await wallet_0.get_new_puzzlehash()
739
+
740
+ async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
741
+ did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
742
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
743
+ )
744
+
745
+ await wallet_environments.process_pending_states(
746
+ [
747
+ WalletStateTransition(
748
+ pre_block_balance_updates={
749
+ "xch": {
750
+ "set_remainder": True,
751
+ },
752
+ "did": {
753
+ "init": True,
754
+ "unconfirmed_wallet_balance": 101,
755
+ "pending_change": 101,
756
+ "pending_coin_removal_count": 1,
757
+ },
758
+ },
759
+ post_block_balance_updates={
760
+ "xch": {
761
+ "set_remainder": True,
762
+ },
763
+ "did": {
764
+ "confirmed_wallet_balance": 101,
765
+ "spendable_balance": 101,
766
+ "max_send_amount": 101,
767
+ "unspent_coin_count": 1,
768
+ "pending_change": -101,
769
+ "pending_coin_removal_count": -1,
770
+ },
771
+ },
772
+ ),
773
+ ]
774
+ )
775
+ coin = await did_wallet.get_coin()
776
+ info: list[tuple[bytes, bytes, int]] = []
777
+ pubkey = (await did_wallet.wallet_state_manager.get_unused_derivation_record(did_wallet.wallet_info.id)).pubkey
778
+ with pytest.raises(Exception): # We expect a CLVM 80 error for this test
779
+ async with did_wallet.wallet_state_manager.new_action_scope(
780
+ wallet_environments.tx_config, push=False
781
+ ) as action_scope:
782
+ await did_wallet.recovery_spend(
783
+ coin,
784
+ ph,
785
+ info,
786
+ pubkey,
787
+ WalletSpendBundle([], AugSchemeMPL.aggregate([])),
788
+ action_scope,
789
+ )
790
+
791
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
792
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
793
+ @pytest.mark.anyio
794
+ async def test_did_find_lost_did(self, wallet_environments: WalletTestFramework):
795
+ env_0 = wallet_environments.environments[0]
796
+ wallet_node_0 = env_0.node
797
+ wallet_0 = env_0.xch_wallet
798
+ api_0 = env_0.rpc_api
799
+
800
+ env_0.wallet_aliases = {
801
+ "xch": 1,
802
+ "did": 2,
803
+ }
804
+
805
+ async with wallet_0.wallet_state_manager.new_action_scope(
806
+ wallet_environments.tx_config, push=True
807
+ ) as action_scope:
808
+ did_wallet = await DIDWallet.create_new_did_wallet(
809
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
810
+ )
811
+
812
+ await wallet_environments.process_pending_states(
813
+ [
814
+ WalletStateTransition(
815
+ pre_block_balance_updates={
816
+ "xch": {
817
+ "set_remainder": True,
818
+ },
819
+ "did": {
820
+ "init": True,
821
+ "unconfirmed_wallet_balance": 101,
822
+ "pending_change": 101,
823
+ "pending_coin_removal_count": 1,
824
+ },
825
+ },
826
+ post_block_balance_updates={
827
+ "xch": {
828
+ "set_remainder": True,
829
+ },
830
+ "did": {
831
+ "confirmed_wallet_balance": 101,
832
+ "spendable_balance": 101,
833
+ "max_send_amount": 101,
834
+ "unspent_coin_count": 1,
835
+ "pending_change": -101,
836
+ "pending_coin_removal_count": -1,
837
+ },
838
+ },
839
+ ),
840
+ ]
841
+ )
842
+
843
+ # Delete the coin and wallet
844
+ coin = await did_wallet.get_coin()
845
+ await wallet_node_0.wallet_state_manager.coin_store.delete_coin_record(coin.name())
846
+ await wallet_node_0.wallet_state_manager.delete_wallet(did_wallet.wallet_info.id)
847
+ wallet_node_0.wallet_state_manager.wallets.pop(did_wallet.wallet_info.id)
848
+ assert len(wallet_node_0.wallet_state_manager.wallets) == 1
849
+ # Find lost DID
850
+ assert did_wallet.did_info.origin_coin is not None # mypy
851
+ resp = await api_0.did_find_lost_did({"coin_id": did_wallet.did_info.origin_coin.name().hex()})
852
+ assert resp["success"]
853
+ did_wallets = list(
854
+ filter(
855
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
856
+ await wallet_node_0.wallet_state_manager.get_all_wallet_info_entries(),
857
+ )
858
+ )
859
+ did_wallet = wallet_node_0.wallet_state_manager.wallets[did_wallets[0].id]
860
+ env_0.wallet_aliases["did_found"] = did_wallets[0].id
861
+ await env_0.change_balances(
862
+ {
863
+ "did_found": {
864
+ "init": True,
865
+ "confirmed_wallet_balance": 101,
866
+ "unconfirmed_wallet_balance": 101,
867
+ "spendable_balance": 101,
868
+ "max_send_amount": 101,
869
+ "unspent_coin_count": 1,
870
+ }
871
+ }
872
+ )
873
+ await env_0.check_balances()
874
+
875
+ # Spend DID
876
+ recovery_list = [bytes32.fromhex(did_wallet.get_my_DID())]
877
+ await did_wallet.update_recovery_list(recovery_list, uint64(1))
878
+ assert did_wallet.did_info.backup_ids == recovery_list
879
+ async with did_wallet.wallet_state_manager.new_action_scope(
880
+ wallet_environments.tx_config, push=True
881
+ ) as action_scope:
882
+ await did_wallet.create_update_spend(action_scope)
883
+
884
+ await wallet_environments.process_pending_states(
885
+ [
886
+ WalletStateTransition(
887
+ pre_block_balance_updates={
888
+ "did_found": {
889
+ "spendable_balance": -101,
890
+ "max_send_amount": -101,
891
+ "pending_change": 101,
892
+ "pending_coin_removal_count": 1,
893
+ },
894
+ },
895
+ post_block_balance_updates={
896
+ "did_found": {
897
+ "spendable_balance": 101,
898
+ "max_send_amount": 101,
899
+ "pending_change": -101,
900
+ "pending_coin_removal_count": -1,
901
+ },
902
+ },
903
+ ),
904
+ ]
905
+ )
906
+
907
+ # Delete the coin and change inner puzzle
908
+ coin = await did_wallet.get_coin()
909
+ await wallet_node_0.wallet_state_manager.coin_store.delete_coin_record(coin.name())
910
+ new_inner_puzzle = await did_wallet.get_did_innerpuz(new=True)
911
+ did_wallet.did_info = dataclasses.replace(did_wallet.did_info, current_inner=new_inner_puzzle)
912
+ # Recovery the coin
913
+ assert did_wallet.did_info.origin_coin is not None # mypy
914
+ resp = await api_0.did_find_lost_did({"coin_id": did_wallet.did_info.origin_coin.name().hex()})
915
+ assert resp["success"]
916
+ found_coin = await did_wallet.get_coin()
917
+ assert found_coin == coin
918
+ assert did_wallet.did_info.current_inner != new_inner_puzzle
919
+
920
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
921
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
922
+ @pytest.mark.anyio
923
+ async def test_did_attest_after_recovery(self, wallet_environments: WalletTestFramework):
924
+ env_0 = wallet_environments.environments[0]
925
+ env_1 = wallet_environments.environments[1]
926
+ wallet_node_0 = env_0.node
927
+ wallet_node_1 = env_1.node
928
+ wallet_0 = env_0.xch_wallet
929
+ wallet_1 = env_1.xch_wallet
930
+
931
+ env_0.wallet_aliases = {
932
+ "xch": 1,
933
+ "did": 2,
934
+ }
935
+ env_1.wallet_aliases = {
936
+ "xch": 1,
937
+ "did": 2,
938
+ }
939
+
940
+ async with wallet_0.wallet_state_manager.new_action_scope(
941
+ wallet_environments.tx_config, push=True
942
+ ) as action_scope:
943
+ did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
944
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
945
+ )
946
+ await wallet_environments.process_pending_states(
947
+ [
948
+ WalletStateTransition(
949
+ pre_block_balance_updates={
950
+ "xch": {
951
+ "set_remainder": True,
952
+ },
953
+ "did": {
954
+ "init": True,
955
+ "unconfirmed_wallet_balance": 101,
956
+ "pending_change": 101,
957
+ "pending_coin_removal_count": 1,
958
+ },
959
+ },
960
+ post_block_balance_updates={
961
+ "xch": {
962
+ "set_remainder": True,
963
+ },
964
+ "did": {
965
+ "confirmed_wallet_balance": 101,
966
+ "spendable_balance": 101,
967
+ "max_send_amount": 101,
968
+ "unspent_coin_count": 1,
969
+ "pending_change": -101,
970
+ "pending_coin_removal_count": -1,
971
+ },
972
+ },
973
+ ),
974
+ WalletStateTransition(),
975
+ ]
976
+ )
977
+
978
+ await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
979
+ await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
980
+ recovery_list = [bytes32.from_hexstr(did_wallet.get_my_DID())]
981
+
982
+ async with wallet_1.wallet_state_manager.new_action_scope(
983
+ wallet_environments.tx_config, push=True
984
+ ) as action_scope:
985
+ did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet(
986
+ wallet_node_1.wallet_state_manager, wallet_1, uint64(101), action_scope, recovery_list
987
+ )
988
+ await wallet_environments.process_pending_states(
989
+ [
990
+ WalletStateTransition(),
991
+ WalletStateTransition(
992
+ pre_block_balance_updates={
993
+ "xch": {
994
+ "set_remainder": True,
995
+ },
996
+ "did": {
997
+ "init": True,
998
+ "unconfirmed_wallet_balance": 101,
999
+ "pending_change": 101,
1000
+ "pending_coin_removal_count": 1,
1001
+ },
1002
+ },
1003
+ post_block_balance_updates={
1004
+ "xch": {
1005
+ "set_remainder": True,
1006
+ },
1007
+ "did": {
1008
+ "confirmed_wallet_balance": 101,
1009
+ "spendable_balance": 101,
1010
+ "max_send_amount": 101,
1011
+ "unspent_coin_count": 1,
1012
+ "pending_change": -101,
1013
+ "pending_coin_removal_count": -1,
1014
+ },
1015
+ },
1016
+ ),
1017
+ ]
1018
+ )
1019
+
1020
+ assert did_wallet_2.did_info.backup_ids == recovery_list
1021
+
1022
+ # Update coin with new ID info
1023
+ recovery_list = [bytes32.from_hexstr(did_wallet_2.get_my_DID())]
1024
+ await did_wallet.update_recovery_list(recovery_list, uint64(1))
1025
+ assert did_wallet.did_info.backup_ids == recovery_list
1026
+ async with did_wallet.wallet_state_manager.new_action_scope(
1027
+ wallet_environments.tx_config, push=True
1028
+ ) as action_scope:
1029
+ await did_wallet.create_update_spend(action_scope)
1030
+
1031
+ await wallet_environments.process_pending_states(
1032
+ [
1033
+ WalletStateTransition(
1034
+ pre_block_balance_updates={
1035
+ "did": {
1036
+ "set_remainder": True,
1037
+ }
1038
+ },
1039
+ post_block_balance_updates={
1040
+ "did": {
1041
+ "set_remainder": True,
1042
+ }
1043
+ },
1044
+ ),
1045
+ WalletStateTransition(),
1046
+ ]
1047
+ )
1048
+
1049
+ # DID Wallet 2 recovers into DID Wallet 3 with new innerpuz
1050
+ backup_data = did_wallet_2.create_backup()
1051
+
1052
+ async with wallet_node_0.wallet_state_manager.lock:
1053
+ did_wallet_3 = await DIDWallet.create_new_did_wallet_from_recovery(
1054
+ wallet_node_0.wallet_state_manager,
1055
+ wallet_0,
1056
+ backup_data,
1057
+ )
1058
+ env_0.wallet_aliases["did_2"] = 3
1059
+ new_ph = await did_wallet_3.get_did_inner_hash(new=True)
1060
+ coin = await did_wallet_2.get_coin()
1061
+ pubkey = (
1062
+ await did_wallet_3.wallet_state_manager.get_unused_derivation_record(did_wallet_3.wallet_info.id)
1063
+ ).pubkey
1064
+
1065
+ async with did_wallet.wallet_state_manager.new_action_scope(
1066
+ wallet_environments.tx_config, push=True
1067
+ ) as action_scope:
1068
+ message_spend_bundle, attest_data = await did_wallet.create_attestment(
1069
+ coin.name(), new_ph, pubkey, action_scope
1070
+ )
1071
+ await wallet_environments.process_pending_states(
1072
+ [
1073
+ WalletStateTransition(
1074
+ pre_block_balance_updates={
1075
+ "did": {
1076
+ "set_remainder": True,
1077
+ },
1078
+ "did_2": {
1079
+ "init": True,
1080
+ "set_remainder": True,
1081
+ },
1082
+ },
1083
+ post_block_balance_updates={
1084
+ "did": {
1085
+ "set_remainder": True,
1086
+ },
1087
+ "did_2": {
1088
+ "set_remainder": True,
1089
+ },
1090
+ },
1091
+ ),
1092
+ WalletStateTransition(),
1093
+ ]
1094
+ )
1095
+
1096
+ (
1097
+ info,
1098
+ message_spend_bundle,
1099
+ ) = await did_wallet_3.load_attest_files_for_recovery_spend([attest_data])
1100
+ async with did_wallet_3.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1101
+ await did_wallet_3.recovery_spend(coin, new_ph, info, pubkey, message_spend_bundle, action_scope)
1102
+ await wallet_environments.process_pending_states(
1103
+ [
1104
+ WalletStateTransition(
1105
+ pre_block_balance_updates={
1106
+ "did_2": {
1107
+ "unconfirmed_wallet_balance": 101,
1108
+ "set_remainder": True,
1109
+ },
1110
+ },
1111
+ post_block_balance_updates={
1112
+ "did_2": {
1113
+ "confirmed_wallet_balance": 101,
1114
+ "set_remainder": True,
1115
+ },
1116
+ },
1117
+ ),
1118
+ WalletStateTransition(
1119
+ pre_block_balance_updates={
1120
+ "did": {
1121
+ "unconfirmed_wallet_balance": 0, # TODO: fix pre-block balances for recovery
1122
+ "set_remainder": True,
1123
+ },
1124
+ },
1125
+ post_block_balance_updates={
1126
+ "did": {
1127
+ "confirmed_wallet_balance": -101,
1128
+ "set_remainder": True,
1129
+ },
1130
+ },
1131
+ ),
1132
+ ]
1133
+ )
1134
+
1135
+ # DID Wallet 1 recovery spends into DID Wallet 4
1136
+ backup_data = did_wallet.create_backup()
1137
+
1138
+ async with wallet_node_1.wallet_state_manager.lock:
1139
+ did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery(
1140
+ wallet_node_1.wallet_state_manager,
1141
+ wallet_1,
1142
+ backup_data,
1143
+ )
1144
+ env_1.wallet_aliases["did_2"] = 3
1145
+ coin = await did_wallet.get_coin()
1146
+ new_ph = await did_wallet_4.get_did_inner_hash(new=True)
1147
+ pubkey = (
1148
+ await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_4.wallet_info.id)
1149
+ ).pubkey
1150
+ async with did_wallet_3.wallet_state_manager.new_action_scope(
1151
+ wallet_environments.tx_config, push=True
1152
+ ) as action_scope:
1153
+ message_spend_bundle, attest1 = await did_wallet_3.create_attestment(
1154
+ coin.name(), new_ph, pubkey, action_scope
1155
+ )
1156
+
1157
+ await wallet_environments.process_pending_states(
1158
+ [
1159
+ WalletStateTransition(
1160
+ pre_block_balance_updates={
1161
+ "did_2": {
1162
+ "unconfirmed_wallet_balance": 0,
1163
+ "set_remainder": True,
1164
+ },
1165
+ },
1166
+ post_block_balance_updates={
1167
+ "did_2": {
1168
+ "confirmed_wallet_balance": 0,
1169
+ "set_remainder": True,
1170
+ },
1171
+ },
1172
+ ),
1173
+ WalletStateTransition(
1174
+ pre_block_balance_updates={
1175
+ "did_2": {
1176
+ "init": True,
1177
+ "set_remainder": True,
1178
+ },
1179
+ },
1180
+ post_block_balance_updates={
1181
+ "did_2": {
1182
+ "confirmed_wallet_balance": 0,
1183
+ "set_remainder": True,
1184
+ },
1185
+ },
1186
+ ),
1187
+ ]
1188
+ )
1189
+
1190
+ (
1191
+ test_info_list,
1192
+ test_message_spend_bundle,
1193
+ ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1])
1194
+ async with did_wallet_4.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1195
+ await did_wallet_4.recovery_spend(
1196
+ coin, new_ph, test_info_list, pubkey, test_message_spend_bundle, action_scope
1197
+ )
1198
+
1199
+ await wallet_environments.process_pending_states(
1200
+ [
1201
+ WalletStateTransition(
1202
+ pre_block_balance_updates={
1203
+ "did": {
1204
+ "set_remainder": True,
1205
+ },
1206
+ },
1207
+ post_block_balance_updates={
1208
+ "did": {
1209
+ "confirmed_wallet_balance": -101,
1210
+ "set_remainder": True,
1211
+ },
1212
+ },
1213
+ ),
1214
+ WalletStateTransition(
1215
+ pre_block_balance_updates={
1216
+ "did_2": {
1217
+ "set_remainder": True,
1218
+ },
1219
+ },
1220
+ post_block_balance_updates={
1221
+ "did_2": {
1222
+ "confirmed_wallet_balance": 101,
1223
+ "set_remainder": True,
1224
+ },
1225
+ },
1226
+ ),
1227
+ ]
1228
+ )
1229
+
1230
+ for wallet in [did_wallet, did_wallet_3, did_wallet_4]:
1231
+ assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
1232
+
1233
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1234
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
1235
+ @pytest.mark.parametrize(
1236
+ "with_recovery",
1237
+ [True, False],
1238
+ )
1239
+ @pytest.mark.anyio
1240
+ async def test_did_transfer(self, wallet_environments: WalletTestFramework, with_recovery: bool):
1241
+ env_0 = wallet_environments.environments[0]
1242
+ env_1 = wallet_environments.environments[1]
1243
+ wallet_node_0 = env_0.node
1244
+ wallet_node_1 = env_1.node
1245
+ wallet_0 = env_0.xch_wallet
1246
+ wallet_1 = env_1.xch_wallet
1247
+
1248
+ env_0.wallet_aliases = {
1249
+ "xch": 1,
1250
+ "did": 2,
1251
+ }
1252
+ env_1.wallet_aliases = {
1253
+ "xch": 1,
1254
+ "did": 2,
1255
+ }
1256
+ ph = await wallet_0.get_new_puzzlehash()
1257
+ fee = uint64(1000)
1258
+
1259
+ async with wallet_0.wallet_state_manager.new_action_scope(
1260
+ wallet_environments.tx_config, push=True
1261
+ ) as action_scope:
1262
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1263
+ wallet_node_0.wallet_state_manager,
1264
+ wallet_0,
1265
+ uint64(101),
1266
+ action_scope,
1267
+ [ph],
1268
+ uint64(1),
1269
+ {"Twitter": "Test", "GitHub": "测试"},
1270
+ fee=fee,
1271
+ )
1272
+ assert did_wallet_1.get_name() == "Profile 1"
1273
+
1274
+ await wallet_environments.process_pending_states(
1275
+ [
1276
+ WalletStateTransition(
1277
+ pre_block_balance_updates={
1278
+ "xch": {
1279
+ "set_remainder": True,
1280
+ },
1281
+ "did": {
1282
+ "init": True,
1283
+ "unconfirmed_wallet_balance": 101,
1284
+ "pending_change": 101,
1285
+ "pending_coin_removal_count": 1,
1286
+ },
1287
+ },
1288
+ post_block_balance_updates={
1289
+ "xch": {
1290
+ "set_remainder": True,
1291
+ },
1292
+ "did": {
1293
+ "confirmed_wallet_balance": 101,
1294
+ "spendable_balance": 101,
1295
+ "max_send_amount": 101,
1296
+ "unspent_coin_count": 1,
1297
+ "pending_change": -101,
1298
+ "pending_coin_removal_count": -1,
1299
+ },
1300
+ },
1301
+ ),
1302
+ WalletStateTransition(),
1303
+ ]
1304
+ )
1305
+
1306
+ # Transfer DID
1307
+ new_puzhash = await wallet_1.get_new_puzzlehash()
1308
+ async with did_wallet_1.wallet_state_manager.new_action_scope(
1309
+ wallet_environments.tx_config, push=True
1310
+ ) as action_scope:
1311
+ await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, action_scope)
1312
+
1313
+ await wallet_environments.process_pending_states(
1314
+ [
1315
+ WalletStateTransition(
1316
+ pre_block_balance_updates={
1317
+ "xch": {
1318
+ "set_remainder": True,
1319
+ },
1320
+ "did": {
1321
+ "unconfirmed_wallet_balance": -101,
1322
+ "set_remainder": True,
1323
+ },
1324
+ },
1325
+ post_block_balance_updates={
1326
+ "xch": {
1327
+ "set_remainder": True,
1328
+ },
1329
+ },
1330
+ ),
1331
+ WalletStateTransition(
1332
+ pre_block_balance_updates={},
1333
+ post_block_balance_updates={
1334
+ "did": {
1335
+ "init": True,
1336
+ "confirmed_wallet_balance": 101,
1337
+ "set_remainder": True,
1338
+ },
1339
+ },
1340
+ ),
1341
+ ]
1342
+ )
1343
+
1344
+ # Get the new DID wallet
1345
+ did_wallets = list(
1346
+ filter(
1347
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1348
+ await wallet_node_1.wallet_state_manager.get_all_wallet_info_entries(),
1349
+ )
1350
+ )
1351
+ did_wallet_2 = wallet_node_1.wallet_state_manager.wallets[did_wallets[0].id]
1352
+ assert isinstance(did_wallet_2, DIDWallet) # mypy
1353
+ assert len(wallet_node_0.wallet_state_manager.wallets) == 1
1354
+ assert did_wallet_1.did_info.origin_coin == did_wallet_2.did_info.origin_coin
1355
+ if with_recovery:
1356
+ assert did_wallet_1.did_info.backup_ids[0] == did_wallet_2.did_info.backup_ids[0]
1357
+ assert did_wallet_1.did_info.num_of_backup_ids_needed == did_wallet_2.did_info.num_of_backup_ids_needed
1358
+ metadata = json.loads(did_wallet_2.did_info.metadata)
1359
+ assert metadata["Twitter"] == "Test"
1360
+ assert metadata["GitHub"] == "测试"
1361
+
1362
+ # Test match_hinted_coin
1363
+ assert await did_wallet_2.match_hinted_coin(
1364
+ await did_wallet_2.get_coin(),
1365
+ new_puzhash,
1366
+ )
1367
+
1368
+ @pytest.mark.parametrize(
1369
+ "trusted",
1370
+ [True, False],
1371
+ )
1372
+ @pytest.mark.anyio
1373
+ async def test_did_auto_transfer_limit(
1374
+ self,
1375
+ self_hostname: str,
1376
+ two_wallet_nodes: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
1377
+ trusted: bool,
1378
+ ) -> None:
1379
+ fee = uint64(1000)
1380
+ full_nodes, wallets, _ = two_wallet_nodes
1381
+ full_node_api = full_nodes[0]
1382
+ server_1 = full_node_api.server
1383
+ wallet_node, server_2 = wallets[0]
1384
+ wallet_node_2, server_3 = wallets[1]
1385
+ wallet = wallet_node.wallet_state_manager.main_wallet
1386
+ wallet2 = wallet_node_2.wallet_state_manager.main_wallet
1387
+ api_1 = WalletRpcApi(wallet_node_2)
1388
+ ph = await wallet.get_new_puzzlehash()
1389
+
1390
+ if trusted:
1391
+ wallet_node.config["trusted_peers"] = {
1392
+ full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1393
+ }
1394
+ wallet_node_2.config["trusted_peers"] = {
1395
+ full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1396
+ }
1397
+ else:
1398
+ wallet_node.config["trusted_peers"] = {}
1399
+ wallet_node_2.config["trusted_peers"] = {}
1400
+
1401
+ await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1402
+ await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1403
+ await full_node_api.farm_blocks_to_wallet(1, wallet)
1404
+
1405
+ # Check that we cap out at 10 DID Wallets automatically created upon transfer received
1406
+ for i in range(0, 14):
1407
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1408
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1409
+ wallet_node.wallet_state_manager,
1410
+ wallet,
1411
+ uint64(101),
1412
+ action_scope,
1413
+ [bytes32(bytes(ph))],
1414
+ uint64(1),
1415
+ {"Twitter": "Test", "GitHub": "测试"},
1416
+ fee=fee,
1417
+ )
1418
+ assert did_wallet_1.get_name() == "Profile 1"
1419
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1420
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1421
+ await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
1422
+ await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
1423
+ # Transfer DID
1424
+ assert did_wallet_1.did_info.origin_coin is not None
1425
+ origin_coin = did_wallet_1.did_info.origin_coin
1426
+ new_puzhash = await wallet2.get_new_puzzlehash()
1427
+ async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1428
+ await did_wallet_1.transfer_did(new_puzhash, fee, False, action_scope)
1429
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1430
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1431
+ # Check if the DID wallet is created in the wallet2
1432
+
1433
+ await time_out_assert(
1434
+ 30, get_wallet_num, min(2 + i, 11), wallet_node_2.wallet_state_manager
1435
+ ) # check we haven't made more than 10 DID wallets
1436
+ await time_out_assert(30, get_wallet_num, 1, wallet_node.wallet_state_manager)
1437
+ # Get the new DID wallets
1438
+ did_wallets = list(
1439
+ filter(
1440
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1441
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1442
+ )
1443
+ )
1444
+
1445
+ assert len(did_wallets) == 10
1446
+ # Test we can use the DID
1447
+ did_wallet_10 = wallet_node_2.wallet_state_manager.get_wallet(
1448
+ id=uint32(did_wallets[9].id), required_type=DIDWallet
1449
+ )
1450
+ # Delete the coin and change inner puzzle
1451
+ coin = await did_wallet_10.get_coin()
1452
+ # origin_coin = did_wallet_10.did_info.origin_coin
1453
+ backup_data = did_wallet_10.create_backup()
1454
+ await wallet_node_2.wallet_state_manager.coin_store.delete_coin_record(coin.name())
1455
+ await time_out_assert(15, did_wallet_10.get_confirmed_balance, 0)
1456
+ await wallet_node_2.wallet_state_manager.user_store.delete_wallet(did_wallet_10.wallet_info.id)
1457
+ wallet_node_2.wallet_state_manager.wallets.pop(did_wallet_10.wallet_info.id)
1458
+ # Recover the coin
1459
+ async with wallet_node_2.wallet_state_manager.lock:
1460
+ did_wallet_10 = await DIDWallet.create_new_did_wallet_from_recovery(
1461
+ wallet_node_2.wallet_state_manager,
1462
+ wallet2,
1463
+ backup_data,
1464
+ )
1465
+ assert did_wallet_10.did_info.origin_coin is not None
1466
+ resp = await api_1.did_find_lost_did({"coin_id": did_wallet_10.did_info.origin_coin.name().hex()})
1467
+ assert resp["success"]
1468
+ await time_out_assert(15, did_wallet_10.get_confirmed_balance, 101)
1469
+ await time_out_assert(15, did_wallet_10.get_unconfirmed_balance, 101)
1470
+
1471
+ # Check we can recover an auto-discarded DID
1472
+ did_wallet_9 = wallet_node_2.wallet_state_manager.get_wallet(
1473
+ id=uint32(did_wallets[8].id), required_type=DIDWallet
1474
+ )
1475
+ # Delete the coin and wallet to make space for a auto-discarded DID
1476
+ coin = await did_wallet_9.get_coin()
1477
+ await wallet_node_2.wallet_state_manager.coin_store.delete_coin_record(coin.name())
1478
+ await time_out_assert(15, did_wallet_9.get_confirmed_balance, 0)
1479
+ await wallet_node_2.wallet_state_manager.user_store.delete_wallet(did_wallet_9.wallet_info.id)
1480
+ wallet_node_2.wallet_state_manager.wallets.pop(did_wallet_9.wallet_info.id)
1481
+
1482
+ did_wallets = list(
1483
+ filter(
1484
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1485
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1486
+ )
1487
+ )
1488
+ assert len(did_wallets) == 9
1489
+
1490
+ # Try and find lost coin
1491
+ resp = await api_1.did_find_lost_did({"coin_id": origin_coin.name().hex()})
1492
+ did_wallets = list(
1493
+ filter(
1494
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1495
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1496
+ )
1497
+ )
1498
+ assert len(did_wallets) == 10
1499
+
1500
+ # Check we can still manually add new DIDs while at cap
1501
+ await full_node_api.farm_blocks_to_wallet(1, wallet2)
1502
+ ph = await wallet2.get_new_puzzlehash()
1503
+ async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1504
+ did_wallet_11: DIDWallet = await DIDWallet.create_new_did_wallet(
1505
+ wallet_node_2.wallet_state_manager,
1506
+ wallet2,
1507
+ uint64(101),
1508
+ action_scope,
1509
+ [bytes32(bytes(ph))],
1510
+ uint64(1),
1511
+ {"Twitter": "Test", "GitHub": "测试"},
1512
+ fee=fee,
1513
+ )
1514
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1515
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1516
+ await time_out_assert(15, did_wallet_11.get_confirmed_balance, 101)
1517
+ await time_out_assert(15, did_wallet_11.get_unconfirmed_balance, 101)
1518
+
1519
+ did_wallets = list(
1520
+ filter(
1521
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1522
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1523
+ )
1524
+ )
1525
+ assert len(did_wallets) == 11
1526
+
1527
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1528
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1529
+ @pytest.mark.anyio
1530
+ async def test_update_recovery_list(self, wallet_environments: WalletTestFramework):
1531
+ env = wallet_environments.environments[0]
1532
+ wallet_node = env.node
1533
+ wallet = env.xch_wallet
1534
+
1535
+ env.wallet_aliases = {
1536
+ "xch": 1,
1537
+ "did": 2,
1538
+ }
1539
+
1540
+ ph = await wallet.get_new_puzzlehash()
1541
+
1542
+ async with wallet.wallet_state_manager.new_action_scope(
1543
+ wallet_environments.tx_config, push=True
1544
+ ) as action_scope:
1545
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1546
+ wallet_node.wallet_state_manager, wallet, uint64(101), action_scope, []
1547
+ )
1548
+
1549
+ await wallet_environments.process_pending_states(
1550
+ [
1551
+ WalletStateTransition(
1552
+ pre_block_balance_updates={
1553
+ "xch": {
1554
+ "set_remainder": True,
1555
+ },
1556
+ "did": {
1557
+ "init": True,
1558
+ "unconfirmed_wallet_balance": 101,
1559
+ "pending_change": 101,
1560
+ "pending_coin_removal_count": 1,
1561
+ },
1562
+ },
1563
+ post_block_balance_updates={
1564
+ "xch": {
1565
+ "set_remainder": True,
1566
+ },
1567
+ "did": {
1568
+ "confirmed_wallet_balance": 101,
1569
+ "spendable_balance": 101,
1570
+ "max_send_amount": 101,
1571
+ "unspent_coin_count": 1,
1572
+ "pending_change": -101,
1573
+ "pending_coin_removal_count": -1,
1574
+ },
1575
+ },
1576
+ ),
1577
+ ]
1578
+ )
1579
+ await did_wallet_1.update_recovery_list([ph], uint64(1))
1580
+ async with did_wallet_1.wallet_state_manager.new_action_scope(
1581
+ wallet_environments.tx_config, push=True
1582
+ ) as action_scope:
1583
+ await did_wallet_1.create_update_spend(action_scope)
1584
+
1585
+ await wallet_environments.process_pending_states(
1586
+ [
1587
+ WalletStateTransition(
1588
+ pre_block_balance_updates={
1589
+ "did": {
1590
+ "set_remainder": True,
1591
+ },
1592
+ },
1593
+ post_block_balance_updates={
1594
+ "did": {
1595
+ "set_remainder": True,
1596
+ },
1597
+ },
1598
+ ),
1599
+ ]
1600
+ )
1601
+ assert did_wallet_1.did_info.backup_ids[0] == bytes(ph)
1602
+ assert did_wallet_1.did_info.num_of_backup_ids_needed == 1
1603
+
1604
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1605
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
1606
+ @pytest.mark.anyio
1607
+ async def test_get_info(self, wallet_environments: WalletTestFramework):
1608
+ env_0 = wallet_environments.environments[0]
1609
+ env_1 = wallet_environments.environments[1]
1610
+ wallet_node_0 = env_0.node
1611
+ wallet_0 = env_0.xch_wallet
1612
+ wallet_1 = env_1.xch_wallet
1613
+ api_0 = env_0.rpc_api
1614
+
1615
+ env_0.wallet_aliases = {
1616
+ "xch": 1,
1617
+ "did": 2,
1618
+ }
1619
+ env_1.wallet_aliases = {
1620
+ "xch": 1,
1621
+ "did": 2,
1622
+ }
1623
+
1624
+ fee = uint64(1000)
1625
+ did_amount = uint64(101)
1626
+ ph_1 = await wallet_1.get_new_puzzlehash()
1627
+
1628
+ async with wallet_0.wallet_state_manager.new_action_scope(
1629
+ wallet_environments.tx_config, push=True
1630
+ ) as action_scope:
1631
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1632
+ wallet_node_0.wallet_state_manager,
1633
+ wallet_0,
1634
+ did_amount,
1635
+ action_scope,
1636
+ [],
1637
+ metadata={"twitter": "twitter"},
1638
+ fee=fee,
1639
+ )
1640
+
1641
+ await wallet_environments.process_pending_states(
1642
+ [
1643
+ WalletStateTransition(
1644
+ pre_block_balance_updates={
1645
+ "xch": {
1646
+ "set_remainder": True,
1647
+ },
1648
+ "did": {
1649
+ "init": True,
1650
+ "unconfirmed_wallet_balance": did_amount,
1651
+ "pending_change": did_amount,
1652
+ "pending_coin_removal_count": 1,
1653
+ },
1654
+ },
1655
+ post_block_balance_updates={
1656
+ "xch": {
1657
+ "set_remainder": True,
1658
+ },
1659
+ "did": {
1660
+ "confirmed_wallet_balance": did_amount,
1661
+ "spendable_balance": did_amount,
1662
+ "max_send_amount": did_amount,
1663
+ "unspent_coin_count": 1,
1664
+ "pending_change": -did_amount,
1665
+ "pending_coin_removal_count": -1,
1666
+ },
1667
+ },
1668
+ ),
1669
+ WalletStateTransition(),
1670
+ ]
1671
+ )
1672
+ assert did_wallet_1.did_info.origin_coin is not None # mypy
1673
+ response = await api_0.did_get_info({"coin_id": did_wallet_1.did_info.origin_coin.name().hex()})
1674
+ assert response["did_id"] == encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value)
1675
+ assert response["launcher_id"] == did_wallet_1.did_info.origin_coin.name().hex()
1676
+ assert did_wallet_1.did_info.current_inner is not None # mypy
1677
+ assert response["full_puzzle"].to_program() == create_singleton_puzzle(
1678
+ did_wallet_1.did_info.current_inner, did_wallet_1.did_info.origin_coin.name()
1679
+ )
1680
+ assert response["metadata"]["twitter"] == "twitter"
1681
+ assert response["latest_coin"] == (await did_wallet_1.get_coin()).name().hex()
1682
+ assert response["num_verification"] == 0
1683
+ assert response["recovery_list_hash"] == Program(Program.to([])).get_tree_hash().hex()
1684
+ assert decode_puzzle_hash(response["p2_address"]).hex() == response["hints"][0]
1685
+
1686
+ # Test non-singleton coin
1687
+ async with wallet_0.wallet_state_manager.new_action_scope(
1688
+ wallet_environments.tx_config, push=True
1689
+ ) as action_scope:
1690
+ coin = (await wallet_0.select_coins(uint64(1), action_scope)).pop()
1691
+ assert coin.amount % 2 == 1
1692
+ coin_id = coin.name()
1693
+ response = await api_0.did_get_info({"coin_id": coin_id.hex()})
1694
+ assert not response["success"]
1695
+
1696
+ # Test multiple odd coins
1697
+ odd_amount = uint64(1)
1698
+ async with wallet_0.wallet_state_manager.new_action_scope(
1699
+ wallet_environments.tx_config, push=True
1700
+ ) as action_scope:
1701
+ async with action_scope.use() as interface:
1702
+ interface.side_effects.selected_coins.append(coin)
1703
+ coin_1 = (await wallet_0.select_coins(odd_amount, action_scope)).pop()
1704
+ assert coin_1.amount % 2 == 0
1705
+ async with wallet_0.wallet_state_manager.new_action_scope(
1706
+ wallet_environments.tx_config.override(excluded_coin_ids=[coin_id]), push=True
1707
+ ) as action_scope:
1708
+ await wallet_0.generate_signed_transaction(odd_amount, ph_1, action_scope, fee)
1709
+
1710
+ await wallet_environments.process_pending_states(
1711
+ [
1712
+ WalletStateTransition(
1713
+ pre_block_balance_updates={
1714
+ "xch": {
1715
+ "unconfirmed_wallet_balance": -odd_amount - fee,
1716
+ "set_remainder": True,
1717
+ },
1718
+ "did": {
1719
+ "set_remainder": True,
1720
+ },
1721
+ },
1722
+ post_block_balance_updates={
1723
+ "xch": {
1724
+ "confirmed_wallet_balance": -odd_amount - fee,
1725
+ "set_remainder": True,
1726
+ },
1727
+ "did": {
1728
+ "set_remainder": True,
1729
+ },
1730
+ },
1731
+ ),
1732
+ WalletStateTransition(
1733
+ pre_block_balance_updates={
1734
+ "xch": {
1735
+ "unconfirmed_wallet_balance": 0,
1736
+ "set_remainder": True,
1737
+ }
1738
+ },
1739
+ post_block_balance_updates={
1740
+ "xch": {
1741
+ "confirmed_wallet_balance": odd_amount,
1742
+ "set_remainder": True,
1743
+ }
1744
+ },
1745
+ ),
1746
+ ]
1747
+ )
1748
+
1749
+ with pytest.raises(ValueError):
1750
+ await api_0.did_get_info({"coin_id": coin_1.name().hex()})
1751
+
1752
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1753
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1754
+ @pytest.mark.anyio
1755
+ async def test_message_spend(self, wallet_environments: WalletTestFramework):
1756
+ env = wallet_environments.environments[0]
1757
+ wallet_node = env.node
1758
+ wallet = env.xch_wallet
1759
+ api_0 = env.rpc_api
1760
+
1761
+ env.wallet_aliases = {
1762
+ "xch": 1,
1763
+ "did": 2,
1764
+ }
1765
+
1766
+ fee = uint64(1000)
1767
+
1768
+ async with wallet.wallet_state_manager.new_action_scope(
1769
+ wallet_environments.tx_config, push=True
1770
+ ) as action_scope:
1771
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1772
+ wallet_node.wallet_state_manager, wallet, uint64(101), action_scope, [], fee=fee
1773
+ )
1774
+ await wallet_environments.process_pending_states(
1775
+ [
1776
+ WalletStateTransition(
1777
+ pre_block_balance_updates={
1778
+ "xch": {
1779
+ "set_remainder": True,
1780
+ },
1781
+ "did": {
1782
+ "init": True,
1783
+ "unconfirmed_wallet_balance": 101,
1784
+ "pending_change": 101,
1785
+ "pending_coin_removal_count": 1,
1786
+ },
1787
+ },
1788
+ post_block_balance_updates={
1789
+ "xch": {
1790
+ "set_remainder": True,
1791
+ },
1792
+ "did": {
1793
+ "confirmed_wallet_balance": 101,
1794
+ "spendable_balance": 101,
1795
+ "max_send_amount": 101,
1796
+ "unspent_coin_count": 1,
1797
+ "pending_change": -101,
1798
+ "pending_coin_removal_count": -1,
1799
+ },
1800
+ },
1801
+ ),
1802
+ ]
1803
+ )
1804
+ response = await api_0.did_message_spend(
1805
+ {"wallet_id": did_wallet_1.wallet_id, "coin_announcements": ["0abc"], "puzzle_announcements": ["0def"]}
1806
+ )
1807
+ spend = response["spend_bundle"].coin_spends[0]
1808
+ conditions = conditions_dict_for_solution(
1809
+ spend.puzzle_reveal, spend.solution, wallet.wallet_state_manager.constants.MAX_BLOCK_COST_CLVM
1810
+ )
1811
+
1812
+ assert len(conditions[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT]) == 1
1813
+ assert conditions[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0].hex() == "0abc"
1814
+ assert len(conditions[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT]) == 1
1815
+ assert conditions[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT][0].vars[0].hex() == "0def"
1816
+
1817
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1818
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1819
+ @pytest.mark.anyio
1820
+ async def test_update_metadata(self, wallet_environments: WalletTestFramework):
1821
+ env = wallet_environments.environments[0]
1822
+ wallet_node = env.node
1823
+ wallet = env.xch_wallet
1824
+
1825
+ env.wallet_aliases = {
1826
+ "xch": 1,
1827
+ "did": 2,
1828
+ }
1829
+
1830
+ fee = uint64(1000)
1831
+ did_amount = uint64(101)
1832
+
1833
+ async with wallet.wallet_state_manager.new_action_scope(
1834
+ wallet_environments.tx_config, push=True
1835
+ ) as action_scope:
1836
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1837
+ wallet_node.wallet_state_manager, wallet, did_amount, action_scope, [], fee=fee
1838
+ )
1839
+
1840
+ await wallet_environments.process_pending_states(
1841
+ [
1842
+ WalletStateTransition(
1843
+ pre_block_balance_updates={
1844
+ "xch": {
1845
+ "set_remainder": True,
1846
+ },
1847
+ "did": {
1848
+ "init": True,
1849
+ "unconfirmed_wallet_balance": 101,
1850
+ "pending_change": 101,
1851
+ "pending_coin_removal_count": 1,
1852
+ },
1853
+ },
1854
+ post_block_balance_updates={
1855
+ "xch": {
1856
+ "set_remainder": True,
1857
+ },
1858
+ "did": {
1859
+ "confirmed_wallet_balance": 101,
1860
+ "spendable_balance": 101,
1861
+ "max_send_amount": 101,
1862
+ "unspent_coin_count": 1,
1863
+ "pending_change": -101,
1864
+ "pending_coin_removal_count": -1,
1865
+ },
1866
+ },
1867
+ ),
1868
+ ]
1869
+ )
1870
+
1871
+ assert did_wallet_1.did_info.current_inner is not None # mypy
1872
+ puzhash = did_wallet_1.did_info.current_inner.get_tree_hash()
1873
+ parent_num = get_parent_num(did_wallet_1)
1874
+
1875
+ bad_metadata = {"Twitter": {"url": "http://www.twitter.com"}}
1876
+ with pytest.raises(ValueError) as e:
1877
+ await did_wallet_1.update_metadata(bad_metadata) # type: ignore
1878
+ assert e.match("Metadata key value pairs must be strings.")
1879
+
1880
+ metadata = {}
1881
+ metadata["Twitter"] = "http://www.twitter.com"
1882
+ await did_wallet_1.update_metadata(metadata)
1883
+ async with did_wallet_1.wallet_state_manager.new_action_scope(
1884
+ wallet_environments.tx_config, push=True
1885
+ ) as action_scope:
1886
+ await did_wallet_1.create_update_spend(action_scope, fee)
1887
+
1888
+ await wallet_environments.process_pending_states(
1889
+ [
1890
+ WalletStateTransition(
1891
+ pre_block_balance_updates={
1892
+ "xch": {
1893
+ "unconfirmed_wallet_balance": -fee,
1894
+ "set_remainder": True,
1895
+ },
1896
+ "did": {
1897
+ "unconfirmed_wallet_balance": 0,
1898
+ "set_remainder": True,
1899
+ },
1900
+ },
1901
+ post_block_balance_updates={
1902
+ "xch": {
1903
+ "confirmed_wallet_balance": -fee,
1904
+ "set_remainder": True,
1905
+ },
1906
+ "did": {
1907
+ "confirmed_wallet_balance": 0,
1908
+ "set_remainder": True,
1909
+ },
1910
+ },
1911
+ ),
1912
+ ]
1913
+ )
1914
+
1915
+ assert get_parent_num(did_wallet_1) == parent_num + 2
1916
+ assert did_wallet_1.did_info.current_inner is not None # mypy
1917
+ assert puzhash != did_wallet_1.did_info.current_inner.get_tree_hash()
1918
+ assert did_wallet_1.did_info.metadata.find("Twitter") > 0
1919
+
1920
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1921
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1922
+ @pytest.mark.anyio
1923
+ async def test_did_sign_message(self, wallet_environments: WalletTestFramework):
1924
+ env = wallet_environments.environments[0]
1925
+ wallet_node = env.node
1926
+ wallet = env.xch_wallet
1927
+ api_0 = env.rpc_api
1928
+
1929
+ env.wallet_aliases = {
1930
+ "xch": 1,
1931
+ "did": 2,
1932
+ }
1933
+ fee = uint64(1000)
1934
+ ph = await wallet.get_new_puzzlehash()
1935
+
1936
+ async with wallet.wallet_state_manager.new_action_scope(
1937
+ wallet_environments.tx_config, push=True
1938
+ ) as action_scope:
1939
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1940
+ wallet_node.wallet_state_manager,
1941
+ wallet,
1942
+ uint64(101),
1943
+ action_scope,
1944
+ [ph],
1945
+ uint64(1),
1946
+ {"Twitter": "Test", "GitHub": "测试"},
1947
+ fee=fee,
1948
+ )
1949
+ assert did_wallet_1.get_name() == "Profile 1"
1950
+
1951
+ await wallet_environments.process_pending_states(
1952
+ [
1953
+ WalletStateTransition(
1954
+ pre_block_balance_updates={
1955
+ "xch": {
1956
+ "set_remainder": True,
1957
+ },
1958
+ "did": {
1959
+ "init": True,
1960
+ "unconfirmed_wallet_balance": 101,
1961
+ "pending_change": 101,
1962
+ "pending_coin_removal_count": 1,
1963
+ },
1964
+ },
1965
+ post_block_balance_updates={
1966
+ "xch": {
1967
+ "set_remainder": True,
1968
+ },
1969
+ "did": {
1970
+ "confirmed_wallet_balance": 101,
1971
+ "spendable_balance": 101,
1972
+ "max_send_amount": 101,
1973
+ "unspent_coin_count": 1,
1974
+ "pending_change": -101,
1975
+ "pending_coin_removal_count": -1,
1976
+ },
1977
+ },
1978
+ ),
1979
+ ]
1980
+ )
1981
+ # Test general string
1982
+ assert did_wallet_1.did_info.origin_coin is not None # mypy
1983
+ message = "Hello World"
1984
+ assert did_wallet_1.did_info.origin_coin is not None
1985
+ response = await api_0.sign_message_by_id(
1986
+ {
1987
+ "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
1988
+ "message": message,
1989
+ }
1990
+ )
1991
+ puzzle: Program = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message))
1992
+ assert AugSchemeMPL.verify(
1993
+ G1Element.from_bytes(bytes.fromhex(response["pubkey"])),
1994
+ puzzle.get_tree_hash(),
1995
+ G2Element.from_bytes(bytes.fromhex(response["signature"])),
1996
+ )
1997
+ # Test hex string
1998
+ message = "0123456789ABCDEF"
1999
+ response = await api_0.sign_message_by_id(
2000
+ {
2001
+ "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
2002
+ "message": message,
2003
+ "is_hex": True,
2004
+ }
2005
+ )
2006
+ puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message)))
2007
+
2008
+ assert AugSchemeMPL.verify(
2009
+ G1Element.from_bytes(bytes.fromhex(response["pubkey"])),
2010
+ puzzle.get_tree_hash(),
2011
+ G2Element.from_bytes(bytes.fromhex(response["signature"])),
2012
+ )
2013
+
2014
+ # Test BLS sign string
2015
+ message = "Hello World"
2016
+ assert did_wallet_1.did_info.origin_coin is not None
2017
+ response = await api_0.sign_message_by_id(
2018
+ {
2019
+ "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
2020
+ "message": message,
2021
+ "is_hex": "False",
2022
+ "safe_mode": "False",
2023
+ }
2024
+ )
2025
+
2026
+ assert AugSchemeMPL.verify(
2027
+ G1Element.from_bytes(bytes.fromhex(response["pubkey"])),
2028
+ bytes(message, "utf-8"),
2029
+ G2Element.from_bytes(bytes.fromhex(response["signature"])),
2030
+ )
2031
+ # Test BLS sign hex
2032
+ message = "0123456789ABCDEF"
2033
+ assert did_wallet_1.did_info.origin_coin is not None
2034
+ response = await api_0.sign_message_by_id(
2035
+ {
2036
+ "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
2037
+ "message": message,
2038
+ "is_hex": True,
2039
+ "safe_mode": False,
2040
+ }
2041
+ )
2042
+
2043
+ assert AugSchemeMPL.verify(
2044
+ G1Element.from_bytes(bytes.fromhex(response["pubkey"])),
2045
+ bytes.fromhex(message),
2046
+ G2Element.from_bytes(bytes.fromhex(response["signature"])),
2047
+ )
2048
+
2049
+ @pytest.mark.parametrize(
2050
+ "trusted",
2051
+ [True, False],
2052
+ )
2053
+ @pytest.mark.anyio
2054
+ async def test_create_did_with_recovery_list(
2055
+ self, self_hostname: str, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted: bool
2056
+ ) -> None:
2057
+ """
2058
+ A DID is created on-chain in client0, causing a DID Wallet to be created in client1, which shares the same key.
2059
+ This can happen if someone uses the same key on multiple computers, or is syncing a wallet from scratch.
2060
+
2061
+ For this test, we assign a recovery list hash at DID creation time, but the recovery list is not yet available
2062
+ to the wallet_node that the DID Wallet is being created in (client1).
2063
+
2064
+ """
2065
+ full_nodes, wallets, _ = two_nodes_two_wallets_with_same_keys
2066
+ full_node_api = full_nodes[0]
2067
+ full_node_server = full_node_api.server
2068
+ wallet_node_0, server_0 = wallets[0]
2069
+ wallet_node_1, server_1 = wallets[1]
2070
+
2071
+ wallet_0 = wallet_node_0.wallet_state_manager.main_wallet
2072
+ wallet_1 = wallet_node_1.wallet_state_manager.main_wallet
2073
+
2074
+ ph0 = await wallet_0.get_new_puzzlehash()
2075
+ ph1 = await wallet_1.get_new_puzzlehash()
2076
+
2077
+ sk0 = await wallet_node_0.wallet_state_manager.get_private_key(ph0)
2078
+ sk1 = await wallet_node_1.wallet_state_manager.get_private_key(ph1)
2079
+ assert sk0 == sk1
2080
+
2081
+ if trusted:
2082
+ wallet_node_0.config["trusted_peers"] = {
2083
+ full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2084
+ }
2085
+ wallet_node_1.config["trusted_peers"] = {
2086
+ full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
2087
+ }
2088
+
2089
+ else:
2090
+ wallet_node_0.config["trusted_peers"] = {}
2091
+ wallet_node_1.config["trusted_peers"] = {}
2092
+ await server_0.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2093
+ await server_1.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
2094
+
2095
+ await full_node_api.farm_blocks_to_wallet(1, wallet_0)
2096
+ await full_node_api.farm_blocks_to_wallet(1, wallet_1)
2097
+
2098
+ # Node 0 sets up a DID Wallet with a backup set, but num_of_backup_ids_needed=0
2099
+ # (a malformed solution, but legal for the clvm puzzle)
2100
+ recovery_list = [bytes32(bytes.fromhex("00" * 32))]
2101
+ async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2102
+ did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet(
2103
+ wallet_node_0.wallet_state_manager,
2104
+ wallet_0,
2105
+ uint64(101),
2106
+ action_scope,
2107
+ backups_ids=recovery_list,
2108
+ num_of_backup_ids_needed=uint64(0),
2109
+ )
2110
+
2111
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
2112
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_0])
2113
+
2114
+ await time_out_assert(15, did_wallet_0.get_confirmed_balance, 101)
2115
+ await time_out_assert(15, did_wallet_0.get_unconfirmed_balance, 101)
2116
+ await time_out_assert(15, did_wallet_0.get_pending_change_balance, 0)
2117
+
2118
+ await full_node_api.farm_blocks_to_wallet(1, wallet_0)
2119
+
2120
+ #######################
2121
+ all_node_0_wallets = await wallet_node_0.wallet_state_manager.user_store.get_all_wallet_info_entries()
2122
+ all_node_1_wallets = await wallet_node_1.wallet_state_manager.user_store.get_all_wallet_info_entries()
2123
+ assert len(all_node_0_wallets) == len(all_node_1_wallets)
2124
+
2125
+ # Note that the inner program we expect is different than the on-chain inner.
2126
+ # This means that we have more work to do in the checks for the two different spend cases of
2127
+ # the DID wallet Singleton
2128
+ # assert (
2129
+ # json.loads(all_node_0_wallets[1].data)["current_inner"]
2130
+ # == json.loads(all_node_1_wallets[1].data)["current_inner"]
2131
+ # )
2132
+
2133
+ # TODO: See Issue CHIA-1544
2134
+ # This test should be ported to WalletTestFramework once we can replace keys in the wallet node
2135
+ @pytest.mark.parametrize(
2136
+ "trusted",
2137
+ [True, False],
2138
+ )
2139
+ @pytest.mark.anyio
2140
+ async def test_did_resync(
2141
+ self,
2142
+ self_hostname: str,
2143
+ two_wallet_nodes: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
2144
+ trusted: bool,
2145
+ ) -> None:
2146
+ full_nodes, wallets, _ = two_wallet_nodes
2147
+ full_node_api = full_nodes[0]
2148
+ full_node_server = full_node_api.full_node.server
2149
+ wallet_node_1, wallet_server_1 = wallets[0]
2150
+ wallet_node_2, wallet_server_2 = wallets[1]
2151
+ wallet = wallet_node_1.wallet_state_manager.main_wallet
2152
+ wallet2 = wallet_node_2.wallet_state_manager.main_wallet
2153
+ fee = uint64(0)
2154
+ wallet_api_1 = WalletRpcApi(wallet_node_1)
2155
+ wallet_api_2 = WalletRpcApi(wallet_node_2)
2156
+ ph = await wallet.get_new_puzzlehash()
2157
+ if trusted:
2158
+ wallet_node_1.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
2159
+ wallet_node_2.config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
2160
+ else:
2161
+ wallet_node_1.config["trusted_peers"] = {}
2162
+ wallet_node_2.config["trusted_peers"] = {}
2163
+ assert full_node_server._port is not None
2164
+ await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
2165
+ await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
2166
+ await full_node_api.farm_blocks_to_wallet(1, wallet)
2167
+
2168
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2169
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
2170
+ wallet_node_1.wallet_state_manager,
2171
+ wallet,
2172
+ uint64(101),
2173
+ action_scope,
2174
+ [bytes32(ph)],
2175
+ uint64(1),
2176
+ {"Twitter": "Test", "GitHub": "测试"},
2177
+ fee=fee,
2178
+ )
2179
+ assert did_wallet_1.get_name() == "Profile 1"
2180
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
2181
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_1, wallet_node_2])
2182
+ await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
2183
+ await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
2184
+ # Transfer DID
2185
+ new_puzhash = await wallet2.get_new_puzzlehash()
2186
+ async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2187
+ await did_wallet_1.transfer_did(new_puzhash, fee, True, action_scope=action_scope)
2188
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
2189
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node_1, wallet_node_2])
2190
+ # Check if the DID wallet is created in the wallet2
2191
+ await time_out_assert(30, get_wallet_num, 2, wallet_node_2.wallet_state_manager)
2192
+ await time_out_assert(30, get_wallet_num, 1, wallet_node_1.wallet_state_manager)
2193
+ did_wallet_2 = wallet_node_2.wallet_state_manager.get_wallet(uint32(2), DIDWallet)
2194
+ did_info = did_wallet_2.did_info
2195
+ # set flag to reset wallet sync data on start
2196
+ await wallet_api_1.set_wallet_resync_on_startup({"enable": True})
2197
+ fingerprint_1 = wallet_node_1.logged_in_fingerprint
2198
+ await wallet_api_2.set_wallet_resync_on_startup({"enable": True})
2199
+ fingerprint_2 = wallet_node_2.logged_in_fingerprint
2200
+ # 2 reward coins
2201
+ assert len(await wallet_node_1.wallet_state_manager.coin_store.get_all_unspent_coins()) == 2
2202
+ # Delete tx records
2203
+ await wallet_node_1.wallet_state_manager.tx_store.rollback_to_block(0)
2204
+ wallet_node_1._close()
2205
+ await wallet_node_1._await_closed()
2206
+ wallet_node_2._close()
2207
+ await wallet_node_2._await_closed()
2208
+ wallet_node_1.config["database_path"] = "wallet/db/blockchain_wallet_v2_test_1_CHALLENGE_KEY.sqlite"
2209
+ wallet_node_2.config["database_path"] = "wallet/db/blockchain_wallet_v2_test_2_CHALLENGE_KEY.sqlite"
2210
+ # Start resync
2211
+ await wallet_node_1._start_with_fingerprint(fingerprint_1)
2212
+ await wallet_node_2._start_with_fingerprint(fingerprint_2)
2213
+ assert full_node_server._port is not None
2214
+ await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
2215
+ await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
2216
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32(b"\00" * 32)))
2217
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=20)
2218
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_2, timeout=20)
2219
+ await time_out_assert(30, get_wallet_num, 1, wallet_node_1.wallet_state_manager)
2220
+ await time_out_assert(30, get_wallet_num, 2, wallet_node_2.wallet_state_manager)
2221
+ did_wallet_2 = wallet_node_2.wallet_state_manager.get_wallet(uint32(2), DIDWallet)
2222
+ assert did_info == did_wallet_2.did_info
2223
+
2224
+
2225
+ @pytest.mark.parametrize(
2226
+ "wallet_environments",
2227
+ [
2228
+ {
2229
+ "num_environments": 1,
2230
+ "blocks_needed": [1],
2231
+ }
2232
+ ],
2233
+ indirect=True,
2234
+ )
2235
+ @pytest.mark.anyio
2236
+ async def test_did_coin_records(wallet_environments: WalletTestFramework, monkeypatch: pytest.MonkeyPatch) -> None:
2237
+ # Setup
2238
+ wallet_node = wallet_environments.environments[0].node
2239
+ wallet = wallet_environments.environments[0].xch_wallet
2240
+
2241
+ # Generate DID wallet
2242
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
2243
+ did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
2244
+ wallet_node.wallet_state_manager, wallet, uint64(1), action_scope
2245
+ )
2246
+
2247
+ await wallet_environments.process_pending_states(
2248
+ [
2249
+ WalletStateTransition(
2250
+ pre_block_balance_updates={
2251
+ 1: {"set_remainder": True},
2252
+ 2: {"init": True, "set_remainder": True},
2253
+ },
2254
+ post_block_balance_updates={
2255
+ 1: {"set_remainder": True},
2256
+ 2: {"set_remainder": True},
2257
+ },
2258
+ ),
2259
+ WalletStateTransition(),
2260
+ ]
2261
+ )
2262
+
2263
+ for _ in range(0, 2):
2264
+ async with did_wallet.wallet_state_manager.new_action_scope(
2265
+ wallet_environments.tx_config, push=True
2266
+ ) as action_scope:
2267
+ await did_wallet.transfer_did(await wallet.get_puzzle_hash(new=False), uint64(0), True, action_scope)
2268
+ await wallet_environments.process_pending_states(
2269
+ [
2270
+ WalletStateTransition(
2271
+ pre_block_balance_updates={
2272
+ 1: {"set_remainder": True},
2273
+ 2: {"set_remainder": True},
2274
+ },
2275
+ post_block_balance_updates={
2276
+ 1: {"set_remainder": True},
2277
+ 2: {"set_remainder": True},
2278
+ },
2279
+ ),
2280
+ WalletStateTransition(),
2281
+ ]
2282
+ )
2283
+
2284
+ assert len(await wallet.wallet_state_manager.get_spendable_coins_for_wallet(did_wallet.id())) == 1