chia-blockchain 2.5.1rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1042) hide show
  1. chia/__init__.py +10 -0
  2. chia/__main__.py +5 -0
  3. chia/_tests/README.md +53 -0
  4. chia/_tests/__init__.py +0 -0
  5. chia/_tests/blockchain/__init__.py +0 -0
  6. chia/_tests/blockchain/blockchain_test_utils.py +195 -0
  7. chia/_tests/blockchain/config.py +4 -0
  8. chia/_tests/blockchain/test_augmented_chain.py +145 -0
  9. chia/_tests/blockchain/test_blockchain.py +4202 -0
  10. chia/_tests/blockchain/test_blockchain_transactions.py +1031 -0
  11. chia/_tests/blockchain/test_build_chains.py +59 -0
  12. chia/_tests/blockchain/test_get_block_generator.py +72 -0
  13. chia/_tests/blockchain/test_lookup_fork_chain.py +194 -0
  14. chia/_tests/build-init-files.py +92 -0
  15. chia/_tests/build-job-matrix.py +204 -0
  16. chia/_tests/check_pytest_monitor_output.py +34 -0
  17. chia/_tests/check_sql_statements.py +72 -0
  18. chia/_tests/chia-start-sim +42 -0
  19. chia/_tests/clvm/__init__.py +0 -0
  20. chia/_tests/clvm/benchmark_costs.py +23 -0
  21. chia/_tests/clvm/coin_store.py +149 -0
  22. chia/_tests/clvm/test_chialisp_deserialization.py +101 -0
  23. chia/_tests/clvm/test_clvm_step.py +37 -0
  24. chia/_tests/clvm/test_condition_codes.py +13 -0
  25. chia/_tests/clvm/test_curry_and_treehash.py +55 -0
  26. chia/_tests/clvm/test_message_conditions.py +184 -0
  27. chia/_tests/clvm/test_program.py +150 -0
  28. chia/_tests/clvm/test_puzzle_compression.py +143 -0
  29. chia/_tests/clvm/test_puzzle_drivers.py +45 -0
  30. chia/_tests/clvm/test_puzzles.py +242 -0
  31. chia/_tests/clvm/test_singletons.py +540 -0
  32. chia/_tests/clvm/test_spend_sim.py +181 -0
  33. chia/_tests/cmds/__init__.py +0 -0
  34. chia/_tests/cmds/cmd_test_utils.py +469 -0
  35. chia/_tests/cmds/config.py +3 -0
  36. chia/_tests/cmds/conftest.py +23 -0
  37. chia/_tests/cmds/test_click_types.py +200 -0
  38. chia/_tests/cmds/test_cmd_framework.py +620 -0
  39. chia/_tests/cmds/test_cmds_util.py +97 -0
  40. chia/_tests/cmds/test_daemon.py +92 -0
  41. chia/_tests/cmds/test_dev_gh.py +131 -0
  42. chia/_tests/cmds/test_farm_cmd.py +66 -0
  43. chia/_tests/cmds/test_show.py +116 -0
  44. chia/_tests/cmds/test_sim.py +207 -0
  45. chia/_tests/cmds/test_timelock_args.py +75 -0
  46. chia/_tests/cmds/test_tx_config_args.py +154 -0
  47. chia/_tests/cmds/testing_classes.py +59 -0
  48. chia/_tests/cmds/wallet/__init__.py +0 -0
  49. chia/_tests/cmds/wallet/test_consts.py +47 -0
  50. chia/_tests/cmds/wallet/test_dao.py +565 -0
  51. chia/_tests/cmds/wallet/test_did.py +403 -0
  52. chia/_tests/cmds/wallet/test_nft.py +471 -0
  53. chia/_tests/cmds/wallet/test_notifications.py +124 -0
  54. chia/_tests/cmds/wallet/test_offer.toffer +1 -0
  55. chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
  56. chia/_tests/cmds/wallet/test_vcs.py +400 -0
  57. chia/_tests/cmds/wallet/test_wallet.py +1125 -0
  58. chia/_tests/cmds/wallet/test_wallet_check.py +109 -0
  59. chia/_tests/conftest.py +1419 -0
  60. chia/_tests/connection_utils.py +125 -0
  61. chia/_tests/core/__init__.py +0 -0
  62. chia/_tests/core/cmds/__init__.py +0 -0
  63. chia/_tests/core/cmds/test_beta.py +382 -0
  64. chia/_tests/core/cmds/test_keys.py +1734 -0
  65. chia/_tests/core/cmds/test_wallet.py +126 -0
  66. chia/_tests/core/config.py +3 -0
  67. chia/_tests/core/consensus/__init__.py +0 -0
  68. chia/_tests/core/consensus/test_block_creation.py +54 -0
  69. chia/_tests/core/consensus/test_pot_iterations.py +117 -0
  70. chia/_tests/core/custom_types/__init__.py +0 -0
  71. chia/_tests/core/custom_types/test_coin.py +107 -0
  72. chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
  73. chia/_tests/core/custom_types/test_spend_bundle.py +70 -0
  74. chia/_tests/core/daemon/__init__.py +0 -0
  75. chia/_tests/core/daemon/config.py +4 -0
  76. chia/_tests/core/daemon/test_daemon.py +2128 -0
  77. chia/_tests/core/daemon/test_daemon_register.py +109 -0
  78. chia/_tests/core/daemon/test_keychain_proxy.py +101 -0
  79. chia/_tests/core/data_layer/__init__.py +0 -0
  80. chia/_tests/core/data_layer/config.py +5 -0
  81. chia/_tests/core/data_layer/conftest.py +106 -0
  82. chia/_tests/core/data_layer/test_data_cli.py +56 -0
  83. chia/_tests/core/data_layer/test_data_layer.py +83 -0
  84. chia/_tests/core/data_layer/test_data_layer_util.py +218 -0
  85. chia/_tests/core/data_layer/test_data_rpc.py +3847 -0
  86. chia/_tests/core/data_layer/test_data_store.py +2424 -0
  87. chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
  88. chia/_tests/core/data_layer/test_plugin.py +91 -0
  89. chia/_tests/core/data_layer/util.py +233 -0
  90. chia/_tests/core/farmer/__init__.py +0 -0
  91. chia/_tests/core/farmer/config.py +3 -0
  92. chia/_tests/core/farmer/test_farmer_api.py +103 -0
  93. chia/_tests/core/full_node/__init__.py +0 -0
  94. chia/_tests/core/full_node/config.py +4 -0
  95. chia/_tests/core/full_node/dos/__init__.py +0 -0
  96. chia/_tests/core/full_node/dos/config.py +3 -0
  97. chia/_tests/core/full_node/full_sync/__init__.py +0 -0
  98. chia/_tests/core/full_node/full_sync/config.py +4 -0
  99. chia/_tests/core/full_node/full_sync/test_full_sync.py +443 -0
  100. chia/_tests/core/full_node/ram_db.py +27 -0
  101. chia/_tests/core/full_node/stores/__init__.py +0 -0
  102. chia/_tests/core/full_node/stores/config.py +4 -0
  103. chia/_tests/core/full_node/stores/test_block_store.py +590 -0
  104. chia/_tests/core/full_node/stores/test_coin_store.py +897 -0
  105. chia/_tests/core/full_node/stores/test_full_node_store.py +1219 -0
  106. chia/_tests/core/full_node/stores/test_hint_store.py +229 -0
  107. chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
  108. chia/_tests/core/full_node/test_address_manager.py +588 -0
  109. chia/_tests/core/full_node/test_block_height_map.py +556 -0
  110. chia/_tests/core/full_node/test_conditions.py +556 -0
  111. chia/_tests/core/full_node/test_full_node.py +2700 -0
  112. chia/_tests/core/full_node/test_generator_tools.py +82 -0
  113. chia/_tests/core/full_node/test_hint_management.py +104 -0
  114. chia/_tests/core/full_node/test_node_load.py +34 -0
  115. chia/_tests/core/full_node/test_performance.py +179 -0
  116. chia/_tests/core/full_node/test_subscriptions.py +492 -0
  117. chia/_tests/core/full_node/test_transactions.py +203 -0
  118. chia/_tests/core/full_node/test_tx_processing_queue.py +155 -0
  119. chia/_tests/core/large_block.py +2388 -0
  120. chia/_tests/core/make_block_generator.py +70 -0
  121. chia/_tests/core/mempool/__init__.py +0 -0
  122. chia/_tests/core/mempool/config.py +4 -0
  123. chia/_tests/core/mempool/test_mempool.py +3255 -0
  124. chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
  125. chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
  126. chia/_tests/core/mempool/test_mempool_item_queries.py +190 -0
  127. chia/_tests/core/mempool/test_mempool_manager.py +2084 -0
  128. chia/_tests/core/mempool/test_mempool_performance.py +64 -0
  129. chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
  130. chia/_tests/core/node_height.py +28 -0
  131. chia/_tests/core/server/__init__.py +0 -0
  132. chia/_tests/core/server/config.py +3 -0
  133. chia/_tests/core/server/flood.py +84 -0
  134. chia/_tests/core/server/serve.py +135 -0
  135. chia/_tests/core/server/test_api_protocol.py +21 -0
  136. chia/_tests/core/server/test_capabilities.py +66 -0
  137. chia/_tests/core/server/test_dos.py +319 -0
  138. chia/_tests/core/server/test_event_loop.py +109 -0
  139. chia/_tests/core/server/test_loop.py +294 -0
  140. chia/_tests/core/server/test_node_discovery.py +73 -0
  141. chia/_tests/core/server/test_rate_limits.py +482 -0
  142. chia/_tests/core/server/test_server.py +226 -0
  143. chia/_tests/core/server/test_upnp.py +8 -0
  144. chia/_tests/core/services/__init__.py +0 -0
  145. chia/_tests/core/services/config.py +3 -0
  146. chia/_tests/core/services/test_services.py +188 -0
  147. chia/_tests/core/ssl/__init__.py +0 -0
  148. chia/_tests/core/ssl/config.py +3 -0
  149. chia/_tests/core/ssl/test_ssl.py +202 -0
  150. chia/_tests/core/test_coins.py +33 -0
  151. chia/_tests/core/test_cost_calculation.py +313 -0
  152. chia/_tests/core/test_crawler.py +175 -0
  153. chia/_tests/core/test_crawler_rpc.py +53 -0
  154. chia/_tests/core/test_daemon_rpc.py +24 -0
  155. chia/_tests/core/test_db_conversion.py +130 -0
  156. chia/_tests/core/test_db_validation.py +162 -0
  157. chia/_tests/core/test_farmer_harvester_rpc.py +505 -0
  158. chia/_tests/core/test_filter.py +35 -0
  159. chia/_tests/core/test_full_node_rpc.py +768 -0
  160. chia/_tests/core/test_merkle_set.py +343 -0
  161. chia/_tests/core/test_program.py +47 -0
  162. chia/_tests/core/test_rpc_util.py +86 -0
  163. chia/_tests/core/test_seeder.py +420 -0
  164. chia/_tests/core/test_setproctitle.py +13 -0
  165. chia/_tests/core/util/__init__.py +0 -0
  166. chia/_tests/core/util/config.py +4 -0
  167. chia/_tests/core/util/test_block_cache.py +44 -0
  168. chia/_tests/core/util/test_cached_bls.py +57 -0
  169. chia/_tests/core/util/test_config.py +337 -0
  170. chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
  171. chia/_tests/core/util/test_files.py +391 -0
  172. chia/_tests/core/util/test_jsonify.py +146 -0
  173. chia/_tests/core/util/test_keychain.py +522 -0
  174. chia/_tests/core/util/test_keyring_wrapper.py +491 -0
  175. chia/_tests/core/util/test_lockfile.py +380 -0
  176. chia/_tests/core/util/test_log_exceptions.py +187 -0
  177. chia/_tests/core/util/test_lru_cache.py +56 -0
  178. chia/_tests/core/util/test_significant_bits.py +40 -0
  179. chia/_tests/core/util/test_streamable.py +883 -0
  180. chia/_tests/db/__init__.py +0 -0
  181. chia/_tests/db/test_db_wrapper.py +566 -0
  182. chia/_tests/environments/__init__.py +0 -0
  183. chia/_tests/environments/common.py +35 -0
  184. chia/_tests/environments/full_node.py +47 -0
  185. chia/_tests/environments/wallet.py +429 -0
  186. chia/_tests/ether.py +19 -0
  187. chia/_tests/farmer_harvester/__init__.py +0 -0
  188. chia/_tests/farmer_harvester/config.py +3 -0
  189. chia/_tests/farmer_harvester/test_farmer.py +1264 -0
  190. chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
  191. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +131 -0
  192. chia/_tests/farmer_harvester/test_third_party_harvesters.py +528 -0
  193. chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
  194. chia/_tests/fee_estimation/__init__.py +0 -0
  195. chia/_tests/fee_estimation/config.py +3 -0
  196. chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
  197. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
  198. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +144 -0
  199. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
  200. chia/_tests/generator/__init__.py +0 -0
  201. chia/_tests/generator/puzzles/__init__.py +0 -0
  202. chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
  203. chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
  204. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
  205. chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
  206. chia/_tests/generator/test_compression.py +201 -0
  207. chia/_tests/generator/test_generator_types.py +44 -0
  208. chia/_tests/generator/test_rom.py +180 -0
  209. chia/_tests/plot_sync/__init__.py +0 -0
  210. chia/_tests/plot_sync/config.py +3 -0
  211. chia/_tests/plot_sync/test_delta.py +101 -0
  212. chia/_tests/plot_sync/test_plot_sync.py +618 -0
  213. chia/_tests/plot_sync/test_receiver.py +451 -0
  214. chia/_tests/plot_sync/test_sender.py +116 -0
  215. chia/_tests/plot_sync/test_sync_simulated.py +451 -0
  216. chia/_tests/plot_sync/util.py +68 -0
  217. chia/_tests/plotting/__init__.py +0 -0
  218. chia/_tests/plotting/config.py +3 -0
  219. chia/_tests/plotting/test_plot_manager.py +781 -0
  220. chia/_tests/plotting/util.py +12 -0
  221. chia/_tests/pools/__init__.py +0 -0
  222. chia/_tests/pools/config.py +5 -0
  223. chia/_tests/pools/test_pool_cli_parsing.py +128 -0
  224. chia/_tests/pools/test_pool_cmdline.py +1001 -0
  225. chia/_tests/pools/test_pool_config.py +42 -0
  226. chia/_tests/pools/test_pool_puzzles_lifecycle.py +397 -0
  227. chia/_tests/pools/test_pool_rpc.py +1123 -0
  228. chia/_tests/pools/test_pool_wallet.py +205 -0
  229. chia/_tests/pools/test_wallet_pool_store.py +161 -0
  230. chia/_tests/process_junit.py +348 -0
  231. chia/_tests/rpc/__init__.py +0 -0
  232. chia/_tests/rpc/test_rpc_client.py +138 -0
  233. chia/_tests/rpc/test_rpc_server.py +183 -0
  234. chia/_tests/simulation/__init__.py +0 -0
  235. chia/_tests/simulation/config.py +6 -0
  236. chia/_tests/simulation/test_simulation.py +501 -0
  237. chia/_tests/simulation/test_simulator.py +232 -0
  238. chia/_tests/simulation/test_start_simulator.py +107 -0
  239. chia/_tests/testconfig.py +13 -0
  240. chia/_tests/timelord/__init__.py +0 -0
  241. chia/_tests/timelord/config.py +3 -0
  242. chia/_tests/timelord/test_new_peak.py +437 -0
  243. chia/_tests/timelord/test_timelord.py +11 -0
  244. chia/_tests/tools/1315537.json +170 -0
  245. chia/_tests/tools/1315544.json +160 -0
  246. chia/_tests/tools/1315630.json +150 -0
  247. chia/_tests/tools/300000.json +105 -0
  248. chia/_tests/tools/442734.json +140 -0
  249. chia/_tests/tools/466212.json +130 -0
  250. chia/_tests/tools/__init__.py +0 -0
  251. chia/_tests/tools/config.py +5 -0
  252. chia/_tests/tools/test-blockchain-db.sqlite +0 -0
  253. chia/_tests/tools/test_full_sync.py +30 -0
  254. chia/_tests/tools/test_legacy_keyring.py +82 -0
  255. chia/_tests/tools/test_run_block.py +128 -0
  256. chia/_tests/tools/test_virtual_project.py +591 -0
  257. chia/_tests/util/__init__.py +0 -0
  258. chia/_tests/util/benchmark_cost.py +170 -0
  259. chia/_tests/util/benchmarks.py +153 -0
  260. chia/_tests/util/bip39_test_vectors.json +148 -0
  261. chia/_tests/util/blockchain.py +134 -0
  262. chia/_tests/util/blockchain_mock.py +132 -0
  263. chia/_tests/util/build_network_protocol_files.py +302 -0
  264. chia/_tests/util/clvm_generator.bin +0 -0
  265. chia/_tests/util/config.py +3 -0
  266. chia/_tests/util/constants.py +20 -0
  267. chia/_tests/util/db_connection.py +37 -0
  268. chia/_tests/util/full_sync.py +253 -0
  269. chia/_tests/util/gen_ssl_certs.py +114 -0
  270. chia/_tests/util/generator_tools_testing.py +45 -0
  271. chia/_tests/util/get_name_puzzle_conditions.py +52 -0
  272. chia/_tests/util/key_tool.py +36 -0
  273. chia/_tests/util/misc.py +675 -0
  274. chia/_tests/util/network_protocol_data.py +1072 -0
  275. chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
  276. chia/_tests/util/protocol_messages_json.py +2701 -0
  277. chia/_tests/util/rpc.py +26 -0
  278. chia/_tests/util/run_block.py +163 -0
  279. chia/_tests/util/setup_nodes.py +481 -0
  280. chia/_tests/util/spend_sim.py +492 -0
  281. chia/_tests/util/split_managers.py +102 -0
  282. chia/_tests/util/temp_file.py +14 -0
  283. chia/_tests/util/test_action_scope.py +144 -0
  284. chia/_tests/util/test_async_pool.py +366 -0
  285. chia/_tests/util/test_build_job_matrix.py +42 -0
  286. chia/_tests/util/test_build_network_protocol_files.py +7 -0
  287. chia/_tests/util/test_chia_version.py +50 -0
  288. chia/_tests/util/test_collection.py +11 -0
  289. chia/_tests/util/test_condition_tools.py +229 -0
  290. chia/_tests/util/test_config.py +426 -0
  291. chia/_tests/util/test_dump_keyring.py +60 -0
  292. chia/_tests/util/test_errors.py +10 -0
  293. chia/_tests/util/test_full_block_utils.py +279 -0
  294. chia/_tests/util/test_installed.py +20 -0
  295. chia/_tests/util/test_limited_semaphore.py +53 -0
  296. chia/_tests/util/test_logging_filter.py +42 -0
  297. chia/_tests/util/test_misc.py +445 -0
  298. chia/_tests/util/test_network.py +73 -0
  299. chia/_tests/util/test_network_protocol_files.py +578 -0
  300. chia/_tests/util/test_network_protocol_json.py +267 -0
  301. chia/_tests/util/test_network_protocol_test.py +256 -0
  302. chia/_tests/util/test_paginator.py +71 -0
  303. chia/_tests/util/test_pprint.py +17 -0
  304. chia/_tests/util/test_priority_mutex.py +488 -0
  305. chia/_tests/util/test_recursive_replace.py +116 -0
  306. chia/_tests/util/test_replace_str_to_bytes.py +137 -0
  307. chia/_tests/util/test_service_groups.py +15 -0
  308. chia/_tests/util/test_ssl_check.py +31 -0
  309. chia/_tests/util/test_testnet_overrides.py +19 -0
  310. chia/_tests/util/test_tests_misc.py +38 -0
  311. chia/_tests/util/test_timing.py +37 -0
  312. chia/_tests/util/test_trusted_peer.py +51 -0
  313. chia/_tests/util/time_out_assert.py +191 -0
  314. chia/_tests/wallet/__init__.py +0 -0
  315. chia/_tests/wallet/cat_wallet/__init__.py +0 -0
  316. chia/_tests/wallet/cat_wallet/config.py +4 -0
  317. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
  318. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
  319. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1826 -0
  320. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
  321. chia/_tests/wallet/cat_wallet/test_trades.py +2600 -0
  322. chia/_tests/wallet/clawback/__init__.py +0 -0
  323. chia/_tests/wallet/clawback/config.py +3 -0
  324. chia/_tests/wallet/clawback/test_clawback_decorator.py +78 -0
  325. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
  326. chia/_tests/wallet/clawback/test_clawback_metadata.py +50 -0
  327. chia/_tests/wallet/config.py +4 -0
  328. chia/_tests/wallet/conftest.py +278 -0
  329. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  330. chia/_tests/wallet/dao_wallet/config.py +3 -0
  331. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1330 -0
  332. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
  333. chia/_tests/wallet/db_wallet/__init__.py +0 -0
  334. chia/_tests/wallet/db_wallet/config.py +3 -0
  335. chia/_tests/wallet/db_wallet/test_db_graftroot.py +141 -0
  336. chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
  337. chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
  338. chia/_tests/wallet/did_wallet/__init__.py +0 -0
  339. chia/_tests/wallet/did_wallet/config.py +4 -0
  340. chia/_tests/wallet/did_wallet/test_did.py +2284 -0
  341. chia/_tests/wallet/nft_wallet/__init__.py +0 -0
  342. chia/_tests/wallet/nft_wallet/config.py +4 -0
  343. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1493 -0
  344. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1024 -0
  345. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +375 -0
  346. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
  347. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
  348. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2584 -0
  349. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
  350. chia/_tests/wallet/rpc/__init__.py +0 -0
  351. chia/_tests/wallet/rpc/config.py +4 -0
  352. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +285 -0
  353. chia/_tests/wallet/rpc/test_wallet_rpc.py +3153 -0
  354. chia/_tests/wallet/simple_sync/__init__.py +0 -0
  355. chia/_tests/wallet/simple_sync/config.py +3 -0
  356. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +718 -0
  357. chia/_tests/wallet/sync/__init__.py +0 -0
  358. chia/_tests/wallet/sync/config.py +4 -0
  359. chia/_tests/wallet/sync/test_wallet_sync.py +1692 -0
  360. chia/_tests/wallet/test_address_type.py +189 -0
  361. chia/_tests/wallet/test_bech32m.py +45 -0
  362. chia/_tests/wallet/test_clvm_streamable.py +244 -0
  363. chia/_tests/wallet/test_coin_management.py +354 -0
  364. chia/_tests/wallet/test_coin_selection.py +588 -0
  365. chia/_tests/wallet/test_conditions.py +400 -0
  366. chia/_tests/wallet/test_debug_spend_bundle.py +218 -0
  367. chia/_tests/wallet/test_new_wallet_protocol.py +1174 -0
  368. chia/_tests/wallet/test_nft_store.py +192 -0
  369. chia/_tests/wallet/test_notifications.py +196 -0
  370. chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
  371. chia/_tests/wallet/test_puzzle_store.py +132 -0
  372. chia/_tests/wallet/test_sign_coin_spends.py +159 -0
  373. chia/_tests/wallet/test_signer_protocol.py +947 -0
  374. chia/_tests/wallet/test_singleton.py +122 -0
  375. chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
  376. chia/_tests/wallet/test_singleton_store.py +152 -0
  377. chia/_tests/wallet/test_taproot.py +19 -0
  378. chia/_tests/wallet/test_transaction_store.py +945 -0
  379. chia/_tests/wallet/test_util.py +185 -0
  380. chia/_tests/wallet/test_wallet.py +2139 -0
  381. chia/_tests/wallet/test_wallet_action_scope.py +85 -0
  382. chia/_tests/wallet/test_wallet_blockchain.py +111 -0
  383. chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
  384. chia/_tests/wallet/test_wallet_interested_store.py +43 -0
  385. chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
  386. chia/_tests/wallet/test_wallet_node.py +780 -0
  387. chia/_tests/wallet/test_wallet_retry.py +95 -0
  388. chia/_tests/wallet/test_wallet_state_manager.py +259 -0
  389. chia/_tests/wallet/test_wallet_test_framework.py +275 -0
  390. chia/_tests/wallet/test_wallet_trade_store.py +218 -0
  391. chia/_tests/wallet/test_wallet_user_store.py +34 -0
  392. chia/_tests/wallet/test_wallet_utils.py +156 -0
  393. chia/_tests/wallet/vc_wallet/__init__.py +0 -0
  394. chia/_tests/wallet/vc_wallet/config.py +3 -0
  395. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
  396. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
  397. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +830 -0
  398. chia/_tests/wallet/wallet_block_tools.py +327 -0
  399. chia/_tests/weight_proof/__init__.py +0 -0
  400. chia/_tests/weight_proof/config.py +3 -0
  401. chia/_tests/weight_proof/test_weight_proof.py +528 -0
  402. chia/apis.py +19 -0
  403. chia/clvm/__init__.py +0 -0
  404. chia/cmds/__init__.py +0 -0
  405. chia/cmds/beta.py +184 -0
  406. chia/cmds/beta_funcs.py +137 -0
  407. chia/cmds/check_wallet_db.py +420 -0
  408. chia/cmds/chia.py +151 -0
  409. chia/cmds/cmd_classes.py +323 -0
  410. chia/cmds/cmd_helpers.py +242 -0
  411. chia/cmds/cmds_util.py +488 -0
  412. chia/cmds/coin_funcs.py +275 -0
  413. chia/cmds/coins.py +182 -0
  414. chia/cmds/completion.py +49 -0
  415. chia/cmds/configure.py +332 -0
  416. chia/cmds/dao.py +1064 -0
  417. chia/cmds/dao_funcs.py +598 -0
  418. chia/cmds/data.py +708 -0
  419. chia/cmds/data_funcs.py +385 -0
  420. chia/cmds/db.py +87 -0
  421. chia/cmds/db_backup_func.py +77 -0
  422. chia/cmds/db_upgrade_func.py +452 -0
  423. chia/cmds/db_validate_func.py +184 -0
  424. chia/cmds/dev.py +18 -0
  425. chia/cmds/farm.py +100 -0
  426. chia/cmds/farm_funcs.py +200 -0
  427. chia/cmds/gh.py +275 -0
  428. chia/cmds/init.py +63 -0
  429. chia/cmds/init_funcs.py +367 -0
  430. chia/cmds/installers.py +131 -0
  431. chia/cmds/keys.py +527 -0
  432. chia/cmds/keys_funcs.py +863 -0
  433. chia/cmds/netspace.py +50 -0
  434. chia/cmds/netspace_funcs.py +54 -0
  435. chia/cmds/options.py +32 -0
  436. chia/cmds/param_types.py +238 -0
  437. chia/cmds/passphrase.py +131 -0
  438. chia/cmds/passphrase_funcs.py +292 -0
  439. chia/cmds/peer.py +51 -0
  440. chia/cmds/peer_funcs.py +129 -0
  441. chia/cmds/plotnft.py +260 -0
  442. chia/cmds/plotnft_funcs.py +405 -0
  443. chia/cmds/plots.py +230 -0
  444. chia/cmds/plotters.py +18 -0
  445. chia/cmds/rpc.py +208 -0
  446. chia/cmds/show.py +72 -0
  447. chia/cmds/show_funcs.py +215 -0
  448. chia/cmds/signer.py +296 -0
  449. chia/cmds/sim.py +225 -0
  450. chia/cmds/sim_funcs.py +509 -0
  451. chia/cmds/start.py +24 -0
  452. chia/cmds/start_funcs.py +109 -0
  453. chia/cmds/stop.py +62 -0
  454. chia/cmds/units.py +9 -0
  455. chia/cmds/wallet.py +1901 -0
  456. chia/cmds/wallet_funcs.py +1874 -0
  457. chia/consensus/__init__.py +0 -0
  458. chia/consensus/block_body_validation.py +562 -0
  459. chia/consensus/block_creation.py +546 -0
  460. chia/consensus/block_header_validation.py +1059 -0
  461. chia/consensus/block_record.py +31 -0
  462. chia/consensus/block_rewards.py +53 -0
  463. chia/consensus/blockchain.py +1087 -0
  464. chia/consensus/blockchain_interface.py +56 -0
  465. chia/consensus/coinbase.py +30 -0
  466. chia/consensus/condition_costs.py +9 -0
  467. chia/consensus/constants.py +49 -0
  468. chia/consensus/cost_calculator.py +15 -0
  469. chia/consensus/default_constants.py +89 -0
  470. chia/consensus/deficit.py +55 -0
  471. chia/consensus/difficulty_adjustment.py +412 -0
  472. chia/consensus/find_fork_point.py +111 -0
  473. chia/consensus/full_block_to_block_record.py +167 -0
  474. chia/consensus/get_block_challenge.py +106 -0
  475. chia/consensus/get_block_generator.py +27 -0
  476. chia/consensus/make_sub_epoch_summary.py +210 -0
  477. chia/consensus/multiprocess_validation.py +268 -0
  478. chia/consensus/pos_quality.py +19 -0
  479. chia/consensus/pot_iterations.py +67 -0
  480. chia/consensus/puzzles/__init__.py +0 -0
  481. chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
  482. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
  483. chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
  484. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
  485. chia/consensus/vdf_info_computation.py +156 -0
  486. chia/daemon/__init__.py +0 -0
  487. chia/daemon/client.py +252 -0
  488. chia/daemon/keychain_proxy.py +502 -0
  489. chia/daemon/keychain_server.py +365 -0
  490. chia/daemon/server.py +1606 -0
  491. chia/daemon/windows_signal.py +56 -0
  492. chia/data_layer/__init__.py +0 -0
  493. chia/data_layer/data_layer.py +1291 -0
  494. chia/data_layer/data_layer_api.py +33 -0
  495. chia/data_layer/data_layer_errors.py +50 -0
  496. chia/data_layer/data_layer_server.py +170 -0
  497. chia/data_layer/data_layer_util.py +985 -0
  498. chia/data_layer/data_layer_wallet.py +1311 -0
  499. chia/data_layer/data_store.py +2267 -0
  500. chia/data_layer/dl_wallet_store.py +407 -0
  501. chia/data_layer/download_data.py +389 -0
  502. chia/data_layer/puzzles/__init__.py +0 -0
  503. chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
  504. chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
  505. chia/data_layer/s3_plugin_config.yml +33 -0
  506. chia/data_layer/s3_plugin_service.py +468 -0
  507. chia/data_layer/util/__init__.py +0 -0
  508. chia/data_layer/util/benchmark.py +107 -0
  509. chia/data_layer/util/plugin.py +40 -0
  510. chia/farmer/__init__.py +0 -0
  511. chia/farmer/farmer.py +923 -0
  512. chia/farmer/farmer_api.py +820 -0
  513. chia/full_node/__init__.py +0 -0
  514. chia/full_node/bitcoin_fee_estimator.py +85 -0
  515. chia/full_node/block_height_map.py +271 -0
  516. chia/full_node/block_store.py +576 -0
  517. chia/full_node/bundle_tools.py +19 -0
  518. chia/full_node/coin_store.py +647 -0
  519. chia/full_node/fee_estimate.py +54 -0
  520. chia/full_node/fee_estimate_store.py +24 -0
  521. chia/full_node/fee_estimation.py +92 -0
  522. chia/full_node/fee_estimator.py +90 -0
  523. chia/full_node/fee_estimator_constants.py +38 -0
  524. chia/full_node/fee_estimator_interface.py +42 -0
  525. chia/full_node/fee_history.py +25 -0
  526. chia/full_node/fee_tracker.py +564 -0
  527. chia/full_node/full_node.py +3327 -0
  528. chia/full_node/full_node_api.py +2025 -0
  529. chia/full_node/full_node_store.py +1033 -0
  530. chia/full_node/hint_management.py +56 -0
  531. chia/full_node/hint_store.py +93 -0
  532. chia/full_node/mempool.py +589 -0
  533. chia/full_node/mempool_check_conditions.py +146 -0
  534. chia/full_node/mempool_manager.py +853 -0
  535. chia/full_node/pending_tx_cache.py +112 -0
  536. chia/full_node/puzzles/__init__.py +0 -0
  537. chia/full_node/puzzles/block_program_zero.clsp +14 -0
  538. chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
  539. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
  540. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
  541. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
  542. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
  543. chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
  544. chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
  545. chia/full_node/signage_point.py +16 -0
  546. chia/full_node/subscriptions.py +247 -0
  547. chia/full_node/sync_store.py +146 -0
  548. chia/full_node/tx_processing_queue.py +78 -0
  549. chia/full_node/util/__init__.py +0 -0
  550. chia/full_node/weight_proof.py +1720 -0
  551. chia/harvester/__init__.py +0 -0
  552. chia/harvester/harvester.py +272 -0
  553. chia/harvester/harvester_api.py +380 -0
  554. chia/introducer/__init__.py +0 -0
  555. chia/introducer/introducer.py +122 -0
  556. chia/introducer/introducer_api.py +70 -0
  557. chia/legacy/__init__.py +0 -0
  558. chia/legacy/keyring.py +155 -0
  559. chia/plot_sync/__init__.py +0 -0
  560. chia/plot_sync/delta.py +61 -0
  561. chia/plot_sync/exceptions.py +56 -0
  562. chia/plot_sync/receiver.py +386 -0
  563. chia/plot_sync/sender.py +340 -0
  564. chia/plot_sync/util.py +43 -0
  565. chia/plotters/__init__.py +0 -0
  566. chia/plotters/bladebit.py +388 -0
  567. chia/plotters/chiapos.py +63 -0
  568. chia/plotters/madmax.py +224 -0
  569. chia/plotters/plotters.py +577 -0
  570. chia/plotters/plotters_util.py +133 -0
  571. chia/plotting/__init__.py +0 -0
  572. chia/plotting/cache.py +213 -0
  573. chia/plotting/check_plots.py +283 -0
  574. chia/plotting/create_plots.py +278 -0
  575. chia/plotting/manager.py +436 -0
  576. chia/plotting/util.py +336 -0
  577. chia/pools/__init__.py +0 -0
  578. chia/pools/pool_config.py +110 -0
  579. chia/pools/pool_puzzles.py +459 -0
  580. chia/pools/pool_wallet.py +933 -0
  581. chia/pools/pool_wallet_info.py +118 -0
  582. chia/pools/puzzles/__init__.py +0 -0
  583. chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
  584. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
  585. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
  586. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
  587. chia/protocols/__init__.py +0 -0
  588. chia/protocols/farmer_protocol.py +102 -0
  589. chia/protocols/full_node_protocol.py +219 -0
  590. chia/protocols/harvester_protocol.py +216 -0
  591. chia/protocols/introducer_protocol.py +25 -0
  592. chia/protocols/pool_protocol.py +177 -0
  593. chia/protocols/protocol_message_types.py +139 -0
  594. chia/protocols/protocol_state_machine.py +87 -0
  595. chia/protocols/protocol_timing.py +8 -0
  596. chia/protocols/shared_protocol.py +86 -0
  597. chia/protocols/timelord_protocol.py +93 -0
  598. chia/protocols/wallet_protocol.py +401 -0
  599. chia/py.typed +0 -0
  600. chia/rpc/__init__.py +0 -0
  601. chia/rpc/crawler_rpc_api.py +80 -0
  602. chia/rpc/data_layer_rpc_api.py +644 -0
  603. chia/rpc/data_layer_rpc_client.py +188 -0
  604. chia/rpc/data_layer_rpc_util.py +58 -0
  605. chia/rpc/farmer_rpc_api.py +365 -0
  606. chia/rpc/farmer_rpc_client.py +86 -0
  607. chia/rpc/full_node_rpc_api.py +959 -0
  608. chia/rpc/full_node_rpc_client.py +292 -0
  609. chia/rpc/harvester_rpc_api.py +141 -0
  610. chia/rpc/harvester_rpc_client.py +54 -0
  611. chia/rpc/rpc_client.py +164 -0
  612. chia/rpc/rpc_server.py +521 -0
  613. chia/rpc/timelord_rpc_api.py +32 -0
  614. chia/rpc/util.py +93 -0
  615. chia/rpc/wallet_request_types.py +904 -0
  616. chia/rpc/wallet_rpc_api.py +4943 -0
  617. chia/rpc/wallet_rpc_client.py +1814 -0
  618. chia/seeder/__init__.py +0 -0
  619. chia/seeder/crawl_store.py +425 -0
  620. chia/seeder/crawler.py +410 -0
  621. chia/seeder/crawler_api.py +135 -0
  622. chia/seeder/dns_server.py +593 -0
  623. chia/seeder/peer_record.py +146 -0
  624. chia/seeder/start_crawler.py +92 -0
  625. chia/server/__init__.py +0 -0
  626. chia/server/address_manager.py +658 -0
  627. chia/server/address_manager_store.py +237 -0
  628. chia/server/api_protocol.py +116 -0
  629. chia/server/capabilities.py +24 -0
  630. chia/server/chia_policy.py +346 -0
  631. chia/server/introducer_peers.py +76 -0
  632. chia/server/node_discovery.py +714 -0
  633. chia/server/outbound_message.py +33 -0
  634. chia/server/rate_limit_numbers.py +214 -0
  635. chia/server/rate_limits.py +153 -0
  636. chia/server/server.py +741 -0
  637. chia/server/signal_handlers.py +120 -0
  638. chia/server/ssl_context.py +32 -0
  639. chia/server/start_data_layer.py +151 -0
  640. chia/server/start_farmer.py +98 -0
  641. chia/server/start_full_node.py +112 -0
  642. chia/server/start_harvester.py +93 -0
  643. chia/server/start_introducer.py +81 -0
  644. chia/server/start_service.py +316 -0
  645. chia/server/start_timelord.py +89 -0
  646. chia/server/start_wallet.py +113 -0
  647. chia/server/upnp.py +118 -0
  648. chia/server/ws_connection.py +766 -0
  649. chia/simulator/__init__.py +0 -0
  650. chia/simulator/add_blocks_in_batches.py +54 -0
  651. chia/simulator/block_tools.py +2054 -0
  652. chia/simulator/full_node_simulator.py +794 -0
  653. chia/simulator/keyring.py +128 -0
  654. chia/simulator/setup_services.py +506 -0
  655. chia/simulator/simulator_constants.py +13 -0
  656. chia/simulator/simulator_full_node_rpc_api.py +99 -0
  657. chia/simulator/simulator_full_node_rpc_client.py +60 -0
  658. chia/simulator/simulator_protocol.py +29 -0
  659. chia/simulator/simulator_test_tools.py +164 -0
  660. chia/simulator/socket.py +24 -0
  661. chia/simulator/ssl_certs.py +114 -0
  662. chia/simulator/ssl_certs_1.py +697 -0
  663. chia/simulator/ssl_certs_10.py +697 -0
  664. chia/simulator/ssl_certs_2.py +697 -0
  665. chia/simulator/ssl_certs_3.py +697 -0
  666. chia/simulator/ssl_certs_4.py +697 -0
  667. chia/simulator/ssl_certs_5.py +697 -0
  668. chia/simulator/ssl_certs_6.py +697 -0
  669. chia/simulator/ssl_certs_7.py +697 -0
  670. chia/simulator/ssl_certs_8.py +697 -0
  671. chia/simulator/ssl_certs_9.py +697 -0
  672. chia/simulator/start_simulator.py +143 -0
  673. chia/simulator/wallet_tools.py +246 -0
  674. chia/ssl/__init__.py +0 -0
  675. chia/ssl/chia_ca.crt +19 -0
  676. chia/ssl/chia_ca.key +28 -0
  677. chia/ssl/create_ssl.py +249 -0
  678. chia/ssl/dst_root_ca.pem +20 -0
  679. chia/timelord/__init__.py +0 -0
  680. chia/timelord/iters_from_block.py +50 -0
  681. chia/timelord/timelord.py +1226 -0
  682. chia/timelord/timelord_api.py +138 -0
  683. chia/timelord/timelord_launcher.py +190 -0
  684. chia/timelord/timelord_state.py +244 -0
  685. chia/timelord/types.py +22 -0
  686. chia/types/__init__.py +0 -0
  687. chia/types/aliases.py +35 -0
  688. chia/types/block_protocol.py +20 -0
  689. chia/types/blockchain_format/__init__.py +0 -0
  690. chia/types/blockchain_format/classgroup.py +5 -0
  691. chia/types/blockchain_format/coin.py +28 -0
  692. chia/types/blockchain_format/foliage.py +8 -0
  693. chia/types/blockchain_format/pool_target.py +5 -0
  694. chia/types/blockchain_format/program.py +269 -0
  695. chia/types/blockchain_format/proof_of_space.py +135 -0
  696. chia/types/blockchain_format/reward_chain_block.py +6 -0
  697. chia/types/blockchain_format/serialized_program.py +5 -0
  698. chia/types/blockchain_format/sized_bytes.py +11 -0
  699. chia/types/blockchain_format/slots.py +9 -0
  700. chia/types/blockchain_format/sub_epoch_summary.py +5 -0
  701. chia/types/blockchain_format/tree_hash.py +72 -0
  702. chia/types/blockchain_format/vdf.py +86 -0
  703. chia/types/clvm_cost.py +13 -0
  704. chia/types/coin_record.py +43 -0
  705. chia/types/coin_spend.py +115 -0
  706. chia/types/condition_opcodes.py +73 -0
  707. chia/types/condition_with_args.py +16 -0
  708. chia/types/eligible_coin_spends.py +365 -0
  709. chia/types/end_of_slot_bundle.py +5 -0
  710. chia/types/fee_rate.py +38 -0
  711. chia/types/full_block.py +5 -0
  712. chia/types/generator_types.py +13 -0
  713. chia/types/header_block.py +5 -0
  714. chia/types/internal_mempool_item.py +18 -0
  715. chia/types/mempool_inclusion_status.py +9 -0
  716. chia/types/mempool_item.py +85 -0
  717. chia/types/mempool_submission_status.py +30 -0
  718. chia/types/mojos.py +7 -0
  719. chia/types/peer_info.py +64 -0
  720. chia/types/signing_mode.py +29 -0
  721. chia/types/spend_bundle.py +30 -0
  722. chia/types/spend_bundle_conditions.py +7 -0
  723. chia/types/transaction_queue_entry.py +55 -0
  724. chia/types/unfinished_block.py +5 -0
  725. chia/types/unfinished_header_block.py +37 -0
  726. chia/types/validation_state.py +14 -0
  727. chia/types/weight_proof.py +49 -0
  728. chia/util/__init__.py +0 -0
  729. chia/util/action_scope.py +168 -0
  730. chia/util/async_pool.py +226 -0
  731. chia/util/augmented_chain.py +134 -0
  732. chia/util/batches.py +42 -0
  733. chia/util/bech32m.py +126 -0
  734. chia/util/beta_metrics.py +119 -0
  735. chia/util/block_cache.py +56 -0
  736. chia/util/byte_types.py +12 -0
  737. chia/util/check_fork_next_block.py +33 -0
  738. chia/util/chia_logging.py +144 -0
  739. chia/util/chia_version.py +33 -0
  740. chia/util/collection.py +17 -0
  741. chia/util/condition_tools.py +201 -0
  742. chia/util/config.py +367 -0
  743. chia/util/cpu.py +22 -0
  744. chia/util/db_synchronous.py +23 -0
  745. chia/util/db_version.py +32 -0
  746. chia/util/db_wrapper.py +430 -0
  747. chia/util/default_root.py +27 -0
  748. chia/util/dump_keyring.py +93 -0
  749. chia/util/english.txt +2048 -0
  750. chia/util/errors.py +353 -0
  751. chia/util/file_keyring.py +469 -0
  752. chia/util/files.py +97 -0
  753. chia/util/full_block_utils.py +345 -0
  754. chia/util/generator_tools.py +72 -0
  755. chia/util/hash.py +31 -0
  756. chia/util/initial-config.yaml +694 -0
  757. chia/util/inline_executor.py +26 -0
  758. chia/util/ints.py +19 -0
  759. chia/util/ip_address.py +39 -0
  760. chia/util/json_util.py +37 -0
  761. chia/util/keychain.py +676 -0
  762. chia/util/keyring_wrapper.py +327 -0
  763. chia/util/limited_semaphore.py +41 -0
  764. chia/util/lock.py +49 -0
  765. chia/util/log_exceptions.py +32 -0
  766. chia/util/logging.py +36 -0
  767. chia/util/lru_cache.py +31 -0
  768. chia/util/math.py +20 -0
  769. chia/util/network.py +182 -0
  770. chia/util/paginator.py +48 -0
  771. chia/util/path.py +31 -0
  772. chia/util/permissions.py +20 -0
  773. chia/util/prev_transaction_block.py +21 -0
  774. chia/util/priority_mutex.py +95 -0
  775. chia/util/profiler.py +197 -0
  776. chia/util/recursive_replace.py +24 -0
  777. chia/util/safe_cancel_task.py +16 -0
  778. chia/util/service_groups.py +47 -0
  779. chia/util/setproctitle.py +22 -0
  780. chia/util/significant_bits.py +32 -0
  781. chia/util/ssl_check.py +213 -0
  782. chia/util/streamable.py +642 -0
  783. chia/util/task_referencer.py +59 -0
  784. chia/util/task_timing.py +382 -0
  785. chia/util/timing.py +67 -0
  786. chia/util/vdf_prover.py +30 -0
  787. chia/util/virtual_project_analysis.py +540 -0
  788. chia/util/ws_message.py +66 -0
  789. chia/wallet/__init__.py +0 -0
  790. chia/wallet/cat_wallet/__init__.py +0 -0
  791. chia/wallet/cat_wallet/cat_constants.py +75 -0
  792. chia/wallet/cat_wallet/cat_info.py +47 -0
  793. chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
  794. chia/wallet/cat_wallet/cat_utils.py +164 -0
  795. chia/wallet/cat_wallet/cat_wallet.py +855 -0
  796. chia/wallet/cat_wallet/dao_cat_info.py +28 -0
  797. chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
  798. chia/wallet/cat_wallet/lineage_store.py +74 -0
  799. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  800. chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
  801. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
  802. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
  803. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
  804. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
  805. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
  806. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
  807. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
  808. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
  809. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
  810. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
  811. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
  812. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
  813. chia/wallet/coin_selection.py +188 -0
  814. chia/wallet/conditions.py +1512 -0
  815. chia/wallet/dao_wallet/__init__.py +0 -0
  816. chia/wallet/dao_wallet/dao_info.py +61 -0
  817. chia/wallet/dao_wallet/dao_utils.py +811 -0
  818. chia/wallet/dao_wallet/dao_wallet.py +2119 -0
  819. chia/wallet/db_wallet/__init__.py +0 -0
  820. chia/wallet/db_wallet/db_wallet_puzzles.py +111 -0
  821. chia/wallet/derivation_record.py +30 -0
  822. chia/wallet/derive_keys.py +146 -0
  823. chia/wallet/did_wallet/__init__.py +0 -0
  824. chia/wallet/did_wallet/did_info.py +39 -0
  825. chia/wallet/did_wallet/did_wallet.py +1494 -0
  826. chia/wallet/did_wallet/did_wallet_puzzles.py +221 -0
  827. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  828. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
  829. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
  830. chia/wallet/driver_protocol.py +26 -0
  831. chia/wallet/key_val_store.py +55 -0
  832. chia/wallet/lineage_proof.py +58 -0
  833. chia/wallet/nft_wallet/__init__.py +0 -0
  834. chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
  835. chia/wallet/nft_wallet/nft_info.py +120 -0
  836. chia/wallet/nft_wallet/nft_puzzles.py +305 -0
  837. chia/wallet/nft_wallet/nft_wallet.py +1687 -0
  838. chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
  839. chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
  840. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
  841. chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
  842. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
  843. chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
  844. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
  845. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
  846. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
  847. chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
  848. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
  849. chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
  850. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
  851. chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
  852. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
  853. chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
  854. chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
  855. chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
  856. chia/wallet/nft_wallet/uncurry_nft.py +217 -0
  857. chia/wallet/notification_manager.py +117 -0
  858. chia/wallet/notification_store.py +178 -0
  859. chia/wallet/outer_puzzles.py +84 -0
  860. chia/wallet/payment.py +33 -0
  861. chia/wallet/puzzle_drivers.py +118 -0
  862. chia/wallet/puzzles/__init__.py +0 -0
  863. chia/wallet/puzzles/augmented_condition.clsp +13 -0
  864. chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
  865. chia/wallet/puzzles/clawback/__init__.py +0 -0
  866. chia/wallet/puzzles/clawback/drivers.py +188 -0
  867. chia/wallet/puzzles/clawback/metadata.py +38 -0
  868. chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
  869. chia/wallet/puzzles/condition_codes.clib +77 -0
  870. chia/wallet/puzzles/curry-and-treehash.clib +102 -0
  871. chia/wallet/puzzles/curry.clib +135 -0
  872. chia/wallet/puzzles/curry_by_index.clib +16 -0
  873. chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
  874. chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
  875. chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
  876. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
  877. chia/wallet/puzzles/dao_finished_state.clsp +35 -0
  878. chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
  879. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
  880. chia/wallet/puzzles/dao_lockup.clsp +288 -0
  881. chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
  882. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
  883. chia/wallet/puzzles/dao_proposal.clsp +377 -0
  884. chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
  885. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
  886. chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
  887. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
  888. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
  889. chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
  890. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
  891. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
  892. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
  893. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
  894. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
  895. chia/wallet/puzzles/dao_treasury.clsp +115 -0
  896. chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
  897. chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
  898. chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
  899. chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
  900. chia/wallet/puzzles/json.clib +25 -0
  901. chia/wallet/puzzles/load_clvm.py +161 -0
  902. chia/wallet/puzzles/merkle_utils.clib +18 -0
  903. chia/wallet/puzzles/notification.clsp +7 -0
  904. chia/wallet/puzzles/notification.clsp.hex +1 -0
  905. chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
  906. chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
  907. chia/wallet/puzzles/p2_conditions.clsp +3 -0
  908. chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
  909. chia/wallet/puzzles/p2_conditions.py +26 -0
  910. chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
  911. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
  912. chia/wallet/puzzles/p2_delegated_conditions.py +21 -0
  913. chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
  914. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
  915. chia/wallet/puzzles/p2_delegated_puzzle.py +34 -0
  916. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
  917. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
  918. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +160 -0
  919. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
  920. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
  921. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +21 -0
  922. chia/wallet/puzzles/p2_parent.clsp +19 -0
  923. chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
  924. chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
  925. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
  926. chia/wallet/puzzles/p2_puzzle_hash.py +27 -0
  927. chia/wallet/puzzles/p2_singleton.clsp +30 -0
  928. chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
  929. chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
  930. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
  931. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
  932. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
  933. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
  934. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
  935. chia/wallet/puzzles/puzzle_utils.py +34 -0
  936. chia/wallet/puzzles/settlement_payments.clsp +49 -0
  937. chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
  938. chia/wallet/puzzles/sha256tree.clib +11 -0
  939. chia/wallet/puzzles/singleton_launcher.clsp +16 -0
  940. chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
  941. chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
  942. chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
  943. chia/wallet/puzzles/singleton_top_layer.py +296 -0
  944. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
  945. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
  946. chia/wallet/puzzles/singleton_top_layer_v1_1.py +345 -0
  947. chia/wallet/puzzles/singleton_truths.clib +21 -0
  948. chia/wallet/puzzles/tails.py +348 -0
  949. chia/wallet/puzzles/utility_macros.clib +48 -0
  950. chia/wallet/signer_protocol.py +125 -0
  951. chia/wallet/singleton.py +106 -0
  952. chia/wallet/singleton_record.py +30 -0
  953. chia/wallet/trade_manager.py +1102 -0
  954. chia/wallet/trade_record.py +67 -0
  955. chia/wallet/trading/__init__.py +0 -0
  956. chia/wallet/trading/offer.py +702 -0
  957. chia/wallet/trading/trade_status.py +13 -0
  958. chia/wallet/trading/trade_store.py +526 -0
  959. chia/wallet/transaction_record.py +158 -0
  960. chia/wallet/transaction_sorting.py +14 -0
  961. chia/wallet/uncurried_puzzle.py +17 -0
  962. chia/wallet/util/__init__.py +0 -0
  963. chia/wallet/util/address_type.py +55 -0
  964. chia/wallet/util/blind_signer_tl.py +164 -0
  965. chia/wallet/util/clvm_streamable.py +203 -0
  966. chia/wallet/util/compute_hints.py +66 -0
  967. chia/wallet/util/compute_memos.py +43 -0
  968. chia/wallet/util/curry_and_treehash.py +91 -0
  969. chia/wallet/util/debug_spend_bundle.py +232 -0
  970. chia/wallet/util/merkle_tree.py +100 -0
  971. chia/wallet/util/merkle_utils.py +102 -0
  972. chia/wallet/util/new_peak_queue.py +82 -0
  973. chia/wallet/util/notifications.py +12 -0
  974. chia/wallet/util/peer_request_cache.py +174 -0
  975. chia/wallet/util/pprint.py +39 -0
  976. chia/wallet/util/puzzle_compression.py +95 -0
  977. chia/wallet/util/puzzle_decorator.py +100 -0
  978. chia/wallet/util/puzzle_decorator_type.py +7 -0
  979. chia/wallet/util/query_filter.py +59 -0
  980. chia/wallet/util/transaction_type.py +23 -0
  981. chia/wallet/util/tx_config.py +158 -0
  982. chia/wallet/util/wallet_sync_utils.py +351 -0
  983. chia/wallet/util/wallet_types.py +72 -0
  984. chia/wallet/vc_wallet/__init__.py +0 -0
  985. chia/wallet/vc_wallet/cr_cat_drivers.py +664 -0
  986. chia/wallet/vc_wallet/cr_cat_wallet.py +877 -0
  987. chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
  988. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  989. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
  990. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
  991. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
  992. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
  993. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
  994. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
  995. chia/wallet/vc_wallet/vc_drivers.py +838 -0
  996. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  997. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
  998. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
  999. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
  1000. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
  1001. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
  1002. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
  1003. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
  1004. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
  1005. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
  1006. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
  1007. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
  1008. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
  1009. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
  1010. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
  1011. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
  1012. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
  1013. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
  1014. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
  1015. chia/wallet/vc_wallet/vc_store.py +263 -0
  1016. chia/wallet/vc_wallet/vc_wallet.py +638 -0
  1017. chia/wallet/wallet.py +698 -0
  1018. chia/wallet/wallet_action_scope.py +96 -0
  1019. chia/wallet/wallet_blockchain.py +244 -0
  1020. chia/wallet/wallet_coin_record.py +72 -0
  1021. chia/wallet/wallet_coin_store.py +351 -0
  1022. chia/wallet/wallet_info.py +35 -0
  1023. chia/wallet/wallet_interested_store.py +188 -0
  1024. chia/wallet/wallet_nft_store.py +279 -0
  1025. chia/wallet/wallet_node.py +1765 -0
  1026. chia/wallet/wallet_node_api.py +207 -0
  1027. chia/wallet/wallet_pool_store.py +119 -0
  1028. chia/wallet/wallet_protocol.py +90 -0
  1029. chia/wallet/wallet_puzzle_store.py +396 -0
  1030. chia/wallet/wallet_retry_store.py +70 -0
  1031. chia/wallet/wallet_singleton_store.py +259 -0
  1032. chia/wallet/wallet_spend_bundle.py +25 -0
  1033. chia/wallet/wallet_state_manager.py +2819 -0
  1034. chia/wallet/wallet_transaction_store.py +496 -0
  1035. chia/wallet/wallet_user_store.py +110 -0
  1036. chia/wallet/wallet_weight_proof_handler.py +126 -0
  1037. chia_blockchain-2.5.1rc1.dist-info/LICENSE +201 -0
  1038. chia_blockchain-2.5.1rc1.dist-info/METADATA +156 -0
  1039. chia_blockchain-2.5.1rc1.dist-info/RECORD +1042 -0
  1040. chia_blockchain-2.5.1rc1.dist-info/WHEEL +4 -0
  1041. chia_blockchain-2.5.1rc1.dist-info/entry_points.txt +17 -0
  1042. mozilla-ca/cacert.pem +3611 -0
