chia-blockchain 2.5.2rc1__py3-none-any.whl → 2.5.3__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 (640) hide show
  1. chia/__init__.py +7 -0
  2. chia/_tests/blockchain/blockchain_test_utils.py +1 -1
  3. chia/_tests/blockchain/test_augmented_chain.py +54 -5
  4. chia/_tests/blockchain/test_blockchain.py +5 -12
  5. chia/_tests/blockchain/test_blockchain_transactions.py +3 -5
  6. chia/_tests/blockchain/test_get_block_generator.py +2 -2
  7. chia/_tests/blockchain/test_lookup_fork_chain.py +2 -2
  8. chia/_tests/clvm/benchmark_costs.py +2 -1
  9. chia/_tests/clvm/coin_store.py +4 -3
  10. chia/_tests/clvm/test_chialisp_deserialization.py +2 -2
  11. chia/_tests/clvm/test_curry_and_treehash.py +1 -1
  12. chia/_tests/clvm/test_puzzle_compression.py +2 -2
  13. chia/_tests/clvm/test_puzzles.py +2 -2
  14. chia/_tests/clvm/test_singletons.py +2 -2
  15. chia/_tests/clvm/test_spend_sim.py +1 -1
  16. chia/_tests/cmds/cmd_test_utils.py +2 -2
  17. chia/_tests/cmds/test_click_types.py +2 -2
  18. chia/_tests/cmds/test_cmd_framework.py +6 -6
  19. chia/_tests/cmds/test_show.py +4 -3
  20. chia/_tests/cmds/test_tx_config_args.py +1 -1
  21. chia/_tests/cmds/testing_classes.py +2 -2
  22. chia/_tests/cmds/wallet/test_consts.py +2 -2
  23. chia/_tests/cmds/wallet/test_did.py +2 -2
  24. chia/_tests/cmds/wallet/test_nft.py +2 -2
  25. chia/_tests/cmds/wallet/test_notifications.py +3 -2
  26. chia/_tests/cmds/wallet/test_vcs.py +2 -2
  27. chia/_tests/cmds/wallet/test_wallet.py +4 -8
  28. chia/_tests/conftest.py +4 -3
  29. chia/_tests/connection_utils.py +2 -2
  30. chia/_tests/core/cmds/test_keys.py +1 -2
  31. chia/_tests/core/cmds/test_wallet.py +2 -2
  32. chia/_tests/core/consensus/test_block_creation.py +2 -2
  33. chia/_tests/core/consensus/test_pot_iterations.py +1 -1
  34. chia/_tests/core/custom_types/test_coin.py +2 -2
  35. chia/_tests/core/custom_types/test_proof_of_space.py +2 -2
  36. chia/_tests/core/custom_types/test_spend_bundle.py +2 -2
  37. chia/_tests/core/data_layer/conftest.py +1 -1
  38. chia/_tests/core/data_layer/test_data_layer.py +1 -1
  39. chia/_tests/core/data_layer/test_data_layer_util.py +1 -1
  40. chia/_tests/core/data_layer/test_data_rpc.py +2 -2
  41. chia/_tests/core/data_layer/test_data_store.py +1 -1
  42. chia/_tests/core/data_layer/test_data_store_schema.py +1 -1
  43. chia/_tests/core/data_layer/util.py +2 -1
  44. chia/_tests/core/farmer/test_farmer_api.py +1 -1
  45. chia/_tests/core/full_node/full_sync/test_full_sync.py +1 -7
  46. chia/_tests/core/full_node/ram_db.py +2 -1
  47. chia/_tests/core/full_node/stores/test_block_store.py +2 -2
  48. chia/_tests/core/full_node/stores/test_coin_store.py +2 -2
  49. chia/_tests/core/full_node/stores/test_full_node_store.py +3 -3
  50. chia/_tests/core/full_node/stores/test_hint_store.py +2 -2
  51. chia/_tests/core/full_node/stores/test_sync_store.py +1 -1
  52. chia/_tests/core/full_node/test_address_manager.py +1 -1
  53. chia/_tests/core/full_node/test_block_height_map.py +2 -2
  54. chia/_tests/core/full_node/test_conditions.py +1 -1
  55. chia/_tests/core/full_node/test_full_node.py +346 -164
  56. chia/_tests/core/full_node/test_generator_tools.py +3 -2
  57. chia/_tests/core/full_node/test_hint_management.py +2 -2
  58. chia/_tests/core/full_node/test_performance.py +2 -15
  59. chia/_tests/core/full_node/test_subscriptions.py +1 -1
  60. chia/_tests/core/full_node/test_transactions.py +186 -185
  61. chia/_tests/core/full_node/test_tx_processing_queue.py +1 -1
  62. chia/_tests/core/make_block_generator.py +2 -2
  63. chia/_tests/core/mempool/test_mempool.py +165 -22
  64. chia/_tests/core/mempool/test_mempool_fee_estimator.py +1 -1
  65. chia/_tests/core/mempool/test_mempool_fee_protocol.py +1 -1
  66. chia/_tests/core/mempool/test_mempool_manager.py +476 -66
  67. chia/_tests/core/mempool/test_mempool_performance.py +2 -2
  68. chia/_tests/core/mempool/test_singleton_fast_forward.py +19 -25
  69. chia/_tests/core/node_height.py +2 -1
  70. chia/_tests/core/server/test_capabilities.py +1 -1
  71. chia/_tests/core/server/test_dos.py +36 -28
  72. chia/_tests/core/server/test_loop.py +3 -3
  73. chia/_tests/core/server/test_rate_limits.py +1 -1
  74. chia/_tests/core/server/test_server.py +2 -2
  75. chia/_tests/core/services/test_services.py +1 -1
  76. chia/_tests/core/ssl/test_ssl.py +1 -1
  77. chia/_tests/core/test_coins.py +2 -1
  78. chia/_tests/core/test_cost_calculation.py +2 -2
  79. chia/_tests/core/test_crawler.py +2 -2
  80. chia/_tests/core/test_db_conversion.py +2 -2
  81. chia/_tests/core/test_db_validation.py +26 -13
  82. chia/_tests/core/test_farmer_harvester_rpc.py +2 -2
  83. chia/_tests/core/test_full_node_rpc.py +2 -2
  84. chia/_tests/core/test_merkle_set.py +2 -2
  85. chia/_tests/core/test_program.py +2 -2
  86. chia/_tests/core/test_rpc_util.py +1 -1
  87. chia/_tests/core/test_seeder.py +1 -1
  88. chia/_tests/core/util/test_block_cache.py +3 -3
  89. chia/_tests/core/util/test_jsonify.py +3 -2
  90. chia/_tests/core/util/test_keychain.py +3 -3
  91. chia/_tests/core/util/test_streamable.py +3 -4
  92. chia/_tests/environments/wallet.py +3 -2
  93. chia/_tests/farmer_harvester/test_farmer.py +3 -4
  94. chia/_tests/farmer_harvester/test_farmer_harvester.py +2 -2
  95. chia/_tests/farmer_harvester/test_filter_prefix_bits.py +2 -2
  96. chia/_tests/farmer_harvester/test_third_party_harvesters.py +3 -4
  97. chia/_tests/fee_estimation/test_fee_estimation_integration.py +1 -1
  98. chia/_tests/fee_estimation/test_fee_estimation_rpc.py +2 -2
  99. chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +1 -1
  100. chia/_tests/fee_estimation/test_mempoolitem_height_added.py +3 -4
  101. chia/_tests/generator/test_compression.py +20 -10
  102. chia/_tests/generator/test_rom.py +7 -9
  103. chia/_tests/plot_sync/test_delta.py +2 -2
  104. chia/_tests/plot_sync/test_plot_sync.py +2 -2
  105. chia/_tests/plot_sync/test_receiver.py +2 -2
  106. chia/_tests/plot_sync/test_sender.py +2 -2
  107. chia/_tests/plot_sync/test_sync_simulated.py +2 -2
  108. chia/_tests/plot_sync/util.py +3 -2
  109. chia/_tests/plotting/test_plot_manager.py +1 -1
  110. chia/_tests/pools/test_pool_cli_parsing.py +3 -2
  111. chia/_tests/pools/test_pool_cmdline.py +2 -2
  112. chia/_tests/pools/test_pool_puzzles_lifecycle.py +3 -3
  113. chia/_tests/pools/test_pool_rpc.py +4 -5
  114. chia/_tests/pools/test_pool_wallet.py +1 -1
  115. chia/_tests/pools/test_wallet_pool_store.py +2 -2
  116. chia/_tests/rpc/test_rpc_client.py +1 -1
  117. chia/_tests/rpc/test_rpc_server.py +1 -1
  118. chia/_tests/simulation/test_simulation.py +36 -8
  119. chia/_tests/simulation/test_simulator.py +5 -5
  120. chia/_tests/simulation/test_start_simulator.py +2 -2
  121. chia/_tests/timelord/test_new_peak.py +2 -2
  122. chia/_tests/tools/test_run_block.py +3 -2
  123. chia/_tests/util/benchmark_cost.py +2 -2
  124. chia/_tests/util/benchmarks.py +17 -6
  125. chia/_tests/util/blockchain.py +2 -1
  126. chia/_tests/util/blockchain_mock.py +9 -5
  127. chia/_tests/util/build_network_protocol_files.py +2 -1
  128. chia/_tests/util/constants.py +2 -1
  129. chia/_tests/util/full_sync.py +6 -3
  130. chia/_tests/util/gen_ssl_certs.py +2 -2
  131. chia/_tests/util/generator_tools_testing.py +4 -3
  132. chia/_tests/util/get_name_puzzle_conditions.py +2 -2
  133. chia/_tests/util/misc.py +16 -2
  134. chia/_tests/util/network_protocol_data.py +17 -7
  135. chia/_tests/util/run_block.py +6 -8
  136. chia/_tests/util/setup_nodes.py +4 -3
  137. chia/_tests/util/spend_sim.py +9 -5
  138. chia/_tests/util/test_condition_tools.py +2 -2
  139. chia/_tests/util/test_config.py +2 -1
  140. chia/_tests/util/test_errors.py +2 -1
  141. chia/_tests/util/test_full_block_utils.py +17 -7
  142. chia/_tests/util/test_misc.py +1 -1
  143. chia/_tests/util/test_network_protocol_test.py +24 -24
  144. chia/_tests/util/test_replace_str_to_bytes.py +2 -2
  145. chia/_tests/util/test_trusted_peer.py +1 -1
  146. chia/_tests/util/time_out_assert.py +20 -7
  147. chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +1 -1
  148. chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +2 -2
  149. chia/_tests/wallet/cat_wallet/test_cat_wallet.py +5 -6
  150. chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +17 -15
  151. chia/_tests/wallet/cat_wallet/test_trades.py +2 -2
  152. chia/_tests/wallet/clawback/test_clawback_lifecycle.py +2 -2
  153. chia/_tests/wallet/clawback/test_clawback_metadata.py +2 -2
  154. chia/_tests/wallet/conftest.py +3 -3
  155. chia/_tests/wallet/db_wallet/test_db_graftroot.py +3 -5
  156. chia/_tests/wallet/db_wallet/test_dl_offers.py +2 -2
  157. chia/_tests/wallet/db_wallet/test_dl_wallet.py +433 -384
  158. chia/_tests/wallet/did_wallet/test_did.py +3 -3
  159. chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +2 -2
  160. chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +2 -2
  161. chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +3 -4
  162. chia/_tests/wallet/nft_wallet/test_nft_offers.py +1293 -703
  163. chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +28 -30
  164. chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2 -2
  165. chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +2 -2
  166. chia/_tests/wallet/rpc/config.py +1 -1
  167. chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +2 -2
  168. chia/_tests/wallet/rpc/test_wallet_rpc.py +20 -77
  169. chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +9 -7
  170. chia/_tests/wallet/sync/test_wallet_sync.py +79 -31
  171. chia/_tests/wallet/test_clvm_streamable.py +2 -2
  172. chia/_tests/wallet/test_coin_management.py +7 -7
  173. chia/_tests/wallet/test_coin_selection.py +20 -2
  174. chia/_tests/wallet/test_conditions.py +2 -2
  175. chia/_tests/wallet/test_debug_spend_bundle.py +2 -2
  176. chia/_tests/wallet/test_new_wallet_protocol.py +2 -2
  177. chia/_tests/wallet/test_nft_store.py +2 -2
  178. chia/_tests/wallet/test_notifications.py +2 -2
  179. chia/_tests/wallet/test_puzzle_store.py +2 -2
  180. chia/_tests/wallet/test_sign_coin_spends.py +2 -2
  181. chia/_tests/wallet/test_signer_protocol.py +3 -3
  182. chia/_tests/wallet/test_singleton.py +3 -11
  183. chia/_tests/wallet/test_singleton_lifecycle_fast.py +12 -13
  184. chia/_tests/wallet/test_singleton_store.py +2 -4
  185. chia/_tests/wallet/test_transaction_store.py +2 -2
  186. chia/_tests/wallet/test_util.py +2 -2
  187. chia/_tests/wallet/test_wallet.py +53 -49
  188. chia/_tests/wallet/test_wallet_action_scope.py +24 -6
  189. chia/_tests/wallet/test_wallet_blockchain.py +1 -1
  190. chia/_tests/wallet/test_wallet_coin_store.py +2 -2
  191. chia/_tests/wallet/test_wallet_interested_store.py +2 -2
  192. chia/_tests/wallet/test_wallet_node.py +3 -3
  193. chia/_tests/wallet/test_wallet_retry.py +3 -3
  194. chia/_tests/wallet/test_wallet_state_manager.py +8 -8
  195. chia/_tests/wallet/test_wallet_test_framework.py +1 -1
  196. chia/_tests/wallet/test_wallet_trade_store.py +2 -2
  197. chia/_tests/wallet/test_wallet_utils.py +2 -2
  198. chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +3 -2
  199. chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +15 -15
  200. chia/_tests/wallet/vc_wallet/test_vc_wallet.py +5 -3
  201. chia/_tests/wallet/wallet_block_tools.py +15 -7
  202. chia/_tests/weight_proof/test_weight_proof.py +3 -3
  203. chia/cmds/chia.py +0 -2
  204. chia/cmds/cmd_classes.py +3 -3
  205. chia/cmds/cmd_helpers.py +4 -4
  206. chia/cmds/cmds_util.py +2 -2
  207. chia/cmds/coin_funcs.py +3 -2
  208. chia/cmds/coins.py +1 -1
  209. chia/cmds/data.py +2 -2
  210. chia/cmds/data_funcs.py +3 -2
  211. chia/cmds/db_upgrade_func.py +2 -2
  212. chia/cmds/db_validate_func.py +15 -8
  213. chia/cmds/farm.py +2 -4
  214. chia/cmds/keys.py +0 -2
  215. chia/cmds/keys_funcs.py +1 -1
  216. chia/cmds/netspace_funcs.py +2 -1
  217. chia/cmds/param_types.py +2 -2
  218. chia/cmds/plotnft.py +2 -2
  219. chia/cmds/plotnft_funcs.py +2 -2
  220. chia/cmds/rpc.py +1 -1
  221. chia/cmds/show.py +1 -2
  222. chia/cmds/show_funcs.py +6 -3
  223. chia/cmds/signer.py +1 -2
  224. chia/cmds/sim.py +1 -2
  225. chia/cmds/sim_funcs.py +2 -2
  226. chia/cmds/wallet.py +2 -2
  227. chia/cmds/wallet_funcs.py +4 -11
  228. chia/consensus/block_body_validation.py +3 -4
  229. chia/consensus/block_creation.py +10 -6
  230. chia/consensus/block_header_validation.py +3 -4
  231. chia/consensus/block_record.py +2 -3
  232. chia/consensus/block_rewards.py +1 -1
  233. chia/consensus/blockchain.py +20 -17
  234. chia/consensus/blockchain_interface.py +5 -4
  235. chia/consensus/coinbase.py +2 -2
  236. chia/consensus/constants.py +1 -1
  237. chia/consensus/cost_calculator.py +2 -1
  238. chia/consensus/default_constants.py +4 -3
  239. chia/consensus/deficit.py +3 -2
  240. chia/consensus/difficulty_adjustment.py +8 -9
  241. chia/consensus/find_fork_point.py +4 -3
  242. chia/consensus/full_block_to_block_record.py +4 -3
  243. chia/consensus/get_block_challenge.py +4 -3
  244. chia/consensus/get_block_generator.py +3 -2
  245. chia/consensus/make_sub_epoch_summary.py +3 -2
  246. chia/consensus/multiprocess_validation.py +9 -4
  247. chia/consensus/pos_quality.py +1 -1
  248. chia/consensus/pot_iterations.py +4 -3
  249. chia/consensus/vdf_info_computation.py +4 -3
  250. chia/daemon/client.py +1 -1
  251. chia/daemon/keychain_server.py +1 -1
  252. chia/daemon/server.py +1 -1
  253. chia/daemon/windows_signal.py +1 -1
  254. chia/data_layer/data_layer.py +4 -3
  255. chia/data_layer/data_layer_errors.py +1 -1
  256. chia/data_layer/data_layer_util.py +2 -2
  257. chia/data_layer/data_layer_wallet.py +47 -69
  258. chia/data_layer/data_store.py +1 -1
  259. chia/data_layer/dl_wallet_store.py +5 -6
  260. chia/data_layer/download_data.py +1 -1
  261. chia/data_layer/s3_plugin_service.py +4 -4
  262. chia/data_layer/singleton_record.py +23 -0
  263. chia/data_layer/util/benchmark.py +2 -1
  264. chia/farmer/farmer.py +4 -6
  265. chia/farmer/farmer_api.py +4 -6
  266. chia/full_node/bitcoin_fee_estimator.py +2 -1
  267. chia/full_node/block_height_map.py +2 -2
  268. chia/full_node/block_store.py +8 -9
  269. chia/{util → full_node}/check_fork_next_block.py +2 -1
  270. chia/full_node/coin_store.py +10 -10
  271. chia/full_node/fee_estimate.py +2 -1
  272. chia/full_node/fee_estimation.py +2 -1
  273. chia/full_node/fee_estimator.py +2 -1
  274. chia/full_node/fee_estimator_interface.py +1 -1
  275. chia/full_node/fee_history.py +2 -1
  276. chia/full_node/fee_tracker.py +2 -1
  277. chia/full_node/full_node.py +25 -15
  278. chia/full_node/full_node_api.py +12 -32
  279. chia/full_node/full_node_store.py +4 -3
  280. chia/full_node/hint_management.py +2 -1
  281. chia/full_node/hint_store.py +3 -3
  282. chia/full_node/mempool.py +80 -12
  283. chia/full_node/mempool_check_conditions.py +6 -7
  284. chia/full_node/mempool_manager.py +168 -21
  285. chia/full_node/pending_tx_cache.py +2 -2
  286. chia/full_node/subscriptions.py +2 -2
  287. chia/full_node/sync_store.py +2 -3
  288. chia/full_node/tx_processing_queue.py +2 -1
  289. chia/full_node/weight_proof.py +5 -8
  290. chia/harvester/harvester.py +5 -3
  291. chia/harvester/harvester_api.py +2 -2
  292. chia/introducer/introducer.py +30 -2
  293. chia/introducer/introducer_api.py +9 -1
  294. chia/legacy/keyring.py +1 -2
  295. chia/plot_sync/exceptions.py +2 -1
  296. chia/plot_sync/receiver.py +2 -2
  297. chia/plot_sync/sender.py +1 -1
  298. chia/plotting/cache.py +2 -2
  299. chia/plotting/check_plots.py +4 -2
  300. chia/plotting/create_plots.py +1 -1
  301. chia/plotting/manager.py +3 -3
  302. chia/plotting/util.py +2 -2
  303. chia/pools/pool_config.py +1 -1
  304. chia/pools/pool_puzzles.py +23 -17
  305. chia/pools/pool_wallet.py +22 -9
  306. chia/pools/pool_wallet_info.py +2 -2
  307. chia/protocols/farmer_protocol.py +3 -6
  308. chia/protocols/full_node_protocol.py +3 -2
  309. chia/protocols/harvester_protocol.py +3 -4
  310. chia/protocols/pool_protocol.py +2 -2
  311. chia/protocols/shared_protocol.py +2 -1
  312. chia/protocols/timelord_protocol.py +4 -4
  313. chia/protocols/wallet_protocol.py +2 -2
  314. chia/rpc/data_layer_rpc_api.py +3 -4
  315. chia/rpc/data_layer_rpc_client.py +3 -2
  316. chia/rpc/farmer_rpc_api.py +2 -2
  317. chia/rpc/farmer_rpc_client.py +2 -1
  318. chia/rpc/full_node_rpc_api.py +3 -2
  319. chia/rpc/full_node_rpc_client.py +3 -2
  320. chia/rpc/harvester_rpc_api.py +2 -1
  321. chia/rpc/rpc_client.py +2 -2
  322. chia/rpc/rpc_server.py +1 -1
  323. chia/rpc/wallet_request_types.py +2 -62
  324. chia/rpc/wallet_rpc_api.py +98 -628
  325. chia/rpc/wallet_rpc_client.py +5 -253
  326. chia/seeder/crawl_store.py +1 -1
  327. chia/seeder/crawler.py +2 -2
  328. chia/seeder/peer_record.py +2 -1
  329. chia/seeder/start_crawler.py +3 -1
  330. chia/server/address_manager.py +2 -1
  331. chia/server/address_manager_store.py +1 -1
  332. chia/server/capabilities.py +2 -1
  333. chia/server/introducer_peers.py +2 -1
  334. chia/server/node_discovery.py +1 -1
  335. chia/server/outbound_message.py +2 -1
  336. chia/server/server.py +2 -2
  337. chia/server/start_data_layer.py +2 -1
  338. chia/server/start_farmer.py +3 -1
  339. chia/server/start_full_node.py +4 -2
  340. chia/server/start_harvester.py +3 -1
  341. chia/server/start_introducer.py +12 -1
  342. chia/server/start_service.py +2 -1
  343. chia/server/start_timelord.py +3 -1
  344. chia/server/start_wallet.py +3 -1
  345. chia/server/upnp.py +1 -2
  346. chia/server/ws_connection.py +3 -4
  347. chia/simulator/add_blocks_in_batches.py +5 -3
  348. chia/simulator/block_tools.py +16 -12
  349. chia/simulator/full_node_simulator.py +9 -14
  350. chia/simulator/setup_services.py +5 -3
  351. chia/simulator/simulator_full_node_rpc_api.py +3 -2
  352. chia/simulator/simulator_full_node_rpc_client.py +3 -2
  353. chia/simulator/simulator_protocol.py +3 -2
  354. chia/simulator/simulator_test_tools.py +2 -2
  355. chia/simulator/start_simulator.py +3 -2
  356. chia/simulator/wallet_tools.py +3 -4
  357. chia/timelord/iters_from_block.py +4 -4
  358. chia/timelord/timelord.py +7 -12
  359. chia/timelord/timelord_api.py +3 -3
  360. chia/timelord/timelord_state.py +4 -3
  361. chia/types/block_protocol.py +2 -2
  362. chia/types/blockchain_format/coin.py +2 -2
  363. chia/types/blockchain_format/program.py +1 -1
  364. chia/types/blockchain_format/proof_of_space.py +3 -4
  365. chia/types/blockchain_format/tree_hash.py +1 -1
  366. chia/types/blockchain_format/vdf.py +3 -4
  367. chia/types/clvm_cost.py +1 -1
  368. chia/types/coin_record.py +4 -3
  369. chia/types/coin_spend.py +1 -1
  370. chia/types/eligible_coin_spends.py +9 -5
  371. chia/types/fee_rate.py +1 -1
  372. chia/types/generator_types.py +3 -3
  373. chia/types/internal_mempool_item.py +3 -2
  374. chia/types/mempool_item.py +10 -3
  375. chia/types/mempool_submission_status.py +2 -1
  376. chia/types/mojos.py +1 -1
  377. chia/types/peer_info.py +2 -1
  378. chia/types/transaction_queue_entry.py +2 -1
  379. chia/types/unfinished_header_block.py +4 -4
  380. chia/types/validation_state.py +2 -1
  381. chia/types/weight_proof.py +1 -9
  382. chia/util/augmented_chain.py +20 -9
  383. chia/util/block_cache.py +8 -4
  384. chia/util/condition_tools.py +2 -2
  385. chia/util/full_block_utils.py +3 -4
  386. chia/util/generator_tools.py +2 -2
  387. chia/util/initial-config.yaml +2 -11
  388. chia/util/network.py +2 -2
  389. chia/util/prev_transaction_block.py +2 -1
  390. chia/util/task_timing.py +1 -1
  391. chia/util/vdf_prover.py +3 -3
  392. chia/util/ws_message.py +1 -1
  393. chia/wallet/cat_wallet/cat_info.py +3 -2
  394. chia/wallet/cat_wallet/cat_outer_puzzle.py +3 -2
  395. chia/wallet/cat_wallet/cat_utils.py +6 -4
  396. chia/wallet/cat_wallet/cat_wallet.py +16 -18
  397. chia/wallet/cat_wallet/lineage_store.py +2 -1
  398. chia/wallet/coin_selection.py +5 -5
  399. chia/wallet/conditions.py +22 -16
  400. chia/wallet/db_wallet/db_wallet_puzzles.py +15 -15
  401. chia/wallet/derivation_record.py +2 -2
  402. chia/wallet/derive_keys.py +2 -2
  403. chia/wallet/did_wallet/did_info.py +3 -2
  404. chia/wallet/did_wallet/did_wallet.py +41 -19
  405. chia/wallet/did_wallet/did_wallet_puzzles.py +18 -12
  406. chia/wallet/driver_protocol.py +1 -1
  407. chia/wallet/lineage_proof.py +3 -2
  408. chia/wallet/nft_wallet/metadata_outer_puzzle.py +6 -7
  409. chia/wallet/nft_wallet/nft_info.py +5 -5
  410. chia/wallet/nft_wallet/nft_puzzle_utils.py +293 -0
  411. chia/wallet/nft_wallet/nft_puzzles.py +21 -298
  412. chia/wallet/nft_wallet/nft_wallet.py +47 -62
  413. chia/wallet/nft_wallet/ownership_outer_puzzle.py +4 -8
  414. chia/wallet/nft_wallet/singleton_outer_puzzle.py +3 -2
  415. chia/wallet/nft_wallet/transfer_program_puzzle.py +6 -10
  416. chia/wallet/nft_wallet/uncurry_nft.py +6 -8
  417. chia/wallet/notification_manager.py +5 -5
  418. chia/wallet/notification_store.py +3 -2
  419. chia/wallet/outer_puzzles.py +2 -1
  420. chia/wallet/puzzles/clawback/drivers.py +21 -8
  421. chia/wallet/puzzles/clawback/metadata.py +3 -2
  422. chia/wallet/puzzles/clawback/puzzle_decorator.py +5 -4
  423. chia/wallet/puzzles/deployed_puzzle_hashes.json +0 -10
  424. chia/wallet/puzzles/p2_conditions.py +3 -2
  425. chia/wallet/puzzles/p2_delegated_conditions.py +3 -2
  426. chia/wallet/puzzles/p2_delegated_puzzle.py +3 -2
  427. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +3 -3
  428. chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +3 -2
  429. chia/wallet/puzzles/p2_puzzle_hash.py +4 -3
  430. chia/wallet/puzzles/puzzle_utils.py +3 -2
  431. chia/wallet/puzzles/singleton_top_layer.py +26 -10
  432. chia/wallet/puzzles/singleton_top_layer_v1_1.py +21 -9
  433. chia/wallet/puzzles/tails.py +21 -129
  434. chia/wallet/signer_protocol.py +3 -2
  435. chia/wallet/singleton.py +12 -6
  436. chia/wallet/singleton_record.py +3 -2
  437. chia/wallet/trade_manager.py +31 -55
  438. chia/wallet/trade_record.py +3 -2
  439. chia/wallet/trading/offer.py +14 -13
  440. chia/wallet/trading/trade_store.py +3 -4
  441. chia/wallet/transaction_record.py +2 -2
  442. chia/wallet/util/blind_signer_tl.py +3 -2
  443. chia/wallet/util/compute_hints.py +3 -2
  444. chia/wallet/util/compute_memos.py +2 -2
  445. chia/wallet/util/curry_and_treehash.py +1 -2
  446. chia/wallet/util/merkle_tree.py +1 -1
  447. chia/wallet/util/merkle_utils.py +1 -1
  448. chia/wallet/util/new_peak_queue.py +2 -1
  449. chia/wallet/util/notifications.py +5 -4
  450. chia/wallet/util/peer_request_cache.py +3 -2
  451. chia/wallet/util/puzzle_compression.py +6 -4
  452. chia/wallet/util/puzzle_decorator.py +6 -4
  453. chia/wallet/util/query_filter.py +3 -2
  454. chia/wallet/util/tx_config.py +3 -3
  455. chia/wallet/util/wallet_sync_utils.py +2 -2
  456. chia/wallet/util/wallet_types.py +2 -3
  457. chia/wallet/vc_wallet/cr_cat_drivers.py +18 -22
  458. chia/wallet/vc_wallet/cr_cat_wallet.py +14 -10
  459. chia/wallet/vc_wallet/cr_outer_puzzle.py +2 -2
  460. chia/wallet/vc_wallet/vc_drivers.py +50 -68
  461. chia/wallet/vc_wallet/vc_store.py +2 -2
  462. chia/wallet/vc_wallet/vc_wallet.py +47 -15
  463. chia/wallet/wallet.py +51 -46
  464. chia/wallet/wallet_action_scope.py +4 -0
  465. chia/wallet/wallet_blockchain.py +12 -7
  466. chia/wallet/wallet_coin_record.py +3 -2
  467. chia/wallet/wallet_coin_store.py +3 -2
  468. chia/wallet/wallet_info.py +2 -1
  469. chia/wallet/wallet_interested_store.py +3 -2
  470. chia/wallet/wallet_nft_store.py +4 -4
  471. chia/wallet/wallet_node.py +3 -4
  472. chia/wallet/wallet_pool_store.py +3 -4
  473. chia/wallet/wallet_protocol.py +19 -5
  474. chia/wallet/wallet_puzzle_store.py +2 -2
  475. chia/wallet/wallet_retry_store.py +3 -6
  476. chia/wallet/wallet_singleton_store.py +2 -2
  477. chia/wallet/wallet_state_manager.py +20 -197
  478. chia/wallet/wallet_transaction_store.py +2 -2
  479. chia/wallet/wallet_user_store.py +2 -1
  480. chia/wallet/wallet_weight_proof_handler.py +3 -2
  481. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3.dist-info}/METADATA +3 -2
  482. chia_blockchain-2.5.3.dist-info/RECORD +891 -0
  483. mozilla-ca/cacert.pem +64 -33
  484. chia/_tests/clvm/test_condition_codes.py +0 -13
  485. chia/_tests/cmds/wallet/test_dao.py +0 -565
  486. chia/_tests/wallet/dao_wallet/__init__.py +0 -0
  487. chia/_tests/wallet/dao_wallet/config.py +0 -3
  488. chia/_tests/wallet/dao_wallet/test_dao_clvm.py +0 -1330
  489. chia/_tests/wallet/dao_wallet/test_dao_wallets.py +0 -3488
  490. chia/cmds/dao.py +0 -1064
  491. chia/cmds/dao_funcs.py +0 -598
  492. chia/consensus/puzzles/__init__.py +0 -0
  493. chia/consensus/puzzles/chialisp_deserialisation.clsp +0 -69
  494. chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +0 -1
  495. chia/consensus/puzzles/rom_bootstrap_generator.clsp +0 -37
  496. chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +0 -1
  497. chia/full_node/puzzles/__init__.py +0 -0
  498. chia/full_node/puzzles/block_program_zero.clsp +0 -14
  499. chia/full_node/puzzles/block_program_zero.clsp.hex +0 -1
  500. chia/full_node/puzzles/decompress_coin_spend_entry.clsp +0 -5
  501. chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +0 -1
  502. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +0 -7
  503. chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +0 -1
  504. chia/full_node/puzzles/decompress_puzzle.clsp +0 -6
  505. chia/full_node/puzzles/decompress_puzzle.clsp.hex +0 -1
  506. chia/pools/puzzles/__init__.py +0 -0
  507. chia/pools/puzzles/pool_member_innerpuz.clsp +0 -70
  508. chia/pools/puzzles/pool_member_innerpuz.clsp.hex +0 -1
  509. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +0 -69
  510. chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +0 -1
  511. chia/simulator/simulator_constants.py +0 -13
  512. chia/types/blockchain_format/foliage.py +0 -8
  513. chia/types/blockchain_format/pool_target.py +0 -5
  514. chia/types/blockchain_format/reward_chain_block.py +0 -6
  515. chia/types/blockchain_format/sized_bytes.py +0 -11
  516. chia/util/ints.py +0 -19
  517. chia/wallet/cat_wallet/dao_cat_info.py +0 -28
  518. chia/wallet/cat_wallet/dao_cat_wallet.py +0 -669
  519. chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
  520. chia/wallet/cat_wallet/puzzles/cat_truths.clib +0 -31
  521. chia/wallet/cat_wallet/puzzles/cat_v2.clsp +0 -397
  522. chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +0 -1
  523. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +0 -25
  524. chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +0 -1
  525. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +0 -15
  526. chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +0 -1
  527. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +0 -26
  528. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +0 -1
  529. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +0 -42
  530. chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +0 -1
  531. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +0 -24
  532. chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +0 -1
  533. chia/wallet/dao_wallet/__init__.py +0 -0
  534. chia/wallet/dao_wallet/dao_info.py +0 -61
  535. chia/wallet/dao_wallet/dao_utils.py +0 -811
  536. chia/wallet/dao_wallet/dao_wallet.py +0 -2119
  537. chia/wallet/did_wallet/puzzles/__init__.py +0 -0
  538. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +0 -135
  539. chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +0 -1
  540. chia/wallet/payment.py +0 -33
  541. chia/wallet/puzzles/augmented_condition.clsp +0 -13
  542. chia/wallet/puzzles/augmented_condition.clsp.hex +0 -1
  543. chia/wallet/puzzles/condition_codes.clib +0 -77
  544. chia/wallet/puzzles/curry-and-treehash.clib +0 -102
  545. chia/wallet/puzzles/curry.clib +0 -135
  546. chia/wallet/puzzles/curry_by_index.clib +0 -16
  547. chia/wallet/puzzles/dao_cat_eve.clsp +0 -17
  548. chia/wallet/puzzles/dao_cat_eve.clsp.hex +0 -1
  549. chia/wallet/puzzles/dao_cat_launcher.clsp +0 -36
  550. chia/wallet/puzzles/dao_cat_launcher.clsp.hex +0 -1
  551. chia/wallet/puzzles/dao_finished_state.clsp +0 -35
  552. chia/wallet/puzzles/dao_finished_state.clsp.hex +0 -1
  553. chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +0 -1
  554. chia/wallet/puzzles/dao_lockup.clsp +0 -288
  555. chia/wallet/puzzles/dao_lockup.clsp.hex +0 -1
  556. chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +0 -1
  557. chia/wallet/puzzles/dao_proposal.clsp +0 -377
  558. chia/wallet/puzzles/dao_proposal.clsp.hex +0 -1
  559. chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +0 -1
  560. chia/wallet/puzzles/dao_proposal_timer.clsp +0 -78
  561. chia/wallet/puzzles/dao_proposal_timer.clsp.hex +0 -1
  562. chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +0 -1
  563. chia/wallet/puzzles/dao_proposal_validator.clsp +0 -87
  564. chia/wallet/puzzles/dao_proposal_validator.clsp.hex +0 -1
  565. chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +0 -1
  566. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +0 -240
  567. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +0 -1
  568. chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +0 -1
  569. chia/wallet/puzzles/dao_treasury.clsp +0 -115
  570. chia/wallet/puzzles/dao_treasury.clsp.hex +0 -1
  571. chia/wallet/puzzles/dao_update_proposal.clsp +0 -44
  572. chia/wallet/puzzles/dao_update_proposal.clsp.hex +0 -1
  573. chia/wallet/puzzles/json.clib +0 -25
  574. chia/wallet/puzzles/merkle_utils.clib +0 -18
  575. chia/wallet/puzzles/notification.clsp +0 -7
  576. chia/wallet/puzzles/notification.clsp.hex +0 -1
  577. chia/wallet/puzzles/p2_1_of_n.clsp +0 -22
  578. chia/wallet/puzzles/p2_1_of_n.clsp.hex +0 -1
  579. chia/wallet/puzzles/p2_conditions.clsp +0 -3
  580. chia/wallet/puzzles/p2_conditions.clsp.hex +0 -1
  581. chia/wallet/puzzles/p2_delegated_conditions.clsp +0 -18
  582. chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +0 -1
  583. chia/wallet/puzzles/p2_delegated_puzzle.clsp +0 -19
  584. chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +0 -1
  585. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +0 -91
  586. chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +0 -1
  587. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +0 -108
  588. chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +0 -1
  589. chia/wallet/puzzles/p2_parent.clsp +0 -19
  590. chia/wallet/puzzles/p2_parent.clsp.hex +0 -1
  591. chia/wallet/puzzles/p2_puzzle_hash.clsp +0 -18
  592. chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +0 -1
  593. chia/wallet/puzzles/p2_singleton.clsp +0 -30
  594. chia/wallet/puzzles/p2_singleton.clsp.hex +0 -1
  595. chia/wallet/puzzles/p2_singleton_aggregator.clsp +0 -81
  596. chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +0 -1
  597. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +0 -50
  598. chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +0 -1
  599. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +0 -47
  600. chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +0 -1
  601. chia/wallet/puzzles/settlement_payments.clsp +0 -49
  602. chia/wallet/puzzles/settlement_payments.clsp.hex +0 -1
  603. chia/wallet/puzzles/sha256tree.clib +0 -11
  604. chia/wallet/puzzles/singleton_launcher.clsp +0 -16
  605. chia/wallet/puzzles/singleton_launcher.clsp.hex +0 -1
  606. chia/wallet/puzzles/singleton_top_layer.clsp +0 -177
  607. chia/wallet/puzzles/singleton_top_layer.clsp.hex +0 -1
  608. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +0 -107
  609. chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +0 -1
  610. chia/wallet/puzzles/singleton_truths.clib +0 -21
  611. chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
  612. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +0 -3
  613. chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +0 -1
  614. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +0 -304
  615. chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +0 -1
  616. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +0 -45
  617. chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +0 -1
  618. chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
  619. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +0 -30
  620. chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +0 -1
  621. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +0 -75
  622. chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +0 -1
  623. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +0 -32
  624. chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +0 -1
  625. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +0 -80
  626. chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +0 -1
  627. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +0 -163
  628. chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +0 -1
  629. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +0 -16
  630. chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +0 -1
  631. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +0 -74
  632. chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +0 -1
  633. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +0 -23
  634. chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +0 -1
  635. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +0 -64
  636. chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +0 -1
  637. chia_blockchain-2.5.2rc1.dist-info/RECORD +0 -1042
  638. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3.dist-info}/LICENSE +0 -0
  639. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3.dist-info}/WHEEL +0 -0
  640. {chia_blockchain-2.5.2rc1.dist-info → chia_blockchain-2.5.3.dist-info}/entry_points.txt +0 -0
