chia-blockchain 2.4.4__py3-none-any.whl

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