@@ -0,0 +1,1692 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import contextlib
5
+ import functools
6
+ import logging
7
+ from collections.abc import Awaitable
8
+ from dataclasses import dataclass
9
+ from typing import Callable, Optional
10
+ from unittest.mock import MagicMock
11
+
12
+ import pytest
13
+ from aiosqlite import Error as AIOSqliteError
14
+ from chia_rs import G2Element, confirm_not_included_already_hashed
15
+ from chiabip158 import PyBIP158
16
+ from colorlog import getLogger
17
+
18
+ from chia._tests.connection_utils import connect_and_get_peer, disconnect_all, disconnect_all_and_reconnect
19
+ from chia._tests.util.blockchain_mock import BlockchainMock
20
+ from chia._tests.util.misc import patch_request_handler, wallet_height_at_least
21
+ from chia._tests.util.setup_nodes import OldSimulatorsAndWallets
22
+ from chia._tests.util.time_out_assert import time_out_assert, time_out_assert_not_none
23
+ from chia._tests.weight_proof.test_weight_proof import load_blocks_dont_validate
24
+ from chia.consensus.block_body_validation import ForkInfo
25
+ from chia.consensus.block_record import BlockRecord
26
+ from chia.consensus.block_rewards import calculate_base_farmer_reward, calculate_pool_reward
27
+ from chia.consensus.constants import ConsensusConstants
28
+ from chia.consensus.difficulty_adjustment import get_next_sub_slot_iters_and_difficulty
29
+ from chia.full_node.full_node_api import FullNodeAPI
30
+ from chia.full_node.weight_proof import WeightProofHandler
31
+ from chia.protocols import full_node_protocol, wallet_protocol
32
+ from chia.protocols.protocol_message_types import ProtocolMessageTypes
33
+ from chia.protocols.shared_protocol import Capability
34
+ from chia.protocols.wallet_protocol import (
35
+ CoinState,
36
+ RequestAdditions,
37
+ RespondAdditions,
38
+ RespondBlockHeader,
39
+ RespondBlockHeaders,
40
+ SendTransaction,
41
+ )
42
+ from chia.server.outbound_message import Message, make_msg
43
+ from chia.server.server import ChiaServer
44
+ from chia.server.ws_connection import WSChiaConnection
45
+ from chia.simulator.add_blocks_in_batches import add_blocks_in_batches
46
+ from chia.simulator.block_tools import BlockTools
47
+ from chia.simulator.full_node_simulator import FullNodeSimulator
48
+ from chia.simulator.simulator_protocol import FarmNewBlockProtocol
49
+ from chia.types.blockchain_format.program import Program
50
+ from chia.types.blockchain_format.serialized_program import SerializedProgram
51
+ from chia.types.blockchain_format.sized_bytes import bytes32
52
+ from chia.types.coin_spend import make_spend
53
+ from chia.types.condition_opcodes import ConditionOpcode
54
+ from chia.types.full_block import FullBlock
55
+ from chia.types.peer_info import PeerInfo
56
+ from chia.types.spend_bundle import SpendBundle
57
+ from chia.types.validation_state import ValidationState
58
+ from chia.util.hash import std_hash
59
+ from chia.util.ints import uint32, uint64, uint128
60
+ from chia.wallet.nft_wallet.nft_wallet import NFTWallet
61
+ from chia.wallet.payment import Payment
62
+ from chia.wallet.util.compute_memos import compute_memos
63
+ from chia.wallet.util.tx_config import DEFAULT_TX_CONFIG
64
+ from chia.wallet.util.wallet_sync_utils import PeerRequestException
65
+ from chia.wallet.util.wallet_types import WalletIdentifier
66
+ from chia.wallet.wallet_state_manager import WalletStateManager
67
+ from chia.wallet.wallet_weight_proof_handler import get_wp_fork_point
68
+
69
+
70
+ async def get_tx_count(wsm: WalletStateManager, wallet_id: int) -> int:
71
+ txs = await wsm.get_all_transactions(wallet_id)
72
+ return len(txs)
73
+
74
+
75
+ async def get_nft_count(wallet: NFTWallet) -> int:
76
+ return await wallet.get_nft_count()
77
+
78
+
79
+ log = getLogger(__name__)
80
+
81
+
82
+ pytestmark = pytest.mark.standard_block_tools
83
+
84
+
85
+ @pytest.mark.limit_consensus_modes(reason="save time")
86
+ @pytest.mark.anyio
87
+ async def test_request_block_headers(
88
+ simulator_and_wallet: OldSimulatorsAndWallets, default_400_blocks: list[FullBlock]
89
+ ) -> None:
90
+ # Tests the edge case of receiving funds right before the recent blocks in weight proof
91
+ [full_node_api], [(wallet_node, _)], bt = simulator_and_wallet
92
+
93
+ wallet = wallet_node.wallet_state_manager.main_wallet
94
+ ph = await wallet.get_new_puzzlehash()
95
+ await add_blocks_in_batches(default_400_blocks[:100], full_node_api.full_node)
96
+
97
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(10), uint32(15), False))
98
+ assert msg is not None
99
+ assert msg.type == ProtocolMessageTypes.respond_block_headers.value
100
+ res_block_headers = RespondBlockHeaders.from_bytes(msg.data)
101
+ bh = res_block_headers.header_blocks
102
+ assert len(bh) == 6
103
+ assert [x.reward_chain_block.height for x in default_400_blocks[10:16]] == [x.reward_chain_block.height for x in bh]
104
+ assert [x.foliage for x in default_400_blocks[10:16]] == [x.foliage for x in bh]
105
+ assert [x.transactions_filter for x in bh] == [b"\x00"] * 6
106
+
107
+ num_blocks = 20
108
+ new_blocks = bt.get_consecutive_blocks(num_blocks, block_list_input=default_400_blocks, pool_reward_puzzle_hash=ph)
109
+ await add_blocks_in_batches(new_blocks, full_node_api.full_node)
110
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(110), uint32(115), True))
111
+ assert msg is not None
112
+ res_block_headers = RespondBlockHeaders.from_bytes(msg.data)
113
+ bh = res_block_headers.header_blocks
114
+ assert len(bh) == 6
115
+
116
+
117
+ @pytest.mark.limit_consensus_modes(reason="save time")
118
+ @pytest.mark.anyio
119
+ @pytest.mark.parametrize("rewards_only_tx_block", [True, False])
120
+ async def test_request_block_headers_transactions_filter(
121
+ one_node_one_block: tuple[FullNodeSimulator, ChiaServer, BlockTools], rewards_only_tx_block: bool
122
+ ) -> None:
123
+ """
124
+ Tests that `request_block_headers` returns a transactions filter that
125
+ correctly reflects the blocks transactions.
126
+
127
+ We use `rewards_only_tx_block` to control whether the test transaction
128
+ block contains our test spend as well, or just the reward coins.
129
+
130
+ For completeness, we're also comparing the outcome of
131
+ `request_block_headers` in this regard, to `request_header_blocks` as
132
+ well as `request_block_header`.
133
+ """
134
+ full_node_api, _, bt = one_node_one_block
135
+ ph = SerializedProgram.to(1).get_tree_hash()
136
+ for _ in range(2):
137
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
138
+ if rewards_only_tx_block:
139
+ # Generate a transaction block without any spends
140
+ sb = None
141
+ else:
142
+ # Generate a transaction block with our test spend
143
+ coins = await full_node_api.full_node.coin_store.get_coin_records_by_puzzle_hash(False, ph)
144
+ [parent_coin] = [c.coin for c in coins if c.coin.amount == 250_000_000_000]
145
+ sb = SpendBundle(
146
+ [
147
+ make_spend(
148
+ parent_coin, SerializedProgram.to(1), SerializedProgram.to([[ConditionOpcode.CREATE_COIN, ph, 42]])
149
+ )
150
+ ],
151
+ G2Element(),
152
+ )
153
+ blocks = await full_node_api.get_all_full_blocks()
154
+ blocks = bt.get_consecutive_blocks(1, blocks, guarantee_transaction_block=True, transaction_data=sb)
155
+ new_block = blocks[-1]
156
+ await full_node_api.full_node.add_block(new_block)
157
+ # Compute the expected transactions filter
158
+ if rewards_only_tx_block:
159
+ byte_array_tx = [bytearray(coin.puzzle_hash) for coin in new_block.get_included_reward_coins()]
160
+ else:
161
+ assert sb is not None
162
+ [test_spend] = sb.additions()
163
+ byte_array_tx = (
164
+ [bytearray(test_spend.puzzle_hash)]
165
+ + [bytearray(coin.puzzle_hash) for coin in new_block.get_included_reward_coins()]
166
+ + [bytearray(parent_coin.name())]
167
+ )
168
+ expected_transactions_filter = bytes(PyBIP158(byte_array_tx).GetEncoded())
169
+ # Perform the request and check the transactions filter
170
+ msg = await full_node_api.request_block_headers(
171
+ wallet_protocol.RequestBlockHeaders(uint32(new_block.height), uint32(new_block.height), True)
172
+ )
173
+ assert msg is not None
174
+ res_block_headers = RespondBlockHeaders.from_bytes(msg.data)
175
+ block_headers = res_block_headers.header_blocks
176
+ assert len(block_headers) == 1
177
+ block_header = block_headers[0]
178
+ assert block_header.transactions_filter == expected_transactions_filter
179
+ # Go further and compare this to the outcome of request_header_blocks
180
+ msg = await full_node_api.request_header_blocks(
181
+ wallet_protocol.RequestHeaderBlocks(uint32(new_block.height), uint32(new_block.height))
182
+ )
183
+ assert msg is not None
184
+ block_headers_res = RespondBlockHeaders.from_bytes(msg.data)
185
+ assert block_headers_res.header_blocks == block_headers
186
+ assert block_headers_res.header_blocks[0].transactions_filter == expected_transactions_filter
187
+ # Go even further and compare this to the outcome of request_block_header
188
+ msg = await full_node_api.request_block_header(wallet_protocol.RequestBlockHeader(uint32(new_block.height)))
189
+ assert msg is not None
190
+ block_header_res = RespondBlockHeader.from_bytes(msg.data)
191
+ assert block_header_res.header_block == block_header
192
+ assert block_header_res.header_block.transactions_filter == expected_transactions_filter
193
+
194
+
195
+ # @pytest.mark.parametrize(
196
+ # "test_case",
197
+ # [(1_000_000, 10_000_010, False, ProtocolMessageTypes.reject_block_headers)],
198
+ # [(80, 99, False, ProtocolMessageTypes.respond_block_headers)],
199
+ # [(10, 8, False, None)],
200
+ # )
201
+ @pytest.mark.anyio
202
+ async def test_request_block_headers_rejected(
203
+ simulator_and_wallet: OldSimulatorsAndWallets, default_400_blocks: list[FullBlock]
204
+ ) -> None:
205
+ # Tests the edge case of receiving funds right before the recent blocks in weight proof
206
+ [full_node_api], _, _ = simulator_and_wallet
207
+
208
+ # start_height, end_height, return_filter, expected_res = test_case
209
+
210
+ msg = await full_node_api.request_block_headers(
211
+ wallet_protocol.RequestBlockHeaders(uint32(1_000_000), uint32(1_000_010), False)
212
+ )
213
+ assert msg is not None
214
+ assert msg.type == ProtocolMessageTypes.reject_block_headers.value
215
+
216
+ await add_blocks_in_batches(default_400_blocks[:150], full_node_api.full_node)
217
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(80), uint32(99), False))
218
+ assert msg is not None
219
+ assert msg.type == ProtocolMessageTypes.respond_block_headers.value
220
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(10), uint32(8), False))
221
+ assert msg is not None
222
+ assert msg.type == ProtocolMessageTypes.reject_block_headers.value
223
+
224
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(10), uint32(8), True))
225
+ assert msg is not None
226
+ assert msg.type == ProtocolMessageTypes.reject_block_headers.value
227
+
228
+ # test for 128 blocks to fetch at once limit
229
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(10), uint32(140), True))
230
+ assert msg is not None
231
+ assert msg.type == ProtocolMessageTypes.reject_block_headers.value
232
+
233
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(90), uint32(160), False))
234
+ assert msg is not None
235
+ assert msg.type == ProtocolMessageTypes.reject_block_headers.value
236
+ msg = await full_node_api.request_block_headers(wallet_protocol.RequestBlockHeaders(uint32(90), uint32(160), True))
237
+ assert msg is not None
238
+ assert msg.type == ProtocolMessageTypes.reject_block_headers.value
239
+
240
+
241
+ @pytest.mark.parametrize(
242
+ "two_wallet_nodes",
243
+ [dict(disable_capabilities=[Capability.BLOCK_HEADERS]), dict(disable_capabilities=[Capability.BASE])],
244
+ indirect=True,
245
+ )
246
+ @pytest.mark.limit_consensus_modes(reason="save time")
247
+ @pytest.mark.anyio
248
+ async def test_basic_sync_wallet(
249
+ two_wallet_nodes: OldSimulatorsAndWallets,
250
+ default_400_blocks: list[FullBlock],
251
+ self_hostname: str,
252
+ use_delta_sync: bool,
253
+ ) -> None:
254
+ [full_node_api], wallets, bt = two_wallet_nodes
255
+ full_node = full_node_api.full_node
256
+ full_node_server = full_node.server
257
+
258
+ # Trusted node sync
259
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
260
+ wallets[0][0].config["use_delta_sync"] = use_delta_sync
261
+
262
+ # Untrusted node sync
263
+ wallets[1][0].config["trusted_peers"] = {}
264
+ wallets[1][0].config["use_delta_sync"] = use_delta_sync
265
+
266
+ await add_blocks_in_batches(default_400_blocks, full_node)
267
+ for wallet_node, wallet_server in wallets:
268
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
269
+
270
+ for wallet_node, wallet_server in wallets:
271
+ await time_out_assert(100, wallet_height_at_least, True, wallet_node, len(default_400_blocks) - 1)
272
+
273
+ # Tests a reorg with the wallet
274
+ num_blocks = 30
275
+ blocks_reorg = bt.get_consecutive_blocks(num_blocks - 1, block_list_input=default_400_blocks[:-5])
276
+ blocks_reorg = bt.get_consecutive_blocks(1, blocks_reorg, guarantee_transaction_block=True, current_time=True)
277
+
278
+ await add_blocks_in_batches(blocks_reorg[1:], full_node)
279
+
280
+ for wallet_node, wallet_server in wallets:
281
+ await time_out_assert(
282
+ 100, wallet_height_at_least, True, wallet_node, len(default_400_blocks) + num_blocks - 5 - 1
283
+ )
284
+ await time_out_assert(20, wallet_node.wallet_state_manager.synced)
285
+ await disconnect_all(wallet_server)
286
+ assert not (await wallet_node.wallet_state_manager.synced())
287
+
288
+
289
+ @pytest.mark.parametrize(
290
+ "two_wallet_nodes",
291
+ [dict(disable_capabilities=[Capability.BLOCK_HEADERS]), dict(disable_capabilities=[Capability.BASE])],
292
+ indirect=True,
293
+ )
294
+ @pytest.mark.limit_consensus_modes(reason="save time")
295
+ @pytest.mark.anyio
296
+ async def test_almost_recent(
297
+ two_wallet_nodes: OldSimulatorsAndWallets,
298
+ default_400_blocks: list[FullBlock],
299
+ self_hostname: str,
300
+ blockchain_constants: ConsensusConstants,
301
+ use_delta_sync: bool,
302
+ ) -> None:
303
+ # Tests the edge case of receiving funds right before the recent blocks in weight proof
304
+ [full_node_api], wallets, bt = two_wallet_nodes
305
+ full_node = full_node_api.full_node
306
+ full_node_server = full_node.server
307
+
308
+ # Trusted node sync
309
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
310
+ wallets[0][0].config["use_delta_sync"] = use_delta_sync
311
+
312
+ # Untrusted node sync
313
+ wallets[1][0].config["trusted_peers"] = {}
314
+ wallets[1][0].config["use_delta_sync"] = use_delta_sync
315
+
316
+ base_num_blocks = 400
317
+ await add_blocks_in_batches(default_400_blocks, full_node)
318
+
319
+ all_blocks = default_400_blocks
320
+ both_phs = []
321
+ for wallet_node, wallet_server in wallets:
322
+ wallet = wallet_node.wallet_state_manager.main_wallet
323
+ both_phs.append(await wallet.get_new_puzzlehash())
324
+
325
+ for i in range(20):
326
+ # Tests a reorg with the wallet
327
+ ph = both_phs[i % 2]
328
+ all_blocks = bt.get_consecutive_blocks(1, block_list_input=all_blocks, pool_reward_puzzle_hash=ph)
329
+ await full_node.add_block(all_blocks[-1])
330
+
331
+ new_blocks = bt.get_consecutive_blocks(
332
+ blockchain_constants.WEIGHT_PROOF_RECENT_BLOCKS + 10, block_list_input=all_blocks
333
+ )
334
+
335
+ await add_blocks_in_batches(new_blocks[base_num_blocks + 20 :], full_node)
336
+
337
+ for wallet_node, wallet_server in wallets:
338
+ wallet = wallet_node.wallet_state_manager.main_wallet
339
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
340
+ await time_out_assert(30, wallet.get_confirmed_balance, 10 * calculate_pool_reward(uint32(1000)))
341
+
342
+
343
+ @pytest.mark.anyio
344
+ async def test_backtrack_sync_wallet(
345
+ two_wallet_nodes: OldSimulatorsAndWallets,
346
+ default_400_blocks: list[FullBlock],
347
+ self_hostname: str,
348
+ use_delta_sync: bool,
349
+ ) -> None:
350
+ full_nodes, wallets, _ = two_wallet_nodes
351
+ full_node_api = full_nodes[0]
352
+ full_node_server = full_node_api.full_node.server
353
+
354
+ # Trusted node sync
355
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
356
+ wallets[0][0].config["use_delta_sync"] = use_delta_sync
357
+
358
+ # Untrusted node sync
359
+ wallets[1][0].config["trusted_peers"] = {}
360
+ wallets[1][0].config["use_delta_sync"] = use_delta_sync
361
+
362
+ for block in default_400_blocks[:20]:
363
+ await full_node_api.full_node.add_block(block)
364
+
365
+ for wallet_node, wallet_server in wallets:
366
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
367
+
368
+ for wallet_node, wallet_server in wallets:
369
+ await time_out_assert(100, wallet_height_at_least, True, wallet_node, 19)
370
+
371
+
372
+ # Tests a reorg with the wallet
373
+ @pytest.mark.anyio
374
+ async def test_short_batch_sync_wallet(
375
+ two_wallet_nodes: OldSimulatorsAndWallets,
376
+ default_400_blocks: list[FullBlock],
377
+ self_hostname: str,
378
+ use_delta_sync: bool,
379
+ ) -> None:
380
+ [full_node_api], wallets, _ = two_wallet_nodes
381
+ full_node = full_node_api.full_node
382
+ full_node_server = full_node.server
383
+
384
+ # Trusted node sync
385
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
386
+ wallets[0][0].config["use_delta_sync"] = use_delta_sync
387
+
388
+ # Untrusted node sync
389
+ wallets[1][0].config["trusted_peers"] = {}
390
+ wallets[1][0].config["use_delta_sync"] = use_delta_sync
391
+
392
+ await add_blocks_in_batches(default_400_blocks[:200], full_node)
393
+
394
+ for wallet_node, wallet_server in wallets:
395
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
396
+
397
+ for wallet_node, wallet_server in wallets:
398
+ await time_out_assert(100, wallet_height_at_least, True, wallet_node, 199)
399
+
400
+
401
+ @pytest.mark.limit_consensus_modes(reason="save time")
402
+ @pytest.mark.anyio
403
+ async def test_long_sync_wallet(
404
+ two_wallet_nodes: OldSimulatorsAndWallets,
405
+ default_1000_blocks: list[FullBlock],
406
+ default_400_blocks: list[FullBlock],
407
+ self_hostname: str,
408
+ use_delta_sync: bool,
409
+ ) -> None:
410
+ [full_node_api], wallets, bt = two_wallet_nodes
411
+ full_node = full_node_api.full_node
412
+ full_node_server = full_node.server
413
+
414
+ # Trusted node sync
415
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
416
+ wallets[0][0].config["use_delta_sync"] = use_delta_sync
417
+
418
+ # Untrusted node sync
419
+ wallets[1][0].config["trusted_peers"] = {}
420
+ wallets[1][0].config["use_delta_sync"] = use_delta_sync
421
+ await add_blocks_in_batches(default_400_blocks, full_node)
422
+
423
+ for wallet_node, wallet_server in wallets:
424
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
425
+
426
+ for wallet_node, wallet_server in wallets:
427
+ await time_out_assert(600, wallet_height_at_least, True, wallet_node, len(default_400_blocks) - 1)
428
+
429
+ # Tests a long reorg
430
+ await add_blocks_in_batches(default_1000_blocks, full_node)
431
+
432
+ # ony the wallet with untrusted sync needs to reconnect
433
+ await disconnect_all_and_reconnect(wallets[1][1], full_node_server, self_hostname)
434
+ for wallet_node, wallet_server in wallets:
435
+ log.info(f"wallet node height is {await wallet_node.wallet_state_manager.blockchain.get_finished_sync_up_to()}")
436
+ await time_out_assert(200, wallet_height_at_least, True, wallet_node, len(default_1000_blocks) - 1)
437
+
438
+ # Tests a short reorg
439
+ num_blocks = 30
440
+ blocks_reorg = bt.get_consecutive_blocks(num_blocks, block_list_input=default_1000_blocks[:-5])
441
+
442
+ block_record = await full_node.blockchain.get_block_record_from_db(blocks_reorg[-num_blocks - 10].header_hash)
443
+ sub_slot_iters, difficulty = get_next_sub_slot_iters_and_difficulty(
444
+ full_node.constants, True, block_record, full_node.blockchain
445
+ )
446
+ fork_height = blocks_reorg[-num_blocks - 10].height - 1
447
+ await full_node.add_block_batch(
448
+ blocks_reorg[-num_blocks - 10 : -1],
449
+ PeerInfo("0.0.0.0", 0),
450
+ ForkInfo(fork_height, fork_height, blocks_reorg[-num_blocks - 10].prev_header_hash),
451
+ ValidationState(sub_slot_iters, difficulty, None),
452
+ )
453
+ await full_node.add_block(blocks_reorg[-1])
454
+
455
+ for wallet_node, wallet_server in wallets:
456
+ await time_out_assert(
457
+ 120, wallet_height_at_least, True, wallet_node, len(default_1000_blocks) + num_blocks - 5 - 1
458
+ )
459
+
460
+
461
+ @pytest.mark.limit_consensus_modes(reason="save time")
462
+ @pytest.mark.anyio
463
+ async def test_wallet_reorg_sync(
464
+ two_wallet_nodes: OldSimulatorsAndWallets,
465
+ default_400_blocks: list[FullBlock],
466
+ self_hostname: str,
467
+ use_delta_sync: bool,
468
+ ) -> None:
469
+ num_blocks = 5
470
+ [full_node_api], wallets, bt = two_wallet_nodes
471
+ full_node = full_node_api.full_node
472
+ full_node_server = full_node.server
473
+
474
+ # Trusted node sync
475
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
476
+ wallets[0][0].config["use_delta_sync"] = use_delta_sync
477
+
478
+ # Untrusted node sync
479
+ wallets[1][0].config["trusted_peers"] = {}
480
+ wallets[1][0].config["use_delta_sync"] = use_delta_sync
481
+
482
+ phs = []
483
+ for wallet_node, wallet_server in wallets:
484
+ wallet = wallet_node.wallet_state_manager.main_wallet
485
+ phs.append(await wallet.get_new_puzzlehash())
486
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
487
+
488
+ # Insert 400 blocks
489
+ await add_blocks_in_batches(default_400_blocks, full_node)
490
+ # Farm few more with reward
491
+
492
+ wallet_node1, _ = wallets[0]
493
+ wallet1 = wallet_node.wallet_state_manager.main_wallet
494
+ wallet_node2, _ = wallets[1]
495
+ wallet2 = wallet_node2.wallet_state_manager.main_wallet
496
+
497
+ await time_out_assert(60, wallet_height_at_least, True, wallet1, 399)
498
+ await time_out_assert(60, wallet_height_at_least, True, wallet2, 399)
499
+
500
+ for _ in range(num_blocks - 1):
501
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(phs[0]))
502
+ for _ in range(num_blocks):
503
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(phs[1]))
504
+
505
+ # Confirm we have the funds
506
+ funds = sum(
507
+ calculate_pool_reward(uint32(i)) + calculate_base_farmer_reward(uint32(i)) for i in range(1, num_blocks)
508
+ )
509
+
510
+ await time_out_assert(60, wallet_height_at_least, True, wallet1, 408)
511
+ await time_out_assert(60, wallet1.get_confirmed_balance, funds)
512
+ await time_out_assert(60, get_tx_count, 2 * (num_blocks - 1), wallet_node1.wallet_state_manager, 1)
513
+
514
+ await time_out_assert(60, wallet_height_at_least, True, wallet2, 408)
515
+ await time_out_assert(60, wallet2.get_confirmed_balance, funds)
516
+ await time_out_assert(60, get_tx_count, 2 * (num_blocks - 1), wallet_node2.wallet_state_manager, 1)
517
+
518
+ # Reorg blocks that carry reward
519
+ num_blocks = 30
520
+ blocks_reorg = bt.get_consecutive_blocks(num_blocks, block_list_input=default_400_blocks[:-5])
521
+
522
+ await add_blocks_in_batches(blocks_reorg[-30:], full_node)
523
+
524
+ for wallet_node, wallet_server in wallets:
525
+ wallet = wallet_node.wallet_state_manager.main_wallet
526
+ await time_out_assert(60, get_tx_count, 0, wallet_node.wallet_state_manager, 1)
527
+ await time_out_assert(60, wallet.get_confirmed_balance, 0)
528
+
529
+
530
+ @pytest.mark.limit_consensus_modes(reason="save time")
531
+ @pytest.mark.anyio
532
+ async def test_wallet_reorg_get_coinbase(
533
+ two_wallet_nodes: OldSimulatorsAndWallets, default_400_blocks: list[FullBlock], self_hostname: str
534
+ ) -> None:
535
+ [full_node_api], wallets, bt = two_wallet_nodes
536
+ full_node = full_node_api.full_node
537
+ full_node_server = full_node.server
538
+
539
+ # Trusted node sync
540
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
541
+
542
+ # Untrusted node sync
543
+ wallets[1][0].config["trusted_peers"] = {}
544
+
545
+ for wallet_node, wallet_server in wallets:
546
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
547
+
548
+ # Insert 400 blocks
549
+ await add_blocks_in_batches(default_400_blocks, full_node)
550
+
551
+ # Reorg blocks that carry reward
552
+ num_blocks_reorg = 30
553
+ blocks_reorg = bt.get_consecutive_blocks(num_blocks_reorg, block_list_input=default_400_blocks[:-5])
554
+ await add_blocks_in_batches(blocks_reorg[:-6], full_node)
555
+
556
+ await full_node.add_block(blocks_reorg[-6])
557
+
558
+ for wallet_node, wallet_server in wallets:
559
+ await time_out_assert(30, get_tx_count, 0, wallet_node.wallet_state_manager, 1)
560
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=30)
561
+
562
+ num_blocks_reorg_1 = 40
563
+ all_blocks_reorg_2 = blocks_reorg[:-30]
564
+ for wallet_node, wallet_server in wallets:
565
+ wallet = wallet_node.wallet_state_manager.main_wallet
566
+ ph = await wallet.get_new_puzzlehash()
567
+ all_blocks_reorg_2 = bt.get_consecutive_blocks(
568
+ 1, pool_reward_puzzle_hash=ph, farmer_reward_puzzle_hash=ph, block_list_input=all_blocks_reorg_2
569
+ )
570
+ blocks_reorg_2 = bt.get_consecutive_blocks(num_blocks_reorg_1, block_list_input=all_blocks_reorg_2)
571
+ block_record = await full_node.blockchain.get_block_record_from_db(blocks_reorg_2[-45].header_hash)
572
+ sub_slot_iters, difficulty = get_next_sub_slot_iters_and_difficulty(
573
+ full_node.constants, True, block_record, full_node.blockchain
574
+ )
575
+ await full_node.add_block_batch(
576
+ blocks_reorg_2[-44:],
577
+ PeerInfo("0.0.0.0", 0),
578
+ ForkInfo(blocks_reorg_2[-45].height, blocks_reorg_2[-45].height, blocks_reorg_2[-45].header_hash),
579
+ ValidationState(sub_slot_iters, difficulty, None),
580
+ )
581
+
582
+ for wallet_node, wallet_server in wallets:
583
+ await disconnect_all_and_reconnect(wallet_server, full_node_server, self_hostname)
584
+
585
+ # Confirm we have the funds
586
+ funds = calculate_pool_reward(uint32(len(all_blocks_reorg_2))) + calculate_base_farmer_reward(
587
+ uint32(len(all_blocks_reorg_2))
588
+ )
589
+
590
+ for wallet_node, wallet_server in wallets:
591
+ wallet = wallet_node.wallet_state_manager.main_wallet
592
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=60)
593
+
594
+ await time_out_assert(20, get_tx_count, 2, wallet_node.wallet_state_manager, 1)
595
+ await time_out_assert(20, wallet.get_confirmed_balance, funds)
596
+
597
+
598
+ @pytest.mark.anyio
599
+ async def test_request_additions_errors(simulator_and_wallet: OldSimulatorsAndWallets, self_hostname: str) -> None:
600
+ full_nodes, wallets, _ = simulator_and_wallet
601
+ wallet_node, wallet_server = wallets[0]
602
+ wallet = wallet_node.wallet_state_manager.main_wallet
603
+ ph = await wallet.get_new_puzzlehash()
604
+
605
+ full_node_api = full_nodes[0]
606
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_api.full_node.server.get_port()), None)
607
+
608
+ for _ in range(2):
609
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
610
+
611
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
612
+
613
+ last_block: Optional[BlockRecord] = full_node_api.full_node.blockchain.get_peak()
614
+ assert last_block is not None
615
+
616
+ # Invalid height
617
+ with pytest.raises(ValueError):
618
+ await full_node_api.request_additions(RequestAdditions(uint32(100), last_block.header_hash, [ph]))
619
+
620
+ # Invalid header hash
621
+ with pytest.raises(ValueError):
622
+ await full_node_api.request_additions(RequestAdditions(last_block.height, std_hash(b""), [ph]))
623
+
624
+ # No results
625
+ fake_coin = std_hash(b"")
626
+ assert ph != fake_coin
627
+ res1 = await full_node_api.request_additions(
628
+ RequestAdditions(last_block.height, last_block.header_hash, [fake_coin])
629
+ )
630
+ assert res1 is not None
631
+ response = RespondAdditions.from_bytes(res1.data)
632
+ assert response.height == last_block.height
633
+ assert response.header_hash == last_block.header_hash
634
+ assert response.proofs is not None
635
+ assert len(response.proofs) == 1
636
+ assert len(response.coins) == 1
637
+ full_block = await full_node_api.full_node.block_store.get_full_block(last_block.header_hash)
638
+ assert full_block is not None
639
+ assert full_block.foliage_transaction_block is not None
640
+ root = full_block.foliage_transaction_block.additions_root
641
+ assert confirm_not_included_already_hashed(root, response.proofs[0][0], response.proofs[0][1])
642
+ # proofs is a tuple of (puzzlehash, proof, proof_2)
643
+ # proof is a proof of inclusion (or exclusion) of that puzzlehash
644
+ # proof_2 is a proof of all the coins with that puzzlehash
645
+ # all coin names are concatenated and hashed into one entry in the merkle set for proof_2
646
+ # the response contains the list of coins so you can check the proof_2
647
+
648
+ assert response.proofs[0][0] == std_hash(b"")
649
+ assert response.proofs[0][1] is not None
650
+ assert response.proofs[0][2] is None
651
+
652
+
653
+ @pytest.mark.anyio
654
+ async def test_request_additions_success(simulator_and_wallet: OldSimulatorsAndWallets, self_hostname: str) -> None:
655
+ full_nodes, wallets, _ = simulator_and_wallet
656
+ wallet_node, wallet_server = wallets[0]
657
+ wallet = wallet_node.wallet_state_manager.main_wallet
658
+ ph = await wallet.get_new_puzzlehash()
659
+
660
+ full_node_api = full_nodes[0]
661
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_api.full_node.server.get_port()), None)
662
+
663
+ for _ in range(2):
664
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
665
+
666
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
667
+
668
+ payees: list[Payment] = []
669
+ for i in range(10):
670
+ payee_ph = await wallet.get_new_puzzlehash()
671
+ payees.append(Payment(payee_ph, uint64(i + 100)))
672
+ payees.append(Payment(payee_ph, uint64(i + 200)))
673
+
674
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
675
+ await wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
676
+ [tx] = action_scope.side_effects.transactions
677
+ assert tx.spend_bundle is not None
678
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
679
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
680
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
681
+
682
+ last_block = full_node_api.full_node.blockchain.get_peak()
683
+ assert last_block is not None
684
+ await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)
685
+
686
+ res2 = await full_node_api.request_additions(
687
+ RequestAdditions(last_block.height, None, [payees[0].puzzle_hash, payees[2].puzzle_hash, std_hash(b"1")])
688
+ )
689
+
690
+ assert res2 is not None
691
+ response = RespondAdditions.from_bytes(res2.data)
692
+ assert response.height == last_block.height
693
+ assert response.header_hash == last_block.header_hash
694
+ assert response.proofs is not None
695
+ assert len(response.proofs) == 3
696
+
697
+ # First two PHs are included
698
+ for i in range(2):
699
+ assert response.proofs[i][0] in {payees[j].puzzle_hash for j in (0, 2)}
700
+ assert response.proofs[i][1] is not None
701
+ assert response.proofs[i][2] is not None
702
+
703
+ # Third PH is not included
704
+ assert response.proofs[2][2] is None
705
+
706
+ coin_list_dict = {p: coin_list for p, coin_list in response.coins}
707
+
708
+ assert len(coin_list_dict) == 3
709
+ for p, coin_list in coin_list_dict.items():
710
+ if p == std_hash(b"1"):
711
+ # this is the one that is not included
712
+ assert len(coin_list) == 0
713
+ else:
714
+ for coin in coin_list:
715
+ assert coin.puzzle_hash == p
716
+ # The other ones are included
717
+ assert len(coin_list) == 2
718
+
719
+ # None for puzzle hashes returns all coins and no proofs
720
+ res3 = await full_node_api.request_additions(RequestAdditions(last_block.height, last_block.header_hash, None))
721
+
722
+ assert res3 is not None
723
+ response = RespondAdditions.from_bytes(res3.data)
724
+ assert response.height == last_block.height
725
+ assert response.header_hash == last_block.header_hash
726
+ assert response.proofs is None
727
+ assert len(response.coins) == 12
728
+ assert sum(len(c_list) for _, c_list in response.coins) == 24
729
+
730
+ # [] for puzzle hashes returns nothing
731
+ res4 = await full_node_api.request_additions(RequestAdditions(last_block.height, last_block.header_hash, []))
732
+ assert res4 is not None
733
+ response = RespondAdditions.from_bytes(res4.data)
734
+ assert response.proofs == []
735
+ assert len(response.coins) == 0
736
+
737
+
738
+ @pytest.mark.anyio
739
+ async def test_get_wp_fork_point(
740
+ default_10000_blocks: list[FullBlock], blockchain_constants: ConsensusConstants
741
+ ) -> None:
742
+ blocks = default_10000_blocks
743
+ header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks, blockchain_constants)
744
+ wpf = WeightProofHandler(blockchain_constants, BlockchainMock(sub_blocks, header_cache, height_to_hash, summaries))
745
+ wp1 = await wpf.get_proof_of_weight(header_cache[height_to_hash[uint32(9_000)]].header_hash)
746
+ assert wp1 is not None
747
+ wp2 = await wpf.get_proof_of_weight(header_cache[height_to_hash[uint32(9_030)]].header_hash)
748
+ assert wp2 is not None
749
+ wp3 = await wpf.get_proof_of_weight(header_cache[height_to_hash[uint32(7_500)]].header_hash)
750
+ assert wp3 is not None
751
+ wp4 = await wpf.get_proof_of_weight(header_cache[height_to_hash[uint32(8_700)]].header_hash)
752
+ assert wp4 is not None
753
+ wp5 = await wpf.get_proof_of_weight(header_cache[height_to_hash[uint32(9_700)]].header_hash)
754
+ assert wp5 is not None
755
+ wp6 = await wpf.get_proof_of_weight(header_cache[height_to_hash[uint32(9_010)]].header_hash)
756
+ assert wp6 is not None
757
+ fork12 = get_wp_fork_point(blockchain_constants, wp1, wp2)
758
+ fork13 = get_wp_fork_point(blockchain_constants, wp3, wp1)
759
+ fork14 = get_wp_fork_point(blockchain_constants, wp4, wp1)
760
+ fork23 = get_wp_fork_point(blockchain_constants, wp3, wp2)
761
+ fork24 = get_wp_fork_point(blockchain_constants, wp4, wp2)
762
+ fork34 = get_wp_fork_point(blockchain_constants, wp3, wp4)
763
+ fork45 = get_wp_fork_point(blockchain_constants, wp4, wp5)
764
+ fork16 = get_wp_fork_point(blockchain_constants, wp1, wp6)
765
+
766
+ # overlap between recent chain in wps, fork point is the tip of the shorter wp
767
+ assert fork12 == wp1.recent_chain_data[-1].height
768
+ assert fork16 == wp1.recent_chain_data[-1].height
769
+
770
+ # if there is an overlap between the recent chains we can find the exact fork point
771
+ # if not we should get the latest block with a sub epoch summary that exists in both wp's
772
+ # this can happen in fork24 and fork14 since they are not very far and also not very close
773
+
774
+ if wp2.recent_chain_data[0].height > wp4.recent_chain_data[-1].height:
775
+ assert fork24 in summaries.keys()
776
+ assert fork24 < wp4.recent_chain_data[-1].height
777
+ else:
778
+ assert fork24 == wp4.recent_chain_data[-1].height
779
+
780
+ if wp1.recent_chain_data[0].height > wp4.recent_chain_data[-1].height:
781
+ assert fork14 in summaries.keys()
782
+ assert fork14 < wp4.recent_chain_data[-1].height
783
+ else:
784
+ assert fork14 == wp4.recent_chain_data[-1].height
785
+
786
+ # no overlap between recent chain in wps, fork point
787
+ # is the latest block with a sub epoch summary that exists in both wp's
788
+ assert fork13 in summaries.keys()
789
+ assert fork13 < wp3.recent_chain_data[-1].height
790
+ assert fork23 in summaries.keys()
791
+ assert fork23 < wp3.recent_chain_data[-1].height
792
+ assert fork34 in summaries.keys()
793
+ assert fork23 < wp3.recent_chain_data[-1].height
794
+ assert fork45 in summaries.keys()
795
+ assert fork45 < wp4.recent_chain_data[-1].height
796
+
797
+
798
+ """
799
+ This tests that a wallet filters out the dust properly.
800
+ It runs in seven phases:
801
+ 1. Create a single dust coin.
802
+ Typically (though there are edge cases), this coin will not be filtered.
803
+ 2. Create dust coins until the filter threshold has been reached.
804
+ At this point, none of the dust should be filtered.
805
+ 3. Create 10 coins that are exactly the size of the filter threshold.
806
+ These should not be filtered because they are not dust.
807
+ 4. Create one more dust coin. This coin should be filtered.
808
+ 5. Create 5 coins below the threshold and 5 at or above.
809
+ Those below the threshold should get filtered, and those above should not.
810
+ 6. Clear all coins from the dust wallet.
811
+ Send to the dust wallet "spam_filter_after_n_txs" coins that are equal in value to "xch_spam_amount".
812
+ Send 1 mojo from the dust wallet. The dust wallet should receive a change coin valued at "xch_spam_amount-1".
813
+ 7: Create an NFT wallet for the farmer wallet, and generate an NFT in that wallet.
814
+ Create an NFT wallet for the dust wallet.
815
+ Send the NFT to the dust wallet. The NFT should not be filtered.
816
+ """
817
+
818
+
819
+ @pytest.mark.anyio
820
+ @pytest.mark.parametrize(
821
+ "spam_filter_after_n_txs, xch_spam_amount, dust_value",
822
+ [
823
+ # In the following tests, the filter is run right away:
824
+ (0, 1, 1), # nothing is filtered
825
+ # In the following tests, 1 coin will be created in part 1, and 9 in part 2:
826
+ (10, 10_000_000_000, 1), # everything is dust
827
+ (10, 10_000_000_000, 10_000_000_000), # max dust threshold, dust is same size so not filtered
828
+ # Test with more coins
829
+ (105, 1_000_000, 1), # default filter level (1m mojos), default dust size (1)
830
+ ],
831
+ )
832
+ async def test_dusted_wallet(
833
+ self_hostname: str,
834
+ two_wallet_nodes_custom_spam_filtering: OldSimulatorsAndWallets,
835
+ spam_filter_after_n_txs: int,
836
+ xch_spam_amount: int,
837
+ dust_value: int,
838
+ use_delta_sync: bool,
839
+ ) -> None:
840
+ full_nodes, wallets, _ = two_wallet_nodes_custom_spam_filtering
841
+
842
+ farm_wallet_node, farm_wallet_server = wallets[0]
843
+ farm_wallet_node.config["use_delta_sync"] = use_delta_sync
844
+ dust_wallet_node, dust_wallet_server = wallets[1]
845
+ dust_wallet_node.config["use_delta_sync"] = use_delta_sync
846
+
847
+ # Create two wallets, one for farming (not used for testing), and one for testing dust.
848
+ farm_wallet = farm_wallet_node.wallet_state_manager.main_wallet
849
+ dust_wallet = dust_wallet_node.wallet_state_manager.main_wallet
850
+ ph = await farm_wallet.get_new_puzzlehash()
851
+
852
+ full_node_api = full_nodes[0]
853
+
854
+ # It's also possible to obtain the current settings for spam_filter_after_n_txs and xch_spam_amount
855
+ # spam_filter_after_n_txs = wallets[0][0].config["spam_filter_after_n_txs"]
856
+ # xch_spam_amount = wallets[0][0].config["xch_spam_amount"]
857
+ # dust_value=1
858
+
859
+ # Verify legal values for the settings to be tested
860
+ # If spam_filter_after_n_txs is greater than 250, this test will take a long time to run.
861
+ # Current max value for xch_spam_amount is 0.01 XCH.
862
+ # If needed, this could be increased but we would need to farm more blocks.
863
+ # The max dust_value could be increased, but would require farming more blocks.
864
+ assert spam_filter_after_n_txs >= 0
865
+ assert spam_filter_after_n_txs <= 250
866
+ assert xch_spam_amount >= 1
867
+ assert xch_spam_amount <= 10_000_000_000
868
+ assert dust_value >= 1
869
+ assert dust_value <= 10_000_000_000
870
+
871
+ # start both clients
872
+ await farm_wallet_server.start_client(PeerInfo(self_hostname, full_node_api.full_node.server.get_port()), None)
873
+ await dust_wallet_server.start_client(PeerInfo(self_hostname, full_node_api.full_node.server.get_port()), None)
874
+
875
+ # Farm two blocks
876
+ for _ in range(2):
877
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
878
+
879
+ # sync both nodes
880
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
881
+
882
+ # Part 1: create a single dust coin
883
+ payees: list[Payment] = []
884
+ payee_ph = await dust_wallet.get_new_puzzlehash()
885
+ payees.append(Payment(payee_ph, uint64(dust_value)))
886
+
887
+ # construct and send tx
888
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
889
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
890
+ [tx] = action_scope.side_effects.transactions
891
+ assert tx.spend_bundle is not None
892
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
893
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
894
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
895
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
896
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
897
+
898
+ # The dust is only filtered at this point if spam_filter_after_n_txs is 0 and xch_spam_amount is > dust_value.
899
+ if spam_filter_after_n_txs > 0:
900
+ dust_coins = 1
901
+ large_dust_coins = 0
902
+ large_dust_balance = 0
903
+ elif xch_spam_amount <= dust_value:
904
+ dust_coins = 0
905
+ large_dust_coins = 1
906
+ large_dust_balance = dust_value
907
+ else:
908
+ dust_coins = 0
909
+ large_dust_coins = 0
910
+ large_dust_balance = 0
911
+
912
+ # Obtain and log important values
913
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
914
+ log.info(f"all_unspent is {all_unspent}")
915
+ small_unspent_count = len([r for r in all_unspent if r.coin.amount < xch_spam_amount])
916
+ balance = await dust_wallet.get_confirmed_balance()
917
+ async with dust_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=False) as action_scope:
918
+ num_coins = len(await dust_wallet.select_coins(uint64(balance), action_scope))
919
+
920
+ log.info(f"Small coin count is {small_unspent_count}")
921
+ log.info(f"Wallet balance is {balance}")
922
+ log.info(f"Number of coins is {num_coins}")
923
+
924
+ log.info(f"spam_filter_after_n_txs {spam_filter_after_n_txs}")
925
+ log.info(f"xch_spam_amount {xch_spam_amount}")
926
+ log.info(f"dust_value {dust_value}")
927
+
928
+ # Verify balance and number of coins not filtered.
929
+ assert balance == dust_coins * dust_value + large_dust_balance
930
+ assert num_coins == dust_coins + large_dust_coins
931
+
932
+ # Part 2: Create dust coins until the filter threshold has been reached.
933
+ # Nothing should be filtered yet (unless spam_filter_after_n_txs is 0).
934
+ payees = []
935
+
936
+ # Determine how much dust to create, recalling that there already is one dust coin.
937
+ new_dust = spam_filter_after_n_txs - 1
938
+ dust_remaining = new_dust
939
+
940
+ while dust_remaining > 0:
941
+ payee_ph = await dust_wallet.get_new_puzzlehash()
942
+ payees.append(Payment(payee_ph, uint64(dust_value)))
943
+
944
+ # After every 100 (at most) coins added, push the tx and advance the chain
945
+ # This greatly speeds up the overall process
946
+ if dust_remaining % 100 == 0 and dust_remaining != new_dust:
947
+ # construct and send tx
948
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
949
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
950
+ [tx] = action_scope.side_effects.transactions
951
+ assert tx.spend_bundle is not None
952
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
953
+
954
+ # advance the chain and sync both wallets
955
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
956
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
957
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
958
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
959
+ # reset payees
960
+ payees = []
961
+
962
+ dust_remaining -= 1
963
+
964
+ # Only need to create tx if there was new dust to be added
965
+ if new_dust >= 1:
966
+ # construct and send tx
967
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
968
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
969
+ [tx] = action_scope.side_effects.transactions
970
+ assert tx.spend_bundle is not None
971
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
972
+
973
+ # advance the chain and sync both wallets
974
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
975
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
976
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
977
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
978
+
979
+ # Obtain and log important values
980
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
981
+ small_unspent_count = len([r for r in all_unspent if r.coin.amount < xch_spam_amount])
982
+ balance = await dust_wallet.get_confirmed_balance()
983
+ # Selecting coins by using the wallet's coin selection algorithm won't work for large
984
+ # numbers of coins, so we'll use the state manager for the rest of the test
985
+ spendable_coins = await dust_wallet_node.wallet_state_manager.get_spendable_coins_for_wallet(1)
986
+ num_coins = len(spendable_coins)
987
+
988
+ log.info(f"Small coin count is {small_unspent_count}")
989
+ log.info(f"Wallet balance is {balance}")
990
+ log.info(f"Number of coins is {num_coins}")
991
+
992
+ # obtain the total expected coins (new_dust could be negative)
993
+ if new_dust > 0:
994
+ dust_coins += new_dust
995
+
996
+ # Make sure the number of coins matches the expected number.
997
+ # At this point, nothing should be getting filtered unless spam_filter_after_n_txs is 0.
998
+ assert dust_coins == spam_filter_after_n_txs
999
+ assert balance == dust_coins * dust_value + large_dust_balance
1000
+ assert num_coins == dust_coins + large_dust_coins
1001
+
1002
+ # Part 3: Create 10 coins that are exactly the size of the filter threshold.
1003
+ # These should not get filtered.
1004
+ large_coins = 10
1005
+
1006
+ payees = []
1007
+
1008
+ for _ in range(large_coins):
1009
+ payee_ph = await dust_wallet.get_new_puzzlehash()
1010
+ payees.append(Payment(payee_ph, uint64(xch_spam_amount)))
1011
+
1012
+ # construct and send tx
1013
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1014
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1015
+ [tx] = action_scope.side_effects.transactions
1016
+ assert tx.spend_bundle is not None
1017
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1018
+
1019
+ # advance the chain and sync both wallets
1020
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1021
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1022
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1023
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1024
+
1025
+ # Obtain and log important values
1026
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1027
+ small_unspent_count = len([r for r in all_unspent if r.coin.amount < xch_spam_amount])
1028
+ balance = await dust_wallet.get_confirmed_balance()
1029
+ spendable_coins = await dust_wallet_node.wallet_state_manager.get_spendable_coins_for_wallet(1)
1030
+ num_coins = len(spendable_coins)
1031
+
1032
+ log.info(f"Small coin count is {small_unspent_count}")
1033
+ log.info(f"Wallet balance is {balance}")
1034
+ log.info(f"Number of coins is {num_coins}")
1035
+
1036
+ large_coin_balance = large_coins * xch_spam_amount
1037
+
1038
+ # Determine whether the filter should have been activated.
1039
+ # Make sure the number of coins matches the expected number.
1040
+ # At this point, nothing should be getting filtered unless spam_filter_after_n_txs is 0.
1041
+ assert dust_coins == spam_filter_after_n_txs
1042
+ assert balance == dust_coins * dust_value + large_coins * xch_spam_amount + large_dust_balance
1043
+ assert num_coins == dust_coins + large_coins + large_dust_coins
1044
+
1045
+ # Part 4: Create one more dust coin to test the threshold
1046
+ payees = []
1047
+
1048
+ payee_ph = await dust_wallet.get_new_puzzlehash()
1049
+ payees.append(Payment(payee_ph, uint64(dust_value)))
1050
+
1051
+ # construct and send tx
1052
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1053
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1054
+ [tx] = action_scope.side_effects.transactions
1055
+ assert tx.spend_bundle is not None
1056
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1057
+
1058
+ # advance the chain and sync both wallets
1059
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1060
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1061
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1062
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1063
+
1064
+ # Obtain and log important values
1065
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1066
+ small_unspent_count = len([r for r in all_unspent if r.coin.amount < xch_spam_amount])
1067
+ balance = await dust_wallet.get_confirmed_balance()
1068
+ spendable_coins = await dust_wallet_node.wallet_state_manager.get_spendable_coins_for_wallet(1)
1069
+ num_coins = len(spendable_coins)
1070
+
1071
+ log.info(f"Small coin count is {small_unspent_count}")
1072
+ log.info(f"Wallet balance is {balance}")
1073
+ log.info(f"Number of coins is {num_coins}")
1074
+
1075
+ # In the edge case where the new "dust" is larger than the threshold,
1076
+ # then it is actually a large dust coin that won't get filtered.
1077
+ if dust_value >= xch_spam_amount:
1078
+ large_dust_coins += 1
1079
+ large_dust_balance += dust_value
1080
+
1081
+ assert dust_coins == spam_filter_after_n_txs
1082
+ assert balance == dust_coins * dust_value + large_coins * xch_spam_amount + large_dust_balance
1083
+ assert num_coins == dust_coins + large_dust_coins + large_coins
1084
+
1085
+ # Part 5: Create 5 coins below the threshold and 5 at or above.
1086
+ # Those below the threshold should get filtered, and those above should not.
1087
+ payees = []
1088
+
1089
+ for i in range(5):
1090
+ payee_ph = await dust_wallet.get_new_puzzlehash()
1091
+
1092
+ # Create a large coin and add on the appropriate balance.
1093
+ payees.append(Payment(payee_ph, uint64(xch_spam_amount + i)))
1094
+ large_coins += 1
1095
+ large_coin_balance += xch_spam_amount + i
1096
+
1097
+ payee_ph = await dust_wallet.get_new_puzzlehash()
1098
+
1099
+ # Make sure we are always creating coins with a positive value.
1100
+ if xch_spam_amount - dust_value - i > 0:
1101
+ payees.append(Payment(payee_ph, uint64(xch_spam_amount - dust_value - i)))
1102
+ else:
1103
+ payees.append(Payment(payee_ph, uint64(dust_value)))
1104
+ # In cases where xch_spam_amount is sufficiently low,
1105
+ # the new dust should be considered a large coina and not be filtered.
1106
+ if xch_spam_amount <= dust_value:
1107
+ large_dust_coins += 1
1108
+ large_dust_balance += dust_value
1109
+
1110
+ # construct and send tx
1111
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1112
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1113
+ [tx] = action_scope.side_effects.transactions
1114
+ assert tx.spend_bundle is not None
1115
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1116
+
1117
+ # advance the chain and sync both wallets
1118
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1119
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1120
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1121
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1122
+
1123
+ # Obtain and log important values
1124
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1125
+ small_unspent_count = len([r for r in all_unspent if r.coin.amount < xch_spam_amount])
1126
+ balance = await dust_wallet.get_confirmed_balance()
1127
+ spendable_coins = await dust_wallet_node.wallet_state_manager.get_spendable_coins_for_wallet(1)
1128
+ num_coins = len(spendable_coins)
1129
+
1130
+ log.info(f"Small coin count is {small_unspent_count}")
1131
+ log.info(f"Wallet balance is {balance}")
1132
+ log.info(f"Number of coins is {num_coins}")
1133
+
1134
+ # The filter should have automatically been activated by now, regardless of filter value
1135
+ assert dust_coins == spam_filter_after_n_txs
1136
+ assert balance == dust_coins * dust_value + large_coin_balance + large_dust_balance
1137
+ assert num_coins == dust_coins + large_dust_coins + large_coins
1138
+
1139
+ # Part 6: Clear all coins from the dust wallet.
1140
+ # Send to the dust wallet "spam_filter_after_n_txs" coins that are equal in value to "xch_spam_amount".
1141
+ # Send 1 mojo from the dust wallet. The dust wallet should receive a change coin valued at "xch_spam_amount-1".
1142
+
1143
+ payee_ph = await farm_wallet.get_new_puzzlehash()
1144
+ payees = [Payment(payee_ph, uint64(balance))]
1145
+
1146
+ # construct and send tx
1147
+ async with dust_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1148
+ await dust_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1149
+ [tx] = action_scope.side_effects.transactions
1150
+ assert tx.spend_bundle is not None
1151
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1152
+
1153
+ # advance the chain and sync both wallets
1154
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1155
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1156
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1157
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1158
+
1159
+ # Obtain and log important values
1160
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1161
+ unspent_count = len(all_unspent)
1162
+ balance = await dust_wallet.get_confirmed_balance()
1163
+
1164
+ # Make sure the dust wallet is empty
1165
+ assert unspent_count == 0
1166
+ assert balance == 0
1167
+
1168
+ # create the same number of dust coins as the filter
1169
+ if spam_filter_after_n_txs > 0:
1170
+ coins_remaining = spam_filter_after_n_txs
1171
+ else:
1172
+ # in the edge case, create one coin
1173
+ coins_remaining = 1
1174
+
1175
+ # The size of the coin to send the dust wallet is the same as xch_spam_amount
1176
+ if xch_spam_amount > 1:
1177
+ coin_value = xch_spam_amount
1178
+ else:
1179
+ # Handle the edge case to make sure the coin is at least 2 mojos
1180
+ # This is needed to receive change
1181
+ coin_value = 2
1182
+
1183
+ while coins_remaining > 0:
1184
+ payee_ph = await dust_wallet.get_new_puzzlehash()
1185
+ payees.append(Payment(payee_ph, uint64(coin_value)))
1186
+
1187
+ # After every 100 (at most) coins added, push the tx and advance the chain
1188
+ # This greatly speeds up the overall process
1189
+ if coins_remaining % 100 == 0 and coins_remaining != spam_filter_after_n_txs:
1190
+ # construct and send tx
1191
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1192
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1193
+ [tx] = action_scope.side_effects.transactions
1194
+ assert tx.spend_bundle is not None
1195
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1196
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1197
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1198
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1199
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1200
+ # reset payees
1201
+ payees = []
1202
+
1203
+ coins_remaining -= 1
1204
+
1205
+ # construct and send tx
1206
+ async with farm_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1207
+ await farm_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1208
+ [tx] = action_scope.side_effects.transactions
1209
+ assert tx.spend_bundle is not None
1210
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1211
+
1212
+ # advance the chain and sync both wallets
1213
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1214
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1215
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1216
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1217
+
1218
+ # Obtain and log important values
1219
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1220
+ unspent_count = len(all_unspent)
1221
+ balance = await dust_wallet.get_confirmed_balance()
1222
+
1223
+ # Verify the number of coins and value
1224
+ if spam_filter_after_n_txs > 0:
1225
+ assert unspent_count == spam_filter_after_n_txs
1226
+ else:
1227
+ # in the edge case there should be 1 coin
1228
+ assert unspent_count == 1
1229
+ assert balance == unspent_count * coin_value
1230
+
1231
+ # Send a 1 mojo coin from the dust wallet to the farm wallet
1232
+ payee_ph = await farm_wallet.get_new_puzzlehash()
1233
+ payees = [Payment(payee_ph, uint64(1))]
1234
+
1235
+ # construct and send tx
1236
+ async with dust_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1237
+ await dust_wallet.generate_signed_transaction(uint64(0), ph, action_scope, primaries=payees)
1238
+ [tx] = action_scope.side_effects.transactions
1239
+ assert tx.spend_bundle is not None
1240
+ await full_node_api.send_transaction(SendTransaction(tx.spend_bundle))
1241
+
1242
+ # advance the chain and sync both wallets
1243
+ await full_node_api.wait_transaction_records_entered_mempool([tx])
1244
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1245
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1246
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1247
+
1248
+ # Obtain and log important values
1249
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1250
+ unspent_count = len(all_unspent)
1251
+ balance = await dust_wallet.get_confirmed_balance()
1252
+
1253
+ # Make sure the dust wallet received a change coin worth 1 mojo less than the original coin size
1254
+ if spam_filter_after_n_txs > 0:
1255
+ assert unspent_count == spam_filter_after_n_txs
1256
+ else:
1257
+ # in the edge case there should be 1 coin
1258
+ assert unspent_count == 1
1259
+ assert balance == (unspent_count * coin_value) - 1
1260
+
1261
+ # Part 7: Create NFT wallets for the farmer and dust wallets.
1262
+ # Generate an NFT in the farmer wallet.
1263
+ # Send the NFT to the dust wallet, which already has enough coins to trigger the dust filter.
1264
+ # The NFT should not be filtered.
1265
+
1266
+ # Start with new puzzlehashes for each wallet
1267
+ farm_ph = await farm_wallet.get_new_puzzlehash()
1268
+ dust_ph = await dust_wallet.get_new_puzzlehash()
1269
+
1270
+ # Create an NFT wallet for the farmer and dust wallet
1271
+ farm_nft_wallet = await NFTWallet.create_new_nft_wallet(
1272
+ farm_wallet_node.wallet_state_manager, farm_wallet, name="FARM NFT WALLET"
1273
+ )
1274
+ dust_nft_wallet = await NFTWallet.create_new_nft_wallet(
1275
+ dust_wallet_node.wallet_state_manager, dust_wallet, name="DUST NFT WALLET"
1276
+ )
1277
+
1278
+ # Create a new NFT and send it to the farmer's NFT wallet
1279
+ metadata = Program.to(
1280
+ [("u", ["https://www.chia.net/img/branding/chia-logo.svg"]), ("h", "0xD4584AD463139FA8C0D9F68F4B59F185")]
1281
+ )
1282
+ async with farm_nft_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1283
+ await farm_nft_wallet.generate_new_nft(metadata, action_scope)
1284
+ for tx in action_scope.side_effects.transactions:
1285
+ if tx.spend_bundle is not None:
1286
+ assert len(compute_memos(tx.spend_bundle)) > 0
1287
+ await time_out_assert_not_none(
1288
+ 20, full_node_api.full_node.mempool_manager.get_spendbundle, tx.spend_bundle.name()
1289
+ )
1290
+
1291
+ # Farm a new block
1292
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1293
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(farm_ph))
1294
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1295
+
1296
+ # Make sure the dust wallet has enough unspent coins in that the next coin would be filtered
1297
+ # if it were a normal dust coin (and not an NFT)
1298
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1299
+ assert len(all_unspent) >= spam_filter_after_n_txs
1300
+
1301
+ # Make sure the NFT is in the farmer's NFT wallet, and the dust NFT wallet is empty
1302
+ await time_out_assert(15, get_nft_count, 1, farm_nft_wallet)
1303
+ await time_out_assert(15, get_nft_count, 0, dust_nft_wallet)
1304
+
1305
+ nft_coins = await farm_nft_wallet.get_current_nfts()
1306
+ # Send the NFT to the dust wallet
1307
+ async with farm_nft_wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1308
+ await farm_nft_wallet.generate_signed_transaction(
1309
+ [uint64(nft_coins[0].coin.amount)], [dust_ph], action_scope, coins={nft_coins[0].coin}
1310
+ )
1311
+ assert len(action_scope.side_effects.transactions) == 1
1312
+ txs = await farm_wallet_node.wallet_state_manager.add_pending_transactions(action_scope.side_effects.transactions)
1313
+ assert txs[0].spend_bundle is not None
1314
+ assert len(compute_memos(txs[0].spend_bundle)) > 0
1315
+
1316
+ # Farm a new block.
1317
+ await full_node_api.wait_transaction_records_entered_mempool(txs)
1318
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1319
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(farm_ph))
1320
+ await full_node_api.wait_for_wallets_synced(wallet_nodes=[farm_wallet_node, dust_wallet_node], timeout=20)
1321
+
1322
+ # Make sure the dust wallet has enough unspent coins in that the next coin would be filtered
1323
+ # if it were a normal dust coin (and not an NFT)
1324
+ all_unspent = await dust_wallet_node.wallet_state_manager.coin_store.get_all_unspent_coins()
1325
+ assert len(all_unspent) >= spam_filter_after_n_txs
1326
+
1327
+ # The dust wallet should now hold the NFT. It should not be filtered
1328
+ await time_out_assert(15, get_nft_count, 0, farm_nft_wallet)
1329
+ await time_out_assert(15, get_nft_count, 1, dust_nft_wallet)
1330
+
1331
+
1332
+ @pytest.mark.anyio
1333
+ async def test_retry_store(
1334
+ two_wallet_nodes: OldSimulatorsAndWallets, self_hostname: str, monkeypatch: pytest.MonkeyPatch
1335
+ ) -> None:
1336
+ full_nodes, wallets, _ = two_wallet_nodes
1337
+ full_node_api = full_nodes[0]
1338
+ full_node_server = full_node_api.full_node.server
1339
+
1340
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
1341
+
1342
+ # Trusted node sync
1343
+ wallets[0][0].config["trusted_peers"] = {full_node_server.node_id.hex(): full_node_server.node_id.hex()}
1344
+
1345
+ # Untrusted node sync
1346
+ wallets[1][0].config["trusted_peers"] = {}
1347
+
1348
+ @dataclass
1349
+ class FlakinessInfo:
1350
+ coin_state_flaky: bool = True
1351
+ fetch_children_flaky: bool = True
1352
+ get_timestamp_flaky: bool = True
1353
+ db_flaky: bool = True
1354
+
1355
+ def flaky_get_coin_state(
1356
+ flakiness_info: FlakinessInfo,
1357
+ func: Callable[[list[bytes32], WSChiaConnection, Optional[uint32]], Awaitable[list[CoinState]]],
1358
+ ) -> Callable[[list[bytes32], WSChiaConnection, Optional[uint32]], Awaitable[list[CoinState]]]:
1359
+ async def new_func(
1360
+ coin_names: list[bytes32], peer: WSChiaConnection, fork_height: Optional[uint32] = None
1361
+ ) -> list[CoinState]:
1362
+ if flakiness_info.coin_state_flaky:
1363
+ flakiness_info.coin_state_flaky = False
1364
+ raise PeerRequestException()
1365
+ else:
1366
+ return await func(coin_names, peer, fork_height)
1367
+
1368
+ return new_func
1369
+
1370
+ request_puzzle_solution_failure_tested = False
1371
+
1372
+ def flaky_request_puzzle_solution(
1373
+ func: Callable[[FullNodeAPI, wallet_protocol.RequestPuzzleSolution], Awaitable[Optional[Message]]],
1374
+ ) -> Callable[[FullNodeAPI, wallet_protocol.RequestPuzzleSolution], Awaitable[Optional[Message]]]:
1375
+ @functools.wraps(func)
1376
+ async def new_func(self: FullNodeAPI, request: wallet_protocol.RequestPuzzleSolution) -> Optional[Message]:
1377
+ nonlocal request_puzzle_solution_failure_tested
1378
+ if not request_puzzle_solution_failure_tested:
1379
+ request_puzzle_solution_failure_tested = True
1380
+ # This can just return None if we have `none_response` enabled.
1381
+ reject = wallet_protocol.RejectPuzzleSolution(bytes32.zeros, uint32(0))
1382
+ return make_msg(ProtocolMessageTypes.reject_puzzle_solution, reject)
1383
+ else:
1384
+ return await func(self, request)
1385
+
1386
+ return new_func
1387
+
1388
+ def flaky_fetch_children(
1389
+ flakiness_info: FlakinessInfo,
1390
+ func: Callable[[bytes32, WSChiaConnection, Optional[uint32]], Awaitable[list[CoinState]]],
1391
+ ) -> Callable[[bytes32, WSChiaConnection, Optional[uint32]], Awaitable[list[CoinState]]]:
1392
+ async def new_func(
1393
+ coin_name: bytes32, peer: WSChiaConnection, fork_height: Optional[uint32] = None
1394
+ ) -> list[CoinState]:
1395
+ if flakiness_info.fetch_children_flaky:
1396
+ flakiness_info.fetch_children_flaky = False
1397
+ raise PeerRequestException()
1398
+ else:
1399
+ return await func(coin_name, peer, fork_height)
1400
+
1401
+ return new_func
1402
+
1403
+ def flaky_get_timestamp(
1404
+ flakiness_info: FlakinessInfo, func: Callable[[uint32], Awaitable[uint64]]
1405
+ ) -> Callable[[uint32], Awaitable[uint64]]:
1406
+ async def new_func(height: uint32) -> uint64:
1407
+ if flakiness_info.get_timestamp_flaky:
1408
+ flakiness_info.get_timestamp_flaky = False
1409
+ raise PeerRequestException()
1410
+ else:
1411
+ return await func(height)
1412
+
1413
+ return new_func
1414
+
1415
+ def flaky_info_for_puzhash(
1416
+ flakiness_info: FlakinessInfo, func: Callable[[bytes32], Awaitable[Optional[WalletIdentifier]]]
1417
+ ) -> Callable[[bytes32], Awaitable[Optional[WalletIdentifier]]]:
1418
+ async def new_func(puzzle_hash: bytes32) -> Optional[WalletIdentifier]:
1419
+ if flakiness_info.db_flaky:
1420
+ flakiness_info.db_flaky = False
1421
+ raise AIOSqliteError()
1422
+ else:
1423
+ return await func(puzzle_hash)
1424
+
1425
+ return new_func
1426
+
1427
+ with contextlib.ExitStack() as exit_stack:
1428
+ exit_stack.enter_context(
1429
+ patch_request_handler(
1430
+ api=full_node_api,
1431
+ handler=flaky_request_puzzle_solution(FullNodeAPI.request_puzzle_solution),
1432
+ request_type=ProtocolMessageTypes.request_puzzle_solution,
1433
+ )
1434
+ )
1435
+ m = exit_stack.enter_context(monkeypatch.context())
1436
+
1437
+ for wallet_node, wallet_server in wallets:
1438
+ wallet_node.coin_state_retry_seconds = 1
1439
+ request_puzzle_solution_failure_tested = False
1440
+ flakiness_info = FlakinessInfo()
1441
+ m.setattr(wallet_node, "get_coin_state", flaky_get_coin_state(flakiness_info, wallet_node.get_coin_state))
1442
+ m.setattr(wallet_node, "fetch_children", flaky_fetch_children(flakiness_info, wallet_node.fetch_children))
1443
+ m.setattr(
1444
+ wallet_node,
1445
+ "get_timestamp_for_height",
1446
+ flaky_get_timestamp(flakiness_info, wallet_node.get_timestamp_for_height),
1447
+ )
1448
+ m.setattr(
1449
+ wallet_node.wallet_state_manager.puzzle_store,
1450
+ "get_wallet_identifier_for_puzzle_hash",
1451
+ flaky_info_for_puzhash(
1452
+ flakiness_info, wallet_node.wallet_state_manager.puzzle_store.get_wallet_identifier_for_puzzle_hash
1453
+ ),
1454
+ )
1455
+
1456
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1457
+
1458
+ wallet = wallet_node.wallet_state_manager.main_wallet
1459
+ ph = await wallet.get_new_puzzlehash()
1460
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(ph))
1461
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
1462
+
1463
+ async def retry_store_empty() -> bool:
1464
+ return len(await wallet_node.wallet_state_manager.retry_store.get_all_states_to_retry()) == 0
1465
+
1466
+ async def assert_coin_state_retry() -> None:
1467
+ # Wait for retry coin states to show up
1468
+ await time_out_assert(15, retry_store_empty, False)
1469
+ # And become retried/removed
1470
+ await time_out_assert(30, retry_store_empty, True)
1471
+
1472
+ await assert_coin_state_retry()
1473
+
1474
+ async with wallet.wallet_state_manager.new_action_scope(DEFAULT_TX_CONFIG, push=True) as action_scope:
1475
+ await wallet.generate_signed_transaction(
1476
+ uint64(1_000_000_000_000), bytes32.zeros, action_scope, memos=[ph]
1477
+ )
1478
+ [tx] = action_scope.side_effects.transactions
1479
+ await time_out_assert(30, wallet.get_confirmed_balance, 2_000_000_000_000)
1480
+
1481
+ async def tx_in_mempool() -> bool:
1482
+ return full_node_api.full_node.mempool_manager.get_spendbundle(tx.name) is not None
1483
+
1484
+ await time_out_assert(15, tx_in_mempool)
1485
+ await full_node_api.farm_new_transaction_block(FarmNewBlockProtocol(bytes32.zeros))
1486
+
1487
+ await assert_coin_state_retry()
1488
+
1489
+ assert not flakiness_info.coin_state_flaky
1490
+ assert request_puzzle_solution_failure_tested
1491
+ assert not flakiness_info.fetch_children_flaky
1492
+ assert not flakiness_info.get_timestamp_flaky
1493
+ assert not flakiness_info.db_flaky
1494
+ await time_out_assert(30, wallet.get_confirmed_balance, 1_000_000_000_000)
1495
+
1496
+
1497
+ # TODO: fix this test
1498
+ @pytest.mark.limit_consensus_modes(reason="save time")
1499
+ @pytest.mark.anyio
1500
+ @pytest.mark.skip("the test fails with 'wallet_state_manager not assigned'. This test doesn't work, skip it for now")
1501
+ async def test_bad_peak_mismatch(
1502
+ two_wallet_nodes: OldSimulatorsAndWallets,
1503
+ default_1000_blocks: list[FullBlock],
1504
+ self_hostname: str,
1505
+ blockchain_constants: ConsensusConstants,
1506
+ monkeypatch: pytest.MonkeyPatch,
1507
+ ) -> None:
1508
+ [full_node_api], [(wallet_node, wallet_server), _], _ = two_wallet_nodes
1509
+ full_node = full_node_api.full_node
1510
+ full_node_server = full_node.server
1511
+ blocks = default_1000_blocks
1512
+ header_cache, height_to_hash, sub_blocks, summaries = await load_blocks_dont_validate(blocks, blockchain_constants)
1513
+ wpf = WeightProofHandler(blockchain_constants, BlockchainMock(sub_blocks, header_cache, height_to_hash, summaries))
1514
+
1515
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1516
+
1517
+ await add_blocks_in_batches(blocks, full_node)
1518
+
1519
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1520
+
1521
+ # make wp for lower height
1522
+ wp = await wpf.get_proof_of_weight(height_to_hash[uint32(800)])
1523
+ assert wp is not None
1524
+ # create the node respond with the lighter proof
1525
+ wp_msg = make_msg(
1526
+ ProtocolMessageTypes.respond_proof_of_weight,
1527
+ full_node_protocol.RespondProofOfWeight(wp, wp.recent_chain_data[-1].header_hash),
1528
+ )
1529
+ with monkeypatch.context() as m:
1530
+ f: asyncio.Future[Optional[Message]] = asyncio.Future()
1531
+ f.set_result(wp_msg)
1532
+ m.setattr(full_node_api, "request_proof_of_weight", MagicMock(return_value=f))
1533
+
1534
+ # create the node respond with the lighter header block
1535
+ header_block_msg = make_msg(
1536
+ ProtocolMessageTypes.respond_block_header,
1537
+ wallet_protocol.RespondBlockHeader(wp.recent_chain_data[-1]),
1538
+ )
1539
+ f2: asyncio.Future[Optional[Message]] = asyncio.Future()
1540
+ f2.set_result(header_block_msg)
1541
+ m.setattr(full_node_api, "request_block_header", MagicMock(return_value=f2))
1542
+
1543
+ # create new fake peak msg
1544
+ fake_peak_height = uint32(11_000)
1545
+ fake_peak_weight = uint128(1_000_000_000)
1546
+ msg = wallet_protocol.NewPeakWallet(
1547
+ blocks[-1].header_hash, fake_peak_height, fake_peak_weight, uint32(max(blocks[-1].height - 1, uint32(0)))
1548
+ )
1549
+ await asyncio.sleep(3)
1550
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_server.get_port()), None)
1551
+ await wallet_node.new_peak_wallet(msg, wallet_server.all_connections.popitem()[1])
1552
+ await asyncio.sleep(3)
1553
+ peak = await wallet_node.wallet_state_manager.blockchain.get_peak_block()
1554
+ assert peak is not None
1555
+ assert peak.height != fake_peak_height
1556
+
1557
+
1558
+ @pytest.mark.limit_consensus_modes(reason="save time")
1559
+ @pytest.mark.anyio
1560
+ async def test_long_sync_untrusted_break(
1561
+ setup_two_nodes_and_wallet: OldSimulatorsAndWallets,
1562
+ default_1000_blocks: list[FullBlock],
1563
+ default_400_blocks: list[FullBlock],
1564
+ self_hostname: str,
1565
+ caplog: pytest.LogCaptureFixture,
1566
+ use_delta_sync: bool,
1567
+ ) -> None:
1568
+ [trusted_full_node_api, untrusted_full_node_api], [(wallet_node, wallet_server)], _ = setup_two_nodes_and_wallet
1569
+ trusted_full_node_server = trusted_full_node_api.full_node.server
1570
+ untrusted_full_node_server = untrusted_full_node_api.full_node.server
1571
+ wallet_node.config["trusted_peers"] = {trusted_full_node_server.node_id.hex(): None}
1572
+ wallet_node.config["use_delta_sync"] = use_delta_sync
1573
+
1574
+ sync_canceled = False
1575
+
1576
+ async def register_for_ph_updates(
1577
+ self: object,
1578
+ request: wallet_protocol.RegisterForPhUpdates,
1579
+ peer: WSChiaConnection,
1580
+ ) -> None:
1581
+ nonlocal sync_canceled
1582
+ # Just sleep a long time here to simulate a long-running untrusted sync
1583
+ try:
1584
+ await asyncio.sleep(120)
1585
+ except Exception:
1586
+ sync_canceled = True
1587
+ raise
1588
+
1589
+ def wallet_syncing() -> bool:
1590
+ return wallet_node.wallet_state_manager.sync_mode
1591
+
1592
+ def check_sync_canceled() -> bool:
1593
+ return sync_canceled
1594
+
1595
+ def synced_to_trusted() -> bool:
1596
+ return trusted_full_node_server.node_id in wallet_node.synced_peers
1597
+
1598
+ def only_trusted_peer() -> bool:
1599
+ trusted_peers = sum(wallet_node.is_trusted(peer) for peer in wallet_server.all_connections.values())
1600
+ untrusted_peers = sum(not wallet_node.is_trusted(peer) for peer in wallet_server.all_connections.values())
1601
+ return trusted_peers == 1 and untrusted_peers == 0
1602
+
1603
+ await add_blocks_in_batches(default_400_blocks, trusted_full_node_api.full_node)
1604
+
1605
+ await add_blocks_in_batches(default_1000_blocks[:400], untrusted_full_node_api.full_node)
1606
+
1607
+ with patch_request_handler(api=untrusted_full_node_api, handler=register_for_ph_updates):
1608
+ # Connect to the untrusted peer and wait until the long sync started
1609
+ await wallet_server.start_client(PeerInfo(self_hostname, untrusted_full_node_server.get_port()), None)
1610
+ await time_out_assert(30, wallet_syncing)
1611
+ with caplog.at_level(logging.INFO):
1612
+ # Connect to the trusted peer and make sure the running untrusted long sync gets interrupted via disconnect
1613
+ await wallet_server.start_client(PeerInfo(self_hostname, trusted_full_node_server.get_port()), None)
1614
+ await time_out_assert(600, wallet_height_at_least, True, wallet_node, len(default_400_blocks) - 1)
1615
+ assert time_out_assert(10, synced_to_trusted)
1616
+ assert untrusted_full_node_server.node_id not in wallet_node.synced_peers
1617
+ assert "Connected to a synced trusted peer, disconnecting from all untrusted nodes." in caplog.text
1618
+
1619
+ # Make sure the sync was interrupted
1620
+ assert time_out_assert(30, check_sync_canceled)
1621
+ # And that we only have a trusted peer left
1622
+ assert time_out_assert(30, only_trusted_peer)
1623
+
1624
+
1625
+ @pytest.mark.anyio
1626
+ @pytest.mark.parametrize("chain_length", [0, 100])
1627
+ @pytest.mark.parametrize("fork_point", [500, 1500])
1628
+ async def test_long_reorg_nodes_and_wallet(
1629
+ chain_length: int,
1630
+ fork_point: int,
1631
+ three_nodes: list[FullNodeAPI],
1632
+ simulator_and_wallet: OldSimulatorsAndWallets,
1633
+ default_10000_blocks: list[FullBlock],
1634
+ test_long_reorg_blocks: list[FullBlock],
1635
+ test_long_reorg_1500_blocks: list[FullBlock],
1636
+ self_hostname: str,
1637
+ ) -> None:
1638
+ full_node_1, full_node_2, _ = three_nodes
1639
+ _, [wallet], _ = simulator_and_wallet
1640
+ wallet_node = wallet[0]
1641
+ wallet_server = wallet[1]
1642
+ # Trusted node sync
1643
+ wallet_node.config["trusted_peers"] = {full_node_1.server.node_id.hex(): full_node_1.server.node_id.hex()}
1644
+
1645
+ if fork_point == 1500:
1646
+ blocks = default_10000_blocks[: 3600 - chain_length]
1647
+ else:
1648
+ blocks = default_10000_blocks[: 1600 - chain_length]
1649
+ if fork_point == 1500:
1650
+ reorg_blocks = test_long_reorg_1500_blocks[: 3100 - chain_length]
1651
+ else:
1652
+ reorg_blocks = test_long_reorg_blocks[: 1200 - chain_length]
1653
+ pytest.skip("We rely on the light-blocks test for a 0 forkpoint")
1654
+
1655
+ last_blk = blocks[-1]
1656
+ last_reorg_blk = reorg_blocks[-1]
1657
+ assert last_blk.header_hash != last_reorg_blk.header_hash
1658
+ assert last_blk.weight < last_reorg_blk.weight
1659
+
1660
+ await wallet_server.start_client(PeerInfo(self_hostname, full_node_1.server.get_port()), None)
1661
+ assert len(wallet_server.all_connections) == 1
1662
+ assert len(full_node_1.server.all_connections) == 1
1663
+
1664
+ await add_blocks_in_batches(blocks, full_node_1.full_node)
1665
+ node_1_peak = full_node_1.full_node.blockchain.get_peak()
1666
+ assert node_1_peak is not None
1667
+ await time_out_assert(600, wallet_height_at_least, True, wallet_node, node_1_peak.height)
1668
+ log.info(f"wallet node height is {node_1_peak.height}")
1669
+ # full node 2 has the reorg-chain
1670
+ await add_blocks_in_batches(reorg_blocks[:-1], full_node_2.full_node)
1671
+ await connect_and_get_peer(full_node_1.full_node.server, full_node_2.full_node.server, self_hostname)
1672
+
1673
+ # # TODO: There appears to be an issue where the node with the lighter chain
1674
+ # # fails to initiate the reorg until there's a new block farmed onto the
1675
+ # # heavier chain.
1676
+ await full_node_2.full_node.add_block(reorg_blocks[-1])
1677
+
1678
+ def check_nodes_in_sync() -> bool:
1679
+ p1 = full_node_1.full_node.blockchain.get_peak()
1680
+ p2 = full_node_2.full_node.blockchain.get_peak()
1681
+ return p1 is not None and p1 == p2
1682
+
1683
+ await time_out_assert(600, check_nodes_in_sync)
1684
+ node_2_peak = full_node_2.full_node.blockchain.get_peak()
1685
+ assert node_2_peak is not None
1686
+ print(f"peak: {str(node_2_peak.header_hash)[:6]}")
1687
+ await time_out_assert(600, wallet_height_at_least, True, wallet_node, node_2_peak.height)
1688
+ # reorg1_timing = time.monotonic() - start
1689
+ # we already checked p1==p2
1690
+ p1 = full_node_2.full_node.blockchain.get_peak()
1691
+ assert p1 is not None
1692
+ assert p1.header_hash == last_reorg_blk.header_hash