chia-blockchain 2.4.4__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 (1028) 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 +197 -0
  7. chia/_tests/blockchain/config.py +4 -0
  8. chia/_tests/blockchain/test_augmented_chain.py +147 -0
  9. chia/_tests/blockchain/test_blockchain.py +4100 -0
  10. chia/_tests/blockchain/test_blockchain_transactions.py +1050 -0
  11. chia/_tests/blockchain/test_build_chains.py +61 -0
  12. chia/_tests/blockchain/test_get_block_generator.py +72 -0
  13. chia/_tests/blockchain/test_lookup_fork_chain.py +195 -0
  14. chia/_tests/build-init-files.py +93 -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 +73 -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 +147 -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 +57 -0
  26. chia/_tests/clvm/test_program.py +150 -0
  27. chia/_tests/clvm/test_puzzle_compression.py +144 -0
  28. chia/_tests/clvm/test_puzzle_drivers.py +45 -0
  29. chia/_tests/clvm/test_puzzles.py +247 -0
  30. chia/_tests/clvm/test_singletons.py +540 -0
  31. chia/_tests/clvm/test_spend_sim.py +181 -0
  32. chia/_tests/cmds/__init__.py +0 -0
  33. chia/_tests/cmds/cmd_test_utils.py +472 -0
  34. chia/_tests/cmds/config.py +3 -0
  35. chia/_tests/cmds/conftest.py +23 -0
  36. chia/_tests/cmds/test_click_types.py +195 -0
  37. chia/_tests/cmds/test_cmd_framework.py +400 -0
  38. chia/_tests/cmds/test_cmds_util.py +97 -0
  39. chia/_tests/cmds/test_daemon.py +92 -0
  40. chia/_tests/cmds/test_farm_cmd.py +67 -0
  41. chia/_tests/cmds/test_show.py +116 -0
  42. chia/_tests/cmds/test_sim.py +207 -0
  43. chia/_tests/cmds/test_timelock_args.py +75 -0
  44. chia/_tests/cmds/test_tx_config_args.py +153 -0
  45. chia/_tests/cmds/testing_classes.py +59 -0
  46. chia/_tests/cmds/wallet/__init__.py +0 -0
  47. chia/_tests/cmds/wallet/test_coins.py +195 -0
  48. chia/_tests/cmds/wallet/test_consts.py +47 -0
  49. chia/_tests/cmds/wallet/test_dao.py +565 -0
  50. chia/_tests/cmds/wallet/test_did.py +403 -0
  51. chia/_tests/cmds/wallet/test_nft.py +470 -0
  52. chia/_tests/cmds/wallet/test_notifications.py +124 -0
  53. chia/_tests/cmds/wallet/test_offer.toffer +1 -0
  54. chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
  55. chia/_tests/cmds/wallet/test_vcs.py +376 -0
  56. chia/_tests/cmds/wallet/test_wallet.py +1126 -0
  57. chia/_tests/cmds/wallet/test_wallet_check.py +111 -0
  58. chia/_tests/conftest.py +1304 -0
  59. chia/_tests/connection_utils.py +124 -0
  60. chia/_tests/core/__init__.py +0 -0
  61. chia/_tests/core/cmds/__init__.py +0 -0
  62. chia/_tests/core/cmds/test_beta.py +382 -0
  63. chia/_tests/core/cmds/test_keys.py +1734 -0
  64. chia/_tests/core/cmds/test_wallet.py +126 -0
  65. chia/_tests/core/config.py +3 -0
  66. chia/_tests/core/consensus/__init__.py +0 -0
  67. chia/_tests/core/consensus/test_block_creation.py +56 -0
  68. chia/_tests/core/consensus/test_pot_iterations.py +117 -0
  69. chia/_tests/core/custom_types/__init__.py +0 -0
  70. chia/_tests/core/custom_types/test_coin.py +109 -0
  71. chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
  72. chia/_tests/core/custom_types/test_spend_bundle.py +71 -0
  73. chia/_tests/core/daemon/__init__.py +0 -0
  74. chia/_tests/core/daemon/config.py +4 -0
  75. chia/_tests/core/daemon/test_daemon.py +2128 -0
  76. chia/_tests/core/daemon/test_daemon_register.py +109 -0
  77. chia/_tests/core/daemon/test_keychain_proxy.py +100 -0
  78. chia/_tests/core/data_layer/__init__.py +0 -0
  79. chia/_tests/core/data_layer/config.py +5 -0
  80. chia/_tests/core/data_layer/conftest.py +105 -0
  81. chia/_tests/core/data_layer/test_data_cli.py +57 -0
  82. chia/_tests/core/data_layer/test_data_layer.py +83 -0
  83. chia/_tests/core/data_layer/test_data_layer_util.py +219 -0
  84. chia/_tests/core/data_layer/test_data_rpc.py +3865 -0
  85. chia/_tests/core/data_layer/test_data_store.py +2423 -0
  86. chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
  87. chia/_tests/core/data_layer/test_plugin.py +91 -0
  88. chia/_tests/core/data_layer/util.py +232 -0
  89. chia/_tests/core/farmer/__init__.py +0 -0
  90. chia/_tests/core/farmer/config.py +3 -0
  91. chia/_tests/core/farmer/test_farmer_api.py +101 -0
  92. chia/_tests/core/full_node/__init__.py +0 -0
  93. chia/_tests/core/full_node/config.py +4 -0
  94. chia/_tests/core/full_node/dos/__init__.py +0 -0
  95. chia/_tests/core/full_node/dos/config.py +3 -0
  96. chia/_tests/core/full_node/full_sync/__init__.py +0 -0
  97. chia/_tests/core/full_node/full_sync/config.py +4 -0
  98. chia/_tests/core/full_node/full_sync/test_full_sync.py +448 -0
  99. chia/_tests/core/full_node/ram_db.py +27 -0
  100. chia/_tests/core/full_node/stores/__init__.py +0 -0
  101. chia/_tests/core/full_node/stores/config.py +4 -0
  102. chia/_tests/core/full_node/stores/test_block_store.py +488 -0
  103. chia/_tests/core/full_node/stores/test_coin_store.py +888 -0
  104. chia/_tests/core/full_node/stores/test_full_node_store.py +1215 -0
  105. chia/_tests/core/full_node/stores/test_hint_store.py +230 -0
  106. chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
  107. chia/_tests/core/full_node/test_address_manager.py +588 -0
  108. chia/_tests/core/full_node/test_block_height_map.py +556 -0
  109. chia/_tests/core/full_node/test_conditions.py +558 -0
  110. chia/_tests/core/full_node/test_full_node.py +2445 -0
  111. chia/_tests/core/full_node/test_generator_tools.py +82 -0
  112. chia/_tests/core/full_node/test_hint_management.py +104 -0
  113. chia/_tests/core/full_node/test_node_load.py +34 -0
  114. chia/_tests/core/full_node/test_performance.py +182 -0
  115. chia/_tests/core/full_node/test_subscriptions.py +492 -0
  116. chia/_tests/core/full_node/test_transactions.py +203 -0
  117. chia/_tests/core/full_node/test_tx_processing_queue.py +154 -0
  118. chia/_tests/core/large_block.py +2388 -0
  119. chia/_tests/core/make_block_generator.py +72 -0
  120. chia/_tests/core/mempool/__init__.py +0 -0
  121. chia/_tests/core/mempool/config.py +4 -0
  122. chia/_tests/core/mempool/test_mempool.py +3180 -0
  123. chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
  124. chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
  125. chia/_tests/core/mempool/test_mempool_item_queries.py +192 -0
  126. chia/_tests/core/mempool/test_mempool_manager.py +2054 -0
  127. chia/_tests/core/mempool/test_mempool_performance.py +65 -0
  128. chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
  129. chia/_tests/core/node_height.py +28 -0
  130. chia/_tests/core/server/__init__.py +0 -0
  131. chia/_tests/core/server/config.py +3 -0
  132. chia/_tests/core/server/flood.py +82 -0
  133. chia/_tests/core/server/serve.py +132 -0
  134. chia/_tests/core/server/test_capabilities.py +68 -0
  135. chia/_tests/core/server/test_dos.py +320 -0
  136. chia/_tests/core/server/test_event_loop.py +109 -0
  137. chia/_tests/core/server/test_loop.py +290 -0
  138. chia/_tests/core/server/test_node_discovery.py +74 -0
  139. chia/_tests/core/server/test_rate_limits.py +370 -0
  140. chia/_tests/core/server/test_server.py +225 -0
  141. chia/_tests/core/server/test_upnp.py +8 -0
  142. chia/_tests/core/services/__init__.py +0 -0
  143. chia/_tests/core/services/config.py +3 -0
  144. chia/_tests/core/services/test_services.py +166 -0
  145. chia/_tests/core/ssl/__init__.py +0 -0
  146. chia/_tests/core/ssl/config.py +3 -0
  147. chia/_tests/core/ssl/test_ssl.py +198 -0
  148. chia/_tests/core/test_coins.py +33 -0
  149. chia/_tests/core/test_cost_calculation.py +314 -0
  150. chia/_tests/core/test_crawler.py +175 -0
  151. chia/_tests/core/test_crawler_rpc.py +53 -0
  152. chia/_tests/core/test_daemon_rpc.py +24 -0
  153. chia/_tests/core/test_db_conversion.py +129 -0
  154. chia/_tests/core/test_db_validation.py +161 -0
  155. chia/_tests/core/test_farmer_harvester_rpc.py +504 -0
  156. chia/_tests/core/test_filter.py +37 -0
  157. chia/_tests/core/test_full_node_rpc.py +794 -0
  158. chia/_tests/core/test_merkle_set.py +343 -0
  159. chia/_tests/core/test_program.py +49 -0
  160. chia/_tests/core/test_rpc_util.py +87 -0
  161. chia/_tests/core/test_seeder.py +308 -0
  162. chia/_tests/core/test_setproctitle.py +13 -0
  163. chia/_tests/core/util/__init__.py +0 -0
  164. chia/_tests/core/util/config.py +4 -0
  165. chia/_tests/core/util/test_block_cache.py +44 -0
  166. chia/_tests/core/util/test_cached_bls.py +57 -0
  167. chia/_tests/core/util/test_config.py +337 -0
  168. chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
  169. chia/_tests/core/util/test_files.py +391 -0
  170. chia/_tests/core/util/test_jsonify.py +146 -0
  171. chia/_tests/core/util/test_keychain.py +514 -0
  172. chia/_tests/core/util/test_keyring_wrapper.py +490 -0
  173. chia/_tests/core/util/test_lockfile.py +380 -0
  174. chia/_tests/core/util/test_log_exceptions.py +187 -0
  175. chia/_tests/core/util/test_lru_cache.py +56 -0
  176. chia/_tests/core/util/test_significant_bits.py +40 -0
  177. chia/_tests/core/util/test_streamable.py +883 -0
  178. chia/_tests/db/__init__.py +0 -0
  179. chia/_tests/db/test_db_wrapper.py +565 -0
  180. chia/_tests/environments/__init__.py +0 -0
  181. chia/_tests/environments/common.py +35 -0
  182. chia/_tests/environments/full_node.py +47 -0
  183. chia/_tests/environments/wallet.py +368 -0
  184. chia/_tests/ether.py +19 -0
  185. chia/_tests/farmer_harvester/__init__.py +0 -0
  186. chia/_tests/farmer_harvester/config.py +3 -0
  187. chia/_tests/farmer_harvester/test_farmer.py +1264 -0
  188. chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
  189. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +130 -0
  190. chia/_tests/farmer_harvester/test_third_party_harvesters.py +501 -0
  191. chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
  192. chia/_tests/fee_estimation/__init__.py +0 -0
  193. chia/_tests/fee_estimation/config.py +3 -0
  194. chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
  195. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
  196. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +145 -0
  197. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
  198. chia/_tests/generator/__init__.py +0 -0
  199. chia/_tests/generator/puzzles/__init__.py +0 -0
  200. chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
  201. chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
  202. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
  203. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
  204. chia/_tests/generator/test_compression.py +218 -0
  205. chia/_tests/generator/test_generator_types.py +44 -0
  206. chia/_tests/generator/test_rom.py +182 -0
  207. chia/_tests/plot_sync/__init__.py +0 -0
  208. chia/_tests/plot_sync/config.py +3 -0
  209. chia/_tests/plot_sync/test_delta.py +102 -0
  210. chia/_tests/plot_sync/test_plot_sync.py +617 -0
  211. chia/_tests/plot_sync/test_receiver.py +451 -0
  212. chia/_tests/plot_sync/test_sender.py +116 -0
  213. chia/_tests/plot_sync/test_sync_simulated.py +450 -0
  214. chia/_tests/plot_sync/util.py +67 -0
  215. chia/_tests/plotting/__init__.py +0 -0
  216. chia/_tests/plotting/config.py +3 -0
  217. chia/_tests/plotting/test_plot_manager.py +738 -0
  218. chia/_tests/plotting/util.py +13 -0
  219. chia/_tests/pools/__init__.py +0 -0
  220. chia/_tests/pools/config.py +5 -0
  221. chia/_tests/pools/test_pool_cmdline.py +23 -0
  222. chia/_tests/pools/test_pool_config.py +44 -0
  223. chia/_tests/pools/test_pool_puzzles_lifecycle.py +398 -0
  224. chia/_tests/pools/test_pool_rpc.py +1010 -0
  225. chia/_tests/pools/test_pool_wallet.py +201 -0
  226. chia/_tests/pools/test_wallet_pool_store.py +161 -0
  227. chia/_tests/process_junit.py +349 -0
  228. chia/_tests/rpc/__init__.py +0 -0
  229. chia/_tests/rpc/test_rpc_client.py +81 -0
  230. chia/_tests/simulation/__init__.py +0 -0
  231. chia/_tests/simulation/config.py +6 -0
  232. chia/_tests/simulation/test_simulation.py +501 -0
  233. chia/_tests/simulation/test_simulator.py +234 -0
  234. chia/_tests/simulation/test_start_simulator.py +106 -0
  235. chia/_tests/testconfig.py +13 -0
  236. chia/_tests/timelord/__init__.py +0 -0
  237. chia/_tests/timelord/config.py +3 -0
  238. chia/_tests/timelord/test_new_peak.py +437 -0
  239. chia/_tests/timelord/test_timelord.py +11 -0
  240. chia/_tests/tools/1315537.json +170 -0
  241. chia/_tests/tools/1315544.json +160 -0
  242. chia/_tests/tools/1315630.json +150 -0
  243. chia/_tests/tools/300000.json +105 -0
  244. chia/_tests/tools/442734.json +140 -0
  245. chia/_tests/tools/466212.json +130 -0
  246. chia/_tests/tools/__init__.py +0 -0
  247. chia/_tests/tools/config.py +5 -0
  248. chia/_tests/tools/test-blockchain-db.sqlite +0 -0
  249. chia/_tests/tools/test_full_sync.py +30 -0
  250. chia/_tests/tools/test_legacy_keyring.py +82 -0
  251. chia/_tests/tools/test_run_block.py +129 -0
  252. chia/_tests/util/__init__.py +0 -0
  253. chia/_tests/util/benchmark_cost.py +170 -0
  254. chia/_tests/util/benchmarks.py +154 -0
  255. chia/_tests/util/bip39_test_vectors.json +148 -0
  256. chia/_tests/util/blockchain.py +133 -0
  257. chia/_tests/util/blockchain_mock.py +132 -0
  258. chia/_tests/util/build_network_protocol_files.py +302 -0
  259. chia/_tests/util/clvm_generator.bin +0 -0
  260. chia/_tests/util/config.py +3 -0
  261. chia/_tests/util/constants.py +20 -0
  262. chia/_tests/util/db_connection.py +36 -0
  263. chia/_tests/util/full_sync.py +245 -0
  264. chia/_tests/util/gen_ssl_certs.py +115 -0
  265. chia/_tests/util/generator_tools_testing.py +47 -0
  266. chia/_tests/util/key_tool.py +37 -0
  267. chia/_tests/util/misc.py +722 -0
  268. chia/_tests/util/network_protocol_data.py +1074 -0
  269. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  270. chia/_tests/util/protocol_messages_json.py +2700 -0
  271. chia/_tests/util/rpc.py +23 -0
  272. chia/_tests/util/run_block.py +163 -0
  273. chia/_tests/util/setup_nodes.py +479 -0
  274. chia/_tests/util/split_managers.py +99 -0
  275. chia/_tests/util/temp_file.py +14 -0
  276. chia/_tests/util/test_action_scope.py +143 -0
  277. chia/_tests/util/test_async_pool.py +366 -0
  278. chia/_tests/util/test_build_job_matrix.py +43 -0
  279. chia/_tests/util/test_build_network_protocol_files.py +7 -0
  280. chia/_tests/util/test_chia_version.py +50 -0
  281. chia/_tests/util/test_collection.py +11 -0
  282. chia/_tests/util/test_condition_tools.py +231 -0
  283. chia/_tests/util/test_config.py +426 -0
  284. chia/_tests/util/test_dump_keyring.py +60 -0
  285. chia/_tests/util/test_errors.py +10 -0
  286. chia/_tests/util/test_full_block_utils.py +271 -0
  287. chia/_tests/util/test_installed.py +20 -0
  288. chia/_tests/util/test_limited_semaphore.py +52 -0
  289. chia/_tests/util/test_logging_filter.py +43 -0
  290. chia/_tests/util/test_misc.py +444 -0
  291. chia/_tests/util/test_network.py +74 -0
  292. chia/_tests/util/test_network_protocol_files.py +579 -0
  293. chia/_tests/util/test_network_protocol_json.py +266 -0
  294. chia/_tests/util/test_network_protocol_test.py +257 -0
  295. chia/_tests/util/test_paginator.py +72 -0
  296. chia/_tests/util/test_pprint.py +17 -0
  297. chia/_tests/util/test_priority_mutex.py +487 -0
  298. chia/_tests/util/test_recursive_replace.py +116 -0
  299. chia/_tests/util/test_replace_str_to_bytes.py +137 -0
  300. chia/_tests/util/test_service_groups.py +15 -0
  301. chia/_tests/util/test_ssl_check.py +31 -0
  302. chia/_tests/util/test_testnet_overrides.py +19 -0
  303. chia/_tests/util/test_tests_misc.py +38 -0
  304. chia/_tests/util/test_timing.py +37 -0
  305. chia/_tests/util/test_trusted_peer.py +51 -0
  306. chia/_tests/util/time_out_assert.py +154 -0
  307. chia/_tests/wallet/__init__.py +0 -0
  308. chia/_tests/wallet/cat_wallet/__init__.py +0 -0
  309. chia/_tests/wallet/cat_wallet/config.py +4 -0
  310. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
  311. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
  312. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1738 -0
  313. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
  314. chia/_tests/wallet/cat_wallet/test_trades.py +2578 -0
  315. chia/_tests/wallet/clawback/__init__.py +0 -0
  316. chia/_tests/wallet/clawback/config.py +3 -0
  317. chia/_tests/wallet/clawback/test_clawback_decorator.py +80 -0
  318. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
  319. chia/_tests/wallet/clawback/test_clawback_metadata.py +51 -0
  320. chia/_tests/wallet/config.py +4 -0
  321. chia/_tests/wallet/conftest.py +217 -0
  322. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  323. chia/_tests/wallet/dao_wallet/config.py +3 -0
  324. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1322 -0
  325. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
  326. chia/_tests/wallet/db_wallet/__init__.py +0 -0
  327. chia/_tests/wallet/db_wallet/config.py +3 -0
  328. chia/_tests/wallet/db_wallet/test_db_graftroot.py +143 -0
  329. chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
  330. chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
  331. chia/_tests/wallet/did_wallet/__init__.py +0 -0
  332. chia/_tests/wallet/did_wallet/config.py +4 -0
  333. chia/_tests/wallet/did_wallet/test_did.py +1481 -0
  334. chia/_tests/wallet/nft_wallet/__init__.py +0 -0
  335. chia/_tests/wallet/nft_wallet/config.py +4 -0
  336. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1492 -0
  337. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1014 -0
  338. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +376 -0
  339. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
  340. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
  341. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2558 -0
  342. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
  343. chia/_tests/wallet/rpc/__init__.py +0 -0
  344. chia/_tests/wallet/rpc/config.py +4 -0
  345. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +287 -0
  346. chia/_tests/wallet/rpc/test_wallet_rpc.py +3106 -0
  347. chia/_tests/wallet/simple_sync/__init__.py +0 -0
  348. chia/_tests/wallet/simple_sync/config.py +3 -0
  349. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +719 -0
  350. chia/_tests/wallet/sync/__init__.py +0 -0
  351. chia/_tests/wallet/sync/config.py +4 -0
  352. chia/_tests/wallet/sync/test_wallet_sync.py +1529 -0
  353. chia/_tests/wallet/test_address_type.py +189 -0
  354. chia/_tests/wallet/test_bech32m.py +45 -0
  355. chia/_tests/wallet/test_clvm_streamable.py +244 -0
  356. chia/_tests/wallet/test_coin_selection.py +589 -0
  357. chia/_tests/wallet/test_conditions.py +388 -0
  358. chia/_tests/wallet/test_debug_spend_bundle.py +76 -0
  359. chia/_tests/wallet/test_new_wallet_protocol.py +1176 -0
  360. chia/_tests/wallet/test_nft_store.py +193 -0
  361. chia/_tests/wallet/test_notifications.py +196 -0
  362. chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
  363. chia/_tests/wallet/test_puzzle_store.py +133 -0
  364. chia/_tests/wallet/test_sign_coin_spends.py +159 -0
  365. chia/_tests/wallet/test_signer_protocol.py +948 -0
  366. chia/_tests/wallet/test_singleton.py +122 -0
  367. chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
  368. chia/_tests/wallet/test_singleton_store.py +152 -0
  369. chia/_tests/wallet/test_taproot.py +19 -0
  370. chia/_tests/wallet/test_transaction_store.py +941 -0
  371. chia/_tests/wallet/test_util.py +181 -0
  372. chia/_tests/wallet/test_wallet.py +2139 -0
  373. chia/_tests/wallet/test_wallet_action_scope.py +85 -0
  374. chia/_tests/wallet/test_wallet_blockchain.py +113 -0
  375. chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
  376. chia/_tests/wallet/test_wallet_interested_store.py +43 -0
  377. chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
  378. chia/_tests/wallet/test_wallet_node.py +783 -0
  379. chia/_tests/wallet/test_wallet_retry.py +95 -0
  380. chia/_tests/wallet/test_wallet_state_manager.py +252 -0
  381. chia/_tests/wallet/test_wallet_test_framework.py +275 -0
  382. chia/_tests/wallet/test_wallet_trade_store.py +218 -0
  383. chia/_tests/wallet/test_wallet_user_store.py +34 -0
  384. chia/_tests/wallet/test_wallet_utils.py +155 -0
  385. chia/_tests/wallet/vc_wallet/__init__.py +0 -0
  386. chia/_tests/wallet/vc_wallet/config.py +3 -0
  387. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
  388. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
  389. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +801 -0
  390. chia/_tests/wallet/wallet_block_tools.py +327 -0
  391. chia/_tests/weight_proof/__init__.py +0 -0
  392. chia/_tests/weight_proof/config.py +3 -0
  393. chia/_tests/weight_proof/test_weight_proof.py +528 -0
  394. chia/clvm/__init__.py +0 -0
  395. chia/clvm/spend_sim.py +488 -0
  396. chia/cmds/__init__.py +0 -0
  397. chia/cmds/beta.py +183 -0
  398. chia/cmds/beta_funcs.py +133 -0
  399. chia/cmds/check_wallet_db.py +418 -0
  400. chia/cmds/chia.py +143 -0
  401. chia/cmds/cmd_classes.py +315 -0
  402. chia/cmds/cmds_util.py +498 -0
  403. chia/cmds/coin_funcs.py +260 -0
  404. chia/cmds/coins.py +220 -0
  405. chia/cmds/completion.py +49 -0
  406. chia/cmds/configure.py +331 -0
  407. chia/cmds/dao.py +1008 -0
  408. chia/cmds/dao_funcs.py +576 -0
  409. chia/cmds/data.py +707 -0
  410. chia/cmds/data_funcs.py +380 -0
  411. chia/cmds/db.py +86 -0
  412. chia/cmds/db_backup_func.py +77 -0
  413. chia/cmds/db_upgrade_func.py +452 -0
  414. chia/cmds/db_validate_func.py +184 -0
  415. chia/cmds/dev.py +16 -0
  416. chia/cmds/farm.py +87 -0
  417. chia/cmds/farm_funcs.py +207 -0
  418. chia/cmds/init.py +70 -0
  419. chia/cmds/init_funcs.py +367 -0
  420. chia/cmds/installers.py +129 -0
  421. chia/cmds/keys.py +510 -0
  422. chia/cmds/keys_funcs.py +864 -0
  423. chia/cmds/netspace.py +47 -0
  424. chia/cmds/netspace_funcs.py +53 -0
  425. chia/cmds/options.py +32 -0
  426. chia/cmds/param_types.py +228 -0
  427. chia/cmds/passphrase.py +130 -0
  428. chia/cmds/passphrase_funcs.py +346 -0
  429. chia/cmds/peer.py +50 -0
  430. chia/cmds/peer_funcs.py +129 -0
  431. chia/cmds/plotnft.py +206 -0
  432. chia/cmds/plotnft_funcs.py +374 -0
  433. chia/cmds/plots.py +222 -0
  434. chia/cmds/plotters.py +17 -0
  435. chia/cmds/rpc.py +188 -0
  436. chia/cmds/show.py +71 -0
  437. chia/cmds/show_funcs.py +214 -0
  438. chia/cmds/signer.py +304 -0
  439. chia/cmds/sim.py +217 -0
  440. chia/cmds/sim_funcs.py +509 -0
  441. chia/cmds/start.py +24 -0
  442. chia/cmds/start_funcs.py +112 -0
  443. chia/cmds/stop.py +61 -0
  444. chia/cmds/units.py +11 -0
  445. chia/cmds/wallet.py +1745 -0
  446. chia/cmds/wallet_funcs.py +1800 -0
  447. chia/consensus/__init__.py +0 -0
  448. chia/consensus/block_body_validation.py +515 -0
  449. chia/consensus/block_creation.py +525 -0
  450. chia/consensus/block_header_validation.py +1064 -0
  451. chia/consensus/block_record.py +32 -0
  452. chia/consensus/block_rewards.py +53 -0
  453. chia/consensus/block_root_validation.py +46 -0
  454. chia/consensus/blockchain.py +1100 -0
  455. chia/consensus/blockchain_interface.py +56 -0
  456. chia/consensus/coinbase.py +30 -0
  457. chia/consensus/condition_costs.py +9 -0
  458. chia/consensus/constants.py +49 -0
  459. chia/consensus/cost_calculator.py +15 -0
  460. chia/consensus/default_constants.py +90 -0
  461. chia/consensus/deficit.py +55 -0
  462. chia/consensus/difficulty_adjustment.py +412 -0
  463. chia/consensus/find_fork_point.py +111 -0
  464. chia/consensus/full_block_to_block_record.py +167 -0
  465. chia/consensus/get_block_challenge.py +106 -0
  466. chia/consensus/get_block_generator.py +26 -0
  467. chia/consensus/make_sub_epoch_summary.py +210 -0
  468. chia/consensus/multiprocess_validation.py +365 -0
  469. chia/consensus/pos_quality.py +19 -0
  470. chia/consensus/pot_iterations.py +67 -0
  471. chia/consensus/puzzles/__init__.py +0 -0
  472. chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
  473. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
  474. chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
  475. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
  476. chia/consensus/vdf_info_computation.py +156 -0
  477. chia/daemon/__init__.py +0 -0
  478. chia/daemon/client.py +233 -0
  479. chia/daemon/keychain_proxy.py +501 -0
  480. chia/daemon/keychain_server.py +365 -0
  481. chia/daemon/server.py +1616 -0
  482. chia/daemon/windows_signal.py +56 -0
  483. chia/data_layer/__init__.py +0 -0
  484. chia/data_layer/data_layer.py +1303 -0
  485. chia/data_layer/data_layer_api.py +25 -0
  486. chia/data_layer/data_layer_errors.py +50 -0
  487. chia/data_layer/data_layer_server.py +170 -0
  488. chia/data_layer/data_layer_util.py +985 -0
  489. chia/data_layer/data_layer_wallet.py +1315 -0
  490. chia/data_layer/data_store.py +2267 -0
  491. chia/data_layer/dl_wallet_store.py +407 -0
  492. chia/data_layer/download_data.py +389 -0
  493. chia/data_layer/puzzles/__init__.py +0 -0
  494. chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
  495. chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
  496. chia/data_layer/s3_plugin_config.yml +33 -0
  497. chia/data_layer/s3_plugin_service.py +468 -0
  498. chia/data_layer/util/__init__.py +0 -0
  499. chia/data_layer/util/benchmark.py +108 -0
  500. chia/data_layer/util/plugin.py +41 -0
  501. chia/farmer/__init__.py +0 -0
  502. chia/farmer/farmer.py +920 -0
  503. chia/farmer/farmer_api.py +814 -0
  504. chia/full_node/__init__.py +0 -0
  505. chia/full_node/bitcoin_fee_estimator.py +85 -0
  506. chia/full_node/block_height_map.py +271 -0
  507. chia/full_node/block_store.py +570 -0
  508. chia/full_node/bundle_tools.py +19 -0
  509. chia/full_node/coin_store.py +646 -0
  510. chia/full_node/fee_estimate.py +54 -0
  511. chia/full_node/fee_estimate_store.py +24 -0
  512. chia/full_node/fee_estimation.py +93 -0
  513. chia/full_node/fee_estimator.py +90 -0
  514. chia/full_node/fee_estimator_constants.py +38 -0
  515. chia/full_node/fee_estimator_interface.py +42 -0
  516. chia/full_node/fee_history.py +26 -0
  517. chia/full_node/fee_tracker.py +564 -0
  518. chia/full_node/full_node.py +3052 -0
  519. chia/full_node/full_node_api.py +1974 -0
  520. chia/full_node/full_node_store.py +1033 -0
  521. chia/full_node/hint_management.py +56 -0
  522. chia/full_node/hint_store.py +94 -0
  523. chia/full_node/mempool.py +583 -0
  524. chia/full_node/mempool_check_conditions.py +177 -0
  525. chia/full_node/mempool_manager.py +858 -0
  526. chia/full_node/pending_tx_cache.py +112 -0
  527. chia/full_node/puzzles/__init__.py +0 -0
  528. chia/full_node/puzzles/block_program_zero.clsp +14 -0
  529. chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
  530. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
  531. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
  532. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
  533. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
  534. chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
  535. chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
  536. chia/full_node/signage_point.py +16 -0
  537. chia/full_node/subscriptions.py +248 -0
  538. chia/full_node/sync_store.py +145 -0
  539. chia/full_node/tx_processing_queue.py +78 -0
  540. chia/full_node/weight_proof.py +1719 -0
  541. chia/harvester/__init__.py +0 -0
  542. chia/harvester/harvester.py +271 -0
  543. chia/harvester/harvester_api.py +374 -0
  544. chia/introducer/__init__.py +0 -0
  545. chia/introducer/introducer.py +120 -0
  546. chia/introducer/introducer_api.py +64 -0
  547. chia/legacy/__init__.py +0 -0
  548. chia/legacy/keyring.py +154 -0
  549. chia/plot_sync/__init__.py +0 -0
  550. chia/plot_sync/delta.py +61 -0
  551. chia/plot_sync/exceptions.py +56 -0
  552. chia/plot_sync/receiver.py +385 -0
  553. chia/plot_sync/sender.py +337 -0
  554. chia/plot_sync/util.py +43 -0
  555. chia/plotters/__init__.py +0 -0
  556. chia/plotters/bladebit.py +388 -0
  557. chia/plotters/chiapos.py +63 -0
  558. chia/plotters/madmax.py +224 -0
  559. chia/plotters/plotters.py +577 -0
  560. chia/plotters/plotters_util.py +131 -0
  561. chia/plotting/__init__.py +0 -0
  562. chia/plotting/cache.py +212 -0
  563. chia/plotting/check_plots.py +283 -0
  564. chia/plotting/create_plots.py +278 -0
  565. chia/plotting/manager.py +436 -0
  566. chia/plotting/util.py +324 -0
  567. chia/pools/__init__.py +0 -0
  568. chia/pools/pool_config.py +110 -0
  569. chia/pools/pool_puzzles.py +459 -0
  570. chia/pools/pool_wallet.py +926 -0
  571. chia/pools/pool_wallet_info.py +118 -0
  572. chia/pools/puzzles/__init__.py +0 -0
  573. chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
  574. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
  575. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
  576. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
  577. chia/protocols/__init__.py +0 -0
  578. chia/protocols/farmer_protocol.py +102 -0
  579. chia/protocols/full_node_protocol.py +219 -0
  580. chia/protocols/harvester_protocol.py +216 -0
  581. chia/protocols/introducer_protocol.py +26 -0
  582. chia/protocols/pool_protocol.py +177 -0
  583. chia/protocols/protocol_message_types.py +139 -0
  584. chia/protocols/protocol_state_machine.py +87 -0
  585. chia/protocols/protocol_timing.py +7 -0
  586. chia/protocols/shared_protocol.py +86 -0
  587. chia/protocols/timelord_protocol.py +93 -0
  588. chia/protocols/wallet_protocol.py +401 -0
  589. chia/py.typed +0 -0
  590. chia/rpc/__init__.py +0 -0
  591. chia/rpc/crawler_rpc_api.py +75 -0
  592. chia/rpc/data_layer_rpc_api.py +639 -0
  593. chia/rpc/data_layer_rpc_client.py +188 -0
  594. chia/rpc/data_layer_rpc_util.py +62 -0
  595. chia/rpc/farmer_rpc_api.py +360 -0
  596. chia/rpc/farmer_rpc_client.py +86 -0
  597. chia/rpc/full_node_rpc_api.py +954 -0
  598. chia/rpc/full_node_rpc_client.py +292 -0
  599. chia/rpc/harvester_rpc_api.py +136 -0
  600. chia/rpc/harvester_rpc_client.py +54 -0
  601. chia/rpc/rpc_client.py +144 -0
  602. chia/rpc/rpc_server.py +447 -0
  603. chia/rpc/timelord_rpc_api.py +27 -0
  604. chia/rpc/util.py +293 -0
  605. chia/rpc/wallet_request_types.py +688 -0
  606. chia/rpc/wallet_rpc_api.py +4779 -0
  607. chia/rpc/wallet_rpc_client.py +1844 -0
  608. chia/seeder/__init__.py +0 -0
  609. chia/seeder/crawl_store.py +427 -0
  610. chia/seeder/crawler.py +423 -0
  611. chia/seeder/crawler_api.py +129 -0
  612. chia/seeder/dns_server.py +544 -0
  613. chia/seeder/peer_record.py +146 -0
  614. chia/seeder/start_crawler.py +88 -0
  615. chia/server/__init__.py +0 -0
  616. chia/server/address_manager.py +658 -0
  617. chia/server/address_manager_store.py +237 -0
  618. chia/server/api_protocol.py +11 -0
  619. chia/server/capabilities.py +24 -0
  620. chia/server/chia_policy.py +345 -0
  621. chia/server/introducer_peers.py +76 -0
  622. chia/server/node_discovery.py +718 -0
  623. chia/server/outbound_message.py +33 -0
  624. chia/server/rate_limit_numbers.py +204 -0
  625. chia/server/rate_limits.py +113 -0
  626. chia/server/server.py +720 -0
  627. chia/server/signal_handlers.py +117 -0
  628. chia/server/ssl_context.py +32 -0
  629. chia/server/start_data_layer.py +137 -0
  630. chia/server/start_farmer.py +86 -0
  631. chia/server/start_full_node.py +106 -0
  632. chia/server/start_harvester.py +80 -0
  633. chia/server/start_introducer.py +69 -0
  634. chia/server/start_service.py +328 -0
  635. chia/server/start_timelord.py +82 -0
  636. chia/server/start_wallet.py +109 -0
  637. chia/server/upnp.py +117 -0
  638. chia/server/ws_connection.py +752 -0
  639. chia/simulator/__init__.py +0 -0
  640. chia/simulator/block_tools.py +2053 -0
  641. chia/simulator/full_node_simulator.py +802 -0
  642. chia/simulator/keyring.py +128 -0
  643. chia/simulator/setup_services.py +505 -0
  644. chia/simulator/simulator_constants.py +13 -0
  645. chia/simulator/simulator_full_node_rpc_api.py +101 -0
  646. chia/simulator/simulator_full_node_rpc_client.py +62 -0
  647. chia/simulator/simulator_protocol.py +29 -0
  648. chia/simulator/simulator_test_tools.py +163 -0
  649. chia/simulator/socket.py +27 -0
  650. chia/simulator/ssl_certs.py +114 -0
  651. chia/simulator/ssl_certs_1.py +699 -0
  652. chia/simulator/ssl_certs_10.py +699 -0
  653. chia/simulator/ssl_certs_2.py +699 -0
  654. chia/simulator/ssl_certs_3.py +699 -0
  655. chia/simulator/ssl_certs_4.py +699 -0
  656. chia/simulator/ssl_certs_5.py +699 -0
  657. chia/simulator/ssl_certs_6.py +699 -0
  658. chia/simulator/ssl_certs_7.py +699 -0
  659. chia/simulator/ssl_certs_8.py +699 -0
  660. chia/simulator/ssl_certs_9.py +699 -0
  661. chia/simulator/start_simulator.py +135 -0
  662. chia/simulator/wallet_tools.py +245 -0
  663. chia/ssl/__init__.py +0 -0
  664. chia/ssl/chia_ca.crt +19 -0
  665. chia/ssl/chia_ca.key +28 -0
  666. chia/ssl/create_ssl.py +249 -0
  667. chia/ssl/dst_root_ca.pem +20 -0
  668. chia/timelord/__init__.py +0 -0
  669. chia/timelord/iters_from_block.py +50 -0
  670. chia/timelord/timelord.py +1202 -0
  671. chia/timelord/timelord_api.py +132 -0
  672. chia/timelord/timelord_launcher.py +188 -0
  673. chia/timelord/timelord_state.py +244 -0
  674. chia/timelord/types.py +22 -0
  675. chia/types/__init__.py +0 -0
  676. chia/types/aliases.py +35 -0
  677. chia/types/block_protocol.py +20 -0
  678. chia/types/blockchain_format/__init__.py +0 -0
  679. chia/types/blockchain_format/classgroup.py +5 -0
  680. chia/types/blockchain_format/coin.py +28 -0
  681. chia/types/blockchain_format/foliage.py +8 -0
  682. chia/types/blockchain_format/pool_target.py +5 -0
  683. chia/types/blockchain_format/program.py +270 -0
  684. chia/types/blockchain_format/proof_of_space.py +135 -0
  685. chia/types/blockchain_format/reward_chain_block.py +6 -0
  686. chia/types/blockchain_format/serialized_program.py +5 -0
  687. chia/types/blockchain_format/sized_bytes.py +11 -0
  688. chia/types/blockchain_format/slots.py +9 -0
  689. chia/types/blockchain_format/sub_epoch_summary.py +5 -0
  690. chia/types/blockchain_format/tree_hash.py +72 -0
  691. chia/types/blockchain_format/vdf.py +86 -0
  692. chia/types/clvm_cost.py +13 -0
  693. chia/types/coin_record.py +43 -0
  694. chia/types/coin_spend.py +115 -0
  695. chia/types/condition_opcodes.py +73 -0
  696. chia/types/condition_with_args.py +17 -0
  697. chia/types/eligible_coin_spends.py +364 -0
  698. chia/types/end_of_slot_bundle.py +5 -0
  699. chia/types/fee_rate.py +38 -0
  700. chia/types/full_block.py +5 -0
  701. chia/types/generator_types.py +14 -0
  702. chia/types/header_block.py +5 -0
  703. chia/types/internal_mempool_item.py +19 -0
  704. chia/types/mempool_inclusion_status.py +9 -0
  705. chia/types/mempool_item.py +85 -0
  706. chia/types/mempool_submission_status.py +30 -0
  707. chia/types/mojos.py +7 -0
  708. chia/types/peer_info.py +64 -0
  709. chia/types/signing_mode.py +29 -0
  710. chia/types/spend_bundle.py +31 -0
  711. chia/types/spend_bundle_conditions.py +7 -0
  712. chia/types/transaction_queue_entry.py +55 -0
  713. chia/types/unfinished_block.py +5 -0
  714. chia/types/unfinished_header_block.py +37 -0
  715. chia/types/weight_proof.py +50 -0
  716. chia/util/__init__.py +0 -0
  717. chia/util/action_scope.py +168 -0
  718. chia/util/api_decorators.py +89 -0
  719. chia/util/async_pool.py +224 -0
  720. chia/util/augmented_chain.py +130 -0
  721. chia/util/batches.py +39 -0
  722. chia/util/bech32m.py +123 -0
  723. chia/util/beta_metrics.py +118 -0
  724. chia/util/block_cache.py +56 -0
  725. chia/util/byte_types.py +10 -0
  726. chia/util/check_fork_next_block.py +32 -0
  727. chia/util/chia_logging.py +124 -0
  728. chia/util/chia_version.py +33 -0
  729. chia/util/collection.py +17 -0
  730. chia/util/condition_tools.py +201 -0
  731. chia/util/config.py +366 -0
  732. chia/util/cpu.py +20 -0
  733. chia/util/db_synchronous.py +21 -0
  734. chia/util/db_version.py +30 -0
  735. chia/util/db_wrapper.py +427 -0
  736. chia/util/default_root.py +10 -0
  737. chia/util/dump_keyring.py +93 -0
  738. chia/util/english.txt +2048 -0
  739. chia/util/errors.py +351 -0
  740. chia/util/file_keyring.py +480 -0
  741. chia/util/files.py +95 -0
  742. chia/util/full_block_utils.py +321 -0
  743. chia/util/generator_tools.py +62 -0
  744. chia/util/hash.py +29 -0
  745. chia/util/initial-config.yaml +675 -0
  746. chia/util/inline_executor.py +24 -0
  747. chia/util/ints.py +19 -0
  748. chia/util/json_util.py +41 -0
  749. chia/util/keychain.py +673 -0
  750. chia/util/keyring_wrapper.py +266 -0
  751. chia/util/limited_semaphore.py +39 -0
  752. chia/util/lock.py +47 -0
  753. chia/util/log_exceptions.py +29 -0
  754. chia/util/logging.py +34 -0
  755. chia/util/lru_cache.py +29 -0
  756. chia/util/math.py +20 -0
  757. chia/util/network.py +240 -0
  758. chia/util/paginator.py +46 -0
  759. chia/util/path.py +29 -0
  760. chia/util/permissions.py +19 -0
  761. chia/util/pprint.py +40 -0
  762. chia/util/prev_transaction_block.py +23 -0
  763. chia/util/priority_mutex.py +92 -0
  764. chia/util/profiler.py +194 -0
  765. chia/util/recursive_replace.py +22 -0
  766. chia/util/safe_cancel_task.py +14 -0
  767. chia/util/service_groups.py +47 -0
  768. chia/util/setproctitle.py +20 -0
  769. chia/util/significant_bits.py +30 -0
  770. chia/util/ssl_check.py +213 -0
  771. chia/util/streamable.py +654 -0
  772. chia/util/task_timing.py +378 -0
  773. chia/util/timing.py +64 -0
  774. chia/util/vdf_prover.py +31 -0
  775. chia/util/ws_message.py +66 -0
  776. chia/wallet/__init__.py +0 -0
  777. chia/wallet/cat_wallet/__init__.py +0 -0
  778. chia/wallet/cat_wallet/cat_constants.py +75 -0
  779. chia/wallet/cat_wallet/cat_info.py +47 -0
  780. chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
  781. chia/wallet/cat_wallet/cat_utils.py +163 -0
  782. chia/wallet/cat_wallet/cat_wallet.py +869 -0
  783. chia/wallet/cat_wallet/dao_cat_info.py +28 -0
  784. chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
  785. chia/wallet/cat_wallet/lineage_store.py +74 -0
  786. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  787. chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
  788. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
  789. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
  790. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
  791. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
  792. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
  793. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
  794. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
  795. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
  796. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
  797. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
  798. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
  799. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
  800. chia/wallet/coin_selection.py +188 -0
  801. chia/wallet/conditions.py +1326 -0
  802. chia/wallet/dao_wallet/__init__.py +0 -0
  803. chia/wallet/dao_wallet/dao_info.py +61 -0
  804. chia/wallet/dao_wallet/dao_utils.py +810 -0
  805. chia/wallet/dao_wallet/dao_wallet.py +2121 -0
  806. chia/wallet/db_wallet/__init__.py +0 -0
  807. chia/wallet/db_wallet/db_wallet_puzzles.py +107 -0
  808. chia/wallet/derivation_record.py +30 -0
  809. chia/wallet/derive_keys.py +146 -0
  810. chia/wallet/did_wallet/__init__.py +0 -0
  811. chia/wallet/did_wallet/did_info.py +39 -0
  812. chia/wallet/did_wallet/did_wallet.py +1485 -0
  813. chia/wallet/did_wallet/did_wallet_puzzles.py +220 -0
  814. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  815. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
  816. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
  817. chia/wallet/driver_protocol.py +26 -0
  818. chia/wallet/key_val_store.py +55 -0
  819. chia/wallet/lineage_proof.py +58 -0
  820. chia/wallet/nft_wallet/__init__.py +0 -0
  821. chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
  822. chia/wallet/nft_wallet/nft_info.py +120 -0
  823. chia/wallet/nft_wallet/nft_puzzles.py +305 -0
  824. chia/wallet/nft_wallet/nft_wallet.py +1686 -0
  825. chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
  826. chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
  827. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
  828. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
  829. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
  830. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
  831. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
  832. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
  833. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
  834. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
  835. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
  836. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
  837. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
  838. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
  839. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
  840. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
  841. chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
  842. chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
  843. chia/wallet/nft_wallet/uncurry_nft.py +217 -0
  844. chia/wallet/notification_manager.py +117 -0
  845. chia/wallet/notification_store.py +178 -0
  846. chia/wallet/outer_puzzles.py +84 -0
  847. chia/wallet/payment.py +34 -0
  848. chia/wallet/puzzle_drivers.py +118 -0
  849. chia/wallet/puzzles/__init__.py +0 -0
  850. chia/wallet/puzzles/augmented_condition.clsp +13 -0
  851. chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
  852. chia/wallet/puzzles/clawback/__init__.py +0 -0
  853. chia/wallet/puzzles/clawback/drivers.py +188 -0
  854. chia/wallet/puzzles/clawback/metadata.py +38 -0
  855. chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
  856. chia/wallet/puzzles/condition_codes.clib +77 -0
  857. chia/wallet/puzzles/curry-and-treehash.clib +102 -0
  858. chia/wallet/puzzles/curry.clib +135 -0
  859. chia/wallet/puzzles/curry_by_index.clib +16 -0
  860. chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
  861. chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
  862. chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
  863. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
  864. chia/wallet/puzzles/dao_finished_state.clsp +35 -0
  865. chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
  866. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
  867. chia/wallet/puzzles/dao_lockup.clsp +288 -0
  868. chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
  869. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
  870. chia/wallet/puzzles/dao_proposal.clsp +377 -0
  871. chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
  872. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
  873. chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
  874. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
  875. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
  876. chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
  877. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
  878. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
  879. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
  880. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
  881. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
  882. chia/wallet/puzzles/dao_treasury.clsp +115 -0
  883. chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
  884. chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
  885. chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
  886. chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
  887. chia/wallet/puzzles/json.clib +25 -0
  888. chia/wallet/puzzles/load_clvm.py +162 -0
  889. chia/wallet/puzzles/merkle_utils.clib +18 -0
  890. chia/wallet/puzzles/notification.clsp +7 -0
  891. chia/wallet/puzzles/notification.clsp.hex +1 -0
  892. chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
  893. chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
  894. chia/wallet/puzzles/p2_conditions.clsp +3 -0
  895. chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
  896. chia/wallet/puzzles/p2_conditions.py +27 -0
  897. chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
  898. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
  899. chia/wallet/puzzles/p2_delegated_conditions.py +22 -0
  900. chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
  901. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
  902. chia/wallet/puzzles/p2_delegated_puzzle.py +35 -0
  903. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
  904. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
  905. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +161 -0
  906. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
  907. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
  908. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +22 -0
  909. chia/wallet/puzzles/p2_parent.clsp +19 -0
  910. chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
  911. chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
  912. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
  913. chia/wallet/puzzles/p2_puzzle_hash.py +28 -0
  914. chia/wallet/puzzles/p2_singleton.clsp +30 -0
  915. chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
  916. chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
  917. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
  918. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
  919. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
  920. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
  921. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
  922. chia/wallet/puzzles/puzzle_utils.py +34 -0
  923. chia/wallet/puzzles/settlement_payments.clsp +49 -0
  924. chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
  925. chia/wallet/puzzles/sha256tree.clib +11 -0
  926. chia/wallet/puzzles/singleton_launcher.clsp +16 -0
  927. chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
  928. chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
  929. chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
  930. chia/wallet/puzzles/singleton_top_layer.py +295 -0
  931. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
  932. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
  933. chia/wallet/puzzles/singleton_top_layer_v1_1.py +344 -0
  934. chia/wallet/puzzles/singleton_truths.clib +21 -0
  935. chia/wallet/puzzles/tails.py +344 -0
  936. chia/wallet/puzzles/utility_macros.clib +48 -0
  937. chia/wallet/signer_protocol.py +126 -0
  938. chia/wallet/singleton.py +106 -0
  939. chia/wallet/singleton_record.py +30 -0
  940. chia/wallet/trade_manager.py +1088 -0
  941. chia/wallet/trade_record.py +67 -0
  942. chia/wallet/trading/__init__.py +0 -0
  943. chia/wallet/trading/offer.py +703 -0
  944. chia/wallet/trading/trade_status.py +13 -0
  945. chia/wallet/trading/trade_store.py +526 -0
  946. chia/wallet/transaction_record.py +143 -0
  947. chia/wallet/transaction_sorting.py +14 -0
  948. chia/wallet/uncurried_puzzle.py +17 -0
  949. chia/wallet/util/__init__.py +0 -0
  950. chia/wallet/util/address_type.py +55 -0
  951. chia/wallet/util/blind_signer_tl.py +168 -0
  952. chia/wallet/util/clvm_streamable.py +203 -0
  953. chia/wallet/util/compute_hints.py +66 -0
  954. chia/wallet/util/compute_memos.py +45 -0
  955. chia/wallet/util/curry_and_treehash.py +90 -0
  956. chia/wallet/util/debug_spend_bundle.py +234 -0
  957. chia/wallet/util/merkle_tree.py +100 -0
  958. chia/wallet/util/merkle_utils.py +102 -0
  959. chia/wallet/util/new_peak_queue.py +82 -0
  960. chia/wallet/util/notifications.py +12 -0
  961. chia/wallet/util/peer_request_cache.py +174 -0
  962. chia/wallet/util/puzzle_compression.py +96 -0
  963. chia/wallet/util/puzzle_decorator.py +100 -0
  964. chia/wallet/util/puzzle_decorator_type.py +7 -0
  965. chia/wallet/util/query_filter.py +60 -0
  966. chia/wallet/util/transaction_type.py +23 -0
  967. chia/wallet/util/tx_config.py +158 -0
  968. chia/wallet/util/wallet_sync_utils.py +348 -0
  969. chia/wallet/util/wallet_types.py +65 -0
  970. chia/wallet/vc_wallet/__init__.py +0 -0
  971. chia/wallet/vc_wallet/cr_cat_drivers.py +663 -0
  972. chia/wallet/vc_wallet/cr_cat_wallet.py +875 -0
  973. chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
  974. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  975. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
  976. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
  977. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
  978. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
  979. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
  980. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
  981. chia/wallet/vc_wallet/vc_drivers.py +838 -0
  982. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  983. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
  984. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
  985. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
  986. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
  987. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
  988. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
  989. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
  990. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
  991. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
  992. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
  993. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
  994. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
  995. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
  996. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
  997. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
  998. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
  999. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
  1000. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
  1001. chia/wallet/vc_wallet/vc_store.py +263 -0
  1002. chia/wallet/vc_wallet/vc_wallet.py +638 -0
  1003. chia/wallet/wallet.py +698 -0
  1004. chia/wallet/wallet_action_scope.py +95 -0
  1005. chia/wallet/wallet_blockchain.py +244 -0
  1006. chia/wallet/wallet_coin_record.py +72 -0
  1007. chia/wallet/wallet_coin_store.py +351 -0
  1008. chia/wallet/wallet_info.py +36 -0
  1009. chia/wallet/wallet_interested_store.py +188 -0
  1010. chia/wallet/wallet_nft_store.py +279 -0
  1011. chia/wallet/wallet_node.py +1769 -0
  1012. chia/wallet/wallet_node_api.py +201 -0
  1013. chia/wallet/wallet_pool_store.py +120 -0
  1014. chia/wallet/wallet_protocol.py +90 -0
  1015. chia/wallet/wallet_puzzle_store.py +365 -0
  1016. chia/wallet/wallet_retry_store.py +70 -0
  1017. chia/wallet/wallet_singleton_store.py +258 -0
  1018. chia/wallet/wallet_spend_bundle.py +41 -0
  1019. chia/wallet/wallet_state_manager.py +2820 -0
  1020. chia/wallet/wallet_transaction_store.py +470 -0
  1021. chia/wallet/wallet_user_store.py +110 -0
  1022. chia/wallet/wallet_weight_proof_handler.py +126 -0
  1023. chia_blockchain-2.4.4.dist-info/LICENSE +201 -0
  1024. chia_blockchain-2.4.4.dist-info/METADATA +161 -0
  1025. chia_blockchain-2.4.4.dist-info/RECORD +1028 -0
  1026. chia_blockchain-2.4.4.dist-info/WHEEL +4 -0
  1027. chia_blockchain-2.4.4.dist-info/entry_points.txt +17 -0
  1028. mozilla-ca/cacert.pem +3666 -0
