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,1494 @@
1
+ from __future__ import annotations
2
+
3
+ import dataclasses
4
+ import json
5
+ import logging
6
+ import re
7
+ import time
8
+ from typing import TYPE_CHECKING, Any, ClassVar, Optional, cast
9
+
10
+ from chia_rs import AugSchemeMPL, G1Element, G2Element
11
+
12
+ from chia.protocols.wallet_protocol import CoinState
13
+ from chia.server.ws_connection import WSChiaConnection
14
+ from chia.types.blockchain_format.coin import Coin
15
+ from chia.types.blockchain_format.program import Program
16
+ from chia.types.blockchain_format.sized_bytes import bytes32
17
+ from chia.types.coin_spend import CoinSpend, make_spend
18
+ from chia.types.signing_mode import CHIP_0002_SIGN_MESSAGE_PREFIX, SigningMode
19
+ from chia.util.ints import uint16, uint32, uint64, uint128
20
+ from chia.wallet.conditions import (
21
+ AssertCoinAnnouncement,
22
+ Condition,
23
+ ConditionValidTimes,
24
+ CreateCoinAnnouncement,
25
+ parse_timelock_info,
26
+ )
27
+ from chia.wallet.derivation_record import DerivationRecord
28
+ from chia.wallet.did_wallet import did_wallet_puzzles
29
+ from chia.wallet.did_wallet.did_info import DIDCoinData, DIDInfo
30
+ from chia.wallet.did_wallet.did_wallet_puzzles import match_did_puzzle, uncurry_innerpuz
31
+ from chia.wallet.lineage_proof import LineageProof
32
+ from chia.wallet.payment import Payment
33
+ from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import (
34
+ DEFAULT_HIDDEN_PUZZLE_HASH,
35
+ calculate_synthetic_secret_key,
36
+ puzzle_for_pk,
37
+ puzzle_hash_for_pk,
38
+ )
39
+ from chia.wallet.singleton import (
40
+ SINGLETON_LAUNCHER_PUZZLE,
41
+ create_singleton_puzzle,
42
+ create_singleton_puzzle_hash,
43
+ get_inner_puzzle_from_singleton,
44
+ )
45
+ from chia.wallet.transaction_record import TransactionRecord
46
+ from chia.wallet.uncurried_puzzle import uncurry_puzzle
47
+ from chia.wallet.util.compute_memos import compute_memos
48
+ from chia.wallet.util.curry_and_treehash import NIL_TREEHASH, shatree_int, shatree_pair
49
+ from chia.wallet.util.transaction_type import TransactionType
50
+ from chia.wallet.util.wallet_sync_utils import fetch_coin_spend, fetch_coin_spend_for_coin_state
51
+ from chia.wallet.util.wallet_types import WalletType
52
+ from chia.wallet.wallet import Wallet
53
+ from chia.wallet.wallet_action_scope import WalletActionScope
54
+ from chia.wallet.wallet_coin_record import WalletCoinRecord
55
+ from chia.wallet.wallet_info import WalletInfo
56
+ from chia.wallet.wallet_protocol import WalletProtocol
57
+ from chia.wallet.wallet_spend_bundle import WalletSpendBundle
58
+
59
+
60
+ class DIDWallet:
61
+ if TYPE_CHECKING:
62
+ if TYPE_CHECKING:
63
+ _protocol_check: ClassVar[WalletProtocol[DIDCoinData]] = cast("DIDWallet", None)
64
+
65
+ wallet_state_manager: Any
66
+ log: logging.Logger
67
+ wallet_info: WalletInfo
68
+ did_info: DIDInfo
69
+ standard_wallet: Wallet
70
+ base_puzzle_program: Optional[bytes]
71
+ base_inner_puzzle_hash: Optional[bytes32]
72
+ wallet_id: int
73
+
74
+ @staticmethod
75
+ async def create_new_did_wallet(
76
+ wallet_state_manager: Any,
77
+ wallet: Wallet,
78
+ amount: uint64,
79
+ action_scope: WalletActionScope,
80
+ backups_ids: list[bytes32] = [],
81
+ num_of_backup_ids_needed: uint64 = None,
82
+ metadata: dict[str, str] = {},
83
+ name: Optional[str] = None,
84
+ fee: uint64 = uint64(0),
85
+ extra_conditions: tuple[Condition, ...] = tuple(),
86
+ ):
87
+ """
88
+ Create a brand new DID wallet
89
+ This must be called under the wallet state manager lock
90
+ :param wallet_state_manager: Wallet state manager
91
+ :param wallet: Standard wallet
92
+ :param amount: Amount of the DID coin
93
+ :param backups_ids: A list of DIDs used for recovery this DID
94
+ :param num_of_backup_ids_needed: Needs how many recovery DIDs at least
95
+ :param metadata: Metadata saved in the DID
96
+ :param name: Wallet name
97
+ :param fee: transaction fee
98
+ :return: DID wallet
99
+ """
100
+
101
+ self = DIDWallet()
102
+ self.wallet_state_manager = wallet_state_manager
103
+ if name is None:
104
+ name = self.generate_wallet_name()
105
+ self.base_puzzle_program = None
106
+ self.base_inner_puzzle_hash = None
107
+ self.standard_wallet = wallet
108
+ self.log = logging.getLogger(name if name else __name__)
109
+ std_wallet_id = self.standard_wallet.wallet_id
110
+ bal = await wallet_state_manager.get_confirmed_balance_for_wallet(std_wallet_id)
111
+ if amount > bal:
112
+ raise ValueError("Not enough balance")
113
+ if amount & 1 == 0:
114
+ raise ValueError("DID amount must be odd number")
115
+
116
+ if num_of_backup_ids_needed is None:
117
+ num_of_backup_ids_needed = uint64(len(backups_ids))
118
+ if num_of_backup_ids_needed > len(backups_ids):
119
+ raise ValueError("Cannot require more IDs than are known.")
120
+ self.did_info = DIDInfo(
121
+ origin_coin=None,
122
+ backup_ids=backups_ids,
123
+ num_of_backup_ids_needed=num_of_backup_ids_needed,
124
+ parent_info=[],
125
+ current_inner=None,
126
+ temp_coin=None,
127
+ temp_puzhash=None,
128
+ temp_pubkey=None,
129
+ sent_recovery_transaction=False,
130
+ metadata=json.dumps(metadata),
131
+ )
132
+ info_as_string = json.dumps(self.did_info.to_json_dict())
133
+ self.wallet_info = await wallet_state_manager.user_store.create_wallet(
134
+ name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
135
+ )
136
+ self.wallet_id = self.wallet_info.id
137
+ std_wallet_id = self.standard_wallet.wallet_id
138
+ bal = await wallet_state_manager.get_confirmed_balance_for_wallet(std_wallet_id)
139
+ if amount > bal:
140
+ raise ValueError("Not enough balance")
141
+
142
+ try:
143
+ await self.generate_new_decentralised_id(amount, action_scope, fee, extra_conditions)
144
+ except Exception:
145
+ await wallet_state_manager.delete_wallet(self.id())
146
+ raise
147
+
148
+ await self.wallet_state_manager.add_new_wallet(self)
149
+
150
+ return self
151
+
152
+ @staticmethod
153
+ async def create_new_did_wallet_from_recovery(
154
+ wallet_state_manager: Any,
155
+ wallet: Wallet,
156
+ backup_data: str,
157
+ name: Optional[str] = None,
158
+ ):
159
+ """
160
+ Create a DID wallet from a backup file
161
+ :param wallet_state_manager: Wallet state manager
162
+ :param wallet: Standard wallet
163
+ :param backup_data: A serialized backup data
164
+ :param name: Wallet name
165
+ :return: DID wallet
166
+ """
167
+ self = DIDWallet()
168
+ self.wallet_state_manager = wallet_state_manager
169
+ if name is None:
170
+ name = self.generate_wallet_name()
171
+ self.base_puzzle_program = None
172
+ self.base_inner_puzzle_hash = None
173
+ self.standard_wallet = wallet
174
+ self.log = logging.getLogger(name if name else __name__)
175
+ self.log.info("Creating DID wallet from recovery file ...")
176
+ # load backup will also set our DIDInfo
177
+ self.did_info = DIDWallet.deserialize_backup_data(backup_data)
178
+ self.check_existed_did()
179
+ info_as_string = json.dumps(self.did_info.to_json_dict())
180
+ self.wallet_info = await wallet_state_manager.user_store.create_wallet(
181
+ name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
182
+ )
183
+ await self.wallet_state_manager.add_new_wallet(self)
184
+ await self.save_info(self.did_info)
185
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
186
+ await self.load_parent(self.did_info)
187
+ if self.wallet_info is None:
188
+ raise ValueError("Internal Error")
189
+ self.wallet_id = self.wallet_info.id
190
+ return self
191
+
192
+ @staticmethod
193
+ async def create_new_did_wallet_from_coin_spend(
194
+ wallet_state_manager: Any,
195
+ wallet: Wallet,
196
+ launch_coin: Coin,
197
+ inner_puzzle: Program,
198
+ coin_spend: CoinSpend,
199
+ name: Optional[str] = None,
200
+ ):
201
+ """
202
+ Create a DID wallet from a transfer
203
+ :param wallet_state_manager: Wallet state manager
204
+ :param wallet: Main wallet
205
+ :param launch_coin: The launch coin of the DID
206
+ :param inner_puzzle: DID inner puzzle
207
+ :param coin_spend: DID transfer spend
208
+ :param name: Wallet name
209
+ :return: DID wallet
210
+ """
211
+ self = DIDWallet()
212
+ self.wallet_state_manager = wallet_state_manager
213
+ if name is None:
214
+ name = self.generate_wallet_name()
215
+ self.base_puzzle_program = None
216
+ self.base_inner_puzzle_hash = None
217
+ self.standard_wallet = wallet
218
+ self.log = logging.getLogger(name if name else __name__)
219
+
220
+ self.log.info(f"Creating DID wallet from a coin spend {launch_coin} ...")
221
+ # Create did info from the coin spend
222
+ args = did_wallet_puzzles.uncurry_innerpuz(inner_puzzle)
223
+ if args is None:
224
+ raise ValueError("Cannot uncurry the DID puzzle.")
225
+ _, recovery_list_hash, num_verification, _, metadata = args
226
+ full_solution: Program = Program.from_bytes(bytes(coin_spend.solution))
227
+ inner_solution: Program = full_solution.rest().rest().first()
228
+ recovery_list: list[bytes32] = []
229
+ backup_required: int = num_verification.as_int()
230
+ if recovery_list_hash != NIL_TREEHASH:
231
+ try:
232
+ for did in inner_solution.rest().rest().rest().rest().rest().as_python():
233
+ recovery_list.append(bytes32(did[0]))
234
+ except Exception:
235
+ self.log.warning(
236
+ f"DID {launch_coin.name().hex()} has a recovery list hash but missing a reveal,"
237
+ " you may need to reset the recovery info."
238
+ )
239
+ self.did_info = DIDInfo(
240
+ origin_coin=launch_coin,
241
+ backup_ids=recovery_list,
242
+ num_of_backup_ids_needed=uint64(backup_required),
243
+ parent_info=[],
244
+ current_inner=inner_puzzle,
245
+ temp_coin=None,
246
+ temp_puzhash=None,
247
+ temp_pubkey=None,
248
+ sent_recovery_transaction=False,
249
+ metadata=json.dumps(did_wallet_puzzles.did_program_to_metadata(metadata)),
250
+ )
251
+ self.check_existed_did()
252
+ info_as_string = json.dumps(self.did_info.to_json_dict())
253
+
254
+ self.wallet_info = await wallet_state_manager.user_store.create_wallet(
255
+ name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
256
+ )
257
+ await self.wallet_state_manager.add_new_wallet(self)
258
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
259
+ await self.load_parent(self.did_info)
260
+ self.log.info(f"New DID wallet created {info_as_string}.")
261
+ if self.wallet_info is None:
262
+ raise ValueError("Internal Error")
263
+ self.wallet_id = self.wallet_info.id
264
+ return self
265
+
266
+ @staticmethod
267
+ async def create(
268
+ wallet_state_manager: Any,
269
+ wallet: Wallet,
270
+ wallet_info: WalletInfo,
271
+ name: Optional[str] = None,
272
+ ):
273
+ """
274
+ Create a DID wallet based on the local database
275
+ :param wallet_state_manager: Wallet state manager
276
+ :param wallet: Standard wallet
277
+ :param wallet_info: Serialized WalletInfo
278
+ :param name: Wallet name
279
+ :return:
280
+ """
281
+ self = DIDWallet()
282
+ self.log = logging.getLogger(name if name else __name__)
283
+ self.wallet_state_manager = wallet_state_manager
284
+ self.wallet_info = wallet_info
285
+ self.wallet_id = wallet_info.id
286
+ self.standard_wallet = wallet
287
+ self.wallet_info = wallet_info
288
+ self.did_info = DIDInfo.from_json_dict(json.loads(wallet_info.data))
289
+ self.base_puzzle_program = None
290
+ self.base_inner_puzzle_hash = None
291
+ return self
292
+
293
+ @classmethod
294
+ def type(cls) -> WalletType:
295
+ return WalletType.DECENTRALIZED_ID
296
+
297
+ def id(self) -> uint32:
298
+ return self.wallet_info.id
299
+
300
+ async def get_confirmed_balance(self, record_list=None) -> uint128:
301
+ if record_list is None:
302
+ record_list = await self.wallet_state_manager.coin_store.get_unspent_coins_for_wallet(self.id())
303
+
304
+ amount: uint128 = uint128(0)
305
+ for record in record_list:
306
+ parent = self.get_parent_for_coin(record.coin)
307
+ if parent is not None:
308
+ amount = uint128(amount + record.coin.amount)
309
+
310
+ self.log.info(f"Confirmed balance for did wallet is {amount}")
311
+ return uint128(amount)
312
+
313
+ async def get_pending_change_balance(self) -> uint64:
314
+ unconfirmed_tx = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(self.id())
315
+ addition_amount = 0
316
+
317
+ for record in unconfirmed_tx:
318
+ our_spend = False
319
+ # Need to check belonging with hint_dict
320
+ for coin in record.removals:
321
+ if await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id()):
322
+ our_spend = True
323
+ break
324
+
325
+ if our_spend is not True:
326
+ continue
327
+
328
+ for coin in record.additions:
329
+ hint_dict = {
330
+ coin_id: bytes32(memos[0])
331
+ for coin_id, memos in record.memos
332
+ if len(memos) > 0 and len(memos[0]) == 32
333
+ }
334
+ if (await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id(), hint_dict)) and (
335
+ coin not in record.removals
336
+ ):
337
+ addition_amount += coin.amount
338
+
339
+ return uint64(addition_amount)
340
+
341
+ async def get_unconfirmed_balance(self, record_list=None) -> uint128:
342
+ return await self.wallet_state_manager.get_unconfirmed_balance(self.id(), record_list)
343
+
344
+ async def select_coins(
345
+ self,
346
+ amount: uint64,
347
+ action_scope: WalletActionScope,
348
+ ) -> set[Coin]:
349
+ try:
350
+ async with action_scope.use() as interface:
351
+ coin = await self.get_coin()
352
+ interface.side_effects.selected_coins.append(coin)
353
+ return {coin}
354
+ except RuntimeError:
355
+ return set()
356
+
357
+ def _coin_is_first_singleton(self, coin: Coin) -> bool:
358
+ parent = self.get_parent_for_coin(coin)
359
+ if parent is None:
360
+ return False
361
+ assert self.did_info.origin_coin
362
+ return parent.parent_name == self.did_info.origin_coin.name()
363
+
364
+ # This will be used in the recovery case where we don't have the parent info already
365
+ # But it is also called whenever a Singleton coin from this wallet is spent
366
+ # We can improve this interface by passing in the CoinSpend, as well
367
+ # We need to change DID Wallet coin_added to expect p2 spends as well as recovery spends,
368
+ # or only call it in the recovery spend case
369
+ async def coin_added(self, coin: Coin, _: uint32, peer: WSChiaConnection, parent_coin_data: Optional[DIDCoinData]):
370
+ """Notification from wallet state manager that wallet has been received."""
371
+ parent = self.get_parent_for_coin(coin)
372
+ if parent_coin_data is not None:
373
+ assert isinstance(parent_coin_data, DIDCoinData)
374
+ did_data: DIDCoinData = parent_coin_data
375
+ else:
376
+ parent_state: CoinState = (
377
+ await self.wallet_state_manager.wallet_node.get_coin_state(
378
+ coin_names=[coin.parent_coin_info], peer=peer
379
+ )
380
+ )[0]
381
+ coin_spend = await fetch_coin_spend_for_coin_state(parent_state, peer)
382
+ uncurried = uncurry_puzzle(coin_spend.puzzle_reveal)
383
+ did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args)
384
+ assert did_curried_args is not None
385
+ p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args
386
+ did_data = DIDCoinData(
387
+ p2_puzzle=p2_puzzle,
388
+ recovery_list_hash=bytes32(recovery_list_hash.as_atom()),
389
+ num_verification=uint16(num_verification.as_int()),
390
+ singleton_struct=singleton_struct,
391
+ metadata=metadata,
392
+ inner_puzzle=get_inner_puzzle_from_singleton(coin_spend.puzzle_reveal),
393
+ coin_state=parent_state,
394
+ )
395
+ if parent is None:
396
+ # this is the first time we received it, check it's a DID coin
397
+ parent_innerpuz = did_data.inner_puzzle
398
+ if parent_innerpuz:
399
+ parent_info = LineageProof(
400
+ parent_name=did_data.coin_state.coin.parent_coin_info,
401
+ inner_puzzle_hash=parent_innerpuz.get_tree_hash(),
402
+ amount=uint64(did_data.coin_state.coin.amount),
403
+ )
404
+ await self.add_parent(coin.parent_coin_info, parent_info)
405
+ else:
406
+ self.log.warning("Parent coin is not a DID, skipping: %s -> %s", coin.name(), coin)
407
+ return
408
+ self.log.info(f"DID wallet has been notified that coin was added: {coin.name()}:{coin}")
409
+ inner_puzzle = await self.inner_puzzle_for_did_puzzle(coin.puzzle_hash)
410
+ # Check inner puzzle consistency
411
+ assert self.did_info.origin_coin is not None
412
+
413
+ # TODO: if not the first singleton, and solution mode == recovery
414
+ if not self._coin_is_first_singleton(coin):
415
+ full_puzzle = create_singleton_puzzle(inner_puzzle, self.did_info.origin_coin.name())
416
+ assert full_puzzle.get_tree_hash() == coin.puzzle_hash
417
+ if self.did_info.temp_coin is not None:
418
+ self.wallet_state_manager.state_changed("did_coin_added", self.wallet_info.id)
419
+ new_info = DIDInfo(
420
+ origin_coin=self.did_info.origin_coin,
421
+ backup_ids=self.did_info.backup_ids,
422
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
423
+ parent_info=self.did_info.parent_info,
424
+ current_inner=inner_puzzle,
425
+ temp_coin=None,
426
+ temp_puzhash=None,
427
+ temp_pubkey=None,
428
+ sent_recovery_transaction=False,
429
+ metadata=json.dumps(did_wallet_puzzles.did_program_to_metadata(did_data.metadata)),
430
+ )
431
+ await self.save_info(new_info)
432
+
433
+ future_parent = LineageProof(
434
+ parent_name=coin.parent_coin_info,
435
+ inner_puzzle_hash=inner_puzzle.get_tree_hash(),
436
+ amount=uint64(coin.amount),
437
+ )
438
+
439
+ await self.add_parent(coin.name(), future_parent)
440
+ await self.wallet_state_manager.add_interested_coin_ids([coin.name()])
441
+
442
+ def create_backup(self) -> str:
443
+ """
444
+ Create a serialized backup data for DIDInfo
445
+ :return: Serialized backup data
446
+ """
447
+ assert self.did_info.current_inner is not None
448
+ assert self.did_info.origin_coin is not None
449
+ output_str = f"{self.did_info.origin_coin.parent_coin_info.hex()}:"
450
+ output_str += f"{self.did_info.origin_coin.puzzle_hash.hex()}:"
451
+ output_str += f"{self.did_info.origin_coin.amount}:"
452
+ if len(self.did_info.backup_ids) > 0:
453
+ for did in self.did_info.backup_ids:
454
+ output_str = output_str + did.hex() + ","
455
+ output_str = output_str[:-1]
456
+ output_str += f":{bytes(self.did_info.current_inner).hex()}:{self.did_info.num_of_backup_ids_needed}"
457
+ output_str += f":{self.did_info.metadata}"
458
+ return output_str
459
+
460
+ async def load_parent(self, did_info: DIDInfo):
461
+ """
462
+ Load the parent info when importing a DID
463
+ :param did_info: DID info
464
+ :return:
465
+ """
466
+ # full_puz = did_wallet_puzzles.create_fullpuz(innerpuz, origin.name())
467
+ # All additions in this block here:
468
+
469
+ new_puzhash = await self.wallet_state_manager.main_wallet.get_puzzle_hash(new=False)
470
+ new_pubkey = await self.wallet_state_manager.get_public_key(new_puzhash)
471
+ parent_info = None
472
+ assert did_info.origin_coin is not None
473
+ assert did_info.current_inner is not None
474
+ new_did_inner_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2(
475
+ p2_puzhash=new_puzhash,
476
+ recovery_list=did_info.backup_ids,
477
+ num_of_backup_ids_needed=did_info.num_of_backup_ids_needed,
478
+ launcher_id=did_info.origin_coin.name(),
479
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
480
+ )
481
+ wallet_node = self.wallet_state_manager.wallet_node
482
+ parent_coin: Coin = did_info.origin_coin
483
+ while True:
484
+ peer = wallet_node.get_full_node_peer()
485
+ children = await wallet_node.fetch_children(parent_coin.name(), peer)
486
+ if len(children) == 0:
487
+ break
488
+
489
+ children_state: CoinState = children[0]
490
+ child_coin = children_state.coin
491
+ future_parent = LineageProof(
492
+ parent_name=child_coin.parent_coin_info,
493
+ inner_puzzle_hash=did_info.current_inner.get_tree_hash(),
494
+ amount=uint64(child_coin.amount),
495
+ )
496
+ await self.add_parent(child_coin.name(), future_parent)
497
+ if children_state.spent_height != children_state.created_height:
498
+ did_info = DIDInfo(
499
+ origin_coin=did_info.origin_coin,
500
+ backup_ids=did_info.backup_ids,
501
+ num_of_backup_ids_needed=did_info.num_of_backup_ids_needed,
502
+ parent_info=self.did_info.parent_info,
503
+ current_inner=did_info.current_inner,
504
+ temp_coin=child_coin,
505
+ temp_puzhash=new_did_inner_puzhash,
506
+ temp_pubkey=bytes(new_pubkey),
507
+ sent_recovery_transaction=did_info.sent_recovery_transaction,
508
+ metadata=did_info.metadata,
509
+ )
510
+
511
+ await self.save_info(did_info)
512
+ assert children_state.created_height
513
+ parent_spend = await fetch_coin_spend(uint32(children_state.created_height), parent_coin, peer)
514
+ assert parent_spend is not None
515
+ parent_innerpuz = get_inner_puzzle_from_singleton(parent_spend.puzzle_reveal)
516
+ assert parent_innerpuz is not None
517
+ parent_info = LineageProof(
518
+ parent_name=parent_coin.parent_coin_info,
519
+ inner_puzzle_hash=parent_innerpuz.get_tree_hash(),
520
+ amount=uint64(parent_coin.amount),
521
+ )
522
+ await self.add_parent(child_coin.parent_coin_info, parent_info)
523
+ parent_coin = child_coin
524
+ assert parent_info is not None
525
+
526
+ def puzzle_for_pk(self, pubkey: G1Element) -> Program:
527
+ if self.did_info.origin_coin is not None:
528
+ innerpuz = did_wallet_puzzles.create_innerpuz(
529
+ p2_puzzle_or_hash=puzzle_for_pk(pubkey),
530
+ recovery_list=self.did_info.backup_ids,
531
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
532
+ launcher_id=self.did_info.origin_coin.name(),
533
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
534
+ )
535
+ return create_singleton_puzzle(innerpuz, self.did_info.origin_coin.name())
536
+ else:
537
+ innerpuz = Program.to((8, 0))
538
+ return create_singleton_puzzle(innerpuz, bytes32.zeros)
539
+
540
+ def puzzle_hash_for_pk(self, pubkey: G1Element) -> bytes32:
541
+ if self.did_info.origin_coin is None:
542
+ # TODO: this seem dumb. Why bother with this case? Is it ever used?
543
+ # inner puzzle: (8 . 0)
544
+ innerpuz_hash = shatree_pair(shatree_int(8), NIL_TREEHASH)
545
+ return create_singleton_puzzle_hash(innerpuz_hash, bytes32.zeros)
546
+ origin_coin_name = self.did_info.origin_coin.name()
547
+ innerpuz_hash = did_wallet_puzzles.get_inner_puzhash_by_p2(
548
+ p2_puzhash=puzzle_hash_for_pk(pubkey),
549
+ recovery_list=self.did_info.backup_ids,
550
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
551
+ launcher_id=origin_coin_name,
552
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
553
+ )
554
+ return create_singleton_puzzle_hash(innerpuz_hash, origin_coin_name)
555
+
556
+ def get_my_DID(self) -> str:
557
+ assert self.did_info.origin_coin is not None
558
+ core = self.did_info.origin_coin.name()
559
+ assert core is not None
560
+ return core.hex()
561
+
562
+ async def set_name(self, new_name: str):
563
+ new_info = dataclasses.replace(self.wallet_info, name=new_name)
564
+ self.wallet_info = new_info
565
+ await self.wallet_state_manager.user_store.update_wallet(self.wallet_info)
566
+
567
+ def get_name(self):
568
+ return self.wallet_info.name
569
+
570
+ async def create_update_spend(
571
+ self,
572
+ action_scope: WalletActionScope,
573
+ fee: uint64 = uint64(0),
574
+ extra_conditions: tuple[Condition, ...] = tuple(),
575
+ ) -> None:
576
+ assert self.did_info.current_inner is not None
577
+ assert self.did_info.origin_coin is not None
578
+ coin = await self.get_coin()
579
+ new_inner_puzzle = await self.get_did_innerpuz(new=not action_scope.config.tx_config.reuse_puzhash)
580
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(new_inner_puzzle)
581
+ assert uncurried is not None
582
+ p2_puzzle = uncurried[0]
583
+ # innerpuz solution is (mode, p2_solution)
584
+ p2_solution = self.standard_wallet.make_solution(
585
+ primaries=[
586
+ Payment(
587
+ puzzle_hash=new_inner_puzzle.get_tree_hash(),
588
+ amount=uint64(coin.amount),
589
+ memos=[p2_puzzle.get_tree_hash()],
590
+ )
591
+ ],
592
+ conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())),
593
+ )
594
+ innersol: Program = Program.to([1, p2_solution])
595
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
596
+ innerpuz: Program = self.did_info.current_inner
597
+
598
+ full_puzzle: Program = create_singleton_puzzle(
599
+ innerpuz,
600
+ self.did_info.origin_coin.name(),
601
+ )
602
+ parent_info = self.get_parent_for_coin(coin)
603
+ assert parent_info is not None
604
+ fullsol = Program.to(
605
+ [
606
+ [
607
+ parent_info.parent_name,
608
+ parent_info.inner_puzzle_hash,
609
+ parent_info.amount,
610
+ ],
611
+ coin.amount,
612
+ innersol,
613
+ ]
614
+ )
615
+ # Create an additional spend to confirm the change on-chain
616
+ new_full_puzzle: Program = create_singleton_puzzle(
617
+ new_inner_puzzle,
618
+ self.did_info.origin_coin.name(),
619
+ )
620
+ new_full_sol = Program.to(
621
+ [
622
+ [
623
+ coin.parent_coin_info,
624
+ innerpuz.get_tree_hash(),
625
+ coin.amount,
626
+ ],
627
+ coin.amount,
628
+ innersol,
629
+ ]
630
+ )
631
+ new_coin = Coin(coin.name(), new_full_puzzle.get_tree_hash(), coin.amount)
632
+ list_of_coinspends = [
633
+ make_spend(coin, full_puzzle, fullsol),
634
+ make_spend(new_coin, new_full_puzzle, new_full_sol),
635
+ ]
636
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
637
+ if fee > 0:
638
+ coin_name = coin.name()
639
+ await self.standard_wallet.create_tandem_xch_tx(
640
+ fee,
641
+ action_scope,
642
+ extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),),
643
+ )
644
+ did_record = TransactionRecord(
645
+ confirmed_at_height=uint32(0),
646
+ created_at_time=uint64(int(time.time())),
647
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
648
+ amount=uint64(coin.amount),
649
+ fee_amount=uint64(0),
650
+ confirmed=False,
651
+ sent=uint32(0),
652
+ spend_bundle=spend_bundle,
653
+ additions=spend_bundle.additions(),
654
+ removals=spend_bundle.removals(),
655
+ wallet_id=self.wallet_info.id,
656
+ sent_to=[],
657
+ trade_id=None,
658
+ type=uint32(TransactionType.OUTGOING_TX.value),
659
+ name=bytes32.secret(),
660
+ memos=list(compute_memos(spend_bundle).items()),
661
+ valid_times=parse_timelock_info(extra_conditions),
662
+ )
663
+
664
+ async with action_scope.use() as interface:
665
+ interface.side_effects.transactions.append(did_record)
666
+
667
+ async def transfer_did(
668
+ self,
669
+ new_puzhash: bytes32,
670
+ fee: uint64,
671
+ with_recovery: bool,
672
+ action_scope: WalletActionScope,
673
+ extra_conditions: tuple[Condition, ...] = tuple(),
674
+ ) -> None:
675
+ """
676
+ Transfer the current DID to another owner
677
+ :param new_puzhash: New owner's p2_puzzle
678
+ :param fee: Transaction fee
679
+ :param with_recovery: A boolean indicates if the recovery info will be sent through the blockchain
680
+ :return: Spend bundle
681
+ """
682
+ assert self.did_info.current_inner is not None
683
+ assert self.did_info.origin_coin is not None
684
+ coin = await self.get_coin()
685
+ backup_ids = []
686
+ backup_required = uint64(0)
687
+ if with_recovery:
688
+ backup_ids = self.did_info.backup_ids
689
+ backup_required = self.did_info.num_of_backup_ids_needed
690
+ new_did_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2(
691
+ p2_puzhash=new_puzhash,
692
+ recovery_list=backup_ids,
693
+ num_of_backup_ids_needed=backup_required,
694
+ launcher_id=self.did_info.origin_coin.name(),
695
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
696
+ )
697
+ p2_solution = self.standard_wallet.make_solution(
698
+ primaries=[Payment(new_did_puzhash, uint64(coin.amount), [new_puzhash])],
699
+ conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())),
700
+ )
701
+ # Need to include backup list reveal here, even we are don't recover
702
+ # innerpuz solution is
703
+ # (mode, p2_solution)
704
+ innersol: Program = Program.to([2, p2_solution])
705
+ if with_recovery:
706
+ innersol = Program.to([2, p2_solution, [], [], [], self.did_info.backup_ids])
707
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
708
+
709
+ full_puzzle: Program = create_singleton_puzzle(
710
+ self.did_info.current_inner,
711
+ self.did_info.origin_coin.name(),
712
+ )
713
+ parent_info = self.get_parent_for_coin(coin)
714
+ assert parent_info is not None
715
+ fullsol = Program.to(
716
+ [
717
+ [
718
+ parent_info.parent_name,
719
+ parent_info.inner_puzzle_hash,
720
+ parent_info.amount,
721
+ ],
722
+ coin.amount,
723
+ innersol,
724
+ ]
725
+ )
726
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
727
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
728
+ if fee > 0:
729
+ coin_name = coin.name()
730
+ await self.standard_wallet.create_tandem_xch_tx(
731
+ fee,
732
+ action_scope,
733
+ extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),),
734
+ )
735
+ did_record = TransactionRecord(
736
+ confirmed_at_height=uint32(0),
737
+ created_at_time=uint64(int(time.time())),
738
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
739
+ amount=uint64(coin.amount),
740
+ fee_amount=fee,
741
+ confirmed=False,
742
+ sent=uint32(0),
743
+ spend_bundle=spend_bundle,
744
+ additions=spend_bundle.additions(),
745
+ removals=spend_bundle.removals(),
746
+ wallet_id=self.wallet_info.id,
747
+ sent_to=[],
748
+ trade_id=None,
749
+ type=uint32(TransactionType.OUTGOING_TX.value),
750
+ name=spend_bundle.name(),
751
+ memos=list(compute_memos(spend_bundle).items()),
752
+ valid_times=parse_timelock_info(extra_conditions),
753
+ )
754
+
755
+ async with action_scope.use() as interface:
756
+ interface.side_effects.transactions.append(did_record)
757
+
758
+ # The message spend can tests\wallet\rpc\test_wallet_rpc.py send messages and also change your innerpuz
759
+ async def create_message_spend(
760
+ self,
761
+ action_scope: WalletActionScope,
762
+ extra_conditions: tuple[Condition, ...] = tuple(),
763
+ ) -> None:
764
+ assert self.did_info.current_inner is not None
765
+ assert self.did_info.origin_coin is not None
766
+ coin = await self.get_coin()
767
+ innerpuz: Program = self.did_info.current_inner
768
+ # Quote message puzzle & solution
769
+ if action_scope.config.tx_config.reuse_puzhash:
770
+ new_innerpuzzle_hash = innerpuz.get_tree_hash()
771
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
772
+ assert uncurried is not None
773
+ p2_ph = uncurried[0].get_tree_hash()
774
+ else:
775
+ p2_ph = await self.standard_wallet.get_puzzle_hash(new=True)
776
+ new_innerpuzzle_hash = did_wallet_puzzles.get_inner_puzhash_by_p2(
777
+ p2_puzhash=p2_ph,
778
+ recovery_list=self.did_info.backup_ids,
779
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
780
+ launcher_id=self.did_info.origin_coin.name(),
781
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
782
+ )
783
+ p2_solution = self.standard_wallet.make_solution(
784
+ primaries=[Payment(puzzle_hash=new_innerpuzzle_hash, amount=uint64(coin.amount), memos=[p2_ph])],
785
+ conditions=extra_conditions,
786
+ )
787
+ # innerpuz solution is (mode p2_solution)
788
+ innersol: Program = Program.to([1, p2_solution])
789
+
790
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
791
+ full_puzzle: Program = create_singleton_puzzle(
792
+ innerpuz,
793
+ self.did_info.origin_coin.name(),
794
+ )
795
+ parent_info = self.get_parent_for_coin(coin)
796
+ assert parent_info is not None
797
+ fullsol = Program.to(
798
+ [
799
+ [
800
+ parent_info.parent_name,
801
+ parent_info.inner_puzzle_hash,
802
+ parent_info.amount,
803
+ ],
804
+ coin.amount,
805
+ innersol,
806
+ ]
807
+ )
808
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
809
+ unsigned_spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
810
+ tx = TransactionRecord(
811
+ confirmed_at_height=uint32(0),
812
+ created_at_time=uint64(int(time.time())),
813
+ to_puzzle_hash=p2_ph,
814
+ amount=uint64(coin.amount),
815
+ fee_amount=uint64(0),
816
+ confirmed=False,
817
+ sent=uint32(0),
818
+ spend_bundle=unsigned_spend_bundle,
819
+ additions=unsigned_spend_bundle.additions(),
820
+ removals=[coin],
821
+ wallet_id=self.id(),
822
+ sent_to=[],
823
+ trade_id=None,
824
+ type=uint32(TransactionType.OUTGOING_TX.value),
825
+ name=unsigned_spend_bundle.name(),
826
+ memos=list(compute_memos(unsigned_spend_bundle).items()),
827
+ valid_times=parse_timelock_info(extra_conditions),
828
+ )
829
+ async with action_scope.use() as interface:
830
+ interface.side_effects.transactions.append(tx)
831
+
832
+ # This is used to cash out, or update the id_list
833
+ async def create_exit_spend(self, puzhash: bytes32, action_scope: WalletActionScope) -> None:
834
+ assert self.did_info.current_inner is not None
835
+ assert self.did_info.origin_coin is not None
836
+ coin = await self.get_coin()
837
+ message_puz = Program.to((1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]]))
838
+
839
+ # innerpuz solution is (mode p2_solution)
840
+ innersol: Program = Program.to([1, [[], message_puz, []]])
841
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
842
+ innerpuz: Program = self.did_info.current_inner
843
+
844
+ full_puzzle: Program = create_singleton_puzzle(
845
+ innerpuz,
846
+ self.did_info.origin_coin.name(),
847
+ )
848
+ parent_info = self.get_parent_for_coin(coin)
849
+ assert parent_info is not None
850
+ fullsol = Program.to(
851
+ [
852
+ [
853
+ parent_info.parent_name,
854
+ parent_info.inner_puzzle_hash,
855
+ parent_info.amount,
856
+ ],
857
+ coin.amount,
858
+ innersol,
859
+ ]
860
+ )
861
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
862
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
863
+
864
+ async with action_scope.use() as interface:
865
+ interface.side_effects.transactions.append(
866
+ TransactionRecord(
867
+ confirmed_at_height=uint32(0),
868
+ created_at_time=uint64(int(time.time())),
869
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
870
+ amount=uint64(coin.amount),
871
+ fee_amount=uint64(0),
872
+ confirmed=False,
873
+ sent=uint32(0),
874
+ spend_bundle=spend_bundle,
875
+ additions=spend_bundle.additions(),
876
+ removals=spend_bundle.removals(),
877
+ wallet_id=self.wallet_info.id,
878
+ sent_to=[],
879
+ trade_id=None,
880
+ type=uint32(TransactionType.OUTGOING_TX.value),
881
+ name=bytes32.secret(),
882
+ memos=list(compute_memos(spend_bundle).items()),
883
+ valid_times=ConditionValidTimes(),
884
+ )
885
+ )
886
+
887
+ # Pushes a spend bundle to create a message coin on the blockchain
888
+ # Returns a spend bundle for the recoverer to spend the message coin
889
+ async def create_attestment(
890
+ self,
891
+ recovering_coin_name: bytes32,
892
+ newpuz: bytes32,
893
+ pubkey: G1Element,
894
+ action_scope: WalletActionScope,
895
+ extra_conditions: tuple[Condition, ...] = tuple(),
896
+ ) -> tuple[WalletSpendBundle, str]:
897
+ """
898
+ Create an attestment
899
+ TODO:
900
+ 1. We should use/respect `action_scope.config.tx_config` (reuse_puzhash and co)
901
+ 2. We should take a fee as it's a requirement for every transaction function to do so
902
+ :param recovering_coin_name: Coin ID of the DID
903
+ :param newpuz: New puzzle hash
904
+ :param pubkey: New wallet pubkey
905
+ :return: (Spend bundle, attest string)
906
+ """
907
+ assert self.did_info.current_inner is not None
908
+ assert self.did_info.origin_coin is not None
909
+ coin = await self.get_coin()
910
+ message = did_wallet_puzzles.create_recovery_message_puzzle(recovering_coin_name, newpuz, pubkey)
911
+ innermessage = message.get_tree_hash()
912
+ innerpuz: Program = self.did_info.current_inner
913
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
914
+ assert uncurried is not None
915
+ p2_puzzle = uncurried[0]
916
+ # innerpuz solution is (mode, p2_solution)
917
+ p2_solution = self.standard_wallet.make_solution(
918
+ primaries=[
919
+ Payment(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()]),
920
+ Payment(innermessage, uint64(0)),
921
+ ],
922
+ conditions=extra_conditions,
923
+ )
924
+ innersol = Program.to([1, p2_solution])
925
+
926
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
927
+ full_puzzle: Program = create_singleton_puzzle(
928
+ innerpuz,
929
+ self.did_info.origin_coin.name(),
930
+ )
931
+ parent_info = self.get_parent_for_coin(coin)
932
+ assert parent_info is not None
933
+
934
+ fullsol = Program.to(
935
+ [
936
+ [
937
+ parent_info.parent_name,
938
+ parent_info.inner_puzzle_hash,
939
+ parent_info.amount,
940
+ ],
941
+ coin.amount,
942
+ innersol,
943
+ ]
944
+ )
945
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
946
+ message_spend = did_wallet_puzzles.create_spend_for_message(coin.name(), recovering_coin_name, newpuz, pubkey)
947
+ message_spend_bundle = WalletSpendBundle([message_spend], AugSchemeMPL.aggregate([]))
948
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
949
+ did_record = TransactionRecord(
950
+ confirmed_at_height=uint32(0),
951
+ created_at_time=uint64(int(time.time())),
952
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
953
+ amount=uint64(coin.amount),
954
+ fee_amount=uint64(0),
955
+ confirmed=False,
956
+ sent=uint32(0),
957
+ spend_bundle=spend_bundle,
958
+ additions=spend_bundle.additions(),
959
+ removals=spend_bundle.removals(),
960
+ wallet_id=self.wallet_info.id,
961
+ sent_to=[],
962
+ trade_id=None,
963
+ type=uint32(TransactionType.INCOMING_TX.value),
964
+ name=bytes32.secret(),
965
+ memos=list(compute_memos(spend_bundle).items()),
966
+ valid_times=parse_timelock_info(extra_conditions),
967
+ )
968
+ async with action_scope.use() as interface:
969
+ interface.side_effects.transactions.append(did_record)
970
+ attest_str: str = f"{self.get_my_DID()}:{bytes(message_spend_bundle).hex()}:{coin.parent_coin_info.hex()}:"
971
+ attest_str += f"{self.did_info.current_inner.get_tree_hash().hex()}:{coin.amount}"
972
+ return message_spend_bundle, attest_str
973
+
974
+ async def get_info_for_recovery(self) -> Optional[tuple[bytes32, bytes32, uint64]]:
975
+ assert self.did_info.current_inner is not None
976
+ assert self.did_info.origin_coin is not None
977
+ try:
978
+ coin = await self.get_coin()
979
+ except RuntimeError:
980
+ return None
981
+ parent = coin.parent_coin_info
982
+ innerpuzhash = self.did_info.current_inner.get_tree_hash()
983
+ amount = uint64(coin.amount)
984
+ return (parent, innerpuzhash, amount)
985
+
986
+ async def load_attest_files_for_recovery_spend(self, attest_data: list[str]) -> tuple[list, WalletSpendBundle]:
987
+ spend_bundle_list = []
988
+ info_dict = {}
989
+ for attest in attest_data:
990
+ info = attest.split(":")
991
+ info_dict[info[0]] = [
992
+ bytes.fromhex(info[2]),
993
+ bytes.fromhex(info[3]),
994
+ uint64(info[4]),
995
+ ]
996
+ new_sb = WalletSpendBundle.from_bytes(bytes.fromhex(info[1]))
997
+ spend_bundle_list.append(new_sb)
998
+ # info_dict {0xidentity: "(0xparent_info 0xinnerpuz amount)"}
999
+ my_recovery_list: list[bytes32] = self.did_info.backup_ids
1000
+
1001
+ # convert info dict into recovery list - same order as wallet
1002
+ info_list = []
1003
+ for entry in my_recovery_list:
1004
+ if entry.hex() in info_dict:
1005
+ info_list.append(
1006
+ [
1007
+ info_dict[entry.hex()][0],
1008
+ info_dict[entry.hex()][1],
1009
+ info_dict[entry.hex()][2],
1010
+ ]
1011
+ )
1012
+ else:
1013
+ info_list.append([])
1014
+ message_spend_bundle = WalletSpendBundle.aggregate(spend_bundle_list)
1015
+ return info_list, message_spend_bundle
1016
+
1017
+ async def recovery_spend(
1018
+ self,
1019
+ coin: Coin,
1020
+ puzhash: bytes32,
1021
+ parent_innerpuzhash_amounts_for_recovery_ids: list[tuple[bytes, bytes, int]],
1022
+ pubkey: G1Element,
1023
+ spend_bundle: WalletSpendBundle,
1024
+ action_scope: WalletActionScope,
1025
+ ) -> None:
1026
+ assert self.did_info.origin_coin is not None
1027
+
1028
+ # innersol is mode new_amount_or_p2_solution new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey recovery_list_reveal my_id) # noqa
1029
+ innersol: Program = Program.to(
1030
+ [
1031
+ 0,
1032
+ coin.amount,
1033
+ puzhash,
1034
+ parent_innerpuzhash_amounts_for_recovery_ids,
1035
+ bytes(pubkey),
1036
+ self.did_info.backup_ids,
1037
+ coin.name(),
1038
+ ]
1039
+ )
1040
+ # full solution is (parent_info my_amount solution)
1041
+ assert self.did_info.current_inner is not None
1042
+ innerpuz: Program = self.did_info.current_inner
1043
+ full_puzzle: Program = create_singleton_puzzle(
1044
+ innerpuz,
1045
+ self.did_info.origin_coin.name(),
1046
+ )
1047
+ parent_info = self.get_parent_for_coin(coin)
1048
+ assert parent_info is not None
1049
+ fullsol = Program.to(
1050
+ [
1051
+ [
1052
+ parent_info.parent_name,
1053
+ parent_info.inner_puzzle_hash,
1054
+ parent_info.amount,
1055
+ ],
1056
+ coin.amount,
1057
+ innersol,
1058
+ ]
1059
+ )
1060
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
1061
+
1062
+ spend_bundle = spend_bundle.aggregate([spend_bundle, WalletSpendBundle(list_of_coinspends, G2Element())])
1063
+
1064
+ async with action_scope.use() as interface:
1065
+ interface.side_effects.transactions.append(
1066
+ TransactionRecord(
1067
+ confirmed_at_height=uint32(0),
1068
+ created_at_time=uint64(int(time.time())),
1069
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
1070
+ amount=uint64(coin.amount),
1071
+ fee_amount=uint64(0),
1072
+ confirmed=False,
1073
+ sent=uint32(0),
1074
+ spend_bundle=spend_bundle,
1075
+ additions=spend_bundle.additions(),
1076
+ removals=spend_bundle.removals(),
1077
+ wallet_id=self.wallet_info.id,
1078
+ sent_to=[],
1079
+ trade_id=None,
1080
+ type=uint32(TransactionType.OUTGOING_TX.value),
1081
+ name=bytes32.secret(),
1082
+ memos=list(compute_memos(spend_bundle).items()),
1083
+ valid_times=ConditionValidTimes(),
1084
+ )
1085
+ )
1086
+ new_did_info = DIDInfo(
1087
+ origin_coin=self.did_info.origin_coin,
1088
+ backup_ids=self.did_info.backup_ids,
1089
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1090
+ parent_info=self.did_info.parent_info,
1091
+ current_inner=self.did_info.current_inner,
1092
+ temp_coin=self.did_info.temp_coin,
1093
+ temp_puzhash=self.did_info.temp_puzhash,
1094
+ temp_pubkey=self.did_info.temp_pubkey,
1095
+ sent_recovery_transaction=True,
1096
+ metadata=self.did_info.metadata,
1097
+ )
1098
+ await self.save_info(new_did_info)
1099
+
1100
+ async def get_p2_inner_hash(self, new: bool) -> bytes32:
1101
+ return await self.standard_wallet.get_puzzle_hash(new=new)
1102
+
1103
+ async def get_p2_inner_puzzle(self, new: bool) -> Program:
1104
+ return await self.standard_wallet.get_puzzle(new=new)
1105
+
1106
+ async def get_did_innerpuz(self, new: bool, origin_id: Optional[bytes32] = None) -> Program:
1107
+ if self.did_info.origin_coin is not None:
1108
+ launcher_id = self.did_info.origin_coin.name()
1109
+ elif origin_id is not None:
1110
+ launcher_id = origin_id
1111
+ else:
1112
+ raise ValueError("must have origin coin")
1113
+ return did_wallet_puzzles.create_innerpuz(
1114
+ p2_puzzle_or_hash=await self.get_p2_inner_puzzle(new=new),
1115
+ recovery_list=self.did_info.backup_ids,
1116
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1117
+ launcher_id=launcher_id,
1118
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1119
+ )
1120
+
1121
+ async def get_did_inner_hash(self, new: bool) -> bytes32:
1122
+ innerpuz = await self.get_did_innerpuz(new=new)
1123
+ return innerpuz.get_tree_hash()
1124
+
1125
+ async def get_innerpuz_for_new_innerhash(self, pubkey: G1Element):
1126
+ """
1127
+ Get the inner puzzle for a new owner
1128
+ :param pubkey: Pubkey
1129
+ :return: Inner puzzle
1130
+ """
1131
+ # Note: the recovery list will be kept.
1132
+ # In a selling case, the seller should clean the recovery list then transfer to the new owner.
1133
+ assert self.did_info.origin_coin is not None
1134
+ return did_wallet_puzzles.create_innerpuz(
1135
+ p2_puzzle_or_hash=puzzle_for_pk(pubkey),
1136
+ recovery_list=self.did_info.backup_ids,
1137
+ num_of_backup_ids_needed=uint64(self.did_info.num_of_backup_ids_needed),
1138
+ launcher_id=self.did_info.origin_coin.name(),
1139
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1140
+ )
1141
+
1142
+ async def inner_puzzle_for_did_puzzle(self, did_hash: bytes32) -> Program:
1143
+ record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
1144
+ did_hash
1145
+ )
1146
+ assert self.did_info.origin_coin is not None
1147
+ assert self.did_info.current_inner is not None
1148
+ uncurried_args = uncurry_innerpuz(self.did_info.current_inner)
1149
+ assert uncurried_args is not None
1150
+ old_recovery_list_hash: Optional[Program] = None
1151
+ p2_puzzle, old_recovery_list_hash, _, _, _ = uncurried_args
1152
+ if record is None:
1153
+ record = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
1154
+ p2_puzzle.get_tree_hash()
1155
+ )
1156
+ if not (self.did_info.num_of_backup_ids_needed > 0 and len(self.did_info.backup_ids) == 0):
1157
+ # We have the recovery list, don't reset it
1158
+ old_recovery_list_hash = None
1159
+
1160
+ inner_puzzle: Program = did_wallet_puzzles.create_innerpuz(
1161
+ p2_puzzle_or_hash=puzzle_for_pk(record.pubkey),
1162
+ recovery_list=self.did_info.backup_ids,
1163
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1164
+ launcher_id=self.did_info.origin_coin.name(),
1165
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1166
+ recovery_list_hash=old_recovery_list_hash,
1167
+ )
1168
+ return inner_puzzle
1169
+
1170
+ def get_parent_for_coin(self, coin) -> Optional[LineageProof]:
1171
+ parent_info = None
1172
+ for name, ccparent in self.did_info.parent_info:
1173
+ if name == coin.parent_coin_info:
1174
+ parent_info = ccparent
1175
+
1176
+ return parent_info
1177
+
1178
+ async def sign_message(self, message: str, mode: SigningMode) -> tuple[G1Element, G2Element]:
1179
+ if self.did_info.current_inner is None:
1180
+ raise ValueError("Missing DID inner puzzle.")
1181
+ puzzle_args = did_wallet_puzzles.uncurry_innerpuz(self.did_info.current_inner)
1182
+ if puzzle_args is not None:
1183
+ p2_puzzle, _, _, _, _ = puzzle_args
1184
+ puzzle_hash = p2_puzzle.get_tree_hash()
1185
+ private = await self.wallet_state_manager.get_private_key(puzzle_hash)
1186
+ synthetic_secret_key = calculate_synthetic_secret_key(private, DEFAULT_HIDDEN_PUZZLE_HASH)
1187
+ synthetic_pk = synthetic_secret_key.get_g1()
1188
+ if mode == SigningMode.CHIP_0002_HEX_INPUT:
1189
+ hex_message: bytes = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))).get_tree_hash()
1190
+ elif mode == SigningMode.BLS_MESSAGE_AUGMENTATION_UTF8_INPUT:
1191
+ hex_message = bytes(message, "utf-8")
1192
+ elif mode == SigningMode.BLS_MESSAGE_AUGMENTATION_HEX_INPUT:
1193
+ hex_message = bytes.fromhex(message)
1194
+ else:
1195
+ hex_message = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message)).get_tree_hash()
1196
+ return synthetic_pk, AugSchemeMPL.sign(synthetic_secret_key, hex_message)
1197
+ else:
1198
+ raise ValueError("Invalid inner DID puzzle.")
1199
+
1200
+ async def generate_new_decentralised_id(
1201
+ self,
1202
+ amount: uint64,
1203
+ action_scope: WalletActionScope,
1204
+ fee: uint64 = uint64(0),
1205
+ extra_conditions: tuple[Condition, ...] = tuple(),
1206
+ ) -> None:
1207
+ """
1208
+ This must be called under the wallet state manager lock
1209
+ """
1210
+
1211
+ coins = await self.standard_wallet.select_coins(uint64(amount + fee), action_scope)
1212
+
1213
+ origin = coins.copy().pop()
1214
+ genesis_launcher_puz = SINGLETON_LAUNCHER_PUZZLE
1215
+ launcher_coin = Coin(origin.name(), genesis_launcher_puz.get_tree_hash(), amount)
1216
+
1217
+ did_inner: Program = await self.get_did_innerpuz(
1218
+ new=not action_scope.config.tx_config.reuse_puzhash, origin_id=launcher_coin.name()
1219
+ )
1220
+ did_inner_hash = did_inner.get_tree_hash()
1221
+ did_full_puz = create_singleton_puzzle(did_inner, launcher_coin.name())
1222
+ did_puzzle_hash = did_full_puz.get_tree_hash()
1223
+
1224
+ announcement_message = Program.to([did_puzzle_hash, amount, bytes(0x80)]).get_tree_hash()
1225
+
1226
+ await self.standard_wallet.generate_signed_transaction(
1227
+ amount=amount,
1228
+ puzzle_hash=genesis_launcher_puz.get_tree_hash(),
1229
+ action_scope=action_scope,
1230
+ fee=fee,
1231
+ coins=coins,
1232
+ primaries=None,
1233
+ origin_id=origin.name(),
1234
+ extra_conditions=(
1235
+ AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message),
1236
+ *extra_conditions,
1237
+ ),
1238
+ )
1239
+
1240
+ genesis_launcher_solution = Program.to([did_puzzle_hash, amount, bytes(0x80)])
1241
+
1242
+ launcher_cs = make_spend(launcher_coin, genesis_launcher_puz, genesis_launcher_solution)
1243
+ launcher_sb = WalletSpendBundle([launcher_cs], AugSchemeMPL.aggregate([]))
1244
+ eve_coin = Coin(launcher_coin.name(), did_puzzle_hash, amount)
1245
+ future_parent = LineageProof(
1246
+ parent_name=eve_coin.parent_coin_info,
1247
+ inner_puzzle_hash=did_inner_hash,
1248
+ amount=uint64(eve_coin.amount),
1249
+ )
1250
+ eve_parent = LineageProof(
1251
+ parent_name=launcher_coin.parent_coin_info,
1252
+ inner_puzzle_hash=launcher_coin.puzzle_hash,
1253
+ amount=uint64(launcher_coin.amount),
1254
+ )
1255
+ await self.add_parent(eve_coin.parent_coin_info, eve_parent)
1256
+ await self.add_parent(eve_coin.name(), future_parent)
1257
+
1258
+ # Only want to save this information if the transaction is valid
1259
+ did_info = DIDInfo(
1260
+ origin_coin=launcher_coin,
1261
+ backup_ids=self.did_info.backup_ids,
1262
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1263
+ parent_info=self.did_info.parent_info,
1264
+ current_inner=did_inner,
1265
+ temp_coin=None,
1266
+ temp_puzhash=None,
1267
+ temp_pubkey=None,
1268
+ sent_recovery_transaction=False,
1269
+ metadata=self.did_info.metadata,
1270
+ )
1271
+ await self.save_info(did_info)
1272
+ eve_spend = await self.generate_eve_spend(eve_coin, did_full_puz, did_inner)
1273
+ full_spend = WalletSpendBundle.aggregate([eve_spend, launcher_sb])
1274
+ assert self.did_info.origin_coin is not None
1275
+ assert self.did_info.current_inner is not None
1276
+
1277
+ did_record = TransactionRecord(
1278
+ confirmed_at_height=uint32(0),
1279
+ created_at_time=uint64(int(time.time())),
1280
+ amount=uint64(amount),
1281
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
1282
+ fee_amount=fee,
1283
+ confirmed=False,
1284
+ sent=uint32(0),
1285
+ spend_bundle=full_spend,
1286
+ additions=full_spend.additions(),
1287
+ removals=full_spend.removals(),
1288
+ wallet_id=self.id(),
1289
+ sent_to=[],
1290
+ trade_id=None,
1291
+ type=uint32(TransactionType.INCOMING_TX.value),
1292
+ name=full_spend.name(),
1293
+ memos=[],
1294
+ valid_times=ConditionValidTimes(),
1295
+ )
1296
+ async with action_scope.use() as interface:
1297
+ interface.side_effects.transactions.append(did_record)
1298
+
1299
+ async def generate_eve_spend(
1300
+ self,
1301
+ coin: Coin,
1302
+ full_puzzle: Program,
1303
+ innerpuz: Program,
1304
+ extra_conditions: tuple[Condition, ...] = tuple(),
1305
+ ):
1306
+ assert self.did_info.origin_coin is not None
1307
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
1308
+ assert uncurried is not None
1309
+ p2_puzzle = uncurried[0]
1310
+ # innerpuz solution is (mode p2_solution)
1311
+ p2_solution = self.standard_wallet.make_solution(
1312
+ primaries=[Payment(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()])],
1313
+ conditions=extra_conditions,
1314
+ )
1315
+ innersol = Program.to([1, p2_solution])
1316
+ # full solution is (lineage_proof my_amount inner_solution)
1317
+ fullsol = Program.to(
1318
+ [
1319
+ [self.did_info.origin_coin.parent_coin_info, self.did_info.origin_coin.amount],
1320
+ coin.amount,
1321
+ innersol,
1322
+ ]
1323
+ )
1324
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
1325
+ unsigned_spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
1326
+ return unsigned_spend_bundle
1327
+
1328
+ async def get_spendable_balance(self, unspent_records=None) -> uint128:
1329
+ spendable_am = await self.wallet_state_manager.get_confirmed_spendable_balance_for_wallet(
1330
+ self.wallet_info.id, unspent_records
1331
+ )
1332
+ return spendable_am
1333
+
1334
+ async def get_max_send_amount(self, records: Optional[set[WalletCoinRecord]] = None):
1335
+ spendable: list[WalletCoinRecord] = list(
1336
+ await self.wallet_state_manager.get_spendable_coins_for_wallet(self.id(), records)
1337
+ )
1338
+ max_send_amount = sum(cr.coin.amount for cr in spendable)
1339
+ return max_send_amount
1340
+
1341
+ async def add_parent(self, name: bytes32, parent: Optional[LineageProof]):
1342
+ self.log.info(f"Adding parent {name}: {parent}")
1343
+ current_list = self.did_info.parent_info.copy()
1344
+ current_list.append((name, parent))
1345
+ did_info = DIDInfo(
1346
+ origin_coin=self.did_info.origin_coin,
1347
+ backup_ids=self.did_info.backup_ids,
1348
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1349
+ parent_info=current_list,
1350
+ current_inner=self.did_info.current_inner,
1351
+ temp_coin=self.did_info.temp_coin,
1352
+ temp_puzhash=self.did_info.temp_puzhash,
1353
+ temp_pubkey=self.did_info.temp_pubkey,
1354
+ sent_recovery_transaction=self.did_info.sent_recovery_transaction,
1355
+ metadata=self.did_info.metadata,
1356
+ )
1357
+ await self.save_info(did_info)
1358
+
1359
+ async def update_recovery_list(self, recover_list: list[bytes32], num_of_backup_ids_needed: uint64) -> bool:
1360
+ if num_of_backup_ids_needed > len(recover_list):
1361
+ return False
1362
+ did_info = DIDInfo(
1363
+ origin_coin=self.did_info.origin_coin,
1364
+ backup_ids=recover_list,
1365
+ num_of_backup_ids_needed=num_of_backup_ids_needed,
1366
+ parent_info=self.did_info.parent_info,
1367
+ current_inner=self.did_info.current_inner,
1368
+ temp_coin=self.did_info.temp_coin,
1369
+ temp_puzhash=self.did_info.temp_puzhash,
1370
+ temp_pubkey=self.did_info.temp_pubkey,
1371
+ sent_recovery_transaction=self.did_info.sent_recovery_transaction,
1372
+ metadata=self.did_info.metadata,
1373
+ )
1374
+ await self.save_info(did_info)
1375
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
1376
+ return True
1377
+
1378
+ async def update_metadata(self, metadata: dict[str, str]) -> bool:
1379
+ # validate metadata
1380
+ if not all(isinstance(k, str) and isinstance(v, str) for k, v in metadata.items()):
1381
+ raise ValueError("Metadata key value pairs must be strings.")
1382
+ did_info = DIDInfo(
1383
+ origin_coin=self.did_info.origin_coin,
1384
+ backup_ids=self.did_info.backup_ids,
1385
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1386
+ parent_info=self.did_info.parent_info,
1387
+ current_inner=self.did_info.current_inner,
1388
+ temp_coin=self.did_info.temp_coin,
1389
+ temp_puzhash=self.did_info.temp_puzhash,
1390
+ temp_pubkey=self.did_info.temp_pubkey,
1391
+ sent_recovery_transaction=self.did_info.sent_recovery_transaction,
1392
+ metadata=json.dumps(metadata),
1393
+ )
1394
+ await self.save_info(did_info)
1395
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
1396
+ return True
1397
+
1398
+ async def save_info(self, did_info: DIDInfo):
1399
+ self.did_info = did_info
1400
+ current_info = self.wallet_info
1401
+ data_str = json.dumps(did_info.to_json_dict())
1402
+ wallet_info = WalletInfo(current_info.id, current_info.name, current_info.type, data_str)
1403
+ self.wallet_info = wallet_info
1404
+ await self.wallet_state_manager.user_store.update_wallet(wallet_info)
1405
+
1406
+ def generate_wallet_name(self) -> str:
1407
+ """
1408
+ Generate a new DID wallet name
1409
+ :return: wallet name
1410
+ """
1411
+ max_num = 0
1412
+ for wallet in self.wallet_state_manager.wallets.values():
1413
+ if wallet.type() == WalletType.DECENTRALIZED_ID:
1414
+ matched = re.search(r"^Profile (\d+)$", wallet.get_name())
1415
+ if matched and int(matched.group(1)) > max_num:
1416
+ max_num = int(matched.group(1))
1417
+ return f"Profile {max_num + 1}"
1418
+
1419
+ def check_existed_did(self):
1420
+ """
1421
+ Check if the current DID is existed
1422
+ :return: None
1423
+ """
1424
+ for wallet in self.wallet_state_manager.wallets.values():
1425
+ if (
1426
+ wallet.type() == WalletType.DECENTRALIZED_ID
1427
+ and self.did_info.origin_coin.name() == wallet.did_info.origin_coin.name()
1428
+ ):
1429
+ self.log.warning(f"DID {self.did_info.origin_coin} already existed, ignore the wallet creation.")
1430
+ raise ValueError("Wallet already exists")
1431
+
1432
+ @staticmethod
1433
+ def deserialize_backup_data(backup_data: str) -> DIDInfo:
1434
+ """
1435
+ Get a DIDInfo from a serialized string
1436
+ :param backup_data: serialized
1437
+ :return: DIDInfo
1438
+ """
1439
+ details = backup_data.split(":")
1440
+ origin = Coin(bytes32.fromhex(details[0]), bytes32.fromhex(details[1]), uint64(int(details[2])))
1441
+ backup_ids = []
1442
+ if len(details[3]) > 0:
1443
+ for d in details[3].split(","):
1444
+ backup_ids.append(bytes32.from_hexstr(d))
1445
+ num_of_backup_ids_needed = uint64(int(details[5]))
1446
+ if num_of_backup_ids_needed > len(backup_ids):
1447
+ raise Exception
1448
+ innerpuz: Program = Program.from_bytes(bytes.fromhex(details[4]))
1449
+ metadata: str = ""
1450
+ for d in details[6:]:
1451
+ metadata = metadata + d + ":"
1452
+ if len(metadata) > 0:
1453
+ metadata = metadata[:-1]
1454
+ did_info = DIDInfo(
1455
+ origin_coin=origin,
1456
+ backup_ids=backup_ids,
1457
+ num_of_backup_ids_needed=num_of_backup_ids_needed,
1458
+ parent_info=[],
1459
+ current_inner=innerpuz,
1460
+ temp_coin=None,
1461
+ temp_puzhash=None,
1462
+ temp_pubkey=None,
1463
+ sent_recovery_transaction=True,
1464
+ metadata=metadata,
1465
+ )
1466
+ return did_info
1467
+
1468
+ def require_derivation_paths(self) -> bool:
1469
+ return True
1470
+
1471
+ async def get_coin(self) -> Coin:
1472
+ spendable_coins: set[WalletCoinRecord] = await self.wallet_state_manager.get_spendable_coins_for_wallet(
1473
+ self.wallet_info.id
1474
+ )
1475
+ if len(spendable_coins) == 0:
1476
+ raise RuntimeError("DID is not currently spendable")
1477
+ return sorted(list(spendable_coins), key=lambda c: c.confirmed_block_height, reverse=True)[0].coin
1478
+
1479
+ async def match_hinted_coin(self, coin: Coin, hint: bytes32) -> bool:
1480
+ if self.did_info.origin_coin is None:
1481
+ return False # pragma: no cover
1482
+ return (
1483
+ create_singleton_puzzle(
1484
+ did_wallet_puzzles.create_innerpuz(
1485
+ p2_puzzle_or_hash=hint,
1486
+ recovery_list=self.did_info.backup_ids,
1487
+ num_of_backup_ids_needed=uint64(self.did_info.num_of_backup_ids_needed),
1488
+ launcher_id=self.did_info.origin_coin.name(),
1489
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1490
+ ),
1491
+ self.did_info.origin_coin.name(),
1492
+ ).get_tree_hash_precalc(hint)
1493
+ == coin.puzzle_hash
1494
+ )