chia-blockchain 2.5.0rc1__py3-none-any.whl → 2.5.1__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 (637) hide show
  1. chia/_tests/README.md +1 -1
  2. chia/_tests/blockchain/blockchain_test_utils.py +24 -26
  3. chia/_tests/blockchain/test_augmented_chain.py +6 -8
  4. chia/_tests/blockchain/test_blockchain.py +409 -307
  5. chia/_tests/blockchain/test_blockchain_transactions.py +56 -75
  6. chia/_tests/blockchain/test_build_chains.py +11 -13
  7. chia/_tests/blockchain/test_get_block_generator.py +8 -8
  8. chia/_tests/blockchain/test_lookup_fork_chain.py +3 -4
  9. chia/_tests/build-init-files.py +3 -4
  10. chia/_tests/build-job-matrix.py +9 -9
  11. chia/_tests/check_sql_statements.py +2 -3
  12. chia/_tests/clvm/benchmark_costs.py +1 -1
  13. chia/_tests/clvm/coin_store.py +7 -5
  14. chia/_tests/clvm/test_chialisp_deserialization.py +8 -8
  15. chia/_tests/clvm/test_condition_codes.py +2 -2
  16. chia/_tests/clvm/test_curry_and_treehash.py +2 -4
  17. chia/_tests/clvm/test_message_conditions.py +184 -0
  18. chia/_tests/clvm/test_puzzle_compression.py +1 -2
  19. chia/_tests/clvm/test_puzzle_drivers.py +3 -3
  20. chia/_tests/clvm/test_puzzles.py +13 -18
  21. chia/_tests/clvm/test_singletons.py +17 -17
  22. chia/_tests/clvm/test_spend_sim.py +7 -7
  23. chia/_tests/cmds/cmd_test_utils.py +42 -45
  24. chia/_tests/cmds/conftest.py +2 -2
  25. chia/_tests/cmds/test_click_types.py +21 -16
  26. chia/_tests/cmds/test_cmd_framework.py +255 -35
  27. chia/_tests/cmds/test_cmds_util.py +2 -2
  28. chia/_tests/cmds/test_daemon.py +3 -3
  29. chia/_tests/cmds/test_dev_gh.py +131 -0
  30. chia/_tests/cmds/test_farm_cmd.py +1 -2
  31. chia/_tests/cmds/test_show.py +6 -6
  32. chia/_tests/cmds/test_tx_config_args.py +2 -1
  33. chia/_tests/cmds/wallet/test_dao.py +23 -23
  34. chia/_tests/cmds/wallet/test_did.py +29 -29
  35. chia/_tests/cmds/wallet/test_nft.py +24 -23
  36. chia/_tests/cmds/wallet/test_notifications.py +8 -8
  37. chia/_tests/cmds/wallet/test_tx_decorators.py +3 -3
  38. chia/_tests/cmds/wallet/test_vcs.py +97 -73
  39. chia/_tests/cmds/wallet/test_wallet.py +74 -75
  40. chia/_tests/cmds/wallet/test_wallet_check.py +5 -7
  41. chia/_tests/conftest.py +153 -38
  42. chia/_tests/connection_utils.py +7 -6
  43. chia/_tests/core/cmds/test_beta.py +3 -3
  44. chia/_tests/core/cmds/test_keys.py +6 -6
  45. chia/_tests/core/cmds/test_wallet.py +3 -3
  46. chia/_tests/core/consensus/test_block_creation.py +3 -5
  47. chia/_tests/core/custom_types/test_coin.py +1 -3
  48. chia/_tests/core/custom_types/test_spend_bundle.py +3 -4
  49. chia/_tests/core/daemon/test_daemon.py +58 -58
  50. chia/_tests/core/daemon/test_keychain_proxy.py +2 -1
  51. chia/_tests/core/data_layer/conftest.py +4 -3
  52. chia/_tests/core/data_layer/test_data_cli.py +1 -2
  53. chia/_tests/core/data_layer/test_data_layer.py +5 -5
  54. chia/_tests/core/data_layer/test_data_layer_util.py +8 -9
  55. chia/_tests/core/data_layer/test_data_rpc.py +75 -93
  56. chia/_tests/core/data_layer/test_data_store.py +38 -37
  57. chia/_tests/core/data_layer/test_data_store_schema.py +11 -11
  58. chia/_tests/core/data_layer/util.py +11 -10
  59. chia/_tests/core/farmer/test_farmer_api.py +6 -4
  60. chia/_tests/core/full_node/full_sync/test_full_sync.py +5 -10
  61. chia/_tests/core/full_node/ram_db.py +2 -2
  62. chia/_tests/core/full_node/stores/test_block_store.py +113 -11
  63. chia/_tests/core/full_node/stores/test_coin_store.py +37 -28
  64. chia/_tests/core/full_node/stores/test_full_node_store.py +34 -30
  65. chia/_tests/core/full_node/stores/test_hint_store.py +3 -4
  66. chia/_tests/core/full_node/test_address_manager.py +2 -2
  67. chia/_tests/core/full_node/test_block_height_map.py +1 -1
  68. chia/_tests/core/full_node/test_conditions.py +10 -12
  69. chia/_tests/core/full_node/test_full_node.py +2077 -1822
  70. chia/_tests/core/full_node/test_generator_tools.py +4 -4
  71. chia/_tests/core/full_node/test_hint_management.py +2 -2
  72. chia/_tests/core/full_node/test_performance.py +2 -5
  73. chia/_tests/core/full_node/test_subscriptions.py +4 -4
  74. chia/_tests/core/full_node/test_tx_processing_queue.py +5 -4
  75. chia/_tests/core/make_block_generator.py +5 -7
  76. chia/_tests/core/mempool/test_mempool.py +205 -208
  77. chia/_tests/core/mempool/test_mempool_fee_protocol.py +5 -5
  78. chia/_tests/core/mempool/test_mempool_item_queries.py +2 -4
  79. chia/_tests/core/mempool/test_mempool_manager.py +109 -80
  80. chia/_tests/core/mempool/test_mempool_performance.py +3 -4
  81. chia/_tests/core/mempool/test_singleton_fast_forward.py +12 -12
  82. chia/_tests/core/server/flood.py +6 -4
  83. chia/_tests/core/server/serve.py +10 -7
  84. chia/_tests/core/server/test_api_protocol.py +21 -0
  85. chia/_tests/core/server/test_capabilities.py +3 -5
  86. chia/_tests/core/server/test_dos.py +15 -16
  87. chia/_tests/core/server/test_loop.py +14 -10
  88. chia/_tests/core/server/test_node_discovery.py +1 -2
  89. chia/_tests/core/server/test_rate_limits.py +156 -44
  90. chia/_tests/core/server/test_server.py +8 -7
  91. chia/_tests/core/services/test_services.py +59 -37
  92. chia/_tests/core/ssl/test_ssl.py +5 -3
  93. chia/_tests/core/test_cost_calculation.py +5 -6
  94. chia/_tests/core/test_crawler.py +2 -2
  95. chia/_tests/core/test_db_conversion.py +5 -4
  96. chia/_tests/core/test_db_validation.py +6 -5
  97. chia/_tests/core/test_farmer_harvester_rpc.py +8 -7
  98. chia/_tests/core/test_filter.py +3 -5
  99. chia/_tests/core/test_full_node_rpc.py +64 -90
  100. chia/_tests/core/test_merkle_set.py +10 -10
  101. chia/_tests/core/test_program.py +2 -4
  102. chia/_tests/core/test_rpc_util.py +1 -2
  103. chia/_tests/core/test_seeder.py +124 -12
  104. chia/_tests/core/util/test_block_cache.py +5 -5
  105. chia/_tests/core/util/test_cached_bls.py +3 -3
  106. chia/_tests/core/util/test_config.py +13 -13
  107. chia/_tests/core/util/test_files.py +2 -2
  108. chia/_tests/core/util/test_jsonify.py +9 -9
  109. chia/_tests/core/util/test_keychain.py +13 -5
  110. chia/_tests/core/util/test_keyring_wrapper.py +6 -5
  111. chia/_tests/core/util/test_log_exceptions.py +3 -3
  112. chia/_tests/core/util/test_streamable.py +38 -38
  113. chia/_tests/db/test_db_wrapper.py +13 -12
  114. chia/_tests/environments/common.py +2 -2
  115. chia/_tests/environments/full_node.py +2 -2
  116. chia/_tests/environments/wallet.py +109 -48
  117. chia/_tests/farmer_harvester/test_farmer.py +35 -35
  118. chia/_tests/farmer_harvester/test_farmer_harvester.py +17 -17
  119. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +6 -5
  120. chia/_tests/farmer_harvester/test_third_party_harvesters.py +73 -46
  121. chia/_tests/fee_estimation/test_fee_estimation_integration.py +8 -8
  122. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +47 -47
  123. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +6 -7
  124. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +11 -11
  125. chia/_tests/generator/test_compression.py +13 -30
  126. chia/_tests/generator/test_generator_types.py +3 -3
  127. chia/_tests/generator/test_rom.py +7 -9
  128. chia/_tests/plot_sync/test_delta.py +2 -3
  129. chia/_tests/plot_sync/test_plot_sync.py +25 -24
  130. chia/_tests/plot_sync/test_receiver.py +9 -9
  131. chia/_tests/plot_sync/test_sender.py +1 -1
  132. chia/_tests/plot_sync/test_sync_simulated.py +27 -26
  133. chia/_tests/plot_sync/util.py +2 -1
  134. chia/_tests/plotting/test_plot_manager.py +54 -11
  135. chia/_tests/plotting/util.py +2 -3
  136. chia/_tests/pools/test_pool_cli_parsing.py +128 -0
  137. chia/_tests/pools/test_pool_cmdline.py +993 -15
  138. chia/_tests/pools/test_pool_config.py +3 -5
  139. chia/_tests/pools/test_pool_puzzles_lifecycle.py +10 -11
  140. chia/_tests/pools/test_pool_rpc.py +203 -90
  141. chia/_tests/pools/test_pool_wallet.py +12 -8
  142. chia/_tests/pools/test_wallet_pool_store.py +3 -3
  143. chia/_tests/process_junit.py +16 -17
  144. chia/_tests/rpc/test_rpc_client.py +59 -2
  145. chia/_tests/rpc/test_rpc_server.py +183 -0
  146. chia/_tests/simulation/test_simulation.py +5 -5
  147. chia/_tests/simulation/test_simulator.py +8 -10
  148. chia/_tests/simulation/test_start_simulator.py +5 -4
  149. chia/_tests/timelord/test_new_peak.py +19 -19
  150. chia/_tests/tools/test_run_block.py +1 -2
  151. chia/_tests/tools/test_virtual_project.py +591 -0
  152. chia/_tests/util/benchmark_cost.py +9 -9
  153. chia/_tests/util/benchmarks.py +1 -2
  154. chia/_tests/util/blockchain.py +12 -11
  155. chia/_tests/util/blockchain_mock.py +15 -15
  156. chia/_tests/util/build_network_protocol_files.py +12 -12
  157. chia/_tests/util/db_connection.py +3 -2
  158. chia/_tests/util/full_sync.py +14 -6
  159. chia/_tests/util/gen_ssl_certs.py +4 -5
  160. chia/_tests/util/generator_tools_testing.py +5 -7
  161. chia/_tests/util/get_name_puzzle_conditions.py +52 -0
  162. chia/_tests/util/key_tool.py +2 -3
  163. chia/_tests/util/misc.py +59 -106
  164. chia/_tests/util/network_protocol_data.py +7 -9
  165. chia/_tests/util/protocol_messages_json.py +112 -111
  166. chia/_tests/util/rpc.py +3 -0
  167. chia/_tests/util/run_block.py +16 -16
  168. chia/_tests/util/setup_nodes.py +25 -23
  169. chia/{clvm → _tests/util}/spend_sim.py +59 -55
  170. chia/_tests/util/split_managers.py +12 -9
  171. chia/_tests/util/temp_file.py +1 -1
  172. chia/_tests/util/test_action_scope.py +2 -1
  173. chia/_tests/util/test_async_pool.py +8 -8
  174. chia/_tests/util/test_build_job_matrix.py +2 -3
  175. chia/_tests/util/test_condition_tools.py +4 -6
  176. chia/_tests/util/test_config.py +5 -5
  177. chia/_tests/util/test_dump_keyring.py +1 -1
  178. chia/_tests/util/test_full_block_utils.py +19 -11
  179. chia/_tests/util/test_limited_semaphore.py +4 -3
  180. chia/_tests/util/test_logging_filter.py +2 -3
  181. chia/_tests/util/test_misc.py +29 -28
  182. chia/_tests/util/test_network.py +32 -31
  183. chia/_tests/util/test_network_protocol_files.py +2 -3
  184. chia/_tests/util/test_network_protocol_json.py +1 -0
  185. chia/_tests/util/test_network_protocol_test.py +18 -19
  186. chia/_tests/util/test_paginator.py +3 -4
  187. chia/_tests/util/test_pprint.py +1 -1
  188. chia/_tests/util/test_priority_mutex.py +18 -17
  189. chia/_tests/util/test_recursive_replace.py +2 -2
  190. chia/_tests/util/test_testnet_overrides.py +3 -3
  191. chia/_tests/util/test_timing.py +1 -1
  192. chia/_tests/util/test_trusted_peer.py +2 -2
  193. chia/_tests/util/time_out_assert.py +43 -6
  194. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +13 -13
  195. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +1 -1
  196. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +117 -29
  197. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +15 -15
  198. chia/_tests/wallet/cat_wallet/test_trades.py +50 -28
  199. chia/_tests/wallet/clawback/test_clawback_decorator.py +3 -5
  200. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +6 -6
  201. chia/_tests/wallet/clawback/test_clawback_metadata.py +1 -2
  202. chia/_tests/wallet/conftest.py +135 -74
  203. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +25 -17
  204. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +75 -75
  205. chia/_tests/wallet/db_wallet/test_db_graftroot.py +10 -12
  206. chia/_tests/wallet/db_wallet/test_dl_offers.py +6 -6
  207. chia/_tests/wallet/db_wallet/test_dl_wallet.py +18 -18
  208. chia/_tests/wallet/did_wallet/test_did.py +1277 -474
  209. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +12 -11
  210. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +115 -105
  211. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +6 -7
  212. chia/_tests/wallet/nft_wallet/test_nft_offers.py +16 -16
  213. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +3 -3
  214. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +38 -12
  215. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +1 -1
  216. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +31 -33
  217. chia/_tests/wallet/rpc/test_wallet_rpc.py +218 -171
  218. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +36 -37
  219. chia/_tests/wallet/sync/test_wallet_sync.py +241 -78
  220. chia/_tests/wallet/test_address_type.py +20 -20
  221. chia/_tests/wallet/test_clvm_streamable.py +5 -5
  222. chia/_tests/wallet/test_coin_management.py +354 -0
  223. chia/_tests/wallet/test_coin_selection.py +34 -35
  224. chia/_tests/wallet/test_conditions.py +28 -16
  225. chia/_tests/wallet/test_debug_spend_bundle.py +156 -14
  226. chia/_tests/wallet/test_new_wallet_protocol.py +29 -31
  227. chia/_tests/wallet/test_nft_store.py +1 -2
  228. chia/_tests/wallet/test_notifications.py +2 -2
  229. chia/_tests/wallet/test_offer_parsing_performance.py +1 -1
  230. chia/_tests/wallet/test_puzzle_store.py +2 -3
  231. chia/_tests/wallet/test_sign_coin_spends.py +3 -3
  232. chia/_tests/wallet/test_signer_protocol.py +33 -34
  233. chia/_tests/wallet/test_singleton_lifecycle_fast.py +29 -29
  234. chia/_tests/wallet/test_taproot.py +1 -1
  235. chia/_tests/wallet/test_transaction_store.py +23 -19
  236. chia/_tests/wallet/test_util.py +36 -32
  237. chia/_tests/wallet/test_wallet.py +37 -37
  238. chia/_tests/wallet/test_wallet_action_scope.py +8 -8
  239. chia/_tests/wallet/test_wallet_blockchain.py +4 -6
  240. chia/_tests/wallet/test_wallet_coin_store.py +34 -34
  241. chia/_tests/wallet/test_wallet_node.py +69 -72
  242. chia/_tests/wallet/test_wallet_retry.py +3 -3
  243. chia/_tests/wallet/test_wallet_state_manager.py +12 -5
  244. chia/_tests/wallet/test_wallet_trade_store.py +2 -2
  245. chia/_tests/wallet/test_wallet_utils.py +5 -4
  246. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +3 -3
  247. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +18 -18
  248. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +69 -40
  249. chia/_tests/wallet/wallet_block_tools.py +27 -27
  250. chia/_tests/weight_proof/test_weight_proof.py +30 -30
  251. chia/apis.py +19 -0
  252. chia/cmds/beta.py +8 -7
  253. chia/cmds/beta_funcs.py +15 -11
  254. chia/cmds/check_wallet_db.py +29 -27
  255. chia/cmds/chia.py +17 -9
  256. chia/cmds/cmd_classes.py +87 -79
  257. chia/cmds/cmd_helpers.py +242 -0
  258. chia/cmds/cmds_util.py +56 -66
  259. chia/cmds/coin_funcs.py +168 -153
  260. chia/cmds/coins.py +156 -194
  261. chia/cmds/configure.py +4 -3
  262. chia/cmds/dao.py +89 -33
  263. chia/cmds/dao_funcs.py +55 -33
  264. chia/cmds/data.py +7 -6
  265. chia/cmds/data_funcs.py +26 -21
  266. chia/cmds/db.py +4 -3
  267. chia/cmds/db_backup_func.py +2 -2
  268. chia/cmds/db_upgrade_func.py +3 -3
  269. chia/cmds/db_validate_func.py +2 -2
  270. chia/cmds/dev.py +2 -0
  271. chia/cmds/farm.py +18 -5
  272. chia/cmds/farm_funcs.py +17 -24
  273. chia/cmds/gh.py +275 -0
  274. chia/cmds/init.py +4 -11
  275. chia/cmds/init_funcs.py +9 -9
  276. chia/cmds/installers.py +5 -3
  277. chia/cmds/keys.py +56 -39
  278. chia/cmds/keys_funcs.py +30 -31
  279. chia/cmds/netspace.py +6 -3
  280. chia/cmds/netspace_funcs.py +3 -2
  281. chia/cmds/param_types.py +16 -6
  282. chia/cmds/passphrase.py +8 -7
  283. chia/cmds/passphrase_funcs.py +7 -61
  284. chia/cmds/peer.py +2 -1
  285. chia/cmds/peer_funcs.py +5 -5
  286. chia/cmds/plotnft.py +207 -153
  287. chia/cmds/plotnft_funcs.py +205 -174
  288. chia/cmds/plots.py +14 -6
  289. chia/cmds/plotters.py +2 -1
  290. chia/cmds/rpc.py +48 -28
  291. chia/cmds/show.py +2 -1
  292. chia/cmds/show_funcs.py +7 -6
  293. chia/cmds/signer.py +50 -58
  294. chia/cmds/sim.py +22 -14
  295. chia/cmds/sim_funcs.py +11 -11
  296. chia/cmds/start.py +3 -3
  297. chia/cmds/start_funcs.py +9 -12
  298. chia/cmds/stop.py +4 -3
  299. chia/cmds/units.py +1 -3
  300. chia/cmds/wallet.py +252 -96
  301. chia/cmds/wallet_funcs.py +217 -143
  302. chia/consensus/block_body_validation.py +133 -86
  303. chia/consensus/block_creation.py +42 -21
  304. chia/consensus/block_header_validation.py +32 -37
  305. chia/consensus/block_record.py +1 -2
  306. chia/consensus/blockchain.py +167 -180
  307. chia/consensus/blockchain_interface.py +10 -10
  308. chia/consensus/constants.py +2 -2
  309. chia/consensus/default_constants.py +3 -4
  310. chia/consensus/difficulty_adjustment.py +5 -5
  311. chia/consensus/find_fork_point.py +5 -5
  312. chia/consensus/full_block_to_block_record.py +4 -4
  313. chia/consensus/get_block_challenge.py +2 -2
  314. chia/consensus/get_block_generator.py +4 -3
  315. chia/consensus/multiprocess_validation.py +207 -304
  316. chia/consensus/vdf_info_computation.py +3 -3
  317. chia/daemon/client.py +46 -27
  318. chia/daemon/keychain_proxy.py +10 -9
  319. chia/daemon/keychain_server.py +18 -18
  320. chia/daemon/server.py +103 -113
  321. chia/daemon/windows_signal.py +2 -2
  322. chia/data_layer/data_layer.py +64 -76
  323. chia/data_layer/data_layer_api.py +8 -0
  324. chia/data_layer/data_layer_errors.py +3 -3
  325. chia/data_layer/data_layer_server.py +2 -2
  326. chia/data_layer/data_layer_util.py +71 -71
  327. chia/data_layer/data_layer_wallet.py +63 -67
  328. chia/data_layer/data_store.py +72 -72
  329. chia/data_layer/dl_wallet_store.py +10 -10
  330. chia/data_layer/download_data.py +5 -5
  331. chia/data_layer/s3_plugin_service.py +9 -9
  332. chia/data_layer/util/benchmark.py +0 -1
  333. chia/data_layer/util/plugin.py +2 -3
  334. chia/farmer/farmer.py +46 -43
  335. chia/farmer/farmer_api.py +27 -21
  336. chia/full_node/block_height_map.py +6 -6
  337. chia/full_node/block_store.py +41 -35
  338. chia/full_node/coin_store.py +42 -41
  339. chia/full_node/fee_estimate.py +2 -2
  340. chia/full_node/fee_estimation.py +1 -2
  341. chia/full_node/fee_history.py +5 -6
  342. chia/full_node/fee_tracker.py +24 -24
  343. chia/full_node/full_node.py +574 -300
  344. chia/full_node/full_node_api.py +181 -130
  345. chia/full_node/full_node_store.py +43 -43
  346. chia/full_node/hint_management.py +4 -4
  347. chia/full_node/hint_store.py +9 -10
  348. chia/full_node/mempool.py +25 -19
  349. chia/full_node/mempool_check_conditions.py +11 -42
  350. chia/full_node/mempool_manager.py +48 -53
  351. chia/full_node/pending_tx_cache.py +9 -9
  352. chia/full_node/subscriptions.py +23 -24
  353. chia/full_node/sync_store.py +8 -7
  354. chia/full_node/tx_processing_queue.py +3 -3
  355. chia/full_node/util/__init__.py +0 -0
  356. chia/full_node/weight_proof.py +79 -78
  357. chia/harvester/harvester.py +9 -8
  358. chia/harvester/harvester_api.py +19 -13
  359. chia/introducer/introducer.py +7 -5
  360. chia/introducer/introducer_api.py +9 -3
  361. chia/legacy/keyring.py +6 -5
  362. chia/plot_sync/delta.py +8 -8
  363. chia/plot_sync/receiver.py +12 -11
  364. chia/plot_sync/sender.py +15 -12
  365. chia/plotters/bladebit.py +12 -12
  366. chia/plotters/chiapos.py +2 -2
  367. chia/plotters/madmax.py +8 -8
  368. chia/plotters/plotters.py +6 -6
  369. chia/plotters/plotters_util.py +6 -4
  370. chia/plotting/cache.py +8 -7
  371. chia/plotting/check_plots.py +8 -8
  372. chia/plotting/create_plots.py +6 -6
  373. chia/plotting/manager.py +22 -22
  374. chia/plotting/util.py +31 -19
  375. chia/pools/pool_config.py +7 -7
  376. chia/pools/pool_puzzles.py +16 -16
  377. chia/pools/pool_wallet.py +64 -57
  378. chia/pools/pool_wallet_info.py +3 -3
  379. chia/protocols/full_node_protocol.py +3 -3
  380. chia/protocols/harvester_protocol.py +12 -12
  381. chia/protocols/introducer_protocol.py +1 -2
  382. chia/protocols/protocol_message_types.py +4 -4
  383. chia/protocols/protocol_state_machine.py +2 -2
  384. chia/protocols/protocol_timing.py +1 -0
  385. chia/protocols/shared_protocol.py +3 -3
  386. chia/protocols/timelord_protocol.py +2 -2
  387. chia/protocols/wallet_protocol.py +33 -33
  388. chia/rpc/crawler_rpc_api.py +12 -7
  389. chia/rpc/data_layer_rpc_api.py +49 -44
  390. chia/rpc/data_layer_rpc_client.py +41 -41
  391. chia/rpc/data_layer_rpc_util.py +7 -11
  392. chia/rpc/farmer_rpc_api.py +32 -27
  393. chia/rpc/farmer_rpc_client.py +14 -14
  394. chia/rpc/full_node_rpc_api.py +53 -48
  395. chia/rpc/full_node_rpc_client.py +30 -30
  396. chia/rpc/harvester_rpc_api.py +16 -11
  397. chia/rpc/harvester_rpc_client.py +6 -6
  398. chia/rpc/rpc_client.py +34 -14
  399. chia/rpc/rpc_server.py +117 -43
  400. chia/rpc/timelord_rpc_api.py +9 -4
  401. chia/rpc/util.py +11 -211
  402. chia/rpc/wallet_request_types.py +276 -60
  403. chia/rpc/wallet_rpc_api.py +563 -399
  404. chia/rpc/wallet_rpc_client.py +220 -250
  405. chia/seeder/crawl_store.py +6 -8
  406. chia/seeder/crawler.py +23 -36
  407. chia/seeder/crawler_api.py +28 -22
  408. chia/seeder/dns_server.py +99 -50
  409. chia/seeder/start_crawler.py +13 -9
  410. chia/server/address_manager.py +19 -19
  411. chia/server/address_manager_store.py +17 -17
  412. chia/server/api_protocol.py +106 -1
  413. chia/server/capabilities.py +3 -3
  414. chia/server/chia_policy.py +17 -16
  415. chia/server/introducer_peers.py +3 -3
  416. chia/server/node_discovery.py +34 -38
  417. chia/server/rate_limit_numbers.py +26 -16
  418. chia/server/rate_limits.py +67 -27
  419. chia/server/server.py +52 -31
  420. chia/server/signal_handlers.py +6 -3
  421. chia/server/ssl_context.py +5 -5
  422. chia/server/start_data_layer.py +37 -23
  423. chia/server/start_farmer.py +28 -16
  424. chia/server/start_full_node.py +29 -23
  425. chia/server/start_harvester.py +28 -15
  426. chia/server/start_introducer.py +27 -15
  427. chia/server/start_service.py +17 -29
  428. chia/server/start_timelord.py +25 -18
  429. chia/server/start_wallet.py +22 -18
  430. chia/server/upnp.py +4 -3
  431. chia/server/ws_connection.py +68 -54
  432. chia/simulator/add_blocks_in_batches.py +54 -0
  433. chia/simulator/block_tools.py +65 -64
  434. chia/simulator/full_node_simulator.py +66 -74
  435. chia/simulator/setup_services.py +10 -9
  436. chia/simulator/simulator_full_node_rpc_api.py +12 -14
  437. chia/simulator/simulator_full_node_rpc_client.py +3 -5
  438. chia/simulator/simulator_test_tools.py +8 -7
  439. chia/simulator/socket.py +1 -4
  440. chia/simulator/ssl_certs.py +5 -5
  441. chia/simulator/ssl_certs_1.py +2 -4
  442. chia/simulator/ssl_certs_10.py +2 -4
  443. chia/simulator/ssl_certs_2.py +2 -4
  444. chia/simulator/ssl_certs_3.py +2 -4
  445. chia/simulator/ssl_certs_4.py +2 -4
  446. chia/simulator/ssl_certs_5.py +2 -4
  447. chia/simulator/ssl_certs_6.py +2 -4
  448. chia/simulator/ssl_certs_7.py +2 -4
  449. chia/simulator/ssl_certs_8.py +2 -4
  450. chia/simulator/ssl_certs_9.py +2 -4
  451. chia/simulator/start_simulator.py +14 -6
  452. chia/simulator/wallet_tools.py +21 -20
  453. chia/ssl/create_ssl.py +11 -11
  454. chia/timelord/iters_from_block.py +2 -2
  455. chia/timelord/timelord.py +57 -33
  456. chia/timelord/timelord_api.py +12 -6
  457. chia/timelord/timelord_launcher.py +10 -8
  458. chia/timelord/timelord_state.py +5 -5
  459. chia/types/block_protocol.py +2 -2
  460. chia/types/blockchain_format/coin.py +3 -3
  461. chia/types/blockchain_format/program.py +17 -18
  462. chia/types/blockchain_format/tree_hash.py +9 -9
  463. chia/types/coin_spend.py +8 -8
  464. chia/types/condition_with_args.py +1 -2
  465. chia/types/eligible_coin_spends.py +16 -15
  466. chia/types/generator_types.py +1 -2
  467. chia/types/internal_mempool_item.py +1 -2
  468. chia/types/mempool_item.py +7 -7
  469. chia/types/mempool_submission_status.py +2 -2
  470. chia/types/peer_info.py +1 -1
  471. chia/types/spend_bundle.py +1 -2
  472. chia/types/transaction_queue_entry.py +2 -2
  473. chia/types/unfinished_header_block.py +2 -2
  474. chia/types/validation_state.py +14 -0
  475. chia/types/weight_proof.py +5 -6
  476. chia/util/action_scope.py +8 -8
  477. chia/util/async_pool.py +6 -4
  478. chia/util/augmented_chain.py +13 -9
  479. chia/util/batches.py +5 -2
  480. chia/util/bech32m.py +14 -11
  481. chia/util/beta_metrics.py +5 -4
  482. chia/util/block_cache.py +5 -5
  483. chia/util/byte_types.py +2 -0
  484. chia/util/check_fork_next_block.py +3 -2
  485. chia/util/chia_logging.py +41 -21
  486. chia/util/collection.py +3 -3
  487. chia/util/condition_tools.py +18 -18
  488. chia/util/config.py +26 -25
  489. chia/util/cpu.py +2 -0
  490. chia/util/db_synchronous.py +2 -0
  491. chia/util/db_version.py +2 -0
  492. chia/util/db_wrapper.py +13 -10
  493. chia/util/default_root.py +17 -0
  494. chia/util/dump_keyring.py +6 -6
  495. chia/util/errors.py +5 -3
  496. chia/util/file_keyring.py +22 -33
  497. chia/util/files.py +2 -0
  498. chia/util/full_block_utils.py +31 -7
  499. chia/util/generator_tools.py +18 -8
  500. chia/util/hash.py +3 -1
  501. chia/util/initial-config.yaml +19 -0
  502. chia/util/inline_executor.py +2 -0
  503. chia/util/ip_address.py +39 -0
  504. chia/util/json_util.py +0 -4
  505. chia/util/keychain.py +27 -24
  506. chia/util/keyring_wrapper.py +65 -4
  507. chia/util/limited_semaphore.py +3 -1
  508. chia/util/lock.py +4 -2
  509. chia/util/log_exceptions.py +5 -2
  510. chia/util/logging.py +3 -1
  511. chia/util/lru_cache.py +2 -0
  512. chia/util/math.py +4 -4
  513. chia/util/network.py +15 -73
  514. chia/util/paginator.py +3 -1
  515. chia/util/path.py +2 -0
  516. chia/util/permissions.py +3 -2
  517. chia/util/prev_transaction_block.py +1 -3
  518. chia/util/priority_mutex.py +6 -3
  519. chia/util/profiler.py +7 -4
  520. chia/util/recursive_replace.py +2 -0
  521. chia/util/safe_cancel_task.py +2 -0
  522. chia/util/service_groups.py +2 -2
  523. chia/util/setproctitle.py +2 -0
  524. chia/util/significant_bits.py +2 -0
  525. chia/util/ssl_check.py +11 -11
  526. chia/util/streamable.py +44 -56
  527. chia/util/task_referencer.py +59 -0
  528. chia/util/task_timing.py +22 -18
  529. chia/util/timing.py +4 -1
  530. chia/util/vdf_prover.py +2 -3
  531. chia/util/virtual_project_analysis.py +540 -0
  532. chia/util/ws_message.py +6 -6
  533. chia/wallet/cat_wallet/cat_info.py +3 -3
  534. chia/wallet/cat_wallet/cat_outer_puzzle.py +3 -3
  535. chia/wallet/cat_wallet/cat_utils.py +5 -4
  536. chia/wallet/cat_wallet/cat_wallet.py +56 -70
  537. chia/wallet/cat_wallet/dao_cat_info.py +3 -3
  538. chia/wallet/cat_wallet/dao_cat_wallet.py +18 -18
  539. chia/wallet/cat_wallet/lineage_store.py +2 -2
  540. chia/wallet/coin_selection.py +15 -15
  541. chia/wallet/conditions.py +257 -71
  542. chia/wallet/dao_wallet/dao_info.py +4 -4
  543. chia/wallet/dao_wallet/dao_utils.py +43 -42
  544. chia/wallet/dao_wallet/dao_wallet.py +66 -68
  545. chia/wallet/db_wallet/db_wallet_puzzles.py +12 -8
  546. chia/wallet/derive_keys.py +11 -11
  547. chia/wallet/did_wallet/did_info.py +3 -3
  548. chia/wallet/did_wallet/did_wallet.py +56 -47
  549. chia/wallet/did_wallet/did_wallet_puzzles.py +7 -6
  550. chia/wallet/lineage_proof.py +4 -4
  551. chia/wallet/nft_wallet/metadata_outer_puzzle.py +2 -2
  552. chia/wallet/nft_wallet/nft_info.py +4 -4
  553. chia/wallet/nft_wallet/nft_puzzles.py +16 -16
  554. chia/wallet/nft_wallet/nft_wallet.py +90 -89
  555. chia/wallet/nft_wallet/ownership_outer_puzzle.py +2 -2
  556. chia/wallet/nft_wallet/singleton_outer_puzzle.py +2 -2
  557. chia/wallet/nft_wallet/transfer_program_puzzle.py +2 -2
  558. chia/wallet/nft_wallet/uncurry_nft.py +2 -2
  559. chia/wallet/notification_manager.py +5 -5
  560. chia/wallet/notification_store.py +6 -6
  561. chia/wallet/outer_puzzles.py +2 -2
  562. chia/wallet/payment.py +4 -5
  563. chia/wallet/puzzle_drivers.py +4 -4
  564. chia/wallet/puzzles/clawback/drivers.py +5 -5
  565. chia/wallet/puzzles/clawback/puzzle_decorator.py +7 -7
  566. chia/wallet/puzzles/load_clvm.py +2 -3
  567. chia/wallet/puzzles/p2_conditions.py +1 -2
  568. chia/wallet/puzzles/p2_delegated_conditions.py +1 -2
  569. chia/wallet/puzzles/p2_delegated_puzzle.py +2 -3
  570. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +3 -4
  571. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +1 -2
  572. chia/wallet/puzzles/p2_puzzle_hash.py +1 -2
  573. chia/wallet/puzzles/puzzle_utils.py +7 -7
  574. chia/wallet/puzzles/singleton_top_layer.py +6 -5
  575. chia/wallet/puzzles/singleton_top_layer_v1_1.py +6 -5
  576. chia/wallet/puzzles/tails.py +34 -30
  577. chia/wallet/signer_protocol.py +7 -8
  578. chia/wallet/singleton.py +4 -4
  579. chia/wallet/trade_manager.py +155 -141
  580. chia/wallet/trade_record.py +5 -5
  581. chia/wallet/trading/offer.py +100 -101
  582. chia/wallet/trading/trade_store.py +14 -14
  583. chia/wallet/transaction_record.py +31 -16
  584. chia/wallet/util/address_type.py +4 -4
  585. chia/wallet/util/blind_signer_tl.py +8 -12
  586. chia/wallet/util/clvm_streamable.py +15 -15
  587. chia/wallet/util/compute_hints.py +5 -5
  588. chia/wallet/util/compute_memos.py +4 -6
  589. chia/wallet/util/curry_and_treehash.py +3 -2
  590. chia/wallet/util/debug_spend_bundle.py +6 -8
  591. chia/wallet/util/merkle_tree.py +10 -10
  592. chia/wallet/util/merkle_utils.py +10 -10
  593. chia/wallet/util/new_peak_queue.py +3 -3
  594. chia/wallet/util/peer_request_cache.py +8 -8
  595. chia/{util → wallet/util}/pprint.py +2 -3
  596. chia/wallet/util/puzzle_compression.py +3 -4
  597. chia/wallet/util/puzzle_decorator.py +10 -10
  598. chia/wallet/util/query_filter.py +9 -10
  599. chia/wallet/util/tx_config.py +12 -12
  600. chia/wallet/util/wallet_sync_utils.py +24 -21
  601. chia/wallet/util/wallet_types.py +9 -2
  602. chia/wallet/vc_wallet/cr_cat_drivers.py +28 -27
  603. chia/wallet/vc_wallet/cr_cat_wallet.py +42 -40
  604. chia/wallet/vc_wallet/cr_outer_puzzle.py +4 -4
  605. chia/wallet/vc_wallet/vc_drivers.py +16 -16
  606. chia/wallet/vc_wallet/vc_store.py +9 -9
  607. chia/wallet/vc_wallet/vc_wallet.py +35 -35
  608. chia/wallet/wallet.py +54 -54
  609. chia/wallet/wallet_action_scope.py +14 -13
  610. chia/wallet/wallet_blockchain.py +10 -10
  611. chia/wallet/wallet_coin_record.py +2 -2
  612. chia/wallet/wallet_coin_store.py +10 -10
  613. chia/wallet/wallet_info.py +1 -2
  614. chia/wallet/wallet_interested_store.py +5 -5
  615. chia/wallet/wallet_nft_store.py +6 -6
  616. chia/wallet/wallet_node.py +72 -76
  617. chia/wallet/wallet_node_api.py +33 -27
  618. chia/wallet/wallet_pool_store.py +1 -2
  619. chia/wallet/wallet_protocol.py +15 -15
  620. chia/wallet/wallet_puzzle_store.py +35 -4
  621. chia/wallet/wallet_retry_store.py +2 -2
  622. chia/wallet/wallet_singleton_store.py +10 -9
  623. chia/wallet/wallet_spend_bundle.py +4 -20
  624. chia/wallet/wallet_state_manager.py +223 -224
  625. chia/wallet/wallet_transaction_store.py +44 -18
  626. chia/wallet/wallet_user_store.py +2 -2
  627. chia/wallet/wallet_weight_proof_handler.py +2 -2
  628. {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/LICENSE +1 -1
  629. {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/METADATA +67 -72
  630. chia_blockchain-2.5.1.dist-info/RECORD +1042 -0
  631. {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/WHEEL +1 -1
  632. mozilla-ca/cacert.pem +32 -87
  633. chia/_tests/cmds/wallet/test_coins.py +0 -195
  634. chia/consensus/block_root_validation.py +0 -46
  635. chia/util/api_decorators.py +0 -89
  636. chia_blockchain-2.5.0rc1.dist-info/RECORD +0 -1028
  637. {chia_blockchain-2.5.0rc1.dist-info → chia_blockchain-2.5.1.dist-info}/entry_points.txt +0 -0
@@ -2,16 +2,19 @@ from __future__ import annotations
2
2
 
3
3
  import dataclasses
4
4
  import json
5
- from typing import Optional
6
5
 
7
6
  import pytest
8
7
  from chia_rs import AugSchemeMPL, G1Element, G2Element
9
8
 
9
+ from chia._tests.conftest import ConsensusMode
10
10
  from chia._tests.environments.wallet import WalletStateTransition, WalletTestFramework
11
11
  from chia._tests.util.setup_nodes import OldSimulatorsAndWallets
12
12
  from chia._tests.util.time_out_assert import time_out_assert
13
13
  from chia.rpc.wallet_request_types import DIDGetCurrentCoinInfo, DIDGetRecoveryInfo
14
14
  from chia.rpc.wallet_rpc_api import WalletRpcApi
15
+ from chia.server.server import ChiaServer
16
+ from chia.simulator.block_tools import BlockTools
17
+ from chia.simulator.full_node_simulator import FullNodeSimulator
15
18
  from chia.simulator.simulator_protocol import FarmNewBlockProtocol
16
19
  from chia.types.blockchain_format.program import Program
17
20
  from chia.types.blockchain_format.sized_bytes import bytes32
@@ -26,6 +29,7 @@ from chia.wallet.singleton import create_singleton_puzzle
26
29
  from chia.wallet.util.address_type import AddressType
27
30
  from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
28
31
  from chia.wallet.util.wallet_types import WalletType
32
+ from chia.wallet.wallet_node import WalletNode
29
33
  from chia.wallet.wallet_spend_bundle import WalletSpendBundle
30
34
 
31
35
 
@@ -38,14 +42,16 @@ def get_parent_num(did_wallet: DIDWallet):
38
42
 
39
43
 
40
44
  class TestDIDWallet:
45
+ # TODO: See Issue CHIA-1544
46
+ # This test should be ported to WalletTestFramework once we can replace keys in the wallet node
41
47
  @pytest.mark.parametrize(
42
48
  "trusted",
43
49
  [True, False],
44
50
  )
45
51
  @pytest.mark.anyio
46
52
  async def test_creation_from_coin_spend(
47
- self, self_hostname, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted
48
- ):
53
+ self, self_hostname: str, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted: bool
54
+ ) -> None:
49
55
  """
50
56
  Verify that DIDWallet.create_new_did_wallet_from_coin_spend() is called after Singleton creation on
51
57
  the blockchain, and that the wallet is created in the second wallet node.
@@ -110,7 +116,7 @@ class TestDIDWallet:
110
116
  == json.loads(all_node_1_wallets[1].data)["current_inner"]
111
117
  )
112
118
 
113
- # TODO: Porting this test to this fixture revealed some balance peculiarities. Fix them.
119
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
114
120
  @pytest.mark.parametrize(
115
121
  "wallet_environments",
116
122
  [
@@ -163,8 +169,8 @@ class TestDIDWallet:
163
169
  "did": {
164
170
  "init": True,
165
171
  "unconfirmed_wallet_balance": 101,
166
- "pending_change": 202, # TODO: this is not correct, fix this
167
- "pending_coin_removal_count": 2, # TODO: this might not be correct
172
+ "pending_change": 101,
173
+ "pending_coin_removal_count": 1,
168
174
  },
169
175
  },
170
176
  post_block_balance_updates={
@@ -180,8 +186,8 @@ class TestDIDWallet:
180
186
  "spendable_balance": 101,
181
187
  "max_send_amount": 101,
182
188
  "unspent_coin_count": 1,
183
- "pending_change": -202, # TODO: this is not correct, fix this
184
- "pending_coin_removal_count": -2, # TODO: this might not be correct
189
+ "pending_change": -101,
190
+ "pending_coin_removal_count": -1,
185
191
  },
186
192
  },
187
193
  ),
@@ -224,8 +230,8 @@ class TestDIDWallet:
224
230
  "did": {
225
231
  "init": True,
226
232
  "unconfirmed_wallet_balance": 201,
227
- "pending_change": 402, # TODO: this is not correct, fix this
228
- "pending_coin_removal_count": 2, # TODO: this might not be correct
233
+ "pending_change": 201,
234
+ "pending_coin_removal_count": 1,
229
235
  },
230
236
  },
231
237
  post_block_balance_updates={
@@ -241,8 +247,8 @@ class TestDIDWallet:
241
247
  "spendable_balance": 201,
242
248
  "max_send_amount": 201,
243
249
  "unspent_coin_count": 1,
244
- "pending_change": -402, # TODO: this is not correct, fix this
245
- "pending_coin_removal_count": -2, # TODO: this might not be correct
250
+ "pending_change": -201,
251
+ "pending_coin_removal_count": -1,
246
252
  },
247
253
  },
248
254
  ),
@@ -288,6 +294,7 @@ class TestDIDWallet:
288
294
  "spendable_balance": -101,
289
295
  "pending_change": 101,
290
296
  "pending_coin_removal_count": 1,
297
+ "max_send_amount": -101,
291
298
  }
292
299
  },
293
300
  post_block_balance_updates={
@@ -295,6 +302,7 @@ class TestDIDWallet:
295
302
  "spendable_balance": 101,
296
303
  "pending_change": -101,
297
304
  "pending_coin_removal_count": -1,
305
+ "max_send_amount": 101,
298
306
  }
299
307
  },
300
308
  ),
@@ -394,14 +402,13 @@ class TestDIDWallet:
394
402
  "did": {
395
403
  "unconfirmed_wallet_balance": -201,
396
404
  "spendable_balance": -201,
397
- # "max_send_amount": -201, # TODO: Uncomment this
405
+ "max_send_amount": -201,
398
406
  "pending_coin_removal_count": 1,
399
407
  }
400
408
  },
401
409
  post_block_balance_updates={
402
410
  "did": {
403
411
  "confirmed_wallet_balance": -201,
404
- "max_send_amount": -201, # TODO: Delete this when uncommented above
405
412
  "unspent_coin_count": -1,
406
413
  "pending_coin_removal_count": -1,
407
414
  }
@@ -421,97 +428,178 @@ class TestDIDWallet:
421
428
  for wallet in [did_wallet_0, did_wallet_1]:
422
429
  assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
423
430
 
424
- @pytest.mark.parametrize(
425
- "trusted",
426
- [True, False],
427
- )
431
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
432
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
428
433
  @pytest.mark.anyio
429
- async def test_did_recovery_with_multiple_backup_dids(self, self_hostname, two_wallet_nodes, trusted):
430
- full_nodes, wallets, _ = two_wallet_nodes
431
- full_node_api = full_nodes[0]
432
- server_1 = full_node_api.server
433
- wallet_node, server_2 = wallets[0]
434
- wallet_node_2, server_3 = wallets[1]
435
- wallet = wallet_node.wallet_state_manager.main_wallet
436
- wallet2 = wallet_node_2.wallet_state_manager.main_wallet
437
-
438
- if trusted:
439
- wallet_node.config["trusted_peers"] = {
440
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
441
- }
442
- wallet_node_2.config["trusted_peers"] = {
443
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
444
- }
445
- else:
446
- wallet_node.config["trusted_peers"] = {}
447
- wallet_node_2.config["trusted_peers"] = {}
448
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
449
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
434
+ async def test_did_recovery_with_multiple_backup_dids(self, wallet_environments: WalletTestFramework):
435
+ env_0 = wallet_environments.environments[0]
436
+ env_1 = wallet_environments.environments[1]
437
+ wallet_node_0 = env_0.node
438
+ wallet_node_1 = env_1.node
439
+ wallet_0 = env_0.xch_wallet
440
+ wallet_1 = env_1.xch_wallet
450
441
 
451
- await full_node_api.farm_blocks_to_wallet(1, wallet)
452
- await full_node_api.farm_blocks_to_wallet(1, wallet2)
442
+ env_0.wallet_aliases = {
443
+ "xch": 1,
444
+ "did": 2,
445
+ }
446
+ env_1.wallet_aliases = {
447
+ "xch": 1,
448
+ "did": 2,
449
+ }
453
450
 
454
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
451
+ async with wallet_0.wallet_state_manager.new_action_scope(
452
+ wallet_environments.tx_config, push=True
453
+ ) as action_scope:
455
454
  did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
456
- wallet_node.wallet_state_manager, wallet, uint64(101), action_scope
455
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
457
456
  )
458
457
  assert did_wallet.get_name() == "Profile 1"
459
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
460
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
461
-
462
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
463
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
464
-
465
- recovery_list = [bytes.fromhex(did_wallet.get_my_DID())]
458
+ recovery_list = [bytes32.from_hexstr(did_wallet.get_my_DID())]
466
459
 
467
- async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
460
+ async with wallet_1.wallet_state_manager.new_action_scope(
461
+ wallet_environments.tx_config, push=True
462
+ ) as action_scope:
468
463
  did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet(
469
- wallet_node_2.wallet_state_manager, wallet2, uint64(101), action_scope, recovery_list
464
+ wallet_node_1.wallet_state_manager, wallet_1, uint64(101), action_scope, recovery_list
470
465
  )
471
466
 
472
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
473
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
474
-
475
- await time_out_assert(15, did_wallet_2.get_confirmed_balance, 101)
476
- await time_out_assert(15, did_wallet_2.get_unconfirmed_balance, 101)
477
-
467
+ await wallet_environments.process_pending_states(
468
+ [
469
+ WalletStateTransition(
470
+ pre_block_balance_updates={
471
+ "xch": {
472
+ "set_remainder": True,
473
+ },
474
+ "did": {
475
+ "init": True,
476
+ "unconfirmed_wallet_balance": 101,
477
+ "pending_change": 101,
478
+ "pending_coin_removal_count": 1,
479
+ },
480
+ },
481
+ post_block_balance_updates={
482
+ "xch": {
483
+ "set_remainder": True,
484
+ },
485
+ "did": {
486
+ "confirmed_wallet_balance": 101,
487
+ "spendable_balance": 101,
488
+ "max_send_amount": 101,
489
+ "unspent_coin_count": 1,
490
+ "pending_change": -101,
491
+ "pending_coin_removal_count": -1,
492
+ },
493
+ },
494
+ ),
495
+ WalletStateTransition(
496
+ pre_block_balance_updates={
497
+ "xch": {
498
+ "set_remainder": True,
499
+ },
500
+ "did": {
501
+ "init": True,
502
+ "unconfirmed_wallet_balance": 101,
503
+ "pending_change": 101,
504
+ "pending_coin_removal_count": 1,
505
+ },
506
+ },
507
+ post_block_balance_updates={
508
+ "xch": {
509
+ "set_remainder": True,
510
+ },
511
+ "did": {
512
+ "confirmed_wallet_balance": 101,
513
+ "spendable_balance": 101,
514
+ "max_send_amount": 101,
515
+ "unspent_coin_count": 1,
516
+ "pending_change": -101,
517
+ "pending_coin_removal_count": -1,
518
+ },
519
+ },
520
+ ),
521
+ ]
522
+ )
478
523
  assert did_wallet_2.did_info.backup_ids == recovery_list
479
524
 
480
- recovery_list.append(bytes.fromhex(did_wallet_2.get_my_DID()))
525
+ recovery_list.append(bytes32.from_hexstr(did_wallet_2.get_my_DID()))
481
526
 
482
- async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
527
+ async with wallet_1.wallet_state_manager.new_action_scope(
528
+ wallet_environments.tx_config, push=True
529
+ ) as action_scope:
483
530
  did_wallet_3: DIDWallet = await DIDWallet.create_new_did_wallet(
484
- wallet_node_2.wallet_state_manager, wallet2, uint64(201), action_scope, recovery_list
531
+ wallet_node_1.wallet_state_manager, wallet_1, uint64(201), action_scope, recovery_list
485
532
  )
486
533
 
487
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
488
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
534
+ env_1.wallet_aliases["did_2"] = 3
489
535
 
490
- assert did_wallet_3.did_info.backup_ids == recovery_list
491
- await time_out_assert(15, did_wallet_3.get_confirmed_balance, 201)
492
- await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 201)
536
+ await wallet_environments.process_pending_states(
537
+ [
538
+ WalletStateTransition(
539
+ pre_block_balance_updates={},
540
+ post_block_balance_updates={},
541
+ ),
542
+ WalletStateTransition(
543
+ pre_block_balance_updates={
544
+ "xch": {
545
+ "set_remainder": True,
546
+ },
547
+ "did": {
548
+ "set_remainder": True,
549
+ },
550
+ "did_2": {
551
+ "init": True,
552
+ "unconfirmed_wallet_balance": 201,
553
+ "pending_change": 201,
554
+ "pending_coin_removal_count": 1,
555
+ },
556
+ },
557
+ post_block_balance_updates={
558
+ "xch": {
559
+ "set_remainder": True,
560
+ },
561
+ "did": {
562
+ "set_remainder": True,
563
+ },
564
+ "did_2": {
565
+ "confirmed_wallet_balance": 201,
566
+ "spendable_balance": 201,
567
+ "max_send_amount": 201,
568
+ "unspent_coin_count": 1,
569
+ "pending_change": -201,
570
+ "pending_coin_removal_count": -1,
571
+ },
572
+ },
573
+ ),
574
+ ]
575
+ )
493
576
  coin = await did_wallet_3.get_coin()
494
577
 
495
578
  backup_data = did_wallet_3.create_backup()
496
579
 
497
- async with wallet_node.wallet_state_manager.lock:
580
+ async with wallet_node_0.wallet_state_manager.lock:
498
581
  did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery(
499
- wallet_node.wallet_state_manager,
500
- wallet,
582
+ wallet_node_0.wallet_state_manager,
583
+ wallet_0,
501
584
  backup_data,
502
585
  )
503
586
  assert did_wallet_4.get_name() == "Profile 2"
587
+ env_0.wallet_aliases["did_2"] = 3
504
588
 
505
589
  pubkey = (
506
590
  await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_2.wallet_info.id)
507
591
  ).pubkey
508
592
  new_ph = did_wallet_4.did_info.temp_puzhash
509
- async with did_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
593
+ async with did_wallet.wallet_state_manager.new_action_scope(
594
+ wallet_environments.tx_config, push=True
595
+ ) as action_scope:
510
596
  message_spend_bundle, attest1 = await did_wallet.create_attestment(
511
597
  coin.name(), new_ph, pubkey, action_scope
512
598
  )
513
599
 
514
- async with did_wallet_2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope_2:
600
+ async with did_wallet_2.wallet_state_manager.new_action_scope(
601
+ wallet_environments.tx_config, push=True
602
+ ) as action_scope_2:
515
603
  message_spend_bundle2, attest2 = await did_wallet_2.create_attestment(
516
604
  coin.name(), new_ph, pubkey, action_scope_2
517
605
  )
@@ -524,233 +612,486 @@ class TestDIDWallet:
524
612
  ) = await did_wallet_4.load_attest_files_for_recovery_spend([attest1, attest2])
525
613
  assert message_spend_bundle == test_message_spend_bundle
526
614
 
527
- await full_node_api.process_transaction_records(
528
- records=[*action_scope.side_effects.transactions, *action_scope_2.side_effects.transactions]
615
+ await wallet_environments.process_pending_states(
616
+ [
617
+ WalletStateTransition(
618
+ pre_block_balance_updates={
619
+ "did": {
620
+ "spendable_balance": -101,
621
+ "pending_change": 101,
622
+ "max_send_amount": -101,
623
+ "pending_coin_removal_count": 1,
624
+ "set_remainder": True,
625
+ },
626
+ "did_2": {
627
+ "init": True,
628
+ "unconfirmed_wallet_balance": 0,
629
+ "pending_change": 0,
630
+ "pending_coin_removal_count": 0,
631
+ },
632
+ },
633
+ post_block_balance_updates={
634
+ "did": {
635
+ "spendable_balance": 101,
636
+ "pending_change": -101,
637
+ "max_send_amount": 101,
638
+ "pending_coin_removal_count": -1,
639
+ },
640
+ "did_2": {
641
+ "confirmed_wallet_balance": 0,
642
+ "spendable_balance": 0,
643
+ "max_send_amount": 0,
644
+ "unspent_coin_count": 0,
645
+ "pending_change": 0,
646
+ "pending_coin_removal_count": 0,
647
+ },
648
+ },
649
+ ),
650
+ WalletStateTransition(
651
+ pre_block_balance_updates={
652
+ "did": {
653
+ "spendable_balance": -101,
654
+ "pending_change": 101,
655
+ "max_send_amount": -101,
656
+ "pending_coin_removal_count": 1,
657
+ "set_remainder": True,
658
+ },
659
+ },
660
+ post_block_balance_updates={
661
+ "did": {
662
+ "spendable_balance": 101,
663
+ "pending_change": -101,
664
+ "max_send_amount": 101,
665
+ "pending_coin_removal_count": -1,
666
+ },
667
+ },
668
+ ),
669
+ ]
529
670
  )
530
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
531
- await time_out_assert(15, did_wallet_4.get_confirmed_balance, 0)
532
- await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 0)
533
- async with did_wallet_4.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
671
+
672
+ async with did_wallet_4.wallet_state_manager.new_action_scope(
673
+ wallet_environments.tx_config, push=True
674
+ ) as action_scope:
534
675
  await did_wallet_4.recovery_spend(coin, new_ph, test_info_list, pubkey, message_spend_bundle, action_scope)
535
- await full_node_api.process_transaction_records(action_scope.side_effects.transactions)
536
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
537
676
 
538
- await time_out_assert(15, did_wallet_4.get_confirmed_balance, 201)
539
- await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 201)
540
- await time_out_assert(15, did_wallet_3.get_confirmed_balance, 0)
541
- await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 0)
677
+ await wallet_environments.process_pending_states(
678
+ [
679
+ WalletStateTransition(
680
+ pre_block_balance_updates={
681
+ "did_2": {
682
+ "unconfirmed_wallet_balance": 201,
683
+ "pending_change": 0,
684
+ "pending_coin_removal_count": 3,
685
+ },
686
+ },
687
+ post_block_balance_updates={
688
+ "did_2": {
689
+ "confirmed_wallet_balance": 201,
690
+ "spendable_balance": 201,
691
+ "max_send_amount": 201,
692
+ "unspent_coin_count": 1,
693
+ "pending_change": 0,
694
+ "pending_coin_removal_count": -3,
695
+ },
696
+ },
697
+ ),
698
+ WalletStateTransition(
699
+ pre_block_balance_updates={
700
+ "did_2": {
701
+ "unconfirmed_wallet_balance": 0, # TODO: fix pre-block balances for recovery
702
+ "spendable_balance": 0,
703
+ "pending_change": 0,
704
+ "max_send_amount": 0,
705
+ "pending_coin_removal_count": 0,
706
+ "set_remainder": True,
707
+ },
708
+ },
709
+ post_block_balance_updates={
710
+ "did_2": {
711
+ "confirmed_wallet_balance": -201,
712
+ "spendable_balance": -201,
713
+ "max_send_amount": -201,
714
+ "unspent_coin_count": -1,
715
+ "set_remainder": True,
716
+ },
717
+ },
718
+ ),
719
+ ]
720
+ )
542
721
 
543
722
  for wallet in [did_wallet, did_wallet_2, did_wallet_3, did_wallet_4]:
544
723
  assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
545
724
 
546
- @pytest.mark.parametrize(
547
- "trusted",
548
- [True, False],
549
- )
725
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
726
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
550
727
  @pytest.mark.anyio
551
- async def test_did_recovery_with_empty_set(self, self_hostname, two_wallet_nodes, trusted):
552
- full_nodes, wallets, _ = two_wallet_nodes
553
- full_node_api = full_nodes[0]
554
- server_1 = full_node_api.server
555
- wallet_node, server_2 = wallets[0]
556
- wallet_node_2, server_3 = wallets[1]
557
- wallet = wallet_node.wallet_state_manager.main_wallet
728
+ async def test_did_recovery_with_empty_set(self, wallet_environments: WalletTestFramework):
729
+ env_0 = wallet_environments.environments[0]
730
+ wallet_node_0 = env_0.node
731
+ wallet_0 = env_0.xch_wallet
558
732
 
559
- ph = await wallet.get_new_puzzlehash()
560
- if trusted:
561
- wallet_node.config["trusted_peers"] = {
562
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
563
- }
564
- wallet_node_2.config["trusted_peers"] = {
565
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
566
- }
567
- else:
568
- wallet_node.config["trusted_peers"] = {}
569
- wallet_node_2.config["trusted_peers"] = {}
570
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
571
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
733
+ env_0.wallet_aliases = {
734
+ "xch": 1,
735
+ "did": 2,
736
+ }
572
737
 
573
- await full_node_api.farm_blocks_to_wallet(1, wallet)
738
+ ph = await wallet_0.get_new_puzzlehash()
574
739
 
575
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
740
+ async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
576
741
  did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
577
- wallet_node.wallet_state_manager, wallet, uint64(101), action_scope
742
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
578
743
  )
579
744
 
580
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
581
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
582
-
583
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
584
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
745
+ await wallet_environments.process_pending_states(
746
+ [
747
+ WalletStateTransition(
748
+ pre_block_balance_updates={
749
+ "xch": {
750
+ "set_remainder": True,
751
+ },
752
+ "did": {
753
+ "init": True,
754
+ "unconfirmed_wallet_balance": 101,
755
+ "pending_change": 101,
756
+ "pending_coin_removal_count": 1,
757
+ },
758
+ },
759
+ post_block_balance_updates={
760
+ "xch": {
761
+ "set_remainder": True,
762
+ },
763
+ "did": {
764
+ "confirmed_wallet_balance": 101,
765
+ "spendable_balance": 101,
766
+ "max_send_amount": 101,
767
+ "unspent_coin_count": 1,
768
+ "pending_change": -101,
769
+ "pending_coin_removal_count": -1,
770
+ },
771
+ },
772
+ ),
773
+ ]
774
+ )
585
775
  coin = await did_wallet.get_coin()
586
- info = Program.to([])
776
+ info: list[tuple[bytes, bytes, int]] = []
587
777
  pubkey = (await did_wallet.wallet_state_manager.get_unused_derivation_record(did_wallet.wallet_info.id)).pubkey
588
778
  with pytest.raises(Exception): # We expect a CLVM 80 error for this test
589
- async with did_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
779
+ async with did_wallet.wallet_state_manager.new_action_scope(
780
+ wallet_environments.tx_config, push=False
781
+ ) as action_scope:
590
782
  await did_wallet.recovery_spend(
591
- coin, ph, info, pubkey, WalletSpendBundle([], AugSchemeMPL.aggregate([])), action_scope
783
+ coin,
784
+ ph,
785
+ info,
786
+ pubkey,
787
+ WalletSpendBundle([], AugSchemeMPL.aggregate([])),
788
+ action_scope,
592
789
  )
593
790
 
594
- @pytest.mark.parametrize(
595
- "trusted",
596
- [True, False],
597
- )
791
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
792
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
598
793
  @pytest.mark.anyio
599
- async def test_did_find_lost_did(self, self_hostname, two_wallet_nodes, trusted):
600
- full_nodes, wallets, _ = two_wallet_nodes
601
- full_node_api = full_nodes[0]
602
- server_1 = full_node_api.server
603
- wallet_node, server_2 = wallets[0]
604
- wallet_node_2, server_3 = wallets[1]
605
- wallet = wallet_node.wallet_state_manager.main_wallet
606
- api_0 = WalletRpcApi(wallet_node)
607
- if trusted:
608
- wallet_node.config["trusted_peers"] = {
609
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
610
- }
611
- wallet_node_2.config["trusted_peers"] = {
612
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
613
- }
614
- else:
615
- wallet_node.config["trusted_peers"] = {}
616
- wallet_node_2.config["trusted_peers"] = {}
617
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
618
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
619
- await full_node_api.farm_blocks_to_wallet(1, wallet)
794
+ async def test_did_find_lost_did(self, wallet_environments: WalletTestFramework):
795
+ env_0 = wallet_environments.environments[0]
796
+ wallet_node_0 = env_0.node
797
+ wallet_0 = env_0.xch_wallet
798
+ api_0 = env_0.rpc_api
620
799
 
621
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
622
- did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
623
- wallet_node.wallet_state_manager, wallet, uint64(101), action_scope
800
+ env_0.wallet_aliases = {
801
+ "xch": 1,
802
+ "did": 2,
803
+ }
804
+
805
+ async with wallet_0.wallet_state_manager.new_action_scope(
806
+ wallet_environments.tx_config, push=True
807
+ ) as action_scope:
808
+ did_wallet = await DIDWallet.create_new_did_wallet(
809
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
624
810
  )
625
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
626
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
627
811
 
628
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
629
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
812
+ await wallet_environments.process_pending_states(
813
+ [
814
+ WalletStateTransition(
815
+ pre_block_balance_updates={
816
+ "xch": {
817
+ "set_remainder": True,
818
+ },
819
+ "did": {
820
+ "init": True,
821
+ "unconfirmed_wallet_balance": 101,
822
+ "pending_change": 101,
823
+ "pending_coin_removal_count": 1,
824
+ },
825
+ },
826
+ post_block_balance_updates={
827
+ "xch": {
828
+ "set_remainder": True,
829
+ },
830
+ "did": {
831
+ "confirmed_wallet_balance": 101,
832
+ "spendable_balance": 101,
833
+ "max_send_amount": 101,
834
+ "unspent_coin_count": 1,
835
+ "pending_change": -101,
836
+ "pending_coin_removal_count": -1,
837
+ },
838
+ },
839
+ ),
840
+ ]
841
+ )
842
+
630
843
  # Delete the coin and wallet
631
844
  coin = await did_wallet.get_coin()
632
- await wallet_node.wallet_state_manager.coin_store.delete_coin_record(coin.name())
633
- await time_out_assert(15, did_wallet.get_confirmed_balance, 0)
634
- await wallet_node.wallet_state_manager.user_store.delete_wallet(did_wallet.wallet_info.id)
635
- wallet_node.wallet_state_manager.wallets.pop(did_wallet.wallet_info.id)
636
- assert len(wallet_node.wallet_state_manager.wallets) == 1
845
+ await wallet_node_0.wallet_state_manager.coin_store.delete_coin_record(coin.name())
846
+ await wallet_node_0.wallet_state_manager.delete_wallet(did_wallet.wallet_info.id)
847
+ wallet_node_0.wallet_state_manager.wallets.pop(did_wallet.wallet_info.id)
848
+ assert len(wallet_node_0.wallet_state_manager.wallets) == 1
637
849
  # Find lost DID
850
+ assert did_wallet.did_info.origin_coin is not None # mypy
638
851
  resp = await api_0.did_find_lost_did({"coin_id": did_wallet.did_info.origin_coin.name().hex()})
639
852
  assert resp["success"]
640
853
  did_wallets = list(
641
854
  filter(
642
855
  lambda w: (w.type == WalletType.DECENTRALIZED_ID),
643
- await wallet_node.wallet_state_manager.get_all_wallet_info_entries(),
856
+ await wallet_node_0.wallet_state_manager.get_all_wallet_info_entries(),
644
857
  )
645
858
  )
646
- did_wallet: Optional[DIDWallet] = wallet_node.wallet_state_manager.wallets[did_wallets[0].id]
647
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
648
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
859
+ did_wallet = wallet_node_0.wallet_state_manager.wallets[did_wallets[0].id]
860
+ env_0.wallet_aliases["did_found"] = did_wallets[0].id
861
+ await env_0.change_balances(
862
+ {
863
+ "did_found": {
864
+ "init": True,
865
+ "confirmed_wallet_balance": 101,
866
+ "unconfirmed_wallet_balance": 101,
867
+ "spendable_balance": 101,
868
+ "max_send_amount": 101,
869
+ "unspent_coin_count": 1,
870
+ }
871
+ }
872
+ )
873
+ await env_0.check_balances()
874
+
649
875
  # Spend DID
650
876
  recovery_list = [bytes32.fromhex(did_wallet.get_my_DID())]
651
877
  await did_wallet.update_recovery_list(recovery_list, uint64(1))
652
878
  assert did_wallet.did_info.backup_ids == recovery_list
653
- async with did_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
879
+ async with did_wallet.wallet_state_manager.new_action_scope(
880
+ wallet_environments.tx_config, push=True
881
+ ) as action_scope:
654
882
  await did_wallet.create_update_spend(action_scope)
655
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
656
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
657
883
 
658
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
659
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
884
+ await wallet_environments.process_pending_states(
885
+ [
886
+ WalletStateTransition(
887
+ pre_block_balance_updates={
888
+ "did_found": {
889
+ "spendable_balance": -101,
890
+ "max_send_amount": -101,
891
+ "pending_change": 101,
892
+ "pending_coin_removal_count": 1,
893
+ },
894
+ },
895
+ post_block_balance_updates={
896
+ "did_found": {
897
+ "spendable_balance": 101,
898
+ "max_send_amount": 101,
899
+ "pending_change": -101,
900
+ "pending_coin_removal_count": -1,
901
+ },
902
+ },
903
+ ),
904
+ ]
905
+ )
906
+
660
907
  # Delete the coin and change inner puzzle
661
908
  coin = await did_wallet.get_coin()
662
- await wallet_node.wallet_state_manager.coin_store.delete_coin_record(coin.name())
663
- await time_out_assert(15, did_wallet.get_confirmed_balance, 0)
664
- new_inner_puzzle = await did_wallet.get_new_did_innerpuz()
909
+ await wallet_node_0.wallet_state_manager.coin_store.delete_coin_record(coin.name())
910
+ new_inner_puzzle = await did_wallet.get_did_innerpuz(new=True)
665
911
  did_wallet.did_info = dataclasses.replace(did_wallet.did_info, current_inner=new_inner_puzzle)
666
912
  # Recovery the coin
913
+ assert did_wallet.did_info.origin_coin is not None # mypy
667
914
  resp = await api_0.did_find_lost_did({"coin_id": did_wallet.did_info.origin_coin.name().hex()})
668
915
  assert resp["success"]
669
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
916
+ found_coin = await did_wallet.get_coin()
917
+ assert found_coin == coin
670
918
  assert did_wallet.did_info.current_inner != new_inner_puzzle
671
919
 
672
- @pytest.mark.parametrize(
673
- "trusted",
674
- [True, False],
675
- )
920
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
921
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
676
922
  @pytest.mark.anyio
677
- async def test_did_attest_after_recovery(self, self_hostname, two_wallet_nodes, trusted):
678
- full_nodes, wallets, _ = two_wallet_nodes
679
- full_node_api = full_nodes[0]
680
- server_1 = full_node_api.server
681
- wallet_node, server_2 = wallets[0]
682
- wallet_node_2, server_3 = wallets[1]
683
- wallet = wallet_node.wallet_state_manager.main_wallet
684
- wallet2 = wallet_node_2.wallet_state_manager.main_wallet
685
- if trusted:
686
- wallet_node.config["trusted_peers"] = {
687
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
688
- }
689
- wallet_node_2.config["trusted_peers"] = {
690
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
691
- }
692
- else:
693
- wallet_node.config["trusted_peers"] = {}
694
- wallet_node_2.config["trusted_peers"] = {}
695
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
696
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
697
- await full_node_api.farm_blocks_to_wallet(1, wallet)
698
- await full_node_api.farm_blocks_to_wallet(1, wallet2)
923
+ async def test_did_attest_after_recovery(self, wallet_environments: WalletTestFramework):
924
+ env_0 = wallet_environments.environments[0]
925
+ env_1 = wallet_environments.environments[1]
926
+ wallet_node_0 = env_0.node
927
+ wallet_node_1 = env_1.node
928
+ wallet_0 = env_0.xch_wallet
929
+ wallet_1 = env_1.xch_wallet
699
930
 
700
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
931
+ env_0.wallet_aliases = {
932
+ "xch": 1,
933
+ "did": 2,
934
+ }
935
+ env_1.wallet_aliases = {
936
+ "xch": 1,
937
+ "did": 2,
938
+ }
939
+
940
+ async with wallet_0.wallet_state_manager.new_action_scope(
941
+ wallet_environments.tx_config, push=True
942
+ ) as action_scope:
701
943
  did_wallet: DIDWallet = await DIDWallet.create_new_did_wallet(
702
- wallet_node.wallet_state_manager, wallet, uint64(101), action_scope
944
+ wallet_node_0.wallet_state_manager, wallet_0, uint64(101), action_scope
703
945
  )
704
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
705
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
946
+ await wallet_environments.process_pending_states(
947
+ [
948
+ WalletStateTransition(
949
+ pre_block_balance_updates={
950
+ "xch": {
951
+ "set_remainder": True,
952
+ },
953
+ "did": {
954
+ "init": True,
955
+ "unconfirmed_wallet_balance": 101,
956
+ "pending_change": 101,
957
+ "pending_coin_removal_count": 1,
958
+ },
959
+ },
960
+ post_block_balance_updates={
961
+ "xch": {
962
+ "set_remainder": True,
963
+ },
964
+ "did": {
965
+ "confirmed_wallet_balance": 101,
966
+ "spendable_balance": 101,
967
+ "max_send_amount": 101,
968
+ "unspent_coin_count": 1,
969
+ "pending_change": -101,
970
+ "pending_coin_removal_count": -1,
971
+ },
972
+ },
973
+ ),
974
+ WalletStateTransition(),
975
+ ]
976
+ )
706
977
 
707
978
  await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
708
979
  await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
709
- recovery_list = [bytes.fromhex(did_wallet.get_my_DID())]
980
+ recovery_list = [bytes32.from_hexstr(did_wallet.get_my_DID())]
710
981
 
711
- async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
982
+ async with wallet_1.wallet_state_manager.new_action_scope(
983
+ wallet_environments.tx_config, push=True
984
+ ) as action_scope:
712
985
  did_wallet_2: DIDWallet = await DIDWallet.create_new_did_wallet(
713
- wallet_node_2.wallet_state_manager, wallet2, uint64(101), action_scope, recovery_list
986
+ wallet_node_1.wallet_state_manager, wallet_1, uint64(101), action_scope, recovery_list
714
987
  )
715
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
716
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
717
- await time_out_assert(25, did_wallet_2.get_confirmed_balance, 101)
718
- await time_out_assert(25, did_wallet_2.get_unconfirmed_balance, 101)
988
+ await wallet_environments.process_pending_states(
989
+ [
990
+ WalletStateTransition(),
991
+ WalletStateTransition(
992
+ pre_block_balance_updates={
993
+ "xch": {
994
+ "set_remainder": True,
995
+ },
996
+ "did": {
997
+ "init": True,
998
+ "unconfirmed_wallet_balance": 101,
999
+ "pending_change": 101,
1000
+ "pending_coin_removal_count": 1,
1001
+ },
1002
+ },
1003
+ post_block_balance_updates={
1004
+ "xch": {
1005
+ "set_remainder": True,
1006
+ },
1007
+ "did": {
1008
+ "confirmed_wallet_balance": 101,
1009
+ "spendable_balance": 101,
1010
+ "max_send_amount": 101,
1011
+ "unspent_coin_count": 1,
1012
+ "pending_change": -101,
1013
+ "pending_coin_removal_count": -1,
1014
+ },
1015
+ },
1016
+ ),
1017
+ ]
1018
+ )
1019
+
719
1020
  assert did_wallet_2.did_info.backup_ids == recovery_list
720
1021
 
721
1022
  # Update coin with new ID info
722
- recovery_list = [bytes.fromhex(did_wallet_2.get_my_DID())]
1023
+ recovery_list = [bytes32.from_hexstr(did_wallet_2.get_my_DID())]
723
1024
  await did_wallet.update_recovery_list(recovery_list, uint64(1))
724
1025
  assert did_wallet.did_info.backup_ids == recovery_list
725
- async with did_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1026
+ async with did_wallet.wallet_state_manager.new_action_scope(
1027
+ wallet_environments.tx_config, push=True
1028
+ ) as action_scope:
726
1029
  await did_wallet.create_update_spend(action_scope)
727
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
728
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
729
1030
 
730
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
731
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 101)
1031
+ await wallet_environments.process_pending_states(
1032
+ [
1033
+ WalletStateTransition(
1034
+ pre_block_balance_updates={
1035
+ "did": {
1036
+ "set_remainder": True,
1037
+ }
1038
+ },
1039
+ post_block_balance_updates={
1040
+ "did": {
1041
+ "set_remainder": True,
1042
+ }
1043
+ },
1044
+ ),
1045
+ WalletStateTransition(),
1046
+ ]
1047
+ )
732
1048
 
733
1049
  # DID Wallet 2 recovers into DID Wallet 3 with new innerpuz
734
1050
  backup_data = did_wallet_2.create_backup()
735
1051
 
736
- async with wallet_node.wallet_state_manager.lock:
1052
+ async with wallet_node_0.wallet_state_manager.lock:
737
1053
  did_wallet_3 = await DIDWallet.create_new_did_wallet_from_recovery(
738
- wallet_node.wallet_state_manager,
739
- wallet,
1054
+ wallet_node_0.wallet_state_manager,
1055
+ wallet_0,
740
1056
  backup_data,
741
1057
  )
742
- new_ph = await did_wallet_3.get_new_did_inner_hash()
1058
+ env_0.wallet_aliases["did_2"] = 3
1059
+ new_ph = await did_wallet_3.get_did_inner_hash(new=True)
743
1060
  coin = await did_wallet_2.get_coin()
744
1061
  pubkey = (
745
1062
  await did_wallet_3.wallet_state_manager.get_unused_derivation_record(did_wallet_3.wallet_info.id)
746
1063
  ).pubkey
747
- await time_out_assert(15, did_wallet.get_confirmed_balance, 101)
748
- async with did_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1064
+
1065
+ async with did_wallet.wallet_state_manager.new_action_scope(
1066
+ wallet_environments.tx_config, push=True
1067
+ ) as action_scope:
749
1068
  message_spend_bundle, attest_data = await did_wallet.create_attestment(
750
1069
  coin.name(), new_ph, pubkey, action_scope
751
1070
  )
752
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
753
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1071
+ await wallet_environments.process_pending_states(
1072
+ [
1073
+ WalletStateTransition(
1074
+ pre_block_balance_updates={
1075
+ "did": {
1076
+ "set_remainder": True,
1077
+ },
1078
+ "did_2": {
1079
+ "init": True,
1080
+ "set_remainder": True,
1081
+ },
1082
+ },
1083
+ post_block_balance_updates={
1084
+ "did": {
1085
+ "set_remainder": True,
1086
+ },
1087
+ "did_2": {
1088
+ "set_remainder": True,
1089
+ },
1090
+ },
1091
+ ),
1092
+ WalletStateTransition(),
1093
+ ]
1094
+ )
754
1095
 
755
1096
  (
756
1097
  info,
@@ -758,33 +1099,94 @@ class TestDIDWallet:
758
1099
  ) = await did_wallet_3.load_attest_files_for_recovery_spend([attest_data])
759
1100
  async with did_wallet_3.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
760
1101
  await did_wallet_3.recovery_spend(coin, new_ph, info, pubkey, message_spend_bundle, action_scope)
761
- await full_node_api.process_transaction_records(action_scope.side_effects.transactions)
762
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
763
-
764
- await time_out_assert(15, did_wallet_3.get_confirmed_balance, 101)
765
- await time_out_assert(15, did_wallet_3.get_unconfirmed_balance, 101)
1102
+ await wallet_environments.process_pending_states(
1103
+ [
1104
+ WalletStateTransition(
1105
+ pre_block_balance_updates={
1106
+ "did_2": {
1107
+ "unconfirmed_wallet_balance": 101,
1108
+ "set_remainder": True,
1109
+ },
1110
+ },
1111
+ post_block_balance_updates={
1112
+ "did_2": {
1113
+ "confirmed_wallet_balance": 101,
1114
+ "set_remainder": True,
1115
+ },
1116
+ },
1117
+ ),
1118
+ WalletStateTransition(
1119
+ pre_block_balance_updates={
1120
+ "did": {
1121
+ "unconfirmed_wallet_balance": 0, # TODO: fix pre-block balances for recovery
1122
+ "set_remainder": True,
1123
+ },
1124
+ },
1125
+ post_block_balance_updates={
1126
+ "did": {
1127
+ "confirmed_wallet_balance": -101,
1128
+ "set_remainder": True,
1129
+ },
1130
+ },
1131
+ ),
1132
+ ]
1133
+ )
766
1134
 
767
1135
  # DID Wallet 1 recovery spends into DID Wallet 4
768
1136
  backup_data = did_wallet.create_backup()
769
1137
 
770
- async with wallet_node_2.wallet_state_manager.lock:
1138
+ async with wallet_node_1.wallet_state_manager.lock:
771
1139
  did_wallet_4 = await DIDWallet.create_new_did_wallet_from_recovery(
772
- wallet_node_2.wallet_state_manager,
773
- wallet2,
1140
+ wallet_node_1.wallet_state_manager,
1141
+ wallet_1,
774
1142
  backup_data,
775
1143
  )
1144
+ env_1.wallet_aliases["did_2"] = 3
776
1145
  coin = await did_wallet.get_coin()
777
- new_ph = await did_wallet_4.get_new_did_inner_hash()
1146
+ new_ph = await did_wallet_4.get_did_inner_hash(new=True)
778
1147
  pubkey = (
779
1148
  await did_wallet_4.wallet_state_manager.get_unused_derivation_record(did_wallet_4.wallet_info.id)
780
1149
  ).pubkey
781
- async with did_wallet_3.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1150
+ async with did_wallet_3.wallet_state_manager.new_action_scope(
1151
+ wallet_environments.tx_config, push=True
1152
+ ) as action_scope:
782
1153
  message_spend_bundle, attest1 = await did_wallet_3.create_attestment(
783
1154
  coin.name(), new_ph, pubkey, action_scope
784
1155
  )
785
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
786
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
787
- await time_out_assert(15, wallet.get_pending_change_balance, 0)
1156
+
1157
+ await wallet_environments.process_pending_states(
1158
+ [
1159
+ WalletStateTransition(
1160
+ pre_block_balance_updates={
1161
+ "did_2": {
1162
+ "unconfirmed_wallet_balance": 0,
1163
+ "set_remainder": True,
1164
+ },
1165
+ },
1166
+ post_block_balance_updates={
1167
+ "did_2": {
1168
+ "confirmed_wallet_balance": 0,
1169
+ "set_remainder": True,
1170
+ },
1171
+ },
1172
+ ),
1173
+ WalletStateTransition(
1174
+ pre_block_balance_updates={
1175
+ "did_2": {
1176
+ "init": True,
1177
+ "set_remainder": True,
1178
+ },
1179
+ },
1180
+ post_block_balance_updates={
1181
+ "did_2": {
1182
+ "confirmed_wallet_balance": 0,
1183
+ "set_remainder": True,
1184
+ },
1185
+ },
1186
+ ),
1187
+ ]
1188
+ )
1189
+
788
1190
  (
789
1191
  test_info_list,
790
1192
  test_message_spend_bundle,
@@ -794,27 +1196,186 @@ class TestDIDWallet:
794
1196
  coin, new_ph, test_info_list, pubkey, test_message_spend_bundle, action_scope
795
1197
  )
796
1198
 
797
- await full_node_api.process_transaction_records(action_scope.side_effects.transactions)
798
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1199
+ await wallet_environments.process_pending_states(
1200
+ [
1201
+ WalletStateTransition(
1202
+ pre_block_balance_updates={
1203
+ "did": {
1204
+ "set_remainder": True,
1205
+ },
1206
+ },
1207
+ post_block_balance_updates={
1208
+ "did": {
1209
+ "confirmed_wallet_balance": -101,
1210
+ "set_remainder": True,
1211
+ },
1212
+ },
1213
+ ),
1214
+ WalletStateTransition(
1215
+ pre_block_balance_updates={
1216
+ "did_2": {
1217
+ "set_remainder": True,
1218
+ },
1219
+ },
1220
+ post_block_balance_updates={
1221
+ "did_2": {
1222
+ "confirmed_wallet_balance": 101,
1223
+ "set_remainder": True,
1224
+ },
1225
+ },
1226
+ ),
1227
+ ]
1228
+ )
1229
+
1230
+ for wallet in [did_wallet, did_wallet_3, did_wallet_4]:
1231
+ assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
1232
+
1233
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1234
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
1235
+ @pytest.mark.parametrize(
1236
+ "with_recovery",
1237
+ [True, False],
1238
+ )
1239
+ @pytest.mark.anyio
1240
+ async def test_did_transfer(self, wallet_environments: WalletTestFramework, with_recovery: bool):
1241
+ env_0 = wallet_environments.environments[0]
1242
+ env_1 = wallet_environments.environments[1]
1243
+ wallet_node_0 = env_0.node
1244
+ wallet_node_1 = env_1.node
1245
+ wallet_0 = env_0.xch_wallet
1246
+ wallet_1 = env_1.xch_wallet
1247
+
1248
+ env_0.wallet_aliases = {
1249
+ "xch": 1,
1250
+ "did": 2,
1251
+ }
1252
+ env_1.wallet_aliases = {
1253
+ "xch": 1,
1254
+ "did": 2,
1255
+ }
1256
+ ph = await wallet_0.get_new_puzzlehash()
1257
+ fee = uint64(1000)
1258
+
1259
+ async with wallet_0.wallet_state_manager.new_action_scope(
1260
+ wallet_environments.tx_config, push=True
1261
+ ) as action_scope:
1262
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1263
+ wallet_node_0.wallet_state_manager,
1264
+ wallet_0,
1265
+ uint64(101),
1266
+ action_scope,
1267
+ [ph],
1268
+ uint64(1),
1269
+ {"Twitter": "Test", "GitHub": "测试"},
1270
+ fee=fee,
1271
+ )
1272
+ assert did_wallet_1.get_name() == "Profile 1"
1273
+
1274
+ await wallet_environments.process_pending_states(
1275
+ [
1276
+ WalletStateTransition(
1277
+ pre_block_balance_updates={
1278
+ "xch": {
1279
+ "set_remainder": True,
1280
+ },
1281
+ "did": {
1282
+ "init": True,
1283
+ "unconfirmed_wallet_balance": 101,
1284
+ "pending_change": 101,
1285
+ "pending_coin_removal_count": 1,
1286
+ },
1287
+ },
1288
+ post_block_balance_updates={
1289
+ "xch": {
1290
+ "set_remainder": True,
1291
+ },
1292
+ "did": {
1293
+ "confirmed_wallet_balance": 101,
1294
+ "spendable_balance": 101,
1295
+ "max_send_amount": 101,
1296
+ "unspent_coin_count": 1,
1297
+ "pending_change": -101,
1298
+ "pending_coin_removal_count": -1,
1299
+ },
1300
+ },
1301
+ ),
1302
+ WalletStateTransition(),
1303
+ ]
1304
+ )
1305
+
1306
+ # Transfer DID
1307
+ new_puzhash = await wallet_1.get_new_puzzlehash()
1308
+ async with did_wallet_1.wallet_state_manager.new_action_scope(
1309
+ wallet_environments.tx_config, push=True
1310
+ ) as action_scope:
1311
+ await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, action_scope)
1312
+
1313
+ await wallet_environments.process_pending_states(
1314
+ [
1315
+ WalletStateTransition(
1316
+ pre_block_balance_updates={
1317
+ "xch": {
1318
+ "set_remainder": True,
1319
+ },
1320
+ "did": {
1321
+ "unconfirmed_wallet_balance": -101,
1322
+ "set_remainder": True,
1323
+ },
1324
+ },
1325
+ post_block_balance_updates={
1326
+ "xch": {
1327
+ "set_remainder": True,
1328
+ },
1329
+ },
1330
+ ),
1331
+ WalletStateTransition(
1332
+ pre_block_balance_updates={},
1333
+ post_block_balance_updates={
1334
+ "did": {
1335
+ "init": True,
1336
+ "confirmed_wallet_balance": 101,
1337
+ "set_remainder": True,
1338
+ },
1339
+ },
1340
+ ),
1341
+ ]
1342
+ )
799
1343
 
800
- await time_out_assert(15, did_wallet_4.get_confirmed_balance, 101)
801
- await time_out_assert(15, did_wallet_4.get_unconfirmed_balance, 101)
802
- await time_out_assert(15, did_wallet.get_confirmed_balance, 0)
803
- await time_out_assert(15, did_wallet.get_unconfirmed_balance, 0)
1344
+ # Get the new DID wallet
1345
+ did_wallets = list(
1346
+ filter(
1347
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1348
+ await wallet_node_1.wallet_state_manager.get_all_wallet_info_entries(),
1349
+ )
1350
+ )
1351
+ did_wallet_2 = wallet_node_1.wallet_state_manager.wallets[did_wallets[0].id]
1352
+ assert isinstance(did_wallet_2, DIDWallet) # mypy
1353
+ assert len(wallet_node_0.wallet_state_manager.wallets) == 1
1354
+ assert did_wallet_1.did_info.origin_coin == did_wallet_2.did_info.origin_coin
1355
+ if with_recovery:
1356
+ assert did_wallet_1.did_info.backup_ids[0] == did_wallet_2.did_info.backup_ids[0]
1357
+ assert did_wallet_1.did_info.num_of_backup_ids_needed == did_wallet_2.did_info.num_of_backup_ids_needed
1358
+ metadata = json.loads(did_wallet_2.did_info.metadata)
1359
+ assert metadata["Twitter"] == "Test"
1360
+ assert metadata["GitHub"] == "测试"
804
1361
 
805
- for wallet in [did_wallet, did_wallet_3, did_wallet_4]:
806
- assert wallet.wallet_state_manager.wallets[wallet.id()] == wallet
1362
+ # Test match_hinted_coin
1363
+ assert await did_wallet_2.match_hinted_coin(
1364
+ await did_wallet_2.get_coin(),
1365
+ new_puzhash,
1366
+ )
807
1367
 
808
- @pytest.mark.parametrize(
809
- "with_recovery",
810
- [True, False],
811
- )
812
1368
  @pytest.mark.parametrize(
813
1369
  "trusted",
814
1370
  [True, False],
815
1371
  )
816
1372
  @pytest.mark.anyio
817
- async def test_did_transfer(self, self_hostname, two_wallet_nodes, with_recovery, trusted):
1373
+ async def test_did_auto_transfer_limit(
1374
+ self,
1375
+ self_hostname: str,
1376
+ two_wallet_nodes: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
1377
+ trusted: bool,
1378
+ ) -> None:
818
1379
  fee = uint64(1000)
819
1380
  full_nodes, wallets, _ = two_wallet_nodes
820
1381
  full_node_api = full_nodes[0]
@@ -823,6 +1384,7 @@ class TestDIDWallet:
823
1384
  wallet_node_2, server_3 = wallets[1]
824
1385
  wallet = wallet_node.wallet_state_manager.main_wallet
825
1386
  wallet2 = wallet_node_2.wallet_state_manager.main_wallet
1387
+ api_1 = WalletRpcApi(wallet_node_2)
826
1388
  ph = await wallet.get_new_puzzlehash()
827
1389
 
828
1390
  if trusted:
@@ -840,138 +1402,235 @@ class TestDIDWallet:
840
1402
  await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
841
1403
  await full_node_api.farm_blocks_to_wallet(1, wallet)
842
1404
 
843
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
844
- did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
845
- wallet_node.wallet_state_manager,
846
- wallet,
1405
+ # Check that we cap out at 10 DID Wallets automatically created upon transfer received
1406
+ for i in range(0, 14):
1407
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1408
+ did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1409
+ wallet_node.wallet_state_manager,
1410
+ wallet,
1411
+ uint64(101),
1412
+ action_scope,
1413
+ [bytes32(bytes(ph))],
1414
+ uint64(1),
1415
+ {"Twitter": "Test", "GitHub": "测试"},
1416
+ fee=fee,
1417
+ )
1418
+ assert did_wallet_1.get_name() == "Profile 1"
1419
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1420
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1421
+ await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
1422
+ await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
1423
+ # Transfer DID
1424
+ assert did_wallet_1.did_info.origin_coin is not None
1425
+ origin_coin = did_wallet_1.did_info.origin_coin
1426
+ new_puzhash = await wallet2.get_new_puzzlehash()
1427
+ async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1428
+ await did_wallet_1.transfer_did(new_puzhash, fee, False, action_scope)
1429
+ await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1430
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1431
+ # Check if the DID wallet is created in the wallet2
1432
+
1433
+ await time_out_assert(
1434
+ 30, get_wallet_num, min(2 + i, 11), wallet_node_2.wallet_state_manager
1435
+ ) # check we haven't made more than 10 DID wallets
1436
+ await time_out_assert(30, get_wallet_num, 1, wallet_node.wallet_state_manager)
1437
+ # Get the new DID wallets
1438
+ did_wallets = list(
1439
+ filter(
1440
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1441
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1442
+ )
1443
+ )
1444
+
1445
+ assert len(did_wallets) == 10
1446
+ # Test we can use the DID
1447
+ did_wallet_10 = wallet_node_2.wallet_state_manager.get_wallet(
1448
+ id=uint32(did_wallets[9].id), required_type=DIDWallet
1449
+ )
1450
+ # Delete the coin and change inner puzzle
1451
+ coin = await did_wallet_10.get_coin()
1452
+ # origin_coin = did_wallet_10.did_info.origin_coin
1453
+ backup_data = did_wallet_10.create_backup()
1454
+ await wallet_node_2.wallet_state_manager.coin_store.delete_coin_record(coin.name())
1455
+ await time_out_assert(15, did_wallet_10.get_confirmed_balance, 0)
1456
+ await wallet_node_2.wallet_state_manager.user_store.delete_wallet(did_wallet_10.wallet_info.id)
1457
+ wallet_node_2.wallet_state_manager.wallets.pop(did_wallet_10.wallet_info.id)
1458
+ # Recover the coin
1459
+ async with wallet_node_2.wallet_state_manager.lock:
1460
+ did_wallet_10 = await DIDWallet.create_new_did_wallet_from_recovery(
1461
+ wallet_node_2.wallet_state_manager,
1462
+ wallet2,
1463
+ backup_data,
1464
+ )
1465
+ assert did_wallet_10.did_info.origin_coin is not None
1466
+ resp = await api_1.did_find_lost_did({"coin_id": did_wallet_10.did_info.origin_coin.name().hex()})
1467
+ assert resp["success"]
1468
+ await time_out_assert(15, did_wallet_10.get_confirmed_balance, 101)
1469
+ await time_out_assert(15, did_wallet_10.get_unconfirmed_balance, 101)
1470
+
1471
+ # Check we can recover an auto-discarded DID
1472
+ did_wallet_9 = wallet_node_2.wallet_state_manager.get_wallet(
1473
+ id=uint32(did_wallets[8].id), required_type=DIDWallet
1474
+ )
1475
+ # Delete the coin and wallet to make space for a auto-discarded DID
1476
+ coin = await did_wallet_9.get_coin()
1477
+ await wallet_node_2.wallet_state_manager.coin_store.delete_coin_record(coin.name())
1478
+ await time_out_assert(15, did_wallet_9.get_confirmed_balance, 0)
1479
+ await wallet_node_2.wallet_state_manager.user_store.delete_wallet(did_wallet_9.wallet_info.id)
1480
+ wallet_node_2.wallet_state_manager.wallets.pop(did_wallet_9.wallet_info.id)
1481
+
1482
+ did_wallets = list(
1483
+ filter(
1484
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1485
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1486
+ )
1487
+ )
1488
+ assert len(did_wallets) == 9
1489
+
1490
+ # Try and find lost coin
1491
+ resp = await api_1.did_find_lost_did({"coin_id": origin_coin.name().hex()})
1492
+ did_wallets = list(
1493
+ filter(
1494
+ lambda w: (w.type == WalletType.DECENTRALIZED_ID),
1495
+ await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
1496
+ )
1497
+ )
1498
+ assert len(did_wallets) == 10
1499
+
1500
+ # Check we can still manually add new DIDs while at cap
1501
+ await full_node_api.farm_blocks_to_wallet(1, wallet2)
1502
+ ph = await wallet2.get_new_puzzlehash()
1503
+ async with wallet2.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1504
+ did_wallet_11: DIDWallet = await DIDWallet.create_new_did_wallet(
1505
+ wallet_node_2.wallet_state_manager,
1506
+ wallet2,
847
1507
  uint64(101),
848
1508
  action_scope,
849
- [bytes(ph)],
1509
+ [bytes32(bytes(ph))],
850
1510
  uint64(1),
851
1511
  {"Twitter": "Test", "GitHub": "测试"},
852
1512
  fee=fee,
853
1513
  )
854
- assert did_wallet_1.get_name() == "Profile 1"
855
1514
  await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
856
1515
  await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
857
- await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
858
- await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
859
- # Transfer DID
860
- new_puzhash = await wallet2.get_new_puzzlehash()
861
- async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
862
- await did_wallet_1.transfer_did(new_puzhash, fee, with_recovery, action_scope)
863
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
864
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
865
- # Check if the DID wallet is created in the wallet2
1516
+ await time_out_assert(15, did_wallet_11.get_confirmed_balance, 101)
1517
+ await time_out_assert(15, did_wallet_11.get_unconfirmed_balance, 101)
866
1518
 
867
- await time_out_assert(30, get_wallet_num, 2, wallet_node_2.wallet_state_manager)
868
- await time_out_assert(30, get_wallet_num, 1, wallet_node.wallet_state_manager)
869
- # Get the new DID wallet
870
1519
  did_wallets = list(
871
1520
  filter(
872
1521
  lambda w: (w.type == WalletType.DECENTRALIZED_ID),
873
1522
  await wallet_node_2.wallet_state_manager.get_all_wallet_info_entries(),
874
1523
  )
875
1524
  )
876
- did_wallet_2: Optional[DIDWallet] = wallet_node_2.wallet_state_manager.wallets[did_wallets[0].id]
877
- assert len(wallet_node.wallet_state_manager.wallets) == 1
878
- assert did_wallet_1.did_info.origin_coin == did_wallet_2.did_info.origin_coin
879
- if with_recovery:
880
- assert did_wallet_1.did_info.backup_ids[0] == did_wallet_2.did_info.backup_ids[0]
881
- assert did_wallet_1.did_info.num_of_backup_ids_needed == did_wallet_2.did_info.num_of_backup_ids_needed
882
- metadata = json.loads(did_wallet_2.did_info.metadata)
883
- assert metadata["Twitter"] == "Test"
884
- assert metadata["GitHub"] == "测试"
885
-
886
- # Test match_hinted_coin
887
- assert await did_wallet_2.match_hinted_coin(
888
- await did_wallet_2.get_coin(),
889
- new_puzhash,
890
- )
1525
+ assert len(did_wallets) == 11
891
1526
 
892
- @pytest.mark.parametrize(
893
- "trusted",
894
- [True, False],
895
- )
1527
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1528
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
896
1529
  @pytest.mark.anyio
897
- async def test_update_recovery_list(self, self_hostname, two_wallet_nodes, trusted):
898
- full_nodes, wallets, _ = two_wallet_nodes
899
- full_node_api = full_nodes[0]
900
- server_1 = full_node_api.server
901
- wallet_node, server_2 = wallets[0]
902
- wallet_node_2, server_3 = wallets[1]
903
- wallet = wallet_node.wallet_state_manager.main_wallet
904
- ph = await wallet.get_new_puzzlehash()
1530
+ async def test_update_recovery_list(self, wallet_environments: WalletTestFramework):
1531
+ env = wallet_environments.environments[0]
1532
+ wallet_node = env.node
1533
+ wallet = env.xch_wallet
905
1534
 
906
- if trusted:
907
- wallet_node.config["trusted_peers"] = {
908
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
909
- }
910
- wallet_node_2.config["trusted_peers"] = {
911
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
912
- }
913
- else:
914
- wallet_node.config["trusted_peers"] = {}
915
- wallet_node_2.config["trusted_peers"] = {}
1535
+ env.wallet_aliases = {
1536
+ "xch": 1,
1537
+ "did": 2,
1538
+ }
916
1539
 
917
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
918
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
919
- await full_node_api.farm_blocks_to_wallet(1, wallet)
1540
+ ph = await wallet.get_new_puzzlehash()
920
1541
 
921
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1542
+ async with wallet.wallet_state_manager.new_action_scope(
1543
+ wallet_environments.tx_config, push=True
1544
+ ) as action_scope:
922
1545
  did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
923
1546
  wallet_node.wallet_state_manager, wallet, uint64(101), action_scope, []
924
1547
  )
925
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
926
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
927
- await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
928
- await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
929
- await did_wallet_1.update_recovery_list([bytes(ph)], 1)
930
- async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1548
+
1549
+ await wallet_environments.process_pending_states(
1550
+ [
1551
+ WalletStateTransition(
1552
+ pre_block_balance_updates={
1553
+ "xch": {
1554
+ "set_remainder": True,
1555
+ },
1556
+ "did": {
1557
+ "init": True,
1558
+ "unconfirmed_wallet_balance": 101,
1559
+ "pending_change": 101,
1560
+ "pending_coin_removal_count": 1,
1561
+ },
1562
+ },
1563
+ post_block_balance_updates={
1564
+ "xch": {
1565
+ "set_remainder": True,
1566
+ },
1567
+ "did": {
1568
+ "confirmed_wallet_balance": 101,
1569
+ "spendable_balance": 101,
1570
+ "max_send_amount": 101,
1571
+ "unspent_coin_count": 1,
1572
+ "pending_change": -101,
1573
+ "pending_coin_removal_count": -1,
1574
+ },
1575
+ },
1576
+ ),
1577
+ ]
1578
+ )
1579
+ await did_wallet_1.update_recovery_list([ph], uint64(1))
1580
+ async with did_wallet_1.wallet_state_manager.new_action_scope(
1581
+ wallet_environments.tx_config, push=True
1582
+ ) as action_scope:
931
1583
  await did_wallet_1.create_update_spend(action_scope)
932
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
933
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
934
- await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
935
- await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
1584
+
1585
+ await wallet_environments.process_pending_states(
1586
+ [
1587
+ WalletStateTransition(
1588
+ pre_block_balance_updates={
1589
+ "did": {
1590
+ "set_remainder": True,
1591
+ },
1592
+ },
1593
+ post_block_balance_updates={
1594
+ "did": {
1595
+ "set_remainder": True,
1596
+ },
1597
+ },
1598
+ ),
1599
+ ]
1600
+ )
936
1601
  assert did_wallet_1.did_info.backup_ids[0] == bytes(ph)
937
1602
  assert did_wallet_1.did_info.num_of_backup_ids_needed == 1
938
1603
 
939
- @pytest.mark.parametrize(
940
- "trusted",
941
- [True, False],
942
- )
1604
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1605
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 2, "blocks_needed": [1, 1]}], indirect=True)
943
1606
  @pytest.mark.anyio
944
- async def test_get_info(self, self_hostname, two_wallet_nodes, trusted):
945
- fee = uint64(1000)
946
- full_nodes, wallets, _ = two_wallet_nodes
947
- full_node_api = full_nodes[0]
948
- server_1 = full_node_api.server
949
- wallet_node, server_2 = wallets[0]
950
- wallet_node_2, server_3 = wallets[1]
951
- wallet = wallet_node.wallet_state_manager.main_wallet
952
- wallet1 = wallet_node_2.wallet_state_manager.main_wallet
953
- ph1 = await wallet1.get_new_puzzlehash()
954
- api_0 = WalletRpcApi(wallet_node)
955
- if trusted:
956
- wallet_node.config["trusted_peers"] = {
957
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
958
- }
959
- wallet_node_2.config["trusted_peers"] = {
960
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
961
- }
962
- else:
963
- wallet_node.config["trusted_peers"] = {}
964
- wallet_node_2.config["trusted_peers"] = {}
1607
+ async def test_get_info(self, wallet_environments: WalletTestFramework):
1608
+ env_0 = wallet_environments.environments[0]
1609
+ env_1 = wallet_environments.environments[1]
1610
+ wallet_node_0 = env_0.node
1611
+ wallet_0 = env_0.xch_wallet
1612
+ wallet_1 = env_1.xch_wallet
1613
+ api_0 = env_0.rpc_api
965
1614
 
966
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
967
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
968
- await full_node_api.farm_blocks_to_wallet(count=2, wallet=wallet)
1615
+ env_0.wallet_aliases = {
1616
+ "xch": 1,
1617
+ "did": 2,
1618
+ }
1619
+ env_1.wallet_aliases = {
1620
+ "xch": 1,
1621
+ "did": 2,
1622
+ }
1623
+
1624
+ fee = uint64(1000)
969
1625
  did_amount = uint64(101)
1626
+ ph_1 = await wallet_1.get_new_puzzlehash()
970
1627
 
971
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1628
+ async with wallet_0.wallet_state_manager.new_action_scope(
1629
+ wallet_environments.tx_config, push=True
1630
+ ) as action_scope:
972
1631
  did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
973
- wallet_node.wallet_state_manager,
974
- wallet,
1632
+ wallet_node_0.wallet_state_manager,
1633
+ wallet_0,
975
1634
  did_amount,
976
1635
  action_scope,
977
1636
  [],
@@ -979,14 +1638,42 @@ class TestDIDWallet:
979
1638
  fee=fee,
980
1639
  )
981
1640
 
982
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
983
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=15)
984
-
985
- assert await did_wallet_1.get_confirmed_balance() == did_amount
986
- assert await did_wallet_1.get_unconfirmed_balance() == did_amount
1641
+ await wallet_environments.process_pending_states(
1642
+ [
1643
+ WalletStateTransition(
1644
+ pre_block_balance_updates={
1645
+ "xch": {
1646
+ "set_remainder": True,
1647
+ },
1648
+ "did": {
1649
+ "init": True,
1650
+ "unconfirmed_wallet_balance": did_amount,
1651
+ "pending_change": did_amount,
1652
+ "pending_coin_removal_count": 1,
1653
+ },
1654
+ },
1655
+ post_block_balance_updates={
1656
+ "xch": {
1657
+ "set_remainder": True,
1658
+ },
1659
+ "did": {
1660
+ "confirmed_wallet_balance": did_amount,
1661
+ "spendable_balance": did_amount,
1662
+ "max_send_amount": did_amount,
1663
+ "unspent_coin_count": 1,
1664
+ "pending_change": -did_amount,
1665
+ "pending_coin_removal_count": -1,
1666
+ },
1667
+ },
1668
+ ),
1669
+ WalletStateTransition(),
1670
+ ]
1671
+ )
1672
+ assert did_wallet_1.did_info.origin_coin is not None # mypy
987
1673
  response = await api_0.did_get_info({"coin_id": did_wallet_1.did_info.origin_coin.name().hex()})
988
1674
  assert response["did_id"] == encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value)
989
1675
  assert response["launcher_id"] == did_wallet_1.did_info.origin_coin.name().hex()
1676
+ assert did_wallet_1.did_info.current_inner is not None # mypy
990
1677
  assert response["full_puzzle"].to_program() == create_singleton_puzzle(
991
1678
  did_wallet_1.did_info.current_inner, did_wallet_1.did_info.origin_coin.name()
992
1679
  )
@@ -997,8 +1684,10 @@ class TestDIDWallet:
997
1684
  assert decode_puzzle_hash(response["p2_address"]).hex() == response["hints"][0]
998
1685
 
999
1686
  # Test non-singleton coin
1000
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1001
- coin = (await wallet.select_coins(uint64(1), action_scope)).pop()
1687
+ async with wallet_0.wallet_state_manager.new_action_scope(
1688
+ wallet_environments.tx_config, push=True
1689
+ ) as action_scope:
1690
+ coin = (await wallet_0.select_coins(uint64(1), action_scope)).pop()
1002
1691
  assert coin.amount % 2 == 1
1003
1692
  coin_id = coin.name()
1004
1693
  response = await api_0.did_get_info({"coin_id": coin_id.hex()})
@@ -1006,60 +1695,112 @@ class TestDIDWallet:
1006
1695
 
1007
1696
  # Test multiple odd coins
1008
1697
  odd_amount = uint64(1)
1009
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1698
+ async with wallet_0.wallet_state_manager.new_action_scope(
1699
+ wallet_environments.tx_config, push=True
1700
+ ) as action_scope:
1010
1701
  async with action_scope.use() as interface:
1011
1702
  interface.side_effects.selected_coins.append(coin)
1012
- coin_1 = (await wallet.select_coins(odd_amount, action_scope)).pop()
1703
+ coin_1 = (await wallet_0.select_coins(odd_amount, action_scope)).pop()
1013
1704
  assert coin_1.amount % 2 == 0
1014
- async with wallet.wallet_state_manager.new_action_scope(
1015
- DEFAULT_TX_CONFIG.override(excluded_coin_ids=[coin_id]), push=True
1705
+ async with wallet_0.wallet_state_manager.new_action_scope(
1706
+ wallet_environments.tx_config.override(excluded_coin_ids=[coin_id]), push=True
1016
1707
  ) as action_scope:
1017
- await wallet.generate_signed_transaction(odd_amount, ph1, action_scope, fee)
1018
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1019
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node_2, timeout=15)
1708
+ await wallet_0.generate_signed_transaction(odd_amount, ph_1, action_scope, fee)
1709
+
1710
+ await wallet_environments.process_pending_states(
1711
+ [
1712
+ WalletStateTransition(
1713
+ pre_block_balance_updates={
1714
+ "xch": {
1715
+ "unconfirmed_wallet_balance": -odd_amount - fee,
1716
+ "set_remainder": True,
1717
+ },
1718
+ "did": {
1719
+ "set_remainder": True,
1720
+ },
1721
+ },
1722
+ post_block_balance_updates={
1723
+ "xch": {
1724
+ "confirmed_wallet_balance": -odd_amount - fee,
1725
+ "set_remainder": True,
1726
+ },
1727
+ "did": {
1728
+ "set_remainder": True,
1729
+ },
1730
+ },
1731
+ ),
1732
+ WalletStateTransition(
1733
+ pre_block_balance_updates={
1734
+ "xch": {
1735
+ "unconfirmed_wallet_balance": 0,
1736
+ "set_remainder": True,
1737
+ }
1738
+ },
1739
+ post_block_balance_updates={
1740
+ "xch": {
1741
+ "confirmed_wallet_balance": odd_amount,
1742
+ "set_remainder": True,
1743
+ }
1744
+ },
1745
+ ),
1746
+ ]
1747
+ )
1020
1748
 
1021
- assert await wallet1.get_confirmed_balance() == odd_amount
1022
1749
  with pytest.raises(ValueError):
1023
1750
  await api_0.did_get_info({"coin_id": coin_1.name().hex()})
1024
1751
 
1025
- @pytest.mark.parametrize(
1026
- "trusted",
1027
- [True, False],
1028
- )
1752
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1753
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1029
1754
  @pytest.mark.anyio
1030
- async def test_message_spend(self, self_hostname, two_wallet_nodes, trusted):
1031
- fee = uint64(1000)
1032
- full_nodes, wallets, _ = two_wallet_nodes
1033
- full_node_api = full_nodes[0]
1034
- server_1 = full_node_api.server
1035
- wallet_node, server_2 = wallets[0]
1036
- wallet_node_2, server_3 = wallets[1]
1037
- wallet = wallet_node.wallet_state_manager.main_wallet
1038
- api_0 = WalletRpcApi(wallet_node)
1039
- if trusted:
1040
- wallet_node.config["trusted_peers"] = {
1041
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1042
- }
1043
- wallet_node_2.config["trusted_peers"] = {
1044
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1045
- }
1046
- else:
1047
- wallet_node.config["trusted_peers"] = {}
1048
- wallet_node_2.config["trusted_peers"] = {}
1755
+ async def test_message_spend(self, wallet_environments: WalletTestFramework):
1756
+ env = wallet_environments.environments[0]
1757
+ wallet_node = env.node
1758
+ wallet = env.xch_wallet
1759
+ api_0 = env.rpc_api
1049
1760
 
1050
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1051
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1761
+ env.wallet_aliases = {
1762
+ "xch": 1,
1763
+ "did": 2,
1764
+ }
1052
1765
 
1053
- await full_node_api.farm_blocks_to_wallet(1, wallet)
1766
+ fee = uint64(1000)
1054
1767
 
1055
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1768
+ async with wallet.wallet_state_manager.new_action_scope(
1769
+ wallet_environments.tx_config, push=True
1770
+ ) as action_scope:
1056
1771
  did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1057
1772
  wallet_node.wallet_state_manager, wallet, uint64(101), action_scope, [], fee=fee
1058
1773
  )
1059
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1060
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1061
- await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
1062
- await time_out_assert(15, did_wallet_1.get_unconfirmed_balance, 101)
1774
+ await wallet_environments.process_pending_states(
1775
+ [
1776
+ WalletStateTransition(
1777
+ pre_block_balance_updates={
1778
+ "xch": {
1779
+ "set_remainder": True,
1780
+ },
1781
+ "did": {
1782
+ "init": True,
1783
+ "unconfirmed_wallet_balance": 101,
1784
+ "pending_change": 101,
1785
+ "pending_coin_removal_count": 1,
1786
+ },
1787
+ },
1788
+ post_block_balance_updates={
1789
+ "xch": {
1790
+ "set_remainder": True,
1791
+ },
1792
+ "did": {
1793
+ "confirmed_wallet_balance": 101,
1794
+ "spendable_balance": 101,
1795
+ "max_send_amount": 101,
1796
+ "unspent_coin_count": 1,
1797
+ "pending_change": -101,
1798
+ "pending_coin_removal_count": -1,
1799
+ },
1800
+ },
1801
+ ),
1802
+ ]
1803
+ )
1063
1804
  response = await api_0.did_message_spend(
1064
1805
  {"wallet_id": did_wallet_1.wallet_id, "coin_announcements": ["0abc"], "puzzle_announcements": ["0def"]}
1065
1806
  )
@@ -1073,125 +1814,174 @@ class TestDIDWallet:
1073
1814
  assert len(conditions[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT]) == 1
1074
1815
  assert conditions[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT][0].vars[0].hex() == "0def"
1075
1816
 
1076
- @pytest.mark.parametrize(
1077
- "trusted",
1078
- [True, False],
1079
- )
1817
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1818
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1080
1819
  @pytest.mark.anyio
1081
- async def test_update_metadata(self, self_hostname, two_wallet_nodes, trusted):
1082
- fee = uint64(1000)
1083
- full_nodes, wallets, _ = two_wallet_nodes
1084
- full_node_api = full_nodes[0]
1085
- server_1 = full_node_api.server
1086
- wallet_node, server_2 = wallets[0]
1087
- wallet_node_2, server_3 = wallets[1]
1088
- wallet = wallet_node.wallet_state_manager.main_wallet
1089
- if trusted:
1090
- wallet_node.config["trusted_peers"] = {
1091
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1092
- }
1093
- wallet_node_2.config["trusted_peers"] = {
1094
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1095
- }
1096
- else:
1097
- wallet_node.config["trusted_peers"] = {}
1098
- wallet_node_2.config["trusted_peers"] = {}
1820
+ async def test_update_metadata(self, wallet_environments: WalletTestFramework):
1821
+ env = wallet_environments.environments[0]
1822
+ wallet_node = env.node
1823
+ wallet = env.xch_wallet
1099
1824
 
1100
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1101
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1102
- expected_confirmed_balance = await full_node_api.farm_blocks_to_wallet(count=2, wallet=wallet)
1825
+ env.wallet_aliases = {
1826
+ "xch": 1,
1827
+ "did": 2,
1828
+ }
1829
+
1830
+ fee = uint64(1000)
1103
1831
  did_amount = uint64(101)
1104
1832
 
1105
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1833
+ async with wallet.wallet_state_manager.new_action_scope(
1834
+ wallet_environments.tx_config, push=True
1835
+ ) as action_scope:
1106
1836
  did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1107
1837
  wallet_node.wallet_state_manager, wallet, did_amount, action_scope, [], fee=fee
1108
1838
  )
1109
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1110
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=15)
1111
1839
 
1112
- expected_confirmed_balance -= did_amount + fee
1113
- assert await did_wallet_1.get_confirmed_balance() == did_amount
1114
- assert await did_wallet_1.get_unconfirmed_balance() == did_amount
1115
- assert await wallet.get_confirmed_balance() == expected_confirmed_balance
1116
- assert await wallet.get_unconfirmed_balance() == expected_confirmed_balance
1840
+ await wallet_environments.process_pending_states(
1841
+ [
1842
+ WalletStateTransition(
1843
+ pre_block_balance_updates={
1844
+ "xch": {
1845
+ "set_remainder": True,
1846
+ },
1847
+ "did": {
1848
+ "init": True,
1849
+ "unconfirmed_wallet_balance": 101,
1850
+ "pending_change": 101,
1851
+ "pending_coin_removal_count": 1,
1852
+ },
1853
+ },
1854
+ post_block_balance_updates={
1855
+ "xch": {
1856
+ "set_remainder": True,
1857
+ },
1858
+ "did": {
1859
+ "confirmed_wallet_balance": 101,
1860
+ "spendable_balance": 101,
1861
+ "max_send_amount": 101,
1862
+ "unspent_coin_count": 1,
1863
+ "pending_change": -101,
1864
+ "pending_coin_removal_count": -1,
1865
+ },
1866
+ },
1867
+ ),
1868
+ ]
1869
+ )
1870
+
1871
+ assert did_wallet_1.did_info.current_inner is not None # mypy
1117
1872
  puzhash = did_wallet_1.did_info.current_inner.get_tree_hash()
1118
1873
  parent_num = get_parent_num(did_wallet_1)
1119
1874
 
1120
1875
  bad_metadata = {"Twitter": {"url": "http://www.twitter.com"}}
1121
1876
  with pytest.raises(ValueError) as e:
1122
- await did_wallet_1.update_metadata(bad_metadata)
1877
+ await did_wallet_1.update_metadata(bad_metadata) # type: ignore
1123
1878
  assert e.match("Metadata key value pairs must be strings.")
1124
1879
 
1125
1880
  metadata = {}
1126
1881
  metadata["Twitter"] = "http://www.twitter.com"
1127
1882
  await did_wallet_1.update_metadata(metadata)
1128
- async with did_wallet_1.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1883
+ async with did_wallet_1.wallet_state_manager.new_action_scope(
1884
+ wallet_environments.tx_config, push=True
1885
+ ) as action_scope:
1129
1886
  await did_wallet_1.create_update_spend(action_scope, fee)
1130
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1131
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1132
-
1133
- expected_confirmed_balance -= fee
1134
-
1135
- await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=15)
1136
1887
 
1137
- assert await did_wallet_1.get_confirmed_balance() == did_amount
1138
- assert await did_wallet_1.get_unconfirmed_balance() == did_amount
1888
+ await wallet_environments.process_pending_states(
1889
+ [
1890
+ WalletStateTransition(
1891
+ pre_block_balance_updates={
1892
+ "xch": {
1893
+ "unconfirmed_wallet_balance": -fee,
1894
+ "set_remainder": True,
1895
+ },
1896
+ "did": {
1897
+ "unconfirmed_wallet_balance": 0,
1898
+ "set_remainder": True,
1899
+ },
1900
+ },
1901
+ post_block_balance_updates={
1902
+ "xch": {
1903
+ "confirmed_wallet_balance": -fee,
1904
+ "set_remainder": True,
1905
+ },
1906
+ "did": {
1907
+ "confirmed_wallet_balance": 0,
1908
+ "set_remainder": True,
1909
+ },
1910
+ },
1911
+ ),
1912
+ ]
1913
+ )
1139
1914
 
1140
1915
  assert get_parent_num(did_wallet_1) == parent_num + 2
1916
+ assert did_wallet_1.did_info.current_inner is not None # mypy
1141
1917
  assert puzhash != did_wallet_1.did_info.current_inner.get_tree_hash()
1142
- assert await wallet.get_confirmed_balance() == expected_confirmed_balance
1143
- assert await wallet.get_unconfirmed_balance() == expected_confirmed_balance
1144
-
1145
1918
  assert did_wallet_1.did_info.metadata.find("Twitter") > 0
1146
1919
 
1147
- @pytest.mark.parametrize(
1148
- "trusted",
1149
- [True, False],
1150
- )
1920
+ @pytest.mark.limit_consensus_modes(allowed=[ConsensusMode.PLAIN], reason="irrelevant")
1921
+ @pytest.mark.parametrize("wallet_environments", [{"num_environments": 1, "blocks_needed": [1]}], indirect=True)
1151
1922
  @pytest.mark.anyio
1152
- async def test_did_sign_message(self, self_hostname, two_wallet_nodes, trusted):
1923
+ async def test_did_sign_message(self, wallet_environments: WalletTestFramework):
1924
+ env = wallet_environments.environments[0]
1925
+ wallet_node = env.node
1926
+ wallet = env.xch_wallet
1927
+ api_0 = env.rpc_api
1928
+
1929
+ env.wallet_aliases = {
1930
+ "xch": 1,
1931
+ "did": 2,
1932
+ }
1153
1933
  fee = uint64(1000)
1154
- full_nodes, wallets, _ = two_wallet_nodes
1155
- full_node_api = full_nodes[0]
1156
- server_1 = full_node_api.server
1157
- wallet_node, server_2 = wallets[0]
1158
- wallet_node_2, server_3 = wallets[1]
1159
- wallet = wallet_node.wallet_state_manager.main_wallet
1160
- api_0 = WalletRpcApi(wallet_node)
1161
1934
  ph = await wallet.get_new_puzzlehash()
1162
1935
 
1163
- if trusted:
1164
- wallet_node.config["trusted_peers"] = {
1165
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1166
- }
1167
- wallet_node_2.config["trusted_peers"] = {
1168
- full_node_api.full_node.server.node_id.hex(): full_node_api.full_node.server.node_id.hex()
1169
- }
1170
- else:
1171
- wallet_node.config["trusted_peers"] = {}
1172
- wallet_node_2.config["trusted_peers"] = {}
1173
-
1174
- await server_2.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1175
- await server_3.start_client(PeerInfo(self_hostname, server_1.get_port()), None)
1176
- await full_node_api.farm_blocks_to_wallet(1, wallet)
1177
-
1178
- async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1936
+ async with wallet.wallet_state_manager.new_action_scope(
1937
+ wallet_environments.tx_config, push=True
1938
+ ) as action_scope:
1179
1939
  did_wallet_1: DIDWallet = await DIDWallet.create_new_did_wallet(
1180
1940
  wallet_node.wallet_state_manager,
1181
1941
  wallet,
1182
1942
  uint64(101),
1183
1943
  action_scope,
1184
- [bytes(ph)],
1944
+ [ph],
1185
1945
  uint64(1),
1186
1946
  {"Twitter": "Test", "GitHub": "测试"},
1187
1947
  fee=fee,
1188
1948
  )
1189
1949
  assert did_wallet_1.get_name() == "Profile 1"
1190
- await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
1191
- await full_node_api.wait_for_wallets_synced(wallet_nodes=[wallet_node, wallet_node_2])
1192
- await time_out_assert(15, did_wallet_1.get_confirmed_balance, 101)
1950
+
1951
+ await wallet_environments.process_pending_states(
1952
+ [
1953
+ WalletStateTransition(
1954
+ pre_block_balance_updates={
1955
+ "xch": {
1956
+ "set_remainder": True,
1957
+ },
1958
+ "did": {
1959
+ "init": True,
1960
+ "unconfirmed_wallet_balance": 101,
1961
+ "pending_change": 101,
1962
+ "pending_coin_removal_count": 1,
1963
+ },
1964
+ },
1965
+ post_block_balance_updates={
1966
+ "xch": {
1967
+ "set_remainder": True,
1968
+ },
1969
+ "did": {
1970
+ "confirmed_wallet_balance": 101,
1971
+ "spendable_balance": 101,
1972
+ "max_send_amount": 101,
1973
+ "unspent_coin_count": 1,
1974
+ "pending_change": -101,
1975
+ "pending_coin_removal_count": -1,
1976
+ },
1977
+ },
1978
+ ),
1979
+ ]
1980
+ )
1193
1981
  # Test general string
1982
+ assert did_wallet_1.did_info.origin_coin is not None # mypy
1194
1983
  message = "Hello World"
1984
+ assert did_wallet_1.did_info.origin_coin is not None
1195
1985
  response = await api_0.sign_message_by_id(
1196
1986
  {
1197
1987
  "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
@@ -1213,7 +2003,7 @@ class TestDIDWallet:
1213
2003
  "is_hex": True,
1214
2004
  }
1215
2005
  )
1216
- puzzle: Program = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message)))
2006
+ puzzle = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message)))
1217
2007
 
1218
2008
  assert AugSchemeMPL.verify(
1219
2009
  G1Element.from_bytes(bytes.fromhex(response["pubkey"])),
@@ -1223,6 +2013,7 @@ class TestDIDWallet:
1223
2013
 
1224
2014
  # Test BLS sign string
1225
2015
  message = "Hello World"
2016
+ assert did_wallet_1.did_info.origin_coin is not None
1226
2017
  response = await api_0.sign_message_by_id(
1227
2018
  {
1228
2019
  "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
@@ -1239,6 +2030,7 @@ class TestDIDWallet:
1239
2030
  )
1240
2031
  # Test BLS sign hex
1241
2032
  message = "0123456789ABCDEF"
2033
+ assert did_wallet_1.did_info.origin_coin is not None
1242
2034
  response = await api_0.sign_message_by_id(
1243
2035
  {
1244
2036
  "id": encode_puzzle_hash(did_wallet_1.did_info.origin_coin.name(), AddressType.DID.value),
@@ -1259,7 +2051,9 @@ class TestDIDWallet:
1259
2051
  [True, False],
1260
2052
  )
1261
2053
  @pytest.mark.anyio
1262
- async def test_create_did_with_recovery_list(self, self_hostname, two_nodes_two_wallets_with_same_keys, trusted):
2054
+ async def test_create_did_with_recovery_list(
2055
+ self, self_hostname: str, two_nodes_two_wallets_with_same_keys: OldSimulatorsAndWallets, trusted: bool
2056
+ ) -> None:
1263
2057
  """
1264
2058
  A DID is created on-chain in client0, causing a DID Wallet to be created in client1, which shares the same key.
1265
2059
  This can happen if someone uses the same key on multiple computers, or is syncing a wallet from scratch.
@@ -1303,7 +2097,7 @@ class TestDIDWallet:
1303
2097
 
1304
2098
  # Node 0 sets up a DID Wallet with a backup set, but num_of_backup_ids_needed=0
1305
2099
  # (a malformed solution, but legal for the clvm puzzle)
1306
- recovery_list = [bytes.fromhex("00" * 32)]
2100
+ recovery_list = [bytes32(bytes.fromhex("00" * 32))]
1307
2101
  async with wallet_0.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1308
2102
  did_wallet_0: DIDWallet = await DIDWallet.create_new_did_wallet(
1309
2103
  wallet_node_0.wallet_state_manager,
@@ -1311,7 +2105,7 @@ class TestDIDWallet:
1311
2105
  uint64(101),
1312
2106
  action_scope,
1313
2107
  backups_ids=recovery_list,
1314
- num_of_backup_ids_needed=0,
2108
+ num_of_backup_ids_needed=uint64(0),
1315
2109
  )
1316
2110
 
1317
2111
  await full_node_api.process_transaction_records(records=action_scope.side_effects.transactions)
@@ -1336,12 +2130,19 @@ class TestDIDWallet:
1336
2130
  # == json.loads(all_node_1_wallets[1].data)["current_inner"]
1337
2131
  # )
1338
2132
 
2133
+ # TODO: See Issue CHIA-1544
2134
+ # This test should be ported to WalletTestFramework once we can replace keys in the wallet node
1339
2135
  @pytest.mark.parametrize(
1340
2136
  "trusted",
1341
2137
  [True, False],
1342
2138
  )
1343
2139
  @pytest.mark.anyio
1344
- async def test_did_resync(self, self_hostname, two_wallet_nodes, trusted) -> None:
2140
+ async def test_did_resync(
2141
+ self,
2142
+ self_hostname: str,
2143
+ two_wallet_nodes: tuple[list[FullNodeSimulator], list[tuple[WalletNode, ChiaServer]], BlockTools],
2144
+ trusted: bool,
2145
+ ) -> None:
1345
2146
  full_nodes, wallets, _ = two_wallet_nodes
1346
2147
  full_node_api = full_nodes[0]
1347
2148
  full_node_server = full_node_api.full_node.server
@@ -1359,6 +2160,7 @@ class TestDIDWallet:
1359
2160
  else:
1360
2161
  wallet_node_1.config["trusted_peers"] = {}
1361
2162
  wallet_node_2.config["trusted_peers"] = {}
2163
+ assert full_node_server._port is not None
1362
2164
  await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
1363
2165
  await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
1364
2166
  await full_node_api.farm_blocks_to_wallet(1, wallet)
@@ -1408,6 +2210,7 @@ class TestDIDWallet:
1408
2210
  # Start resync
1409
2211
  await wallet_node_1._start_with_fingerprint(fingerprint_1)
1410
2212
  await wallet_node_2._start_with_fingerprint(fingerprint_2)
2213
+ assert full_node_server._port is not None
1411
2214
  await wallet_server_1.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
1412
2215
  await wallet_server_2.start_client(PeerInfo(self_hostname, uint16(full_node_server._port)), None)
1413
2216
  await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32(b"\00" * 32)))