@@ -0,0 +1,1485 @@
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, Dict, List, Optional, Set, Tuple, 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.user_store.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
+
212
+ self = DIDWallet()
213
+ self.wallet_state_manager = wallet_state_manager
214
+ if name is None:
215
+ name = self.generate_wallet_name()
216
+ self.base_puzzle_program = None
217
+ self.base_inner_puzzle_hash = None
218
+ self.standard_wallet = wallet
219
+ self.log = logging.getLogger(name if name else __name__)
220
+
221
+ self.log.info(f"Creating DID wallet from a coin spend {launch_coin} ...")
222
+ # Create did info from the coin spend
223
+ args = did_wallet_puzzles.uncurry_innerpuz(inner_puzzle)
224
+ if args is None:
225
+ raise ValueError("Cannot uncurry the DID puzzle.")
226
+ _, recovery_list_hash, num_verification, _, metadata = args
227
+ full_solution: Program = Program.from_bytes(bytes(coin_spend.solution))
228
+ inner_solution: Program = full_solution.rest().rest().first()
229
+ recovery_list: List[bytes32] = []
230
+ backup_required: int = num_verification.as_int()
231
+ if recovery_list_hash != NIL_TREEHASH:
232
+ try:
233
+ for did in inner_solution.rest().rest().rest().rest().rest().as_python():
234
+ recovery_list.append(bytes32(did[0]))
235
+ except Exception:
236
+ self.log.warning(
237
+ f"DID {launch_coin.name().hex()} has a recovery list hash but missing a reveal,"
238
+ " you may need to reset the recovery info."
239
+ )
240
+ self.did_info = DIDInfo(
241
+ origin_coin=launch_coin,
242
+ backup_ids=recovery_list,
243
+ num_of_backup_ids_needed=uint64(backup_required),
244
+ parent_info=[],
245
+ current_inner=inner_puzzle,
246
+ temp_coin=None,
247
+ temp_puzhash=None,
248
+ temp_pubkey=None,
249
+ sent_recovery_transaction=False,
250
+ metadata=json.dumps(did_wallet_puzzles.did_program_to_metadata(metadata)),
251
+ )
252
+ self.check_existed_did()
253
+ info_as_string = json.dumps(self.did_info.to_json_dict())
254
+
255
+ self.wallet_info = await wallet_state_manager.user_store.create_wallet(
256
+ name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
257
+ )
258
+ await self.wallet_state_manager.add_new_wallet(self)
259
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
260
+ await self.load_parent(self.did_info)
261
+ self.log.info(f"New DID wallet created {info_as_string}.")
262
+ if self.wallet_info is None:
263
+ raise ValueError("Internal Error")
264
+ self.wallet_id = self.wallet_info.id
265
+ return self
266
+
267
+ @staticmethod
268
+ async def create(
269
+ wallet_state_manager: Any,
270
+ wallet: Wallet,
271
+ wallet_info: WalletInfo,
272
+ name: str = None,
273
+ ):
274
+ """
275
+ Create a DID wallet based on the local database
276
+ :param wallet_state_manager: Wallet state manager
277
+ :param wallet: Standard wallet
278
+ :param wallet_info: Serialized WalletInfo
279
+ :param name: Wallet name
280
+ :return:
281
+ """
282
+ self = DIDWallet()
283
+ self.log = logging.getLogger(name if name else __name__)
284
+ self.wallet_state_manager = wallet_state_manager
285
+ self.wallet_info = wallet_info
286
+ self.wallet_id = wallet_info.id
287
+ self.standard_wallet = wallet
288
+ self.wallet_info = wallet_info
289
+ self.did_info = DIDInfo.from_json_dict(json.loads(wallet_info.data))
290
+ self.base_puzzle_program = None
291
+ self.base_inner_puzzle_hash = None
292
+ return self
293
+
294
+ @classmethod
295
+ def type(cls) -> WalletType:
296
+ return WalletType.DECENTRALIZED_ID
297
+
298
+ def id(self) -> uint32:
299
+ return self.wallet_info.id
300
+
301
+ async def get_confirmed_balance(self, record_list=None) -> uint128:
302
+ if record_list is None:
303
+ record_list = await self.wallet_state_manager.coin_store.get_unspent_coins_for_wallet(self.id())
304
+
305
+ amount: uint128 = uint128(0)
306
+ for record in record_list:
307
+ parent = self.get_parent_for_coin(record.coin)
308
+ if parent is not None:
309
+ amount = uint128(amount + record.coin.amount)
310
+
311
+ self.log.info(f"Confirmed balance for did wallet is {amount}")
312
+ return uint128(amount)
313
+
314
+ async def get_pending_change_balance(self) -> uint64:
315
+ unconfirmed_tx = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(self.id())
316
+ addition_amount = 0
317
+
318
+ for record in unconfirmed_tx:
319
+ our_spend = False
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
+ if await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id()):
330
+ addition_amount += coin.amount
331
+
332
+ return uint64(addition_amount)
333
+
334
+ async def get_unconfirmed_balance(self, record_list=None) -> uint128:
335
+ return await self.wallet_state_manager.get_unconfirmed_balance(self.id(), record_list)
336
+
337
+ async def select_coins(
338
+ self,
339
+ amount: uint64,
340
+ action_scope: WalletActionScope,
341
+ ) -> Set[Coin]:
342
+ try:
343
+ async with action_scope.use() as interface:
344
+ coin = await self.get_coin()
345
+ interface.side_effects.selected_coins.append(coin)
346
+ return {coin}
347
+ except RuntimeError:
348
+ return set()
349
+
350
+ def _coin_is_first_singleton(self, coin: Coin) -> bool:
351
+ parent = self.get_parent_for_coin(coin)
352
+ if parent is None:
353
+ return False
354
+ assert self.did_info.origin_coin
355
+ return parent.parent_name == self.did_info.origin_coin.name()
356
+
357
+ # This will be used in the recovery case where we don't have the parent info already
358
+ # But it is also called whenever a Singleton coin from this wallet is spent
359
+ # We can improve this interface by passing in the CoinSpend, as well
360
+ # We need to change DID Wallet coin_added to expect p2 spends as well as recovery spends,
361
+ # or only call it in the recovery spend case
362
+ async def coin_added(self, coin: Coin, _: uint32, peer: WSChiaConnection, parent_coin_data: Optional[DIDCoinData]):
363
+ """Notification from wallet state manager that wallet has been received."""
364
+ parent = self.get_parent_for_coin(coin)
365
+ if parent_coin_data is not None:
366
+ assert isinstance(parent_coin_data, DIDCoinData)
367
+ did_data: DIDCoinData = parent_coin_data
368
+ else:
369
+ parent_state: CoinState = (
370
+ await self.wallet_state_manager.wallet_node.get_coin_state(
371
+ coin_names=[coin.parent_coin_info], peer=peer
372
+ )
373
+ )[0]
374
+ coin_spend = await fetch_coin_spend_for_coin_state(parent_state, peer)
375
+ uncurried = uncurry_puzzle(coin_spend.puzzle_reveal)
376
+ did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args)
377
+ assert did_curried_args is not None
378
+ p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args
379
+ did_data = DIDCoinData(
380
+ p2_puzzle=p2_puzzle,
381
+ recovery_list_hash=bytes32(recovery_list_hash.as_atom()),
382
+ num_verification=uint16(num_verification.as_int()),
383
+ singleton_struct=singleton_struct,
384
+ metadata=metadata,
385
+ inner_puzzle=get_inner_puzzle_from_singleton(coin_spend.puzzle_reveal),
386
+ coin_state=parent_state,
387
+ )
388
+ if parent is None:
389
+ # this is the first time we received it, check it's a DID coin
390
+ parent_innerpuz = did_data.inner_puzzle
391
+ if parent_innerpuz:
392
+ parent_info = LineageProof(
393
+ parent_name=did_data.coin_state.coin.parent_coin_info,
394
+ inner_puzzle_hash=parent_innerpuz.get_tree_hash(),
395
+ amount=uint64(did_data.coin_state.coin.amount),
396
+ )
397
+ await self.add_parent(coin.parent_coin_info, parent_info)
398
+ else:
399
+ self.log.warning("Parent coin is not a DID, skipping: %s -> %s", coin.name(), coin)
400
+ return
401
+ self.log.info(f"DID wallet has been notified that coin was added: {coin.name()}:{coin}")
402
+ inner_puzzle = await self.inner_puzzle_for_did_puzzle(coin.puzzle_hash)
403
+ # Check inner puzzle consistency
404
+ assert self.did_info.origin_coin is not None
405
+
406
+ # TODO: if not the first singleton, and solution mode == recovery
407
+ if not self._coin_is_first_singleton(coin):
408
+ full_puzzle = create_singleton_puzzle(inner_puzzle, self.did_info.origin_coin.name())
409
+ assert full_puzzle.get_tree_hash() == coin.puzzle_hash
410
+ if self.did_info.temp_coin is not None:
411
+ self.wallet_state_manager.state_changed("did_coin_added", self.wallet_info.id)
412
+ new_info = DIDInfo(
413
+ origin_coin=self.did_info.origin_coin,
414
+ backup_ids=self.did_info.backup_ids,
415
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
416
+ parent_info=self.did_info.parent_info,
417
+ current_inner=inner_puzzle,
418
+ temp_coin=None,
419
+ temp_puzhash=None,
420
+ temp_pubkey=None,
421
+ sent_recovery_transaction=False,
422
+ metadata=json.dumps(did_wallet_puzzles.did_program_to_metadata(did_data.metadata)),
423
+ )
424
+ await self.save_info(new_info)
425
+
426
+ future_parent = LineageProof(
427
+ parent_name=coin.parent_coin_info,
428
+ inner_puzzle_hash=inner_puzzle.get_tree_hash(),
429
+ amount=uint64(coin.amount),
430
+ )
431
+
432
+ await self.add_parent(coin.name(), future_parent)
433
+ await self.wallet_state_manager.add_interested_coin_ids([coin.name()])
434
+
435
+ def create_backup(self) -> str:
436
+ """
437
+ Create a serialized backup data for DIDInfo
438
+ :return: Serialized backup data
439
+ """
440
+ assert self.did_info.current_inner is not None
441
+ assert self.did_info.origin_coin is not None
442
+ output_str = f"{self.did_info.origin_coin.parent_coin_info.hex()}:"
443
+ output_str += f"{self.did_info.origin_coin.puzzle_hash.hex()}:"
444
+ output_str += f"{self.did_info.origin_coin.amount}:"
445
+ if len(self.did_info.backup_ids) > 0:
446
+ for did in self.did_info.backup_ids:
447
+ output_str = output_str + did.hex() + ","
448
+ output_str = output_str[:-1]
449
+ output_str += f":{bytes(self.did_info.current_inner).hex()}:{self.did_info.num_of_backup_ids_needed}"
450
+ output_str += f":{self.did_info.metadata}"
451
+ return output_str
452
+
453
+ async def load_parent(self, did_info: DIDInfo):
454
+ """
455
+ Load the parent info when importing a DID
456
+ :param did_info: DID info
457
+ :return:
458
+ """
459
+ # full_puz = did_wallet_puzzles.create_fullpuz(innerpuz, origin.name())
460
+ # All additions in this block here:
461
+
462
+ new_puzhash = await self.wallet_state_manager.main_wallet.get_puzzle_hash(new=False)
463
+ new_pubkey = await self.wallet_state_manager.get_public_key(new_puzhash)
464
+ parent_info = None
465
+ assert did_info.origin_coin is not None
466
+ assert did_info.current_inner is not None
467
+ new_did_inner_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2(
468
+ p2_puzhash=new_puzhash,
469
+ recovery_list=did_info.backup_ids,
470
+ num_of_backup_ids_needed=did_info.num_of_backup_ids_needed,
471
+ launcher_id=did_info.origin_coin.name(),
472
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
473
+ )
474
+ wallet_node = self.wallet_state_manager.wallet_node
475
+ parent_coin: Coin = did_info.origin_coin
476
+ while True:
477
+ peer = wallet_node.get_full_node_peer()
478
+ children = await wallet_node.fetch_children(parent_coin.name(), peer)
479
+ if len(children) == 0:
480
+ break
481
+
482
+ children_state: CoinState = children[0]
483
+ child_coin = children_state.coin
484
+ future_parent = LineageProof(
485
+ parent_name=child_coin.parent_coin_info,
486
+ inner_puzzle_hash=did_info.current_inner.get_tree_hash(),
487
+ amount=uint64(child_coin.amount),
488
+ )
489
+ await self.add_parent(child_coin.name(), future_parent)
490
+ if children_state.spent_height != children_state.created_height:
491
+ did_info = DIDInfo(
492
+ origin_coin=did_info.origin_coin,
493
+ backup_ids=did_info.backup_ids,
494
+ num_of_backup_ids_needed=did_info.num_of_backup_ids_needed,
495
+ parent_info=self.did_info.parent_info,
496
+ current_inner=did_info.current_inner,
497
+ temp_coin=child_coin,
498
+ temp_puzhash=new_did_inner_puzhash,
499
+ temp_pubkey=bytes(new_pubkey),
500
+ sent_recovery_transaction=did_info.sent_recovery_transaction,
501
+ metadata=did_info.metadata,
502
+ )
503
+
504
+ await self.save_info(did_info)
505
+ assert children_state.created_height
506
+ parent_spend = await fetch_coin_spend(uint32(children_state.created_height), parent_coin, peer)
507
+ assert parent_spend is not None
508
+ parent_innerpuz = get_inner_puzzle_from_singleton(parent_spend.puzzle_reveal)
509
+ assert parent_innerpuz is not None
510
+ parent_info = LineageProof(
511
+ parent_name=parent_coin.parent_coin_info,
512
+ inner_puzzle_hash=parent_innerpuz.get_tree_hash(),
513
+ amount=uint64(parent_coin.amount),
514
+ )
515
+ await self.add_parent(child_coin.parent_coin_info, parent_info)
516
+ parent_coin = child_coin
517
+ assert parent_info is not None
518
+
519
+ def puzzle_for_pk(self, pubkey: G1Element) -> Program:
520
+ if self.did_info.origin_coin is not None:
521
+ innerpuz = did_wallet_puzzles.create_innerpuz(
522
+ p2_puzzle_or_hash=puzzle_for_pk(pubkey),
523
+ recovery_list=self.did_info.backup_ids,
524
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
525
+ launcher_id=self.did_info.origin_coin.name(),
526
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
527
+ )
528
+ return create_singleton_puzzle(innerpuz, self.did_info.origin_coin.name())
529
+ else:
530
+ innerpuz = Program.to((8, 0))
531
+ return create_singleton_puzzle(innerpuz, bytes32([0] * 32))
532
+
533
+ def puzzle_hash_for_pk(self, pubkey: G1Element) -> bytes32:
534
+ if self.did_info.origin_coin is None:
535
+ # TODO: this seem dumb. Why bother with this case? Is it ever used?
536
+ # inner puzzle: (8 . 0)
537
+ innerpuz_hash = shatree_pair(shatree_int(8), NIL_TREEHASH)
538
+ return create_singleton_puzzle_hash(innerpuz_hash, bytes32([0] * 32))
539
+ origin_coin_name = self.did_info.origin_coin.name()
540
+ innerpuz_hash = did_wallet_puzzles.get_inner_puzhash_by_p2(
541
+ p2_puzhash=puzzle_hash_for_pk(pubkey),
542
+ recovery_list=self.did_info.backup_ids,
543
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
544
+ launcher_id=origin_coin_name,
545
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
546
+ )
547
+ return create_singleton_puzzle_hash(innerpuz_hash, origin_coin_name)
548
+
549
+ async def get_new_puzzle(self) -> Program:
550
+ return self.puzzle_for_pk(
551
+ (await self.wallet_state_manager.get_unused_derivation_record(self.wallet_info.id)).pubkey
552
+ )
553
+
554
+ def get_my_DID(self) -> str:
555
+ assert self.did_info.origin_coin is not None
556
+ core = self.did_info.origin_coin.name()
557
+ assert core is not None
558
+ return core.hex()
559
+
560
+ async def set_name(self, new_name: str):
561
+ new_info = dataclasses.replace(self.wallet_info, name=new_name)
562
+ self.wallet_info = new_info
563
+ await self.wallet_state_manager.user_store.update_wallet(self.wallet_info)
564
+
565
+ def get_name(self):
566
+ return self.wallet_info.name
567
+
568
+ async def create_update_spend(
569
+ self,
570
+ action_scope: WalletActionScope,
571
+ fee: uint64 = uint64(0),
572
+ extra_conditions: Tuple[Condition, ...] = tuple(),
573
+ ) -> None:
574
+ assert self.did_info.current_inner is not None
575
+ assert self.did_info.origin_coin is not None
576
+ coin = await self.get_coin()
577
+ new_inner_puzzle = await self.get_new_did_innerpuz()
578
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(new_inner_puzzle)
579
+ assert uncurried is not None
580
+ p2_puzzle = uncurried[0]
581
+ # innerpuz solution is (mode, p2_solution)
582
+ p2_solution = self.standard_wallet.make_solution(
583
+ primaries=[
584
+ Payment(
585
+ puzzle_hash=new_inner_puzzle.get_tree_hash(),
586
+ amount=uint64(coin.amount),
587
+ memos=[p2_puzzle.get_tree_hash()],
588
+ )
589
+ ],
590
+ conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())),
591
+ )
592
+ innersol: Program = Program.to([1, p2_solution])
593
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
594
+ innerpuz: Program = self.did_info.current_inner
595
+
596
+ full_puzzle: Program = create_singleton_puzzle(
597
+ innerpuz,
598
+ self.did_info.origin_coin.name(),
599
+ )
600
+ parent_info = self.get_parent_for_coin(coin)
601
+ assert parent_info is not None
602
+ fullsol = Program.to(
603
+ [
604
+ [
605
+ parent_info.parent_name,
606
+ parent_info.inner_puzzle_hash,
607
+ parent_info.amount,
608
+ ],
609
+ coin.amount,
610
+ innersol,
611
+ ]
612
+ )
613
+ # Create an additional spend to confirm the change on-chain
614
+ new_full_puzzle: Program = create_singleton_puzzle(
615
+ new_inner_puzzle,
616
+ self.did_info.origin_coin.name(),
617
+ )
618
+ new_full_sol = Program.to(
619
+ [
620
+ [
621
+ coin.parent_coin_info,
622
+ innerpuz.get_tree_hash(),
623
+ coin.amount,
624
+ ],
625
+ coin.amount,
626
+ innersol,
627
+ ]
628
+ )
629
+ new_coin = Coin(coin.name(), new_full_puzzle.get_tree_hash(), coin.amount)
630
+ list_of_coinspends = [
631
+ make_spend(coin, full_puzzle, fullsol),
632
+ make_spend(new_coin, new_full_puzzle, new_full_sol),
633
+ ]
634
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
635
+ if fee > 0:
636
+ coin_name = coin.name()
637
+ await self.standard_wallet.create_tandem_xch_tx(
638
+ fee,
639
+ action_scope,
640
+ extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),),
641
+ )
642
+ did_record = TransactionRecord(
643
+ confirmed_at_height=uint32(0),
644
+ created_at_time=uint64(int(time.time())),
645
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
646
+ amount=uint64(coin.amount),
647
+ fee_amount=uint64(0),
648
+ confirmed=False,
649
+ sent=uint32(0),
650
+ spend_bundle=spend_bundle,
651
+ additions=spend_bundle.additions(),
652
+ removals=spend_bundle.removals(),
653
+ wallet_id=self.wallet_info.id,
654
+ sent_to=[],
655
+ trade_id=None,
656
+ type=uint32(TransactionType.OUTGOING_TX.value),
657
+ name=bytes32.secret(),
658
+ memos=list(compute_memos(spend_bundle).items()),
659
+ valid_times=parse_timelock_info(extra_conditions),
660
+ )
661
+
662
+ async with action_scope.use() as interface:
663
+ interface.side_effects.transactions.append(did_record)
664
+
665
+ async def transfer_did(
666
+ self,
667
+ new_puzhash: bytes32,
668
+ fee: uint64,
669
+ with_recovery: bool,
670
+ action_scope: WalletActionScope,
671
+ extra_conditions: Tuple[Condition, ...] = tuple(),
672
+ ) -> None:
673
+ """
674
+ Transfer the current DID to another owner
675
+ :param new_puzhash: New owner's p2_puzzle
676
+ :param fee: Transaction fee
677
+ :param with_recovery: A boolean indicates if the recovery info will be sent through the blockchain
678
+ :return: Spend bundle
679
+ """
680
+ assert self.did_info.current_inner is not None
681
+ assert self.did_info.origin_coin is not None
682
+ coin = await self.get_coin()
683
+ backup_ids = []
684
+ backup_required = uint64(0)
685
+ if with_recovery:
686
+ backup_ids = self.did_info.backup_ids
687
+ backup_required = self.did_info.num_of_backup_ids_needed
688
+ new_did_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2(
689
+ p2_puzhash=new_puzhash,
690
+ recovery_list=backup_ids,
691
+ num_of_backup_ids_needed=backup_required,
692
+ launcher_id=self.did_info.origin_coin.name(),
693
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
694
+ )
695
+ p2_solution = self.standard_wallet.make_solution(
696
+ primaries=[Payment(new_did_puzhash, uint64(coin.amount), [new_puzhash])],
697
+ conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())),
698
+ )
699
+ # Need to include backup list reveal here, even we are don't recover
700
+ # innerpuz solution is
701
+ # (mode, p2_solution)
702
+ innersol: Program = Program.to([2, p2_solution])
703
+ if with_recovery:
704
+ innersol = Program.to([2, p2_solution, [], [], [], self.did_info.backup_ids])
705
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
706
+
707
+ full_puzzle: Program = create_singleton_puzzle(
708
+ self.did_info.current_inner,
709
+ self.did_info.origin_coin.name(),
710
+ )
711
+ parent_info = self.get_parent_for_coin(coin)
712
+ assert parent_info is not None
713
+ fullsol = Program.to(
714
+ [
715
+ [
716
+ parent_info.parent_name,
717
+ parent_info.inner_puzzle_hash,
718
+ parent_info.amount,
719
+ ],
720
+ coin.amount,
721
+ innersol,
722
+ ]
723
+ )
724
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
725
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
726
+ if fee > 0:
727
+ coin_name = coin.name()
728
+ await self.standard_wallet.create_tandem_xch_tx(
729
+ fee,
730
+ action_scope,
731
+ extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),),
732
+ )
733
+ did_record = TransactionRecord(
734
+ confirmed_at_height=uint32(0),
735
+ created_at_time=uint64(int(time.time())),
736
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
737
+ amount=uint64(coin.amount),
738
+ fee_amount=fee,
739
+ confirmed=False,
740
+ sent=uint32(0),
741
+ spend_bundle=spend_bundle,
742
+ additions=spend_bundle.additions(),
743
+ removals=spend_bundle.removals(),
744
+ wallet_id=self.wallet_info.id,
745
+ sent_to=[],
746
+ trade_id=None,
747
+ type=uint32(TransactionType.OUTGOING_TX.value),
748
+ name=spend_bundle.name(),
749
+ memos=list(compute_memos(spend_bundle).items()),
750
+ valid_times=parse_timelock_info(extra_conditions),
751
+ )
752
+
753
+ async with action_scope.use() as interface:
754
+ interface.side_effects.transactions.append(did_record)
755
+
756
+ # The message spend can tests\wallet\rpc\test_wallet_rpc.py send messages and also change your innerpuz
757
+ async def create_message_spend(
758
+ self,
759
+ action_scope: WalletActionScope,
760
+ extra_conditions: Tuple[Condition, ...] = tuple(),
761
+ ) -> None:
762
+ assert self.did_info.current_inner is not None
763
+ assert self.did_info.origin_coin is not None
764
+ coin = await self.get_coin()
765
+ innerpuz: Program = self.did_info.current_inner
766
+ # Quote message puzzle & solution
767
+ if action_scope.config.tx_config.reuse_puzhash:
768
+ new_innerpuzzle_hash = innerpuz.get_tree_hash()
769
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
770
+ assert uncurried is not None
771
+ p2_ph = uncurried[0].get_tree_hash()
772
+ else:
773
+ p2_ph = await self.standard_wallet.get_puzzle_hash(new=True)
774
+ new_innerpuzzle_hash = did_wallet_puzzles.get_inner_puzhash_by_p2(
775
+ p2_puzhash=p2_ph,
776
+ recovery_list=self.did_info.backup_ids,
777
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
778
+ launcher_id=self.did_info.origin_coin.name(),
779
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
780
+ )
781
+ p2_solution = self.standard_wallet.make_solution(
782
+ primaries=[Payment(puzzle_hash=new_innerpuzzle_hash, amount=uint64(coin.amount), memos=[p2_ph])],
783
+ conditions=extra_conditions,
784
+ )
785
+ # innerpuz solution is (mode p2_solution)
786
+ innersol: Program = Program.to([1, p2_solution])
787
+
788
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
789
+ full_puzzle: Program = create_singleton_puzzle(
790
+ innerpuz,
791
+ self.did_info.origin_coin.name(),
792
+ )
793
+ parent_info = self.get_parent_for_coin(coin)
794
+ assert parent_info is not None
795
+ fullsol = Program.to(
796
+ [
797
+ [
798
+ parent_info.parent_name,
799
+ parent_info.inner_puzzle_hash,
800
+ parent_info.amount,
801
+ ],
802
+ coin.amount,
803
+ innersol,
804
+ ]
805
+ )
806
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
807
+ unsigned_spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
808
+ tx = TransactionRecord(
809
+ confirmed_at_height=uint32(0),
810
+ created_at_time=uint64(int(time.time())),
811
+ to_puzzle_hash=p2_ph,
812
+ amount=uint64(coin.amount),
813
+ fee_amount=uint64(0),
814
+ confirmed=False,
815
+ sent=uint32(0),
816
+ spend_bundle=unsigned_spend_bundle,
817
+ additions=unsigned_spend_bundle.additions(),
818
+ removals=[coin],
819
+ wallet_id=self.id(),
820
+ sent_to=[],
821
+ trade_id=None,
822
+ type=uint32(TransactionType.OUTGOING_TX.value),
823
+ name=unsigned_spend_bundle.name(),
824
+ memos=list(compute_memos(unsigned_spend_bundle).items()),
825
+ valid_times=parse_timelock_info(extra_conditions),
826
+ )
827
+ async with action_scope.use() as interface:
828
+ interface.side_effects.transactions.append(tx)
829
+
830
+ # This is used to cash out, or update the id_list
831
+ async def create_exit_spend(self, puzhash: bytes32, action_scope: WalletActionScope) -> None:
832
+ assert self.did_info.current_inner is not None
833
+ assert self.did_info.origin_coin is not None
834
+ coin = await self.get_coin()
835
+ message_puz = Program.to((1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]]))
836
+
837
+ # innerpuz solution is (mode p2_solution)
838
+ innersol: Program = Program.to([1, [[], message_puz, []]])
839
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
840
+ innerpuz: Program = self.did_info.current_inner
841
+
842
+ full_puzzle: Program = create_singleton_puzzle(
843
+ innerpuz,
844
+ self.did_info.origin_coin.name(),
845
+ )
846
+ parent_info = self.get_parent_for_coin(coin)
847
+ assert parent_info is not None
848
+ fullsol = Program.to(
849
+ [
850
+ [
851
+ parent_info.parent_name,
852
+ parent_info.inner_puzzle_hash,
853
+ parent_info.amount,
854
+ ],
855
+ coin.amount,
856
+ innersol,
857
+ ]
858
+ )
859
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
860
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
861
+
862
+ async with action_scope.use() as interface:
863
+ interface.side_effects.transactions.append(
864
+ TransactionRecord(
865
+ confirmed_at_height=uint32(0),
866
+ created_at_time=uint64(int(time.time())),
867
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
868
+ amount=uint64(coin.amount),
869
+ fee_amount=uint64(0),
870
+ confirmed=False,
871
+ sent=uint32(0),
872
+ spend_bundle=spend_bundle,
873
+ additions=spend_bundle.additions(),
874
+ removals=spend_bundle.removals(),
875
+ wallet_id=self.wallet_info.id,
876
+ sent_to=[],
877
+ trade_id=None,
878
+ type=uint32(TransactionType.OUTGOING_TX.value),
879
+ name=bytes32.secret(),
880
+ memos=list(compute_memos(spend_bundle).items()),
881
+ valid_times=ConditionValidTimes(),
882
+ )
883
+ )
884
+
885
+ # Pushes a spend bundle to create a message coin on the blockchain
886
+ # Returns a spend bundle for the recoverer to spend the message coin
887
+ async def create_attestment(
888
+ self,
889
+ recovering_coin_name: bytes32,
890
+ newpuz: bytes32,
891
+ pubkey: G1Element,
892
+ action_scope: WalletActionScope,
893
+ extra_conditions: Tuple[Condition, ...] = tuple(),
894
+ ) -> Tuple[WalletSpendBundle, str]:
895
+ """
896
+ Create an attestment
897
+ TODO:
898
+ 1. We should use/respect `action_scope.config.tx_config` (reuse_puzhash and co)
899
+ 2. We should take a fee as it's a requirement for every transaction function to do so
900
+ :param recovering_coin_name: Coin ID of the DID
901
+ :param newpuz: New puzzle hash
902
+ :param pubkey: New wallet pubkey
903
+ :return: (Spend bundle, attest string)
904
+ """
905
+ assert self.did_info.current_inner is not None
906
+ assert self.did_info.origin_coin is not None
907
+ coin = await self.get_coin()
908
+ message = did_wallet_puzzles.create_recovery_message_puzzle(recovering_coin_name, newpuz, pubkey)
909
+ innermessage = message.get_tree_hash()
910
+ innerpuz: Program = self.did_info.current_inner
911
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
912
+ assert uncurried is not None
913
+ p2_puzzle = uncurried[0]
914
+ # innerpuz solution is (mode, p2_solution)
915
+ p2_solution = self.standard_wallet.make_solution(
916
+ primaries=[
917
+ Payment(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()]),
918
+ Payment(innermessage, uint64(0)),
919
+ ],
920
+ conditions=extra_conditions,
921
+ )
922
+ innersol = Program.to([1, p2_solution])
923
+
924
+ # full solution is (corehash parent_info my_amount innerpuz_reveal solution)
925
+ full_puzzle: Program = create_singleton_puzzle(
926
+ innerpuz,
927
+ self.did_info.origin_coin.name(),
928
+ )
929
+ parent_info = self.get_parent_for_coin(coin)
930
+ assert parent_info is not None
931
+
932
+ fullsol = Program.to(
933
+ [
934
+ [
935
+ parent_info.parent_name,
936
+ parent_info.inner_puzzle_hash,
937
+ parent_info.amount,
938
+ ],
939
+ coin.amount,
940
+ innersol,
941
+ ]
942
+ )
943
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
944
+ message_spend = did_wallet_puzzles.create_spend_for_message(coin.name(), recovering_coin_name, newpuz, pubkey)
945
+ message_spend_bundle = WalletSpendBundle([message_spend], AugSchemeMPL.aggregate([]))
946
+ spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
947
+ did_record = TransactionRecord(
948
+ confirmed_at_height=uint32(0),
949
+ created_at_time=uint64(int(time.time())),
950
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
951
+ amount=uint64(coin.amount),
952
+ fee_amount=uint64(0),
953
+ confirmed=False,
954
+ sent=uint32(0),
955
+ spend_bundle=spend_bundle,
956
+ additions=spend_bundle.additions(),
957
+ removals=spend_bundle.removals(),
958
+ wallet_id=self.wallet_info.id,
959
+ sent_to=[],
960
+ trade_id=None,
961
+ type=uint32(TransactionType.INCOMING_TX.value),
962
+ name=bytes32.secret(),
963
+ memos=list(compute_memos(spend_bundle).items()),
964
+ valid_times=parse_timelock_info(extra_conditions),
965
+ )
966
+ async with action_scope.use() as interface:
967
+ interface.side_effects.transactions.append(did_record)
968
+ attest_str: str = f"{self.get_my_DID()}:{bytes(message_spend_bundle).hex()}:{coin.parent_coin_info.hex()}:"
969
+ attest_str += f"{self.did_info.current_inner.get_tree_hash().hex()}:{coin.amount}"
970
+ return message_spend_bundle, attest_str
971
+
972
+ async def get_info_for_recovery(self) -> Optional[Tuple[bytes32, bytes32, uint64]]:
973
+ assert self.did_info.current_inner is not None
974
+ assert self.did_info.origin_coin is not None
975
+ try:
976
+ coin = await self.get_coin()
977
+ except RuntimeError:
978
+ return None
979
+ parent = coin.parent_coin_info
980
+ innerpuzhash = self.did_info.current_inner.get_tree_hash()
981
+ amount = uint64(coin.amount)
982
+ return (parent, innerpuzhash, amount)
983
+
984
+ async def load_attest_files_for_recovery_spend(self, attest_data: List[str]) -> Tuple[List, WalletSpendBundle]:
985
+ spend_bundle_list = []
986
+ info_dict = {}
987
+ for attest in attest_data:
988
+ info = attest.split(":")
989
+ info_dict[info[0]] = [
990
+ bytes.fromhex(info[2]),
991
+ bytes.fromhex(info[3]),
992
+ uint64(info[4]),
993
+ ]
994
+ new_sb = WalletSpendBundle.from_bytes(bytes.fromhex(info[1]))
995
+ spend_bundle_list.append(new_sb)
996
+ # info_dict {0xidentity: "(0xparent_info 0xinnerpuz amount)"}
997
+ my_recovery_list: List[bytes32] = self.did_info.backup_ids
998
+
999
+ # convert info dict into recovery list - same order as wallet
1000
+ info_list = []
1001
+ for entry in my_recovery_list:
1002
+ if entry.hex() in info_dict:
1003
+ info_list.append(
1004
+ [
1005
+ info_dict[entry.hex()][0],
1006
+ info_dict[entry.hex()][1],
1007
+ info_dict[entry.hex()][2],
1008
+ ]
1009
+ )
1010
+ else:
1011
+ info_list.append([])
1012
+ message_spend_bundle = WalletSpendBundle.aggregate(spend_bundle_list)
1013
+ return info_list, message_spend_bundle
1014
+
1015
+ async def recovery_spend(
1016
+ self,
1017
+ coin: Coin,
1018
+ puzhash: bytes32,
1019
+ parent_innerpuzhash_amounts_for_recovery_ids: List[Tuple[bytes, bytes, int]],
1020
+ pubkey: G1Element,
1021
+ spend_bundle: WalletSpendBundle,
1022
+ action_scope: WalletActionScope,
1023
+ ) -> None:
1024
+ assert self.did_info.origin_coin is not None
1025
+
1026
+ # innersol is mode new_amount_or_p2_solution new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey recovery_list_reveal my_id) # noqa
1027
+ innersol: Program = Program.to(
1028
+ [
1029
+ 0,
1030
+ coin.amount,
1031
+ puzhash,
1032
+ parent_innerpuzhash_amounts_for_recovery_ids,
1033
+ bytes(pubkey),
1034
+ self.did_info.backup_ids,
1035
+ coin.name(),
1036
+ ]
1037
+ )
1038
+ # full solution is (parent_info my_amount solution)
1039
+ assert self.did_info.current_inner is not None
1040
+ innerpuz: Program = self.did_info.current_inner
1041
+ full_puzzle: Program = create_singleton_puzzle(
1042
+ innerpuz,
1043
+ self.did_info.origin_coin.name(),
1044
+ )
1045
+ parent_info = self.get_parent_for_coin(coin)
1046
+ assert parent_info is not None
1047
+ fullsol = Program.to(
1048
+ [
1049
+ [
1050
+ parent_info.parent_name,
1051
+ parent_info.inner_puzzle_hash,
1052
+ parent_info.amount,
1053
+ ],
1054
+ coin.amount,
1055
+ innersol,
1056
+ ]
1057
+ )
1058
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
1059
+
1060
+ spend_bundle = spend_bundle.aggregate([spend_bundle, WalletSpendBundle(list_of_coinspends, G2Element())])
1061
+
1062
+ async with action_scope.use() as interface:
1063
+ interface.side_effects.transactions.append(
1064
+ TransactionRecord(
1065
+ confirmed_at_height=uint32(0),
1066
+ created_at_time=uint64(int(time.time())),
1067
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
1068
+ amount=uint64(coin.amount),
1069
+ fee_amount=uint64(0),
1070
+ confirmed=False,
1071
+ sent=uint32(0),
1072
+ spend_bundle=spend_bundle,
1073
+ additions=spend_bundle.additions(),
1074
+ removals=spend_bundle.removals(),
1075
+ wallet_id=self.wallet_info.id,
1076
+ sent_to=[],
1077
+ trade_id=None,
1078
+ type=uint32(TransactionType.OUTGOING_TX.value),
1079
+ name=bytes32.secret(),
1080
+ memos=list(compute_memos(spend_bundle).items()),
1081
+ valid_times=ConditionValidTimes(),
1082
+ )
1083
+ )
1084
+ new_did_info = DIDInfo(
1085
+ origin_coin=self.did_info.origin_coin,
1086
+ backup_ids=self.did_info.backup_ids,
1087
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1088
+ parent_info=self.did_info.parent_info,
1089
+ current_inner=self.did_info.current_inner,
1090
+ temp_coin=self.did_info.temp_coin,
1091
+ temp_puzhash=self.did_info.temp_puzhash,
1092
+ temp_pubkey=self.did_info.temp_pubkey,
1093
+ sent_recovery_transaction=True,
1094
+ metadata=self.did_info.metadata,
1095
+ )
1096
+ await self.save_info(new_did_info)
1097
+
1098
+ async def get_new_p2_inner_hash(self) -> bytes32:
1099
+ puzzle = await self.get_new_p2_inner_puzzle()
1100
+ return puzzle.get_tree_hash()
1101
+
1102
+ async def get_new_p2_inner_puzzle(self) -> Program:
1103
+ return await self.standard_wallet.get_new_puzzle()
1104
+
1105
+ async def get_new_did_innerpuz(self, origin_id: Optional[bytes32] = None) -> Program:
1106
+ if self.did_info.origin_coin is not None:
1107
+ launcher_id = self.did_info.origin_coin.name()
1108
+ elif origin_id is not None:
1109
+ launcher_id = origin_id
1110
+ else:
1111
+ raise ValueError("must have origin coin")
1112
+ return did_wallet_puzzles.create_innerpuz(
1113
+ p2_puzzle_or_hash=await self.get_new_p2_inner_puzzle(),
1114
+ recovery_list=self.did_info.backup_ids,
1115
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1116
+ launcher_id=launcher_id,
1117
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1118
+ )
1119
+
1120
+ async def get_new_did_inner_hash(self) -> bytes32:
1121
+ innerpuz = await self.get_new_did_innerpuz()
1122
+ return innerpuz.get_tree_hash()
1123
+
1124
+ async def get_innerpuz_for_new_innerhash(self, pubkey: G1Element):
1125
+ """
1126
+ Get the inner puzzle for a new owner
1127
+ :param pubkey: Pubkey
1128
+ :return: Inner puzzle
1129
+ """
1130
+ # Note: the recovery list will be kept.
1131
+ # In a selling case, the seller should clean the recovery list then transfer to the new owner.
1132
+ assert self.did_info.origin_coin is not None
1133
+ return did_wallet_puzzles.create_innerpuz(
1134
+ p2_puzzle_or_hash=puzzle_for_pk(pubkey),
1135
+ recovery_list=self.did_info.backup_ids,
1136
+ num_of_backup_ids_needed=uint64(self.did_info.num_of_backup_ids_needed),
1137
+ launcher_id=self.did_info.origin_coin.name(),
1138
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1139
+ )
1140
+
1141
+ async def inner_puzzle_for_did_puzzle(self, did_hash: bytes32) -> Program:
1142
+ record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
1143
+ did_hash
1144
+ )
1145
+ assert self.did_info.origin_coin is not None
1146
+ assert self.did_info.current_inner is not None
1147
+ uncurried_args = uncurry_innerpuz(self.did_info.current_inner)
1148
+ assert uncurried_args is not None
1149
+ old_recovery_list_hash: Optional[Program] = None
1150
+ p2_puzzle, old_recovery_list_hash, _, _, _ = uncurried_args
1151
+ if record is None:
1152
+ record = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
1153
+ p2_puzzle.get_tree_hash()
1154
+ )
1155
+ if not (self.did_info.num_of_backup_ids_needed > 0 and len(self.did_info.backup_ids) == 0):
1156
+ # We have the recovery list, don't reset it
1157
+ old_recovery_list_hash = None
1158
+
1159
+ inner_puzzle: Program = did_wallet_puzzles.create_innerpuz(
1160
+ p2_puzzle_or_hash=puzzle_for_pk(record.pubkey),
1161
+ recovery_list=self.did_info.backup_ids,
1162
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1163
+ launcher_id=self.did_info.origin_coin.name(),
1164
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1165
+ recovery_list_hash=old_recovery_list_hash,
1166
+ )
1167
+ return inner_puzzle
1168
+
1169
+ def get_parent_for_coin(self, coin) -> Optional[LineageProof]:
1170
+ parent_info = None
1171
+ for name, ccparent in self.did_info.parent_info:
1172
+ if name == coin.parent_coin_info:
1173
+ parent_info = ccparent
1174
+
1175
+ return parent_info
1176
+
1177
+ async def sign_message(self, message: str, mode: SigningMode) -> Tuple[G1Element, G2Element]:
1178
+ if self.did_info.current_inner is None:
1179
+ raise ValueError("Missing DID inner puzzle.")
1180
+ puzzle_args = did_wallet_puzzles.uncurry_innerpuz(self.did_info.current_inner)
1181
+ if puzzle_args is not None:
1182
+ p2_puzzle, _, _, _, _ = puzzle_args
1183
+ puzzle_hash = p2_puzzle.get_tree_hash()
1184
+ private = await self.wallet_state_manager.get_private_key(puzzle_hash)
1185
+ synthetic_secret_key = calculate_synthetic_secret_key(private, DEFAULT_HIDDEN_PUZZLE_HASH)
1186
+ synthetic_pk = synthetic_secret_key.get_g1()
1187
+ if mode == SigningMode.CHIP_0002_HEX_INPUT:
1188
+ hex_message: bytes = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))).get_tree_hash()
1189
+ elif mode == SigningMode.BLS_MESSAGE_AUGMENTATION_UTF8_INPUT:
1190
+ hex_message = bytes(message, "utf-8")
1191
+ elif mode == SigningMode.BLS_MESSAGE_AUGMENTATION_HEX_INPUT:
1192
+ hex_message = bytes.fromhex(message)
1193
+ else:
1194
+ hex_message = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message)).get_tree_hash()
1195
+ return synthetic_pk, AugSchemeMPL.sign(synthetic_secret_key, hex_message)
1196
+ else:
1197
+ raise ValueError("Invalid inner DID puzzle.")
1198
+
1199
+ async def generate_new_decentralised_id(
1200
+ self,
1201
+ amount: uint64,
1202
+ action_scope: WalletActionScope,
1203
+ fee: uint64 = uint64(0),
1204
+ extra_conditions: Tuple[Condition, ...] = tuple(),
1205
+ ) -> None:
1206
+ """
1207
+ This must be called under the wallet state manager lock
1208
+ """
1209
+
1210
+ coins = await self.standard_wallet.select_coins(uint64(amount + fee), action_scope)
1211
+
1212
+ origin = coins.copy().pop()
1213
+ genesis_launcher_puz = SINGLETON_LAUNCHER_PUZZLE
1214
+ launcher_coin = Coin(origin.name(), genesis_launcher_puz.get_tree_hash(), amount)
1215
+
1216
+ did_inner: Program = await self.get_new_did_innerpuz(launcher_coin.name())
1217
+ did_inner_hash = did_inner.get_tree_hash()
1218
+ did_full_puz = create_singleton_puzzle(did_inner, launcher_coin.name())
1219
+ did_puzzle_hash = did_full_puz.get_tree_hash()
1220
+
1221
+ announcement_message = Program.to([did_puzzle_hash, amount, bytes(0x80)]).get_tree_hash()
1222
+
1223
+ await self.standard_wallet.generate_signed_transaction(
1224
+ amount=amount,
1225
+ puzzle_hash=genesis_launcher_puz.get_tree_hash(),
1226
+ action_scope=action_scope,
1227
+ fee=fee,
1228
+ coins=coins,
1229
+ primaries=None,
1230
+ origin_id=origin.name(),
1231
+ extra_conditions=(
1232
+ AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message),
1233
+ *extra_conditions,
1234
+ ),
1235
+ )
1236
+
1237
+ genesis_launcher_solution = Program.to([did_puzzle_hash, amount, bytes(0x80)])
1238
+
1239
+ launcher_cs = make_spend(launcher_coin, genesis_launcher_puz, genesis_launcher_solution)
1240
+ launcher_sb = WalletSpendBundle([launcher_cs], AugSchemeMPL.aggregate([]))
1241
+ eve_coin = Coin(launcher_coin.name(), did_puzzle_hash, amount)
1242
+ future_parent = LineageProof(
1243
+ parent_name=eve_coin.parent_coin_info,
1244
+ inner_puzzle_hash=did_inner_hash,
1245
+ amount=uint64(eve_coin.amount),
1246
+ )
1247
+ eve_parent = LineageProof(
1248
+ parent_name=launcher_coin.parent_coin_info,
1249
+ inner_puzzle_hash=launcher_coin.puzzle_hash,
1250
+ amount=uint64(launcher_coin.amount),
1251
+ )
1252
+ await self.add_parent(eve_coin.parent_coin_info, eve_parent)
1253
+ await self.add_parent(eve_coin.name(), future_parent)
1254
+
1255
+ # Only want to save this information if the transaction is valid
1256
+ did_info = DIDInfo(
1257
+ origin_coin=launcher_coin,
1258
+ backup_ids=self.did_info.backup_ids,
1259
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1260
+ parent_info=self.did_info.parent_info,
1261
+ current_inner=did_inner,
1262
+ temp_coin=None,
1263
+ temp_puzhash=None,
1264
+ temp_pubkey=None,
1265
+ sent_recovery_transaction=False,
1266
+ metadata=self.did_info.metadata,
1267
+ )
1268
+ await self.save_info(did_info)
1269
+ eve_spend = await self.generate_eve_spend(eve_coin, did_full_puz, did_inner)
1270
+ full_spend = WalletSpendBundle.aggregate([eve_spend, launcher_sb])
1271
+ assert self.did_info.origin_coin is not None
1272
+ assert self.did_info.current_inner is not None
1273
+
1274
+ did_record = TransactionRecord(
1275
+ confirmed_at_height=uint32(0),
1276
+ created_at_time=uint64(int(time.time())),
1277
+ amount=uint64(amount),
1278
+ to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
1279
+ fee_amount=fee,
1280
+ confirmed=False,
1281
+ sent=uint32(0),
1282
+ spend_bundle=full_spend,
1283
+ additions=full_spend.additions(),
1284
+ removals=full_spend.removals(),
1285
+ wallet_id=self.id(),
1286
+ sent_to=[],
1287
+ trade_id=None,
1288
+ type=uint32(TransactionType.INCOMING_TX.value),
1289
+ name=full_spend.name(),
1290
+ memos=[],
1291
+ valid_times=ConditionValidTimes(),
1292
+ )
1293
+ async with action_scope.use() as interface:
1294
+ interface.side_effects.transactions.append(did_record)
1295
+
1296
+ async def generate_eve_spend(
1297
+ self,
1298
+ coin: Coin,
1299
+ full_puzzle: Program,
1300
+ innerpuz: Program,
1301
+ extra_conditions: Tuple[Condition, ...] = tuple(),
1302
+ ):
1303
+ assert self.did_info.origin_coin is not None
1304
+ uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
1305
+ assert uncurried is not None
1306
+ p2_puzzle = uncurried[0]
1307
+ # innerpuz solution is (mode p2_solution)
1308
+ p2_solution = self.standard_wallet.make_solution(
1309
+ primaries=[Payment(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()])],
1310
+ conditions=extra_conditions,
1311
+ )
1312
+ innersol = Program.to([1, p2_solution])
1313
+ # full solution is (lineage_proof my_amount inner_solution)
1314
+ fullsol = Program.to(
1315
+ [
1316
+ [self.did_info.origin_coin.parent_coin_info, self.did_info.origin_coin.amount],
1317
+ coin.amount,
1318
+ innersol,
1319
+ ]
1320
+ )
1321
+ list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
1322
+ unsigned_spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
1323
+ return unsigned_spend_bundle
1324
+
1325
+ async def get_spendable_balance(self, unspent_records=None) -> uint128:
1326
+ spendable_am = await self.wallet_state_manager.get_confirmed_spendable_balance_for_wallet(
1327
+ self.wallet_info.id, unspent_records
1328
+ )
1329
+ return spendable_am
1330
+
1331
+ async def get_max_send_amount(self, records: Optional[Set[WalletCoinRecord]] = None):
1332
+ max_send_amount = await self.get_confirmed_balance()
1333
+
1334
+ return max_send_amount
1335
+
1336
+ async def add_parent(self, name: bytes32, parent: Optional[LineageProof]):
1337
+ self.log.info(f"Adding parent {name}: {parent}")
1338
+ current_list = self.did_info.parent_info.copy()
1339
+ current_list.append((name, parent))
1340
+ did_info = DIDInfo(
1341
+ origin_coin=self.did_info.origin_coin,
1342
+ backup_ids=self.did_info.backup_ids,
1343
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1344
+ parent_info=current_list,
1345
+ current_inner=self.did_info.current_inner,
1346
+ temp_coin=self.did_info.temp_coin,
1347
+ temp_puzhash=self.did_info.temp_puzhash,
1348
+ temp_pubkey=self.did_info.temp_pubkey,
1349
+ sent_recovery_transaction=self.did_info.sent_recovery_transaction,
1350
+ metadata=self.did_info.metadata,
1351
+ )
1352
+ await self.save_info(did_info)
1353
+
1354
+ async def update_recovery_list(self, recover_list: List[bytes32], num_of_backup_ids_needed: uint64) -> bool:
1355
+ if num_of_backup_ids_needed > len(recover_list):
1356
+ return False
1357
+ did_info = DIDInfo(
1358
+ origin_coin=self.did_info.origin_coin,
1359
+ backup_ids=recover_list,
1360
+ num_of_backup_ids_needed=num_of_backup_ids_needed,
1361
+ parent_info=self.did_info.parent_info,
1362
+ current_inner=self.did_info.current_inner,
1363
+ temp_coin=self.did_info.temp_coin,
1364
+ temp_puzhash=self.did_info.temp_puzhash,
1365
+ temp_pubkey=self.did_info.temp_pubkey,
1366
+ sent_recovery_transaction=self.did_info.sent_recovery_transaction,
1367
+ metadata=self.did_info.metadata,
1368
+ )
1369
+ await self.save_info(did_info)
1370
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
1371
+ return True
1372
+
1373
+ async def update_metadata(self, metadata: Dict[str, str]) -> bool:
1374
+ # validate metadata
1375
+ if not all(isinstance(k, str) and isinstance(v, str) for k, v in metadata.items()):
1376
+ raise ValueError("Metadata key value pairs must be strings.")
1377
+ did_info = DIDInfo(
1378
+ origin_coin=self.did_info.origin_coin,
1379
+ backup_ids=self.did_info.backup_ids,
1380
+ num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
1381
+ parent_info=self.did_info.parent_info,
1382
+ current_inner=self.did_info.current_inner,
1383
+ temp_coin=self.did_info.temp_coin,
1384
+ temp_puzhash=self.did_info.temp_puzhash,
1385
+ temp_pubkey=self.did_info.temp_pubkey,
1386
+ sent_recovery_transaction=self.did_info.sent_recovery_transaction,
1387
+ metadata=json.dumps(metadata),
1388
+ )
1389
+ await self.save_info(did_info)
1390
+ await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
1391
+ return True
1392
+
1393
+ async def save_info(self, did_info: DIDInfo):
1394
+ self.did_info = did_info
1395
+ current_info = self.wallet_info
1396
+ data_str = json.dumps(did_info.to_json_dict())
1397
+ wallet_info = WalletInfo(current_info.id, current_info.name, current_info.type, data_str)
1398
+ self.wallet_info = wallet_info
1399
+ await self.wallet_state_manager.user_store.update_wallet(wallet_info)
1400
+
1401
+ def generate_wallet_name(self) -> str:
1402
+ """
1403
+ Generate a new DID wallet name
1404
+ :return: wallet name
1405
+ """
1406
+ max_num = 0
1407
+ for wallet in self.wallet_state_manager.wallets.values():
1408
+ if wallet.type() == WalletType.DECENTRALIZED_ID:
1409
+ matched = re.search(r"^Profile (\d+)$", wallet.get_name())
1410
+ if matched and int(matched.group(1)) > max_num:
1411
+ max_num = int(matched.group(1))
1412
+ return f"Profile {max_num + 1}"
1413
+
1414
+ def check_existed_did(self):
1415
+ """
1416
+ Check if the current DID is existed
1417
+ :return: None
1418
+ """
1419
+ for wallet in self.wallet_state_manager.wallets.values():
1420
+ if (
1421
+ wallet.type() == WalletType.DECENTRALIZED_ID
1422
+ and self.did_info.origin_coin.name() == wallet.did_info.origin_coin.name()
1423
+ ):
1424
+ self.log.warning(f"DID {self.did_info.origin_coin} already existed, ignore the wallet creation.")
1425
+ raise ValueError("Wallet already exists")
1426
+
1427
+ @staticmethod
1428
+ def deserialize_backup_data(backup_data: str) -> DIDInfo:
1429
+ """
1430
+ Get a DIDInfo from a serialized string
1431
+ :param backup_data: serialized
1432
+ :return: DIDInfo
1433
+ """
1434
+ details = backup_data.split(":")
1435
+ origin = Coin(bytes32.fromhex(details[0]), bytes32.fromhex(details[1]), uint64(int(details[2])))
1436
+ backup_ids = []
1437
+ if len(details[3]) > 0:
1438
+ for d in details[3].split(","):
1439
+ backup_ids.append(bytes32.from_hexstr(d))
1440
+ num_of_backup_ids_needed = uint64(int(details[5]))
1441
+ if num_of_backup_ids_needed > len(backup_ids):
1442
+ raise Exception
1443
+ innerpuz: Program = Program.from_bytes(bytes.fromhex(details[4]))
1444
+ metadata: str = details[6]
1445
+ did_info = DIDInfo(
1446
+ origin_coin=origin,
1447
+ backup_ids=backup_ids,
1448
+ num_of_backup_ids_needed=num_of_backup_ids_needed,
1449
+ parent_info=[],
1450
+ current_inner=innerpuz,
1451
+ temp_coin=None,
1452
+ temp_puzhash=None,
1453
+ temp_pubkey=None,
1454
+ sent_recovery_transaction=True,
1455
+ metadata=metadata,
1456
+ )
1457
+ return did_info
1458
+
1459
+ def require_derivation_paths(self) -> bool:
1460
+ return True
1461
+
1462
+ async def get_coin(self) -> Coin:
1463
+ spendable_coins: Set[WalletCoinRecord] = await self.wallet_state_manager.get_spendable_coins_for_wallet(
1464
+ self.wallet_info.id
1465
+ )
1466
+ if len(spendable_coins) == 0:
1467
+ raise RuntimeError("DID is not currently spendable")
1468
+ return sorted(list(spendable_coins), key=lambda c: c.confirmed_block_height, reverse=True)[0].coin
1469
+
1470
+ async def match_hinted_coin(self, coin: Coin, hint: bytes32) -> bool:
1471
+ if self.did_info.origin_coin is None:
1472
+ return False # pragma: no cover
1473
+ return (
1474
+ create_singleton_puzzle(
1475
+ did_wallet_puzzles.create_innerpuz(
1476
+ p2_puzzle_or_hash=hint,
1477
+ recovery_list=self.did_info.backup_ids,
1478
+ num_of_backup_ids_needed=uint64(self.did_info.num_of_backup_ids_needed),
1479
+ launcher_id=self.did_info.origin_coin.name(),
1480
+ metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
1481
+ ),
1482
+ self.did_info.origin_coin.name(),
1483
+ ).get_tree_hash_precalc(hint)
1484
+ == coin.puzzle_hash
1485
+ )