@@ -1,1330 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any, Optional
4
-
5
- import pytest
6
- from chia_rs import AugSchemeMPL
7
- from clvm.casts import int_to_bytes
8
-
9
- from chia._tests.util.spend_sim import SimClient, SpendSim, sim_and_client
10
- from chia.types.blockchain_format.coin import Coin
11
- from chia.types.blockchain_format.program import INFINITE_COST, Program
12
- from chia.types.blockchain_format.sized_bytes import bytes32
13
- from chia.types.coin_spend import make_spend
14
- from chia.types.condition_opcodes import ConditionOpcode
15
- from chia.types.mempool_inclusion_status import MempoolInclusionStatus
16
- from chia.util.condition_tools import conditions_dict_for_solution
17
- from chia.util.errors import Err
18
- from chia.util.hash import std_hash
19
- from chia.util.ints import uint32, uint64
20
- from chia.wallet.cat_wallet.cat_utils import CAT_MOD
21
- from chia.wallet.dao_wallet.dao_info import DAORules
22
- from chia.wallet.dao_wallet.dao_utils import curry_singleton, get_p2_singleton_puzhash, get_treasury_puzzle
23
- from chia.wallet.puzzles.load_clvm import load_clvm
24
- from chia.wallet.singleton import create_singleton_puzzle_hash
25
- from chia.wallet.wallet_spend_bundle import WalletSpendBundle
26
-
27
- CAT_MOD_HASH: bytes32 = CAT_MOD.get_tree_hash()
28
- SINGLETON_MOD: Program = load_clvm("singleton_top_layer_v1_1.clsp")
29
- SINGLETON_MOD_HASH: bytes32 = SINGLETON_MOD.get_tree_hash()
30
- SINGLETON_LAUNCHER: Program = load_clvm("singleton_launcher.clsp")
31
- SINGLETON_LAUNCHER_HASH: bytes32 = SINGLETON_LAUNCHER.get_tree_hash()
32
- DAO_LOCKUP_MOD: Program = load_clvm("dao_lockup.clsp")
33
- DAO_LOCKUP_MOD_HASH: bytes32 = DAO_LOCKUP_MOD.get_tree_hash()
34
- DAO_PROPOSAL_TIMER_MOD: Program = load_clvm("dao_proposal_timer.clsp")
35
- DAO_PROPOSAL_TIMER_MOD_HASH: bytes32 = DAO_PROPOSAL_TIMER_MOD.get_tree_hash()
36
- DAO_PROPOSAL_MOD: Program = load_clvm("dao_proposal.clsp")
37
- DAO_PROPOSAL_MOD_HASH: bytes32 = DAO_PROPOSAL_MOD.get_tree_hash()
38
- DAO_PROPOSAL_VALIDATOR_MOD: Program = load_clvm("dao_proposal_validator.clsp")
39
- DAO_PROPOSAL_VALIDATOR_MOD_HASH: bytes32 = DAO_PROPOSAL_VALIDATOR_MOD.get_tree_hash()
40
- DAO_TREASURY_MOD: Program = load_clvm("dao_treasury.clsp")
41
- DAO_TREASURY_MOD_HASH: bytes32 = DAO_TREASURY_MOD.get_tree_hash()
42
- SPEND_P2_SINGLETON_MOD: Program = load_clvm("dao_spend_p2_singleton_v2.clsp")
43
- SPEND_P2_SINGLETON_MOD_HASH: bytes32 = SPEND_P2_SINGLETON_MOD.get_tree_hash()
44
- DAO_FINISHED_STATE: Program = load_clvm("dao_finished_state.clsp")
45
- DAO_FINISHED_STATE_HASH: bytes32 = DAO_FINISHED_STATE.get_tree_hash()
46
- DAO_CAT_TAIL: Program = load_clvm(
47
- "genesis_by_coin_id_or_singleton.clsp", package_or_requirement="chia.wallet.cat_wallet.puzzles"
48
- )
49
- DAO_CAT_TAIL_HASH: bytes32 = DAO_CAT_TAIL.get_tree_hash()
50
- P2_SINGLETON_MOD: Program = load_clvm("p2_singleton_via_delegated_puzzle.clsp")
51
- P2_SINGLETON_MOD_HASH: bytes32 = P2_SINGLETON_MOD.get_tree_hash()
52
- P2_SINGLETON_AGGREGATOR_MOD: Program = load_clvm("p2_singleton_aggregator.clsp")
53
- P2_SINGLETON_AGGREGATOR_MOD_HASH: bytes32 = P2_SINGLETON_AGGREGATOR_MOD.get_tree_hash()
54
- DAO_UPDATE_MOD: Program = load_clvm("dao_update_proposal.clsp")
55
- DAO_UPDATE_MOD_HASH: bytes32 = DAO_UPDATE_MOD.get_tree_hash()
56
-
57
-
58
- def test_finished_state() -> None:
59
- """
60
- Once a proposal has closed, it becomes a 'beacon' singleton which announces
61
- its proposal ID. This is referred to as the finished state and is used to
62
- confirm that a proposal has closed in order to release voting CATs from
63
- the lockup puzzle.
64
- """
65
- proposal_id = Program.to("proposal_id").get_tree_hash()
66
- singleton_struct: Program = Program.to(
67
- (SINGLETON_MOD.get_tree_hash(), (proposal_id, SINGLETON_LAUNCHER.get_tree_hash()))
68
- )
69
- finished_inner_puz = DAO_FINISHED_STATE.curry(singleton_struct, DAO_FINISHED_STATE_HASH)
70
- finished_full_puz = SINGLETON_MOD.curry(singleton_struct, finished_inner_puz)
71
- inner_sol = Program.to([1])
72
-
73
- conds = finished_inner_puz.run(inner_sol).as_python()
74
- assert conds[0][1] == finished_full_puz.get_tree_hash()
75
- assert conds[2][1] == finished_inner_puz.get_tree_hash()
76
-
77
- lineage = Program.to([proposal_id, finished_inner_puz.get_tree_hash(), 1])
78
- full_sol = Program.to([lineage, 1, inner_sol])
79
-
80
- conds = conditions_dict_for_solution(finished_full_puz, full_sol, INFINITE_COST)
81
- assert conds[ConditionOpcode.ASSERT_MY_PUZZLEHASH][0].vars[0] == finished_full_puz.get_tree_hash()
82
- assert conds[ConditionOpcode.CREATE_COIN][0].vars[0] == finished_full_puz.get_tree_hash()
83
-
84
-
85
- def test_proposal() -> None:
86
- """
87
- This test covers the three paths for closing a proposal:
88
- - Close a passed proposal
89
- - Close a failed proposal
90
- - Self-destruct a broken proposal
91
- """
92
- proposal_pass_percentage: uint64 = uint64(5100)
93
- CAT_TAIL_HASH = Program.to("tail").get_tree_hash()
94
- treasury_id = Program.to("treasury").get_tree_hash()
95
- singleton_id = Program.to("singleton_id").get_tree_hash()
96
- singleton_struct: Program = Program.to(
97
- (SINGLETON_MOD.get_tree_hash(), (singleton_id, SINGLETON_LAUNCHER.get_tree_hash()))
98
- )
99
- self_destruct_time = 1000 # number of blocks
100
- oracle_spend_delay = 10
101
- active_votes_list = [0xFADEDDAB] # are the ids of previously voted on proposals?
102
- acs: Program = Program.to(1)
103
- acs_ph: bytes32 = acs.get_tree_hash()
104
-
105
- dao_lockup_self = DAO_LOCKUP_MOD.curry(
106
- SINGLETON_MOD_HASH,
107
- SINGLETON_LAUNCHER_HASH,
108
- DAO_FINISHED_STATE_HASH,
109
- CAT_MOD_HASH,
110
- CAT_TAIL_HASH,
111
- )
112
-
113
- proposal_curry_one = DAO_PROPOSAL_MOD.curry(
114
- DAO_PROPOSAL_TIMER_MOD_HASH,
115
- SINGLETON_MOD_HASH,
116
- SINGLETON_LAUNCHER_HASH,
117
- CAT_MOD_HASH,
118
- DAO_FINISHED_STATE_HASH,
119
- DAO_TREASURY_MOD_HASH,
120
- dao_lockup_self.get_tree_hash(),
121
- CAT_TAIL_HASH,
122
- treasury_id,
123
- )
124
-
125
- # make a lockup puz for the dao cat
126
- lockup_puz = dao_lockup_self.curry(
127
- dao_lockup_self.get_tree_hash(),
128
- active_votes_list,
129
- acs, # innerpuz
130
- )
131
-
132
- dao_cat_puz: Program = CAT_MOD.curry(CAT_MOD_HASH, CAT_TAIL_HASH, lockup_puz)
133
- dao_cat_puzhash: bytes32 = dao_cat_puz.get_tree_hash()
134
-
135
- # Test Voting
136
- current_yes_votes = 20
137
- current_total_votes = 100
138
- full_proposal: Program = proposal_curry_one.curry(
139
- proposal_curry_one.get_tree_hash(),
140
- singleton_id,
141
- acs_ph,
142
- current_yes_votes,
143
- current_total_votes,
144
- )
145
-
146
- vote_amount = 10
147
- vote_type = 1 # yes vote
148
- vote_coin_id = Program.to("vote_coin").get_tree_hash()
149
- solution: Program = Program.to(
150
- [
151
- [vote_amount], # vote amounts
152
- vote_type, # vote type (yes)
153
- [vote_coin_id], # vote coin ids
154
- [active_votes_list], # previous votes
155
- [acs_ph], # lockup inner puz hash
156
- 0, # inner puz reveal
157
- 0, # soft close len
158
- self_destruct_time,
159
- oracle_spend_delay,
160
- 0,
161
- 1,
162
- ]
163
- )
164
-
165
- # Run the proposal and check its conditions
166
- conditions = conditions_dict_for_solution(full_proposal, solution, INFINITE_COST)
167
-
168
- # Puzzle Announcement of vote_coin_ids
169
- assert bytes32(conditions[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT][0].vars[0]) == vote_coin_id
170
-
171
- # Assert puzzle announcement from dao_cat of proposal_id and all vote details
172
- apa_msg = Program.to([singleton_id, vote_amount, vote_type, vote_coin_id]).get_tree_hash()
173
- assert conditions[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == std_hash(dao_cat_puzhash + apa_msg)
174
-
175
- # Check that the proposal recreates itself with updated vote amounts
176
- next_proposal: Program = proposal_curry_one.curry(
177
- proposal_curry_one.get_tree_hash(),
178
- singleton_id,
179
- acs_ph,
180
- current_yes_votes + vote_amount,
181
- current_total_votes + vote_amount,
182
- )
183
- assert bytes32(conditions[ConditionOpcode.CREATE_COIN][0].vars[0]) == next_proposal.get_tree_hash()
184
- assert conditions[ConditionOpcode.CREATE_COIN][0].vars[1] == int_to_bytes(1)
185
-
186
- # Try to vote using multiple coin ids
187
- vote_coin_id_1 = Program.to("vote_coin_1").get_tree_hash()
188
- vote_coin_id_2 = Program.to("vote_coin_2").get_tree_hash()
189
- repeat_solution_1: Program = Program.to(
190
- [
191
- [vote_amount, 20], # vote amounts
192
- vote_type, # vote type (yes)
193
- [vote_coin_id_1, vote_coin_id_2], # vote coin ids
194
- [active_votes_list, 0], # previous votes
195
- [acs_ph, acs_ph], # lockup inner puz hash
196
- 0, # inner puz reveal
197
- 0, # soft close len
198
- self_destruct_time,
199
- oracle_spend_delay,
200
- 0,
201
- 1,
202
- ]
203
- )
204
-
205
- conds_repeated = conditions_dict_for_solution(full_proposal, repeat_solution_1, INFINITE_COST)
206
- assert len(conds_repeated) == 5
207
-
208
- # Try to vote using repeated coin ids
209
- repeat_solution_2: Program = Program.to(
210
- [
211
- [vote_amount, vote_amount, 20], # vote amounts
212
- vote_type, # vote type (yes)
213
- [vote_coin_id_1, vote_coin_id_1, vote_coin_id_2], # vote coin ids
214
- [active_votes_list], # previous votes
215
- [acs_ph], # lockup inner puz hash
216
- 0, # inner puz reveal
217
- 0, # soft close len
218
- self_destruct_time,
219
- oracle_spend_delay,
220
- 0,
221
- 1,
222
- ]
223
- )
224
-
225
- with pytest.raises(ValueError) as e_info:
226
- conditions_dict_for_solution(full_proposal, repeat_solution_2, INFINITE_COST)
227
- assert "clvm raise" in e_info.value.args[0]
228
-
229
- # Test Launch
230
- current_yes_votes = 0
231
- current_total_votes = 0
232
- launch_proposal: Program = proposal_curry_one.curry(
233
- proposal_curry_one.get_tree_hash(),
234
- singleton_id,
235
- acs_ph,
236
- current_yes_votes,
237
- current_total_votes,
238
- )
239
- vote_amount = 10
240
- vote_type = 1 # yes vote
241
- vote_coin_id = Program.to("vote_coin").get_tree_hash()
242
- solution = Program.to(
243
- [
244
- [vote_amount], # vote amounts
245
- vote_type, # vote type (yes)
246
- [vote_coin_id], # vote coin ids
247
- # TODO: Check whether previous votes should be 0 in the first spend since
248
- # proposal looks at (f previous_votes) during loop_over_vote_coins
249
- [0], # previous votes
250
- [acs_ph], # lockup inner puz hash
251
- acs, # inner puz reveal
252
- 0, # soft close len
253
- self_destruct_time,
254
- oracle_spend_delay,
255
- 0,
256
- 1,
257
- ]
258
- )
259
- # Run the proposal and check its conditions
260
- conditions = conditions_dict_for_solution(launch_proposal, solution, INFINITE_COST)
261
- # check that the timer is created
262
- timer_puz = DAO_PROPOSAL_TIMER_MOD.curry(
263
- proposal_curry_one.get_tree_hash(),
264
- singleton_struct,
265
- )
266
- timer_puzhash = timer_puz.get_tree_hash()
267
- assert conditions[ConditionOpcode.CREATE_COIN][1].vars[0] == timer_puzhash
268
-
269
- # Test exits
270
-
271
- # Test attempt to close a passing proposal
272
- current_yes_votes = 200
273
- current_total_votes = 350
274
- full_proposal = proposal_curry_one.curry(
275
- proposal_curry_one.get_tree_hash(),
276
- singleton_id,
277
- acs_ph,
278
- current_yes_votes,
279
- current_total_votes,
280
- )
281
- attendance_required = 200
282
- proposal_timelock = 20
283
- soft_close_length = 5
284
- solution = Program.to(
285
- [
286
- Program.to("validator_hash").get_tree_hash(),
287
- 0,
288
- # Program.to("receiver_hash").get_tree_hash(), # not needed anymore?
289
- proposal_timelock,
290
- proposal_pass_percentage,
291
- attendance_required,
292
- 0,
293
- soft_close_length,
294
- self_destruct_time,
295
- oracle_spend_delay,
296
- 0,
297
- 1,
298
- ]
299
- )
300
-
301
- conds = conditions_dict_for_solution(full_proposal, solution, INFINITE_COST)
302
-
303
- # make a matching treasury puzzle for the APA
304
- treasury_inner: Program = DAO_TREASURY_MOD.curry(
305
- DAO_TREASURY_MOD_HASH,
306
- Program.to("validator_hash"),
307
- proposal_timelock,
308
- soft_close_length,
309
- attendance_required,
310
- proposal_pass_percentage,
311
- self_destruct_time,
312
- oracle_spend_delay,
313
- )
314
- treasury: Program = SINGLETON_MOD.curry(
315
- Program.to((SINGLETON_MOD_HASH, (treasury_id, SINGLETON_LAUNCHER_HASH))),
316
- treasury_inner,
317
- )
318
- treasury_puzhash = treasury.get_tree_hash()
319
- apa_msg_bytes = singleton_id
320
-
321
- timer_apa = std_hash(timer_puzhash + singleton_id)
322
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == timer_apa
323
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][1].vars[0] == std_hash(treasury_puzhash + apa_msg_bytes)
324
-
325
- # close a failed proposal
326
- full_proposal = proposal_curry_one.curry(
327
- proposal_curry_one.get_tree_hash(),
328
- singleton_id,
329
- acs_ph,
330
- 20, # failing number of yes votes
331
- current_total_votes,
332
- )
333
- solution = Program.to(
334
- [
335
- Program.to("validator_hash").get_tree_hash(),
336
- 0,
337
- # Program.to("receiver_hash").get_tree_hash(), # not needed anymore?
338
- proposal_timelock,
339
- proposal_pass_percentage,
340
- attendance_required,
341
- 0,
342
- soft_close_length,
343
- self_destruct_time,
344
- oracle_spend_delay,
345
- 0,
346
- 1,
347
- ]
348
- )
349
- conds = conditions_dict_for_solution(full_proposal, solution, INFINITE_COST)
350
- apa_msg_int = int_to_bytes(0)
351
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][1].vars[0] == std_hash(treasury_puzhash + apa_msg_int)
352
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == timer_apa
353
-
354
- finished_puz = DAO_FINISHED_STATE.curry(singleton_struct, DAO_FINISHED_STATE_HASH)
355
- assert conds[ConditionOpcode.CREATE_COIN][0].vars[0] == finished_puz.get_tree_hash()
356
-
357
- # self destruct a proposal
358
- attendance_required = 200
359
- solution = Program.to(
360
- [
361
- Program.to("validator_hash").get_tree_hash(),
362
- 0,
363
- # Program.to("receiver_hash").get_tree_hash(), # not needed anymore?
364
- proposal_timelock,
365
- proposal_pass_percentage,
366
- attendance_required,
367
- 0,
368
- soft_close_length,
369
- self_destruct_time,
370
- oracle_spend_delay,
371
- 1,
372
- 1,
373
- ]
374
- )
375
- conds = conditions_dict_for_solution(full_proposal, solution, INFINITE_COST)
376
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == std_hash(treasury_puzhash + apa_msg_int)
377
- assert conds[ConditionOpcode.CREATE_COIN][0].vars[0] == finished_puz.get_tree_hash()
378
-
379
-
380
- def test_proposal_timer() -> None:
381
- """
382
- The timer puzzle is created at the same time as a proposal, and enforces a relative time condition on proposals
383
- The closing time is passed in via the timer solution and confirmed via announcement from the proposal.
384
- It creates/asserts announcements to pair it with the finishing spend of a proposal.
385
- The timer puzzle only has one spend path so there is only one test case for this puzzle.
386
- """
387
- CAT_TAIL_HASH = Program.to("tail").get_tree_hash()
388
- treasury_id = Program.to("treasury").get_tree_hash()
389
- singleton_id = Program.to("singleton_id").get_tree_hash()
390
- singleton_struct: Program = Program.to(
391
- (SINGLETON_MOD.get_tree_hash(), (singleton_id, SINGLETON_LAUNCHER.get_tree_hash()))
392
- )
393
- dao_lockup_self = DAO_LOCKUP_MOD.curry(
394
- SINGLETON_MOD_HASH,
395
- SINGLETON_LAUNCHER_HASH,
396
- DAO_FINISHED_STATE_HASH,
397
- CAT_MOD_HASH,
398
- CAT_TAIL_HASH,
399
- )
400
-
401
- proposal_curry_one = DAO_PROPOSAL_MOD.curry(
402
- DAO_PROPOSAL_TIMER_MOD_HASH,
403
- SINGLETON_MOD_HASH,
404
- SINGLETON_LAUNCHER_HASH,
405
- CAT_MOD_HASH,
406
- DAO_FINISHED_STATE_HASH,
407
- DAO_TREASURY_MOD_HASH,
408
- dao_lockup_self.get_tree_hash(),
409
- CAT_TAIL_HASH,
410
- treasury_id,
411
- )
412
-
413
- proposal_timer_full: Program = DAO_PROPOSAL_TIMER_MOD.curry(
414
- proposal_curry_one.get_tree_hash(),
415
- singleton_struct,
416
- )
417
-
418
- timelock = int_to_bytes(101)
419
- parent_parent_id = Program.to("parent_parent").get_tree_hash()
420
- parent_amount = 2000
421
- solution: Program = Program.to(
422
- [
423
- 140, # yes votes
424
- 180, # total votes
425
- Program.to(1).get_tree_hash(), # proposal innerpuz
426
- timelock,
427
- parent_parent_id,
428
- parent_amount,
429
- ]
430
- )
431
- # run the timer puzzle.
432
- conds = conditions_dict_for_solution(proposal_timer_full, solution, INFINITE_COST)
433
- assert len(conds) == 4
434
-
435
- # Validate the output conditions
436
- # Check the timelock is present
437
- assert conds[ConditionOpcode.ASSERT_HEIGHT_RELATIVE][0].vars[0] == timelock
438
- # Check the proposal id is announced by the timer puz
439
- assert conds[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT][0].vars[0] == singleton_id
440
- # Check the proposal puz announces the timelock
441
- expected_proposal_puzhash: bytes32 = create_singleton_puzzle_hash(
442
- proposal_curry_one.curry(
443
- proposal_curry_one.get_tree_hash(), singleton_id, Program.to(1).get_tree_hash(), 140, 180
444
- ).get_tree_hash(),
445
- singleton_id,
446
- )
447
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == std_hash(
448
- expected_proposal_puzhash + timelock
449
- )
450
- # Check the parent is a proposal
451
- expected_parent_puzhash: bytes32 = create_singleton_puzzle_hash(
452
- proposal_curry_one.curry(
453
- proposal_curry_one.get_tree_hash(),
454
- singleton_id,
455
- Program.to(1).get_tree_hash(),
456
- 0,
457
- 0,
458
- ).get_tree_hash(),
459
- singleton_id,
460
- )
461
- parent_id = std_hash(parent_parent_id + expected_parent_puzhash + int_to_bytes(parent_amount))
462
- assert conds[ConditionOpcode.ASSERT_MY_PARENT_ID][0].vars[0] == parent_id
463
-
464
-
465
- def test_validator() -> None:
466
- """
467
- The proposal validator is run by the treasury when a passing proposal is closed.
468
- Its main purpose is to check that the proposal's vote amounts adehere to
469
- the DAO rules contained in the treasury (which are passed in from the
470
- treasury as Truth values). It creates a puzzle announcement of the
471
- proposal ID, that the proposal itself asserts. It also spends the value
472
- held in the proposal to the excess payout puzhash.
473
-
474
- The test cases covered are:
475
- - Executing a spend proposal in which the validator executes the spend of a
476
- `spend_p2_singleton` coin. This is just a proposal that spends some the treasury
477
- - Executing an update proposal that changes the DAO rules.
478
- """
479
- # Setup the treasury
480
- treasury_id = Program.to("treasury_id").get_tree_hash()
481
- treasury_struct: Program = Program.to((SINGLETON_MOD_HASH, (treasury_id, SINGLETON_LAUNCHER_HASH)))
482
-
483
- # Setup the proposal
484
- proposal_id = Program.to("proposal_id").get_tree_hash()
485
- proposal_struct: Program = Program.to((SINGLETON_MOD.get_tree_hash(), (proposal_id, SINGLETON_LAUNCHER_HASH)))
486
- CAT_TAIL_HASH = Program.to("tail").get_tree_hash()
487
- acs: Program = Program.to(1)
488
- acs_ph: bytes32 = acs.get_tree_hash()
489
-
490
- p2_singleton = P2_SINGLETON_MOD.curry(treasury_struct, P2_SINGLETON_AGGREGATOR_MOD)
491
- p2_singleton_puzhash = p2_singleton.get_tree_hash()
492
- parent_id = Program.to("parent").get_tree_hash()
493
- locked_amount = 100000
494
- spend_amount = 1100
495
- conditions = [[51, 0xDABBAD00, 1000], [51, 0xCAFEF00D, 100]]
496
-
497
- # Setup the validator
498
- minimum_amt = 1
499
- excess_puzhash = bytes32(b"1" * 32)
500
- dao_lockup_self = DAO_LOCKUP_MOD.curry(
501
- SINGLETON_MOD_HASH,
502
- SINGLETON_LAUNCHER_HASH,
503
- DAO_FINISHED_STATE_HASH,
504
- CAT_MOD_HASH,
505
- CAT_TAIL_HASH,
506
- )
507
-
508
- proposal_curry_one = DAO_PROPOSAL_MOD.curry(
509
- DAO_PROPOSAL_TIMER_MOD_HASH,
510
- SINGLETON_MOD_HASH,
511
- SINGLETON_LAUNCHER_HASH,
512
- CAT_MOD_HASH,
513
- DAO_FINISHED_STATE_HASH,
514
- DAO_TREASURY_MOD_HASH,
515
- dao_lockup_self.get_tree_hash(),
516
- CAT_TAIL_HASH,
517
- treasury_id,
518
- )
519
- proposal_validator = DAO_PROPOSAL_VALIDATOR_MOD.curry(
520
- treasury_struct,
521
- proposal_curry_one.get_tree_hash(),
522
- minimum_amt,
523
- excess_puzhash,
524
- )
525
-
526
- # Can now create the treasury inner puz
527
- treasury_inner = DAO_TREASURY_MOD.curry(
528
- DAO_TREASURY_MOD_HASH,
529
- proposal_validator,
530
- 10, # proposal len
531
- 5, # soft close
532
- 1000, # attendance
533
- 5100, # pass margin
534
- 20, # self_destruct len
535
- 3, # oracle delay
536
- )
537
-
538
- # Setup the spend_p2_singleton (proposal inner puz)
539
- spend_p2_singleton = SPEND_P2_SINGLETON_MOD.curry(
540
- treasury_struct,
541
- CAT_MOD_HASH,
542
- conditions,
543
- [],
544
- p2_singleton_puzhash, # tailhash conds
545
- )
546
- spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash()
547
-
548
- parent_amt_list = [[parent_id, locked_amount]]
549
- cat_parent_amt_list: list[Optional[Any]] = []
550
- spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()])
551
-
552
- output_conds = spend_p2_singleton.run(spend_p2_singleton_solution)
553
-
554
- proposal: Program = proposal_curry_one.curry(
555
- proposal_curry_one.get_tree_hash(),
556
- proposal_id,
557
- spend_p2_singleton_puzhash,
558
- 950,
559
- 1200,
560
- )
561
- full_proposal = SINGLETON_MOD.curry(proposal_struct, proposal)
562
- proposal_amt = uint64(10)
563
- proposal_coin_id = Coin(parent_id, full_proposal.get_tree_hash(), proposal_amt).name()
564
- solution = Program.to(
565
- [
566
- 1000,
567
- 5100,
568
- [proposal_coin_id, spend_p2_singleton_puzhash, 0],
569
- [proposal_id, 1200, 950, parent_id, proposal_amt],
570
- output_conds,
571
- ]
572
- )
573
-
574
- conds: Program = proposal_validator.run(solution)
575
- assert len(conds.as_python()) == 7 + len(conditions)
576
-
577
- # test update
578
- proposal = proposal_curry_one.curry(
579
- proposal_curry_one.get_tree_hash(),
580
- proposal_id,
581
- acs_ph,
582
- 950,
583
- 1200,
584
- )
585
- full_proposal = SINGLETON_MOD.curry(proposal_struct, proposal)
586
- proposal_coin_id = Coin(parent_id, full_proposal.get_tree_hash(), proposal_amt).name()
587
- solution = Program.to(
588
- [
589
- 1000,
590
- 5100,
591
- [proposal_coin_id, acs_ph, 0],
592
- [proposal_id, 1200, 950, parent_id, proposal_amt],
593
- [[51, 0xCAFEF00D, spend_amount]],
594
- ]
595
- )
596
- conds = proposal_validator.run(solution)
597
- assert len(conds.as_python()) == 3
598
-
599
-
600
- def test_spend_p2_singleton() -> None:
601
- # Curried values
602
- singleton_id = Program.to("singleton_id").get_tree_hash()
603
- singleton_struct: Program = Program.to((SINGLETON_MOD_HASH, (singleton_id, SINGLETON_LAUNCHER_HASH)))
604
- p2_singleton_puzhash = P2_SINGLETON_MOD.curry(singleton_struct, P2_SINGLETON_AGGREGATOR_MOD).get_tree_hash()
605
- cat_tail_1 = Program.to("cat_tail_1").get_tree_hash()
606
- cat_tail_2 = Program.to("cat_tail_2").get_tree_hash()
607
- conditions = [[51, 0xCAFEF00D, 100], [51, 0xFEEDBEEF, 200]]
608
- list_of_tailhash_conds = [
609
- [cat_tail_1, [[51, 0x8BADF00D, 123], [51, 0xF00DF00D, 321]]],
610
- [cat_tail_2, [[51, 0x8BADF00D, 123], [51, 0xF00DF00D, 321]]],
611
- ]
612
-
613
- # Solution Values
614
- xch_parent_amt_list = [[b"x" * 32, 10], [b"y" * 32, 100]]
615
- cat_parent_amt_list = [
616
- [cat_tail_1, [["b" * 32, 100], [b"c" * 32, 400]]],
617
- [cat_tail_2, [[b"e" * 32, 100], [b"f" * 32, 400]]],
618
- ]
619
- # cat_parent_amt_list = []
620
- treasury_inner_puzhash = Program.to("treasury_inner").get_tree_hash()
621
-
622
- # Puzzle
623
- spend_p2_puz = SPEND_P2_SINGLETON_MOD.curry(
624
- singleton_struct, CAT_MOD_HASH, conditions, list_of_tailhash_conds, p2_singleton_puzhash
625
- )
626
-
627
- # Solution
628
- spend_p2_sol = Program.to([xch_parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash])
629
-
630
- conds = spend_p2_puz.run(spend_p2_sol)
631
- assert conds
632
-
633
- # spend only cats
634
- conditions = []
635
- list_of_tailhash_conds = [
636
- [cat_tail_1, [[51, b"q" * 32, 123], [51, b"w" * 32, 321]]],
637
- [cat_tail_2, [[51, b"e" * 32, 123], [51, b"r" * 32, 321]]],
638
- ]
639
- xch_parent_amt_list = []
640
- cat_parent_amt_list = [
641
- [cat_tail_1, [[b"b" * 32, 100], [b"c" * 32, 400]]],
642
- [cat_tail_2, [[b"e" * 32, 100], [b"f" * 32, 400]]],
643
- ]
644
- treasury_inner_puzhash = Program.to("treasury_inner").get_tree_hash()
645
-
646
- # Puzzle
647
- spend_p2_puz = SPEND_P2_SINGLETON_MOD.curry(
648
- singleton_struct, CAT_MOD_HASH, conditions, list_of_tailhash_conds, p2_singleton_puzhash
649
- )
650
-
651
- # Solution
652
- spend_p2_sol = Program.to([xch_parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash])
653
- conds = spend_p2_puz.run(spend_p2_sol)
654
- assert conds
655
-
656
- # test deduplicate cat_parent_amount_list
657
- cat_parent_amt_list = [
658
- [cat_tail_1, [[b"b" * 32, 100], [b"c" * 32, 400], [b"b" * 32, 100], [b"b" * 32, 100]]],
659
- [cat_tail_2, [[b"e" * 32, 100], [b"f" * 32, 400], [b"f" * 32, 400], [b"e" * 32, 100]]],
660
- ]
661
-
662
- spend_p2_sol = Program.to([xch_parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash])
663
- dupe_conds = spend_p2_puz.run(spend_p2_sol)
664
- assert dupe_conds == conds
665
-
666
-
667
- def test_merge_p2_singleton() -> None:
668
- """
669
- The treasury funds are held by `p2_singleton_via_delegated` puzzles.
670
- Because a DAO can have a large number of these coins, it's possible to
671
- merge them together without requiring a treasury spend.
672
- There are two cases tested:
673
- - For the merge coins that do not create the single output coin, and
674
- - For the coin that does create the output.
675
- """
676
- # Setup a singleton struct
677
- singleton_inner: Program = Program.to(1)
678
- singleton_id = Program.to("singleton_id").get_tree_hash()
679
- singleton_struct: Program = Program.to((SINGLETON_MOD_HASH, (singleton_id, SINGLETON_LAUNCHER_HASH)))
680
-
681
- # Setup p2_singleton_via_delegated puz
682
- my_id = Program.to("my_id").get_tree_hash()
683
- p2_singleton = P2_SINGLETON_MOD.curry(singleton_struct, P2_SINGLETON_AGGREGATOR_MOD)
684
- my_puzhash = p2_singleton.get_tree_hash()
685
-
686
- # Spend to delegated puz
687
- delegated_puz = Program.to(1)
688
- delegated_sol = Program.to([[51, 0xCAFEF00D, 300]])
689
- solution = Program.to([0, singleton_inner.get_tree_hash(), delegated_puz, delegated_sol, my_id])
690
- conds = conditions_dict_for_solution(p2_singleton, solution, INFINITE_COST)
691
- apa = std_hash(
692
- SINGLETON_MOD.curry(singleton_struct, singleton_inner).get_tree_hash()
693
- + Program.to([my_id, delegated_puz.get_tree_hash()]).get_tree_hash()
694
- )
695
- assert len(conds) == 4
696
- assert conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT][0].vars[0] == apa
697
- assert conds[ConditionOpcode.CREATE_COIN][0].vars[1] == int_to_bytes(300)
698
-
699
- # Merge Spend (not output creator)
700
- output_parent_id = Program.to("output_parent").get_tree_hash()
701
- output_coin_amount = uint64(100)
702
- aggregator_sol = Program.to([my_id, my_puzhash, 300, 0, [output_parent_id, output_coin_amount]])
703
- merge_p2_singleton_sol = Program.to([aggregator_sol, 0, 0, 0, 0])
704
- conds = conditions_dict_for_solution(p2_singleton, merge_p2_singleton_sol, INFINITE_COST)
705
- assert len(conds) == 5
706
- assert conds[ConditionOpcode.ASSERT_MY_PUZZLEHASH][0].vars[0] == my_puzhash
707
- assert conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0] == int_to_bytes(0)
708
-
709
- # Merge Spend (output creator)
710
- fake_parent_id = Program.to("fake_parent").get_tree_hash()
711
- merged_coin_id = Coin(fake_parent_id, my_puzhash, uint64(200)).name()
712
- merge_sol = Program.to([[my_id, my_puzhash, 100, [[fake_parent_id, my_puzhash, 200]], 0]])
713
- conds = conditions_dict_for_solution(p2_singleton, merge_sol, INFINITE_COST)
714
- assert len(conds) == 7
715
- assert conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT][0].vars[0] == std_hash(merged_coin_id)
716
- assert conds[ConditionOpcode.CREATE_COIN][0].vars[1] == int_to_bytes(300)
717
-
718
- # Test merge and aggregate announcements match up
719
- parent_ids = [
720
- Program.to("fake_parent_1").get_tree_hash(),
721
- Program.to("fake_parent_2").get_tree_hash(),
722
- Program.to("fake_parent_3").get_tree_hash(),
723
- ]
724
- amounts = [uint64(1000), uint64(2000), uint64(3000)]
725
- parent_puzhash_amounts = []
726
- merge_coin_ids: list[bytes32] = []
727
- for pid, amt in zip(parent_ids, amounts):
728
- parent_puzhash_amounts.append([pid, my_puzhash, amt])
729
- merge_coin_ids.append(Coin(pid, my_puzhash, amt).name())
730
-
731
- output_parent_amount = [output_parent_id, output_coin_amount]
732
- output_coin_id = Coin(output_parent_id, my_puzhash, output_coin_amount).name()
733
-
734
- agg_sol = Program.to([[output_coin_id, my_puzhash, output_coin_amount, parent_puzhash_amounts, 0]])
735
- agg_conds = conditions_dict_for_solution(p2_singleton, agg_sol, INFINITE_COST)
736
- # aggregator coin announces merge coin IDs
737
- agg_ccas = [std_hash(output_coin_id + x.vars[0]) for x in agg_conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT]]
738
- # aggregator coin asserts 0 from merge coins
739
- agg_acas = [x.vars[0] for x in agg_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT]]
740
-
741
- for coin_id, ppa in zip(merge_coin_ids, parent_puzhash_amounts):
742
- sol = Program.to([[coin_id, ppa[1], ppa[2], 0, output_parent_amount]])
743
- merge_conds = conditions_dict_for_solution(p2_singleton, sol, INFINITE_COST)
744
- # merge coin announces 0
745
- cca = std_hash(coin_id + merge_conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0])
746
- # merge coin asserts my_id from aggregator
747
- aca = merge_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT][0].vars[0]
748
- assert aca in agg_ccas
749
- assert cca in agg_acas
750
- assert merge_conds[ConditionOpcode.ASSERT_MY_COIN_ID][0].vars[0] == coin_id
751
-
752
-
753
- def test_treasury() -> None:
754
- """
755
- The treasury has two spend paths:
756
- - Proposal Path: when a proposal is being closed the treasury spend runs the
757
- validator and the actual proposed code (if passed)
758
- - Oracle Path: The treasury can make announcements about itself that are
759
- used to close invalid proposals
760
- """
761
- # Setup the treasury
762
- treasury_id = Program.to("treasury_id").get_tree_hash()
763
- treasury_struct: Program = Program.to((SINGLETON_MOD_HASH, (treasury_id, SINGLETON_LAUNCHER_HASH)))
764
- CAT_TAIL_HASH = Program.to("tail").get_tree_hash()
765
-
766
- proposal_id = Program.to("singleton_id").get_tree_hash()
767
- proposal_struct: Program = Program.to((SINGLETON_MOD_HASH, (proposal_id, SINGLETON_LAUNCHER_HASH)))
768
- p2_singleton = P2_SINGLETON_MOD.curry(treasury_struct, P2_SINGLETON_AGGREGATOR_MOD)
769
- p2_singleton_puzhash = p2_singleton.get_tree_hash()
770
- parent_id = Program.to("parent").get_tree_hash()
771
- locked_amount = 100000
772
- oracle_spend_delay = 10
773
- self_destruct_time = 1000
774
- proposal_length = 40
775
- soft_close_length = 5
776
- attendance = 1000
777
- pass_margin = 5100
778
- conditions = [[51, 0xDABBAD00, 1000], [51, 0xCAFEF00D, 100]]
779
-
780
- # Setup the validator
781
- minimum_amt = 1
782
- excess_puzhash = bytes32(b"1" * 32)
783
- dao_lockup_self = DAO_LOCKUP_MOD.curry(
784
- SINGLETON_MOD_HASH,
785
- SINGLETON_LAUNCHER_HASH,
786
- DAO_FINISHED_STATE_HASH,
787
- CAT_MOD_HASH,
788
- CAT_TAIL_HASH,
789
- )
790
-
791
- proposal_curry_one = DAO_PROPOSAL_MOD.curry(
792
- DAO_PROPOSAL_TIMER_MOD_HASH,
793
- SINGLETON_MOD_HASH,
794
- SINGLETON_LAUNCHER_HASH,
795
- CAT_MOD_HASH,
796
- DAO_FINISHED_STATE_HASH,
797
- DAO_TREASURY_MOD_HASH,
798
- dao_lockup_self.get_tree_hash(),
799
- CAT_TAIL_HASH,
800
- treasury_id,
801
- )
802
- proposal_validator = DAO_PROPOSAL_VALIDATOR_MOD.curry(
803
- treasury_struct,
804
- proposal_curry_one.get_tree_hash(),
805
- minimum_amt,
806
- excess_puzhash,
807
- )
808
-
809
- # Can now create the treasury inner puz
810
- treasury_inner = DAO_TREASURY_MOD.curry(
811
- DAO_TREASURY_MOD_HASH,
812
- proposal_validator,
813
- proposal_length,
814
- soft_close_length,
815
- attendance,
816
- pass_margin,
817
- self_destruct_time,
818
- oracle_spend_delay,
819
- )
820
-
821
- # Setup the spend_p2_singleton (proposal inner puz)
822
- spend_p2_singleton = SPEND_P2_SINGLETON_MOD.curry(
823
- treasury_struct,
824
- CAT_MOD_HASH,
825
- conditions,
826
- [],
827
- p2_singleton_puzhash, # tailhash conds
828
- )
829
- spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash()
830
-
831
- parent_amt_list = [[parent_id, locked_amount]]
832
- cat_parent_amt_list: list[Optional[Any]] = []
833
- spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner.get_tree_hash()])
834
-
835
- proposal: Program = proposal_curry_one.curry(
836
- proposal_curry_one.get_tree_hash(),
837
- proposal_id,
838
- spend_p2_singleton_puzhash,
839
- 950,
840
- 1200,
841
- )
842
- full_proposal = SINGLETON_MOD.curry(proposal_struct, proposal)
843
-
844
- # Oracle spend
845
- solution: Program = Program.to([0, 0, 0, 0, 0, treasury_struct])
846
- conds: Program = treasury_inner.run(solution)
847
- assert len(conds.as_python()) == 3
848
-
849
- # Proposal Spend
850
- proposal_amt = uint64(10)
851
- proposal_coin_id = Coin(parent_id, full_proposal.get_tree_hash(), proposal_amt).name()
852
- solution = Program.to(
853
- [
854
- [proposal_coin_id, spend_p2_singleton_puzhash, 0, "s"],
855
- [proposal_id, 1200, 950, parent_id, proposal_amt],
856
- spend_p2_singleton,
857
- spend_p2_singleton_solution,
858
- ]
859
- )
860
- conds = treasury_inner.run(solution)
861
- assert len(conds.as_python()) == 10 + len(conditions)
862
-
863
-
864
- def test_lockup() -> None:
865
- """
866
- The lockup puzzle tracks the voting records of DAO CATs. When a proposal is
867
- voted on, the proposal ID is added to a list, against which, future votes
868
- are checked.
869
- This test checks the addition of new votes to the lockup, and that you can't
870
- re-vote on a proposal twice.
871
- """
872
- CAT_TAIL_HASH = Program.to("tail").get_tree_hash()
873
-
874
- INNERPUZ = Program.to(1)
875
- previous_votes = [0xFADEDDAB]
876
-
877
- dao_lockup_self = DAO_LOCKUP_MOD.curry(
878
- SINGLETON_MOD_HASH,
879
- SINGLETON_LAUNCHER_HASH,
880
- DAO_FINISHED_STATE_HASH,
881
- CAT_MOD_HASH,
882
- CAT_TAIL_HASH,
883
- )
884
-
885
- full_lockup_puz: Program = dao_lockup_self.curry(
886
- dao_lockup_self.get_tree_hash(),
887
- previous_votes,
888
- INNERPUZ,
889
- )
890
- my_id = Program.to("my_id").get_tree_hash()
891
- lockup_coin_amount = 20
892
-
893
- # Test adding vote
894
- new_proposal = 0xBADDADAB
895
- new_vote_list = [new_proposal, 0xFADEDDAB]
896
- child_puzhash = dao_lockup_self.curry(
897
- dao_lockup_self.get_tree_hash(),
898
- new_vote_list,
899
- INNERPUZ,
900
- ).get_tree_hash()
901
- message = Program.to([new_proposal, lockup_coin_amount, 1, my_id]).get_tree_hash()
902
- generated_conditions = [[51, child_puzhash, lockup_coin_amount], [62, message]]
903
- solution: Program = Program.to(
904
- [
905
- my_id,
906
- generated_conditions,
907
- 20,
908
- new_proposal,
909
- INNERPUZ.get_tree_hash(), # fake proposal curry vals
910
- 1,
911
- 20,
912
- child_puzhash,
913
- 0,
914
- ]
915
- )
916
- conds: Program = full_lockup_puz.run(solution)
917
- assert len(conds.as_python()) == 6
918
-
919
- # Test Re-voting on same proposal fails
920
- new_proposal = 0xBADDADAB
921
- new_vote_list = [new_proposal, 0xBADDADAB]
922
- child_puzhash = dao_lockup_self.curry(
923
- dao_lockup_self.get_tree_hash(),
924
- new_vote_list,
925
- INNERPUZ,
926
- ).get_tree_hash()
927
- message = Program.to([new_proposal, lockup_coin_amount, 1, my_id]).get_tree_hash()
928
- generated_conditions = [[51, child_puzhash, lockup_coin_amount], [62, message]]
929
- revote_solution: Program = Program.to(
930
- [
931
- my_id,
932
- generated_conditions,
933
- 20,
934
- new_proposal,
935
- INNERPUZ.get_tree_hash(), # fake proposal curry vals
936
- 1,
937
- 20,
938
- child_puzhash,
939
- 0,
940
- ]
941
- )
942
- with pytest.raises(ValueError) as e_info:
943
- conds = full_lockup_puz.run(revote_solution)
944
- assert "clvm raise" in e_info.value.args[0]
945
-
946
- # Test vote removal
947
- solution = Program.to(
948
- [
949
- 0,
950
- generated_conditions,
951
- 20,
952
- [0xFADEDDAB],
953
- INNERPUZ.get_tree_hash(),
954
- 0,
955
- 0,
956
- 0,
957
- 0,
958
- ]
959
- )
960
- conds = full_lockup_puz.run(solution)
961
- assert len(conds.as_python()) == 3
962
-
963
- new_innerpuz = Program.to("new_inner")
964
- new_innerpuzhash = new_innerpuz.get_tree_hash()
965
- child_lockup = dao_lockup_self.curry(
966
- dao_lockup_self.get_tree_hash(),
967
- previous_votes,
968
- new_innerpuz,
969
- ).get_tree_hash()
970
- message = Program.to([0, 0, 0, my_id]).get_tree_hash()
971
- spend_conds = [[51, child_lockup, lockup_coin_amount], [62, message]]
972
- transfer_sol = Program.to(
973
- [
974
- my_id,
975
- spend_conds,
976
- lockup_coin_amount,
977
- 0,
978
- INNERPUZ.get_tree_hash(), # fake proposal curry vals
979
- 0,
980
- 0,
981
- INNERPUZ.get_tree_hash(),
982
- new_innerpuzhash,
983
- ]
984
- )
985
- conds = full_lockup_puz.run(transfer_sol)
986
- assert conds.at("rrrrfrf").as_atom() == child_lockup
987
-
988
-
989
- def test_proposal_lifecycle() -> None:
990
- """
991
- This test covers the whole lifecycle of a proposal and treasury.
992
- Its main function is to check that the announcement pairs between treasury
993
- and proposal are accurate.
994
- It covers the spend proposal and update proposal types.
995
- """
996
- proposal_pass_percentage: uint64 = uint64(5100)
997
- attendance_required: uint64 = uint64(1000)
998
- proposal_timelock: uint64 = uint64(40)
999
- soft_close_length: uint64 = uint64(5)
1000
- self_destruct_time: uint64 = uint64(1000)
1001
- oracle_spend_delay: uint64 = uint64(10)
1002
- min_amt: uint64 = uint64(1)
1003
- CAT_TAIL_HASH = Program.to("tail").get_tree_hash()
1004
-
1005
- dao_rules = DAORules(
1006
- proposal_timelock=proposal_timelock,
1007
- soft_close_length=soft_close_length,
1008
- attendance_required=attendance_required,
1009
- pass_percentage=proposal_pass_percentage,
1010
- self_destruct_length=self_destruct_time,
1011
- oracle_spend_delay=oracle_spend_delay,
1012
- proposal_minimum_amount=min_amt,
1013
- )
1014
-
1015
- # Setup the treasury
1016
- treasury_id = Program.to("treasury_id").get_tree_hash()
1017
- treasury_singleton_struct: Program = Program.to((SINGLETON_MOD_HASH, (treasury_id, SINGLETON_LAUNCHER_HASH)))
1018
- treasury_amount = 1
1019
-
1020
- # setup the p2_singleton
1021
- p2_singleton = P2_SINGLETON_MOD.curry(treasury_singleton_struct, P2_SINGLETON_AGGREGATOR_MOD)
1022
- p2_singleton_puzhash = p2_singleton.get_tree_hash()
1023
- parent_id = Program.to("parent").get_tree_hash()
1024
- locked_amount = 100000
1025
- conditions = [[51, 0xDABBAD00, 1000], [51, 0xCAFEF00D, 100]]
1026
-
1027
- excess_puzhash = get_p2_singleton_puzhash(treasury_id)
1028
- dao_lockup_self = DAO_LOCKUP_MOD.curry(
1029
- SINGLETON_MOD_HASH,
1030
- SINGLETON_LAUNCHER_HASH,
1031
- DAO_FINISHED_STATE_HASH,
1032
- CAT_MOD_HASH,
1033
- CAT_TAIL_HASH,
1034
- )
1035
-
1036
- proposal_curry_one = DAO_PROPOSAL_MOD.curry(
1037
- DAO_PROPOSAL_TIMER_MOD_HASH,
1038
- SINGLETON_MOD_HASH,
1039
- SINGLETON_LAUNCHER_HASH,
1040
- CAT_MOD_HASH,
1041
- DAO_FINISHED_STATE_HASH,
1042
- DAO_TREASURY_MOD_HASH,
1043
- dao_lockup_self.get_tree_hash(),
1044
- CAT_TAIL_HASH,
1045
- treasury_id,
1046
- )
1047
- proposal_validator = DAO_PROPOSAL_VALIDATOR_MOD.curry(
1048
- treasury_singleton_struct,
1049
- proposal_curry_one.get_tree_hash(),
1050
- min_amt,
1051
- excess_puzhash,
1052
- )
1053
-
1054
- treasury_inner_puz: Program = DAO_TREASURY_MOD.curry(
1055
- DAO_TREASURY_MOD_HASH,
1056
- proposal_validator,
1057
- proposal_timelock,
1058
- soft_close_length,
1059
- attendance_required,
1060
- proposal_pass_percentage,
1061
- self_destruct_time,
1062
- oracle_spend_delay,
1063
- )
1064
- treasury_inner_puzhash = treasury_inner_puz.get_tree_hash()
1065
-
1066
- calculated_treasury_puzhash = get_treasury_puzzle(dao_rules, treasury_id, CAT_TAIL_HASH).get_tree_hash()
1067
- assert treasury_inner_puzhash == calculated_treasury_puzhash
1068
-
1069
- full_treasury_puz = SINGLETON_MOD.curry(treasury_singleton_struct, treasury_inner_puz)
1070
- full_treasury_puzhash = full_treasury_puz.get_tree_hash()
1071
-
1072
- # Setup the spend_p2_singleton (proposal inner puz)
1073
- spend_p2_singleton = SPEND_P2_SINGLETON_MOD.curry(
1074
- treasury_singleton_struct,
1075
- CAT_MOD_HASH,
1076
- conditions,
1077
- [],
1078
- p2_singleton_puzhash, # tailhash conds
1079
- )
1080
- spend_p2_singleton_puzhash = spend_p2_singleton.get_tree_hash()
1081
-
1082
- parent_amt_list = [[parent_id, locked_amount]]
1083
- cat_parent_amt_list: list[Optional[Any]] = []
1084
- spend_p2_singleton_solution = Program.to([parent_amt_list, cat_parent_amt_list, treasury_inner_puzhash])
1085
-
1086
- # Setup Proposal
1087
- proposal_id = Program.to("proposal_id").get_tree_hash()
1088
- proposal_singleton_struct: Program = Program.to((SINGLETON_MOD_HASH, (proposal_id, SINGLETON_LAUNCHER_HASH)))
1089
-
1090
- current_votes = 1200
1091
- yes_votes = 950
1092
- proposal: Program = proposal_curry_one.curry(
1093
- proposal_curry_one.get_tree_hash(),
1094
- proposal_id,
1095
- spend_p2_singleton_puzhash,
1096
- yes_votes,
1097
- current_votes,
1098
- )
1099
- full_proposal: Program = SINGLETON_MOD.curry(proposal_singleton_struct, proposal)
1100
- full_proposal_puzhash: bytes32 = full_proposal.get_tree_hash()
1101
- proposal_amt = uint64(11)
1102
- proposal_coin_id = Coin(parent_id, full_proposal_puzhash, proposal_amt).name()
1103
-
1104
- treasury_solution: Program = Program.to(
1105
- [
1106
- [proposal_coin_id, spend_p2_singleton_puzhash, 0],
1107
- [proposal_id, current_votes, yes_votes, parent_id, proposal_amt],
1108
- spend_p2_singleton,
1109
- spend_p2_singleton_solution,
1110
- ]
1111
- )
1112
-
1113
- proposal_solution = Program.to(
1114
- [
1115
- proposal_validator.get_tree_hash(),
1116
- 0,
1117
- proposal_timelock,
1118
- proposal_pass_percentage,
1119
- attendance_required,
1120
- 0,
1121
- soft_close_length,
1122
- self_destruct_time,
1123
- oracle_spend_delay,
1124
- 0,
1125
- proposal_amt,
1126
- ]
1127
- )
1128
-
1129
- # lineage_proof my_amount inner_solution
1130
- lineage_proof = [treasury_id, treasury_inner_puzhash, treasury_amount]
1131
- full_treasury_solution = Program.to([lineage_proof, treasury_amount, treasury_solution])
1132
- full_proposal_solution = Program.to([lineage_proof, proposal_amt, proposal_solution])
1133
-
1134
- # Run the puzzles
1135
- treasury_conds = conditions_dict_for_solution(full_treasury_puz, full_treasury_solution, INFINITE_COST)
1136
- proposal_conds = conditions_dict_for_solution(full_proposal, full_proposal_solution, INFINITE_COST)
1137
-
1138
- # Announcements
1139
- treasury_aca = treasury_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT][0].vars[0]
1140
- proposal_cca = proposal_conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0]
1141
- assert std_hash(proposal_coin_id + proposal_cca) == treasury_aca
1142
-
1143
- treasury_cpas = [
1144
- std_hash(full_treasury_puzhash + cond.vars[0])
1145
- for cond in treasury_conds[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT]
1146
- ]
1147
- proposal_apas = [cond.vars[0] for cond in proposal_conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT]]
1148
- assert treasury_cpas[1] == proposal_apas[1]
1149
-
1150
- # Test Proposal to update treasury
1151
- # Set up new treasury params
1152
- new_proposal_pass_percentage: uint64 = uint64(2500)
1153
- new_attendance_required: uint64 = uint64(500)
1154
- new_proposal_timelock: uint64 = uint64(900)
1155
- new_soft_close_length: uint64 = uint64(10)
1156
- new_self_destruct_time: uint64 = uint64(1000)
1157
- new_oracle_spend_delay: uint64 = uint64(20)
1158
- new_minimum_amount: uint64 = uint64(10)
1159
- proposal_excess_puzhash: bytes32 = get_p2_singleton_puzhash(treasury_id)
1160
-
1161
- new_dao_rules = DAORules(
1162
- proposal_timelock=new_proposal_timelock,
1163
- soft_close_length=new_soft_close_length,
1164
- attendance_required=new_attendance_required,
1165
- pass_percentage=new_proposal_pass_percentage,
1166
- self_destruct_length=new_self_destruct_time,
1167
- oracle_spend_delay=new_oracle_spend_delay,
1168
- proposal_minimum_amount=new_minimum_amount,
1169
- )
1170
-
1171
- update_proposal = DAO_UPDATE_MOD.curry(
1172
- DAO_TREASURY_MOD_HASH,
1173
- DAO_PROPOSAL_VALIDATOR_MOD_HASH,
1174
- treasury_singleton_struct,
1175
- proposal_curry_one.get_tree_hash(),
1176
- new_minimum_amount,
1177
- proposal_excess_puzhash,
1178
- new_proposal_timelock,
1179
- new_soft_close_length,
1180
- new_attendance_required,
1181
- new_proposal_pass_percentage,
1182
- new_self_destruct_time,
1183
- new_oracle_spend_delay,
1184
- )
1185
- update_proposal_puzhash = update_proposal.get_tree_hash()
1186
- update_proposal_sol = Program.to([])
1187
-
1188
- proposal = proposal_curry_one.curry(
1189
- proposal_curry_one.get_tree_hash(),
1190
- proposal_id,
1191
- update_proposal_puzhash,
1192
- yes_votes,
1193
- current_votes,
1194
- )
1195
- full_proposal = SINGLETON_MOD.curry(proposal_singleton_struct, proposal)
1196
- full_proposal_puzhash = full_proposal.get_tree_hash()
1197
- proposal_coin_id = Coin(parent_id, full_proposal_puzhash, proposal_amt).name()
1198
-
1199
- treasury_solution = Program.to(
1200
- [
1201
- [proposal_coin_id, update_proposal_puzhash, 0, "u"],
1202
- [proposal_id, current_votes, yes_votes, parent_id, proposal_amt],
1203
- update_proposal,
1204
- update_proposal_sol,
1205
- ]
1206
- )
1207
-
1208
- proposal_solution = Program.to(
1209
- [
1210
- proposal_validator.get_tree_hash(),
1211
- 0,
1212
- proposal_timelock,
1213
- proposal_pass_percentage,
1214
- attendance_required,
1215
- 0,
1216
- soft_close_length,
1217
- self_destruct_time,
1218
- oracle_spend_delay,
1219
- 0,
1220
- proposal_amt,
1221
- ]
1222
- )
1223
-
1224
- lineage_proof = [treasury_id, treasury_inner_puzhash, treasury_amount]
1225
- full_treasury_solution = Program.to([lineage_proof, treasury_amount, treasury_solution])
1226
- full_proposal_solution = Program.to([lineage_proof, proposal_amt, proposal_solution])
1227
-
1228
- treasury_conds = conditions_dict_for_solution(full_treasury_puz, full_treasury_solution, INFINITE_COST)
1229
- proposal_conds = conditions_dict_for_solution(full_proposal, full_proposal_solution, INFINITE_COST)
1230
-
1231
- treasury_aca = treasury_conds[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT][0].vars[0]
1232
- proposal_cca = proposal_conds[ConditionOpcode.CREATE_COIN_ANNOUNCEMENT][0].vars[0]
1233
- assert std_hash(proposal_coin_id + proposal_cca) == treasury_aca
1234
-
1235
- treasury_cpas = [
1236
- std_hash(full_treasury_puzhash + cond.vars[0])
1237
- for cond in treasury_conds[ConditionOpcode.CREATE_PUZZLE_ANNOUNCEMENT]
1238
- ]
1239
- proposal_apas = [cond.vars[0] for cond in proposal_conds[ConditionOpcode.ASSERT_PUZZLE_ANNOUNCEMENT]]
1240
- assert treasury_cpas[1] == proposal_apas[1]
1241
-
1242
- new_treasury_inner = update_proposal.run(update_proposal_sol).at("frf").as_atom()
1243
- expected_treasury_inner = get_treasury_puzzle(new_dao_rules, treasury_id, CAT_TAIL_HASH)
1244
- assert new_treasury_inner == expected_treasury_inner.get_tree_hash()
1245
-
1246
- expected_treasury_hash = curry_singleton(treasury_id, expected_treasury_inner).get_tree_hash()
1247
- assert treasury_conds[ConditionOpcode.CREATE_COIN][1].vars[0] == expected_treasury_hash
1248
-
1249
-
1250
- async def do_spend(
1251
- sim: SpendSim,
1252
- sim_client: SimClient,
1253
- coins: list[Coin],
1254
- puzzles: list[Program],
1255
- solutions: list[Program],
1256
- ) -> tuple[MempoolInclusionStatus, Optional[Err]]:
1257
- spends = []
1258
- for coin, puzzle, solution in zip(coins, puzzles, solutions):
1259
- spends.append(make_spend(coin, puzzle, solution))
1260
- spend_bundle = WalletSpendBundle(spends, AugSchemeMPL.aggregate([]))
1261
- result = await sim_client.push_tx(spend_bundle)
1262
- await sim.farm_block()
1263
- return result
1264
-
1265
-
1266
- @pytest.mark.anyio
1267
- async def test_singleton_aggregator() -> None:
1268
- async with sim_and_client() as (sim, sim_client):
1269
- aggregator = P2_SINGLETON_AGGREGATOR_MOD
1270
- aggregator_hash = aggregator.get_tree_hash()
1271
- await sim.farm_block(aggregator_hash)
1272
- await sim.farm_block(aggregator_hash)
1273
- for i in range(5):
1274
- await sim.farm_block()
1275
-
1276
- coin_records = await sim_client.get_coin_records_by_puzzle_hash(aggregator_hash)
1277
- coins = [c.coin for c in coin_records]
1278
-
1279
- output_coin = coins[0]
1280
- output_sol = Program.to(
1281
- [
1282
- output_coin.name(),
1283
- output_coin.puzzle_hash,
1284
- output_coin.amount,
1285
- [[c.parent_coin_info, c.puzzle_hash, c.amount] for c in coins[1:]],
1286
- ]
1287
- )
1288
- merge_sols = [
1289
- Program.to([c.name(), c.puzzle_hash, c.amount, [], [output_coin.parent_coin_info, output_coin.amount]])
1290
- for c in coins[1:]
1291
- ]
1292
-
1293
- res = await do_spend(sim, sim_client, coins, [aggregator] * 4, [output_sol, *merge_sols])
1294
- assert res[0] == MempoolInclusionStatus.SUCCESS
1295
-
1296
- await sim.rewind(uint32(sim.block_height - 1))
1297
-
1298
- # Spend a merge coin with empty output details
1299
- output_sol = Program.to(
1300
- [
1301
- output_coin.name(),
1302
- output_coin.puzzle_hash,
1303
- output_coin.amount,
1304
- [],
1305
- [],
1306
- ]
1307
- )
1308
- res = await do_spend(sim, sim_client, [output_coin], [aggregator], [output_sol])
1309
- assert res[0] == MempoolInclusionStatus.FAILED
1310
-
1311
- # Try to steal treasury coins with a phoney output
1312
- acs = Program.to(1)
1313
- acs_ph = acs.get_tree_hash()
1314
- await sim.farm_block(acs_ph)
1315
- bad_coin = (await sim_client.get_coin_records_by_puzzle_hash(acs_ph))[0].coin
1316
- bad_sol = Program.to(
1317
- [
1318
- [ConditionOpcode.CREATE_COIN, acs_ph, sum(c.amount for c in coins)],
1319
- *[[ConditionOpcode.ASSERT_COIN_ANNOUNCEMENT, std_hash(c.name())] for c in coins],
1320
- [ConditionOpcode.CREATE_COIN_ANNOUNCEMENT, 0],
1321
- ]
1322
- )
1323
-
1324
- merge_sols = [
1325
- Program.to([c.name(), c.puzzle_hash, c.amount, [], [bad_coin.parent_coin_info, bad_coin.amount]])
1326
- for c in coins
1327
- ]
1328
-
1329
- res = await do_spend(sim, sim_client, [bad_coin, *coins], [acs] + [aggregator] * 4, [bad_sol, *merge_sols])
1330
- assert res[0] == MempoolInclusionStatus.FAILED