chia-blockchain 2.5.1rc1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- chia/__init__.py +10 -0
- chia/__main__.py +5 -0
- chia/_tests/README.md +53 -0
- chia/_tests/__init__.py +0 -0
- chia/_tests/blockchain/__init__.py +0 -0
- chia/_tests/blockchain/blockchain_test_utils.py +195 -0
- chia/_tests/blockchain/config.py +4 -0
- chia/_tests/blockchain/test_augmented_chain.py +145 -0
- chia/_tests/blockchain/test_blockchain.py +4202 -0
- chia/_tests/blockchain/test_blockchain_transactions.py +1031 -0
- chia/_tests/blockchain/test_build_chains.py +59 -0
- chia/_tests/blockchain/test_get_block_generator.py +72 -0
- chia/_tests/blockchain/test_lookup_fork_chain.py +194 -0
- chia/_tests/build-init-files.py +92 -0
- chia/_tests/build-job-matrix.py +204 -0
- chia/_tests/check_pytest_monitor_output.py +34 -0
- chia/_tests/check_sql_statements.py +72 -0
- chia/_tests/chia-start-sim +42 -0
- chia/_tests/clvm/__init__.py +0 -0
- chia/_tests/clvm/benchmark_costs.py +23 -0
- chia/_tests/clvm/coin_store.py +149 -0
- chia/_tests/clvm/test_chialisp_deserialization.py +101 -0
- chia/_tests/clvm/test_clvm_step.py +37 -0
- chia/_tests/clvm/test_condition_codes.py +13 -0
- chia/_tests/clvm/test_curry_and_treehash.py +55 -0
- chia/_tests/clvm/test_message_conditions.py +184 -0
- chia/_tests/clvm/test_program.py +150 -0
- chia/_tests/clvm/test_puzzle_compression.py +143 -0
- chia/_tests/clvm/test_puzzle_drivers.py +45 -0
- chia/_tests/clvm/test_puzzles.py +242 -0
- chia/_tests/clvm/test_singletons.py +540 -0
- chia/_tests/clvm/test_spend_sim.py +181 -0
- chia/_tests/cmds/__init__.py +0 -0
- chia/_tests/cmds/cmd_test_utils.py +469 -0
- chia/_tests/cmds/config.py +3 -0
- chia/_tests/cmds/conftest.py +23 -0
- chia/_tests/cmds/test_click_types.py +200 -0
- chia/_tests/cmds/test_cmd_framework.py +620 -0
- chia/_tests/cmds/test_cmds_util.py +97 -0
- chia/_tests/cmds/test_daemon.py +92 -0
- chia/_tests/cmds/test_dev_gh.py +131 -0
- chia/_tests/cmds/test_farm_cmd.py +66 -0
- chia/_tests/cmds/test_show.py +116 -0
- chia/_tests/cmds/test_sim.py +207 -0
- chia/_tests/cmds/test_timelock_args.py +75 -0
- chia/_tests/cmds/test_tx_config_args.py +154 -0
- chia/_tests/cmds/testing_classes.py +59 -0
- chia/_tests/cmds/wallet/__init__.py +0 -0
- chia/_tests/cmds/wallet/test_consts.py +47 -0
- chia/_tests/cmds/wallet/test_dao.py +565 -0
- chia/_tests/cmds/wallet/test_did.py +403 -0
- chia/_tests/cmds/wallet/test_nft.py +471 -0
- chia/_tests/cmds/wallet/test_notifications.py +124 -0
- chia/_tests/cmds/wallet/test_offer.toffer +1 -0
- chia/_tests/cmds/wallet/test_tx_decorators.py +27 -0
- chia/_tests/cmds/wallet/test_vcs.py +400 -0
- chia/_tests/cmds/wallet/test_wallet.py +1125 -0
- chia/_tests/cmds/wallet/test_wallet_check.py +109 -0
- chia/_tests/conftest.py +1419 -0
- chia/_tests/connection_utils.py +125 -0
- chia/_tests/core/__init__.py +0 -0
- chia/_tests/core/cmds/__init__.py +0 -0
- chia/_tests/core/cmds/test_beta.py +382 -0
- chia/_tests/core/cmds/test_keys.py +1734 -0
- chia/_tests/core/cmds/test_wallet.py +126 -0
- chia/_tests/core/config.py +3 -0
- chia/_tests/core/consensus/__init__.py +0 -0
- chia/_tests/core/consensus/test_block_creation.py +54 -0
- chia/_tests/core/consensus/test_pot_iterations.py +117 -0
- chia/_tests/core/custom_types/__init__.py +0 -0
- chia/_tests/core/custom_types/test_coin.py +107 -0
- chia/_tests/core/custom_types/test_proof_of_space.py +144 -0
- chia/_tests/core/custom_types/test_spend_bundle.py +70 -0
- chia/_tests/core/daemon/__init__.py +0 -0
- chia/_tests/core/daemon/config.py +4 -0
- chia/_tests/core/daemon/test_daemon.py +2128 -0
- chia/_tests/core/daemon/test_daemon_register.py +109 -0
- chia/_tests/core/daemon/test_keychain_proxy.py +101 -0
- chia/_tests/core/data_layer/__init__.py +0 -0
- chia/_tests/core/data_layer/config.py +5 -0
- chia/_tests/core/data_layer/conftest.py +106 -0
- chia/_tests/core/data_layer/test_data_cli.py +56 -0
- chia/_tests/core/data_layer/test_data_layer.py +83 -0
- chia/_tests/core/data_layer/test_data_layer_util.py +218 -0
- chia/_tests/core/data_layer/test_data_rpc.py +3847 -0
- chia/_tests/core/data_layer/test_data_store.py +2424 -0
- chia/_tests/core/data_layer/test_data_store_schema.py +381 -0
- chia/_tests/core/data_layer/test_plugin.py +91 -0
- chia/_tests/core/data_layer/util.py +233 -0
- chia/_tests/core/farmer/__init__.py +0 -0
- chia/_tests/core/farmer/config.py +3 -0
- chia/_tests/core/farmer/test_farmer_api.py +103 -0
- chia/_tests/core/full_node/__init__.py +0 -0
- chia/_tests/core/full_node/config.py +4 -0
- chia/_tests/core/full_node/dos/__init__.py +0 -0
- chia/_tests/core/full_node/dos/config.py +3 -0
- chia/_tests/core/full_node/full_sync/__init__.py +0 -0
- chia/_tests/core/full_node/full_sync/config.py +4 -0
- chia/_tests/core/full_node/full_sync/test_full_sync.py +443 -0
- chia/_tests/core/full_node/ram_db.py +27 -0
- chia/_tests/core/full_node/stores/__init__.py +0 -0
- chia/_tests/core/full_node/stores/config.py +4 -0
- chia/_tests/core/full_node/stores/test_block_store.py +590 -0
- chia/_tests/core/full_node/stores/test_coin_store.py +897 -0
- chia/_tests/core/full_node/stores/test_full_node_store.py +1219 -0
- chia/_tests/core/full_node/stores/test_hint_store.py +229 -0
- chia/_tests/core/full_node/stores/test_sync_store.py +135 -0
- chia/_tests/core/full_node/test_address_manager.py +588 -0
- chia/_tests/core/full_node/test_block_height_map.py +556 -0
- chia/_tests/core/full_node/test_conditions.py +556 -0
- chia/_tests/core/full_node/test_full_node.py +2700 -0
- chia/_tests/core/full_node/test_generator_tools.py +82 -0
- chia/_tests/core/full_node/test_hint_management.py +104 -0
- chia/_tests/core/full_node/test_node_load.py +34 -0
- chia/_tests/core/full_node/test_performance.py +179 -0
- chia/_tests/core/full_node/test_subscriptions.py +492 -0
- chia/_tests/core/full_node/test_transactions.py +203 -0
- chia/_tests/core/full_node/test_tx_processing_queue.py +155 -0
- chia/_tests/core/large_block.py +2388 -0
- chia/_tests/core/make_block_generator.py +70 -0
- chia/_tests/core/mempool/__init__.py +0 -0
- chia/_tests/core/mempool/config.py +4 -0
- chia/_tests/core/mempool/test_mempool.py +3255 -0
- chia/_tests/core/mempool/test_mempool_fee_estimator.py +104 -0
- chia/_tests/core/mempool/test_mempool_fee_protocol.py +55 -0
- chia/_tests/core/mempool/test_mempool_item_queries.py +190 -0
- chia/_tests/core/mempool/test_mempool_manager.py +2084 -0
- chia/_tests/core/mempool/test_mempool_performance.py +64 -0
- chia/_tests/core/mempool/test_singleton_fast_forward.py +567 -0
- chia/_tests/core/node_height.py +28 -0
- chia/_tests/core/server/__init__.py +0 -0
- chia/_tests/core/server/config.py +3 -0
- chia/_tests/core/server/flood.py +84 -0
- chia/_tests/core/server/serve.py +135 -0
- chia/_tests/core/server/test_api_protocol.py +21 -0
- chia/_tests/core/server/test_capabilities.py +66 -0
- chia/_tests/core/server/test_dos.py +319 -0
- chia/_tests/core/server/test_event_loop.py +109 -0
- chia/_tests/core/server/test_loop.py +294 -0
- chia/_tests/core/server/test_node_discovery.py +73 -0
- chia/_tests/core/server/test_rate_limits.py +482 -0
- chia/_tests/core/server/test_server.py +226 -0
- chia/_tests/core/server/test_upnp.py +8 -0
- chia/_tests/core/services/__init__.py +0 -0
- chia/_tests/core/services/config.py +3 -0
- chia/_tests/core/services/test_services.py +188 -0
- chia/_tests/core/ssl/__init__.py +0 -0
- chia/_tests/core/ssl/config.py +3 -0
- chia/_tests/core/ssl/test_ssl.py +202 -0
- chia/_tests/core/test_coins.py +33 -0
- chia/_tests/core/test_cost_calculation.py +313 -0
- chia/_tests/core/test_crawler.py +175 -0
- chia/_tests/core/test_crawler_rpc.py +53 -0
- chia/_tests/core/test_daemon_rpc.py +24 -0
- chia/_tests/core/test_db_conversion.py +130 -0
- chia/_tests/core/test_db_validation.py +162 -0
- chia/_tests/core/test_farmer_harvester_rpc.py +505 -0
- chia/_tests/core/test_filter.py +35 -0
- chia/_tests/core/test_full_node_rpc.py +768 -0
- chia/_tests/core/test_merkle_set.py +343 -0
- chia/_tests/core/test_program.py +47 -0
- chia/_tests/core/test_rpc_util.py +86 -0
- chia/_tests/core/test_seeder.py +420 -0
- chia/_tests/core/test_setproctitle.py +13 -0
- chia/_tests/core/util/__init__.py +0 -0
- chia/_tests/core/util/config.py +4 -0
- chia/_tests/core/util/test_block_cache.py +44 -0
- chia/_tests/core/util/test_cached_bls.py +57 -0
- chia/_tests/core/util/test_config.py +337 -0
- chia/_tests/core/util/test_file_keyring_synchronization.py +105 -0
- chia/_tests/core/util/test_files.py +391 -0
- chia/_tests/core/util/test_jsonify.py +146 -0
- chia/_tests/core/util/test_keychain.py +522 -0
- chia/_tests/core/util/test_keyring_wrapper.py +491 -0
- chia/_tests/core/util/test_lockfile.py +380 -0
- chia/_tests/core/util/test_log_exceptions.py +187 -0
- chia/_tests/core/util/test_lru_cache.py +56 -0
- chia/_tests/core/util/test_significant_bits.py +40 -0
- chia/_tests/core/util/test_streamable.py +883 -0
- chia/_tests/db/__init__.py +0 -0
- chia/_tests/db/test_db_wrapper.py +566 -0
- chia/_tests/environments/__init__.py +0 -0
- chia/_tests/environments/common.py +35 -0
- chia/_tests/environments/full_node.py +47 -0
- chia/_tests/environments/wallet.py +429 -0
- chia/_tests/ether.py +19 -0
- chia/_tests/farmer_harvester/__init__.py +0 -0
- chia/_tests/farmer_harvester/config.py +3 -0
- chia/_tests/farmer_harvester/test_farmer.py +1264 -0
- chia/_tests/farmer_harvester/test_farmer_harvester.py +292 -0
- chia/_tests/farmer_harvester/test_filter_prefix_bits.py +131 -0
- chia/_tests/farmer_harvester/test_third_party_harvesters.py +528 -0
- chia/_tests/farmer_harvester/test_third_party_harvesters_data.json +29 -0
- chia/_tests/fee_estimation/__init__.py +0 -0
- chia/_tests/fee_estimation/config.py +3 -0
- chia/_tests/fee_estimation/test_fee_estimation_integration.py +262 -0
- chia/_tests/fee_estimation/test_fee_estimation_rpc.py +287 -0
- chia/_tests/fee_estimation/test_fee_estimation_unit_tests.py +144 -0
- chia/_tests/fee_estimation/test_mempoolitem_height_added.py +146 -0
- chia/_tests/generator/__init__.py +0 -0
- chia/_tests/generator/puzzles/__init__.py +0 -0
- chia/_tests/generator/puzzles/test_generator_deserialize.clsp +3 -0
- chia/_tests/generator/puzzles/test_generator_deserialize.clsp.hex +1 -0
- chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp +19 -0
- chia/_tests/generator/puzzles/test_multiple_generator_input_arguments.clsp.hex +1 -0
- chia/_tests/generator/test_compression.py +201 -0
- chia/_tests/generator/test_generator_types.py +44 -0
- chia/_tests/generator/test_rom.py +180 -0
- chia/_tests/plot_sync/__init__.py +0 -0
- chia/_tests/plot_sync/config.py +3 -0
- chia/_tests/plot_sync/test_delta.py +101 -0
- chia/_tests/plot_sync/test_plot_sync.py +618 -0
- chia/_tests/plot_sync/test_receiver.py +451 -0
- chia/_tests/plot_sync/test_sender.py +116 -0
- chia/_tests/plot_sync/test_sync_simulated.py +451 -0
- chia/_tests/plot_sync/util.py +68 -0
- chia/_tests/plotting/__init__.py +0 -0
- chia/_tests/plotting/config.py +3 -0
- chia/_tests/plotting/test_plot_manager.py +781 -0
- chia/_tests/plotting/util.py +12 -0
- chia/_tests/pools/__init__.py +0 -0
- chia/_tests/pools/config.py +5 -0
- chia/_tests/pools/test_pool_cli_parsing.py +128 -0
- chia/_tests/pools/test_pool_cmdline.py +1001 -0
- chia/_tests/pools/test_pool_config.py +42 -0
- chia/_tests/pools/test_pool_puzzles_lifecycle.py +397 -0
- chia/_tests/pools/test_pool_rpc.py +1123 -0
- chia/_tests/pools/test_pool_wallet.py +205 -0
- chia/_tests/pools/test_wallet_pool_store.py +161 -0
- chia/_tests/process_junit.py +348 -0
- chia/_tests/rpc/__init__.py +0 -0
- chia/_tests/rpc/test_rpc_client.py +138 -0
- chia/_tests/rpc/test_rpc_server.py +183 -0
- chia/_tests/simulation/__init__.py +0 -0
- chia/_tests/simulation/config.py +6 -0
- chia/_tests/simulation/test_simulation.py +501 -0
- chia/_tests/simulation/test_simulator.py +232 -0
- chia/_tests/simulation/test_start_simulator.py +107 -0
- chia/_tests/testconfig.py +13 -0
- chia/_tests/timelord/__init__.py +0 -0
- chia/_tests/timelord/config.py +3 -0
- chia/_tests/timelord/test_new_peak.py +437 -0
- chia/_tests/timelord/test_timelord.py +11 -0
- chia/_tests/tools/1315537.json +170 -0
- chia/_tests/tools/1315544.json +160 -0
- chia/_tests/tools/1315630.json +150 -0
- chia/_tests/tools/300000.json +105 -0
- chia/_tests/tools/442734.json +140 -0
- chia/_tests/tools/466212.json +130 -0
- chia/_tests/tools/__init__.py +0 -0
- chia/_tests/tools/config.py +5 -0
- chia/_tests/tools/test-blockchain-db.sqlite +0 -0
- chia/_tests/tools/test_full_sync.py +30 -0
- chia/_tests/tools/test_legacy_keyring.py +82 -0
- chia/_tests/tools/test_run_block.py +128 -0
- chia/_tests/tools/test_virtual_project.py +591 -0
- chia/_tests/util/__init__.py +0 -0
- chia/_tests/util/benchmark_cost.py +170 -0
- chia/_tests/util/benchmarks.py +153 -0
- chia/_tests/util/bip39_test_vectors.json +148 -0
- chia/_tests/util/blockchain.py +134 -0
- chia/_tests/util/blockchain_mock.py +132 -0
- chia/_tests/util/build_network_protocol_files.py +302 -0
- chia/_tests/util/clvm_generator.bin +0 -0
- chia/_tests/util/config.py +3 -0
- chia/_tests/util/constants.py +20 -0
- chia/_tests/util/db_connection.py +37 -0
- chia/_tests/util/full_sync.py +253 -0
- chia/_tests/util/gen_ssl_certs.py +114 -0
- chia/_tests/util/generator_tools_testing.py +45 -0
- chia/_tests/util/get_name_puzzle_conditions.py +52 -0
- chia/_tests/util/key_tool.py +36 -0
- chia/_tests/util/misc.py +675 -0
- chia/_tests/util/network_protocol_data.py +1072 -0
- chia/_tests/util/protocol_messages_bytes-v1.0 +0 -0
- chia/_tests/util/protocol_messages_json.py +2701 -0
- chia/_tests/util/rpc.py +26 -0
- chia/_tests/util/run_block.py +163 -0
- chia/_tests/util/setup_nodes.py +481 -0
- chia/_tests/util/spend_sim.py +492 -0
- chia/_tests/util/split_managers.py +102 -0
- chia/_tests/util/temp_file.py +14 -0
- chia/_tests/util/test_action_scope.py +144 -0
- chia/_tests/util/test_async_pool.py +366 -0
- chia/_tests/util/test_build_job_matrix.py +42 -0
- chia/_tests/util/test_build_network_protocol_files.py +7 -0
- chia/_tests/util/test_chia_version.py +50 -0
- chia/_tests/util/test_collection.py +11 -0
- chia/_tests/util/test_condition_tools.py +229 -0
- chia/_tests/util/test_config.py +426 -0
- chia/_tests/util/test_dump_keyring.py +60 -0
- chia/_tests/util/test_errors.py +10 -0
- chia/_tests/util/test_full_block_utils.py +279 -0
- chia/_tests/util/test_installed.py +20 -0
- chia/_tests/util/test_limited_semaphore.py +53 -0
- chia/_tests/util/test_logging_filter.py +42 -0
- chia/_tests/util/test_misc.py +445 -0
- chia/_tests/util/test_network.py +73 -0
- chia/_tests/util/test_network_protocol_files.py +578 -0
- chia/_tests/util/test_network_protocol_json.py +267 -0
- chia/_tests/util/test_network_protocol_test.py +256 -0
- chia/_tests/util/test_paginator.py +71 -0
- chia/_tests/util/test_pprint.py +17 -0
- chia/_tests/util/test_priority_mutex.py +488 -0
- chia/_tests/util/test_recursive_replace.py +116 -0
- chia/_tests/util/test_replace_str_to_bytes.py +137 -0
- chia/_tests/util/test_service_groups.py +15 -0
- chia/_tests/util/test_ssl_check.py +31 -0
- chia/_tests/util/test_testnet_overrides.py +19 -0
- chia/_tests/util/test_tests_misc.py +38 -0
- chia/_tests/util/test_timing.py +37 -0
- chia/_tests/util/test_trusted_peer.py +51 -0
- chia/_tests/util/time_out_assert.py +191 -0
- chia/_tests/wallet/__init__.py +0 -0
- chia/_tests/wallet/cat_wallet/__init__.py +0 -0
- chia/_tests/wallet/cat_wallet/config.py +4 -0
- chia/_tests/wallet/cat_wallet/test_cat_lifecycle.py +468 -0
- chia/_tests/wallet/cat_wallet/test_cat_outer_puzzle.py +69 -0
- chia/_tests/wallet/cat_wallet/test_cat_wallet.py +1826 -0
- chia/_tests/wallet/cat_wallet/test_offer_lifecycle.py +291 -0
- chia/_tests/wallet/cat_wallet/test_trades.py +2600 -0
- chia/_tests/wallet/clawback/__init__.py +0 -0
- chia/_tests/wallet/clawback/config.py +3 -0
- chia/_tests/wallet/clawback/test_clawback_decorator.py +78 -0
- chia/_tests/wallet/clawback/test_clawback_lifecycle.py +292 -0
- chia/_tests/wallet/clawback/test_clawback_metadata.py +50 -0
- chia/_tests/wallet/config.py +4 -0
- chia/_tests/wallet/conftest.py +278 -0
- chia/_tests/wallet/dao_wallet/__init__.py +0 -0
- chia/_tests/wallet/dao_wallet/config.py +3 -0
- chia/_tests/wallet/dao_wallet/test_dao_clvm.py +1330 -0
- chia/_tests/wallet/dao_wallet/test_dao_wallets.py +3488 -0
- chia/_tests/wallet/db_wallet/__init__.py +0 -0
- chia/_tests/wallet/db_wallet/config.py +3 -0
- chia/_tests/wallet/db_wallet/test_db_graftroot.py +141 -0
- chia/_tests/wallet/db_wallet/test_dl_offers.py +491 -0
- chia/_tests/wallet/db_wallet/test_dl_wallet.py +823 -0
- chia/_tests/wallet/did_wallet/__init__.py +0 -0
- chia/_tests/wallet/did_wallet/config.py +4 -0
- chia/_tests/wallet/did_wallet/test_did.py +2284 -0
- chia/_tests/wallet/nft_wallet/__init__.py +0 -0
- chia/_tests/wallet/nft_wallet/config.py +4 -0
- chia/_tests/wallet/nft_wallet/test_nft_1_offers.py +1493 -0
- chia/_tests/wallet/nft_wallet/test_nft_bulk_mint.py +1024 -0
- chia/_tests/wallet/nft_wallet/test_nft_lifecycle.py +375 -0
- chia/_tests/wallet/nft_wallet/test_nft_offers.py +1209 -0
- chia/_tests/wallet/nft_wallet/test_nft_puzzles.py +172 -0
- chia/_tests/wallet/nft_wallet/test_nft_wallet.py +2584 -0
- chia/_tests/wallet/nft_wallet/test_ownership_outer_puzzle.py +70 -0
- chia/_tests/wallet/rpc/__init__.py +0 -0
- chia/_tests/wallet/rpc/config.py +4 -0
- chia/_tests/wallet/rpc/test_dl_wallet_rpc.py +285 -0
- chia/_tests/wallet/rpc/test_wallet_rpc.py +3153 -0
- chia/_tests/wallet/simple_sync/__init__.py +0 -0
- chia/_tests/wallet/simple_sync/config.py +3 -0
- chia/_tests/wallet/simple_sync/test_simple_sync_protocol.py +718 -0
- chia/_tests/wallet/sync/__init__.py +0 -0
- chia/_tests/wallet/sync/config.py +4 -0
- chia/_tests/wallet/sync/test_wallet_sync.py +1692 -0
- chia/_tests/wallet/test_address_type.py +189 -0
- chia/_tests/wallet/test_bech32m.py +45 -0
- chia/_tests/wallet/test_clvm_streamable.py +244 -0
- chia/_tests/wallet/test_coin_management.py +354 -0
- chia/_tests/wallet/test_coin_selection.py +588 -0
- chia/_tests/wallet/test_conditions.py +400 -0
- chia/_tests/wallet/test_debug_spend_bundle.py +218 -0
- chia/_tests/wallet/test_new_wallet_protocol.py +1174 -0
- chia/_tests/wallet/test_nft_store.py +192 -0
- chia/_tests/wallet/test_notifications.py +196 -0
- chia/_tests/wallet/test_offer_parsing_performance.py +48 -0
- chia/_tests/wallet/test_puzzle_store.py +132 -0
- chia/_tests/wallet/test_sign_coin_spends.py +159 -0
- chia/_tests/wallet/test_signer_protocol.py +947 -0
- chia/_tests/wallet/test_singleton.py +122 -0
- chia/_tests/wallet/test_singleton_lifecycle_fast.py +772 -0
- chia/_tests/wallet/test_singleton_store.py +152 -0
- chia/_tests/wallet/test_taproot.py +19 -0
- chia/_tests/wallet/test_transaction_store.py +945 -0
- chia/_tests/wallet/test_util.py +185 -0
- chia/_tests/wallet/test_wallet.py +2139 -0
- chia/_tests/wallet/test_wallet_action_scope.py +85 -0
- chia/_tests/wallet/test_wallet_blockchain.py +111 -0
- chia/_tests/wallet/test_wallet_coin_store.py +1002 -0
- chia/_tests/wallet/test_wallet_interested_store.py +43 -0
- chia/_tests/wallet/test_wallet_key_val_store.py +40 -0
- chia/_tests/wallet/test_wallet_node.py +780 -0
- chia/_tests/wallet/test_wallet_retry.py +95 -0
- chia/_tests/wallet/test_wallet_state_manager.py +259 -0
- chia/_tests/wallet/test_wallet_test_framework.py +275 -0
- chia/_tests/wallet/test_wallet_trade_store.py +218 -0
- chia/_tests/wallet/test_wallet_user_store.py +34 -0
- chia/_tests/wallet/test_wallet_utils.py +156 -0
- chia/_tests/wallet/vc_wallet/__init__.py +0 -0
- chia/_tests/wallet/vc_wallet/config.py +3 -0
- chia/_tests/wallet/vc_wallet/test_cr_outer_puzzle.py +70 -0
- chia/_tests/wallet/vc_wallet/test_vc_lifecycle.py +883 -0
- chia/_tests/wallet/vc_wallet/test_vc_wallet.py +830 -0
- chia/_tests/wallet/wallet_block_tools.py +327 -0
- chia/_tests/weight_proof/__init__.py +0 -0
- chia/_tests/weight_proof/config.py +3 -0
- chia/_tests/weight_proof/test_weight_proof.py +528 -0
- chia/apis.py +19 -0
- chia/clvm/__init__.py +0 -0
- chia/cmds/__init__.py +0 -0
- chia/cmds/beta.py +184 -0
- chia/cmds/beta_funcs.py +137 -0
- chia/cmds/check_wallet_db.py +420 -0
- chia/cmds/chia.py +151 -0
- chia/cmds/cmd_classes.py +323 -0
- chia/cmds/cmd_helpers.py +242 -0
- chia/cmds/cmds_util.py +488 -0
- chia/cmds/coin_funcs.py +275 -0
- chia/cmds/coins.py +182 -0
- chia/cmds/completion.py +49 -0
- chia/cmds/configure.py +332 -0
- chia/cmds/dao.py +1064 -0
- chia/cmds/dao_funcs.py +598 -0
- chia/cmds/data.py +708 -0
- chia/cmds/data_funcs.py +385 -0
- chia/cmds/db.py +87 -0
- chia/cmds/db_backup_func.py +77 -0
- chia/cmds/db_upgrade_func.py +452 -0
- chia/cmds/db_validate_func.py +184 -0
- chia/cmds/dev.py +18 -0
- chia/cmds/farm.py +100 -0
- chia/cmds/farm_funcs.py +200 -0
- chia/cmds/gh.py +275 -0
- chia/cmds/init.py +63 -0
- chia/cmds/init_funcs.py +367 -0
- chia/cmds/installers.py +131 -0
- chia/cmds/keys.py +527 -0
- chia/cmds/keys_funcs.py +863 -0
- chia/cmds/netspace.py +50 -0
- chia/cmds/netspace_funcs.py +54 -0
- chia/cmds/options.py +32 -0
- chia/cmds/param_types.py +238 -0
- chia/cmds/passphrase.py +131 -0
- chia/cmds/passphrase_funcs.py +292 -0
- chia/cmds/peer.py +51 -0
- chia/cmds/peer_funcs.py +129 -0
- chia/cmds/plotnft.py +260 -0
- chia/cmds/plotnft_funcs.py +405 -0
- chia/cmds/plots.py +230 -0
- chia/cmds/plotters.py +18 -0
- chia/cmds/rpc.py +208 -0
- chia/cmds/show.py +72 -0
- chia/cmds/show_funcs.py +215 -0
- chia/cmds/signer.py +296 -0
- chia/cmds/sim.py +225 -0
- chia/cmds/sim_funcs.py +509 -0
- chia/cmds/start.py +24 -0
- chia/cmds/start_funcs.py +109 -0
- chia/cmds/stop.py +62 -0
- chia/cmds/units.py +9 -0
- chia/cmds/wallet.py +1901 -0
- chia/cmds/wallet_funcs.py +1874 -0
- chia/consensus/__init__.py +0 -0
- chia/consensus/block_body_validation.py +562 -0
- chia/consensus/block_creation.py +546 -0
- chia/consensus/block_header_validation.py +1059 -0
- chia/consensus/block_record.py +31 -0
- chia/consensus/block_rewards.py +53 -0
- chia/consensus/blockchain.py +1087 -0
- chia/consensus/blockchain_interface.py +56 -0
- chia/consensus/coinbase.py +30 -0
- chia/consensus/condition_costs.py +9 -0
- chia/consensus/constants.py +49 -0
- chia/consensus/cost_calculator.py +15 -0
- chia/consensus/default_constants.py +89 -0
- chia/consensus/deficit.py +55 -0
- chia/consensus/difficulty_adjustment.py +412 -0
- chia/consensus/find_fork_point.py +111 -0
- chia/consensus/full_block_to_block_record.py +167 -0
- chia/consensus/get_block_challenge.py +106 -0
- chia/consensus/get_block_generator.py +27 -0
- chia/consensus/make_sub_epoch_summary.py +210 -0
- chia/consensus/multiprocess_validation.py +268 -0
- chia/consensus/pos_quality.py +19 -0
- chia/consensus/pot_iterations.py +67 -0
- chia/consensus/puzzles/__init__.py +0 -0
- chia/consensus/puzzles/chialisp_deserialisation.clsp +69 -0
- chia/consensus/puzzles/chialisp_deserialisation.clsp.hex +1 -0
- chia/consensus/puzzles/rom_bootstrap_generator.clsp +37 -0
- chia/consensus/puzzles/rom_bootstrap_generator.clsp.hex +1 -0
- chia/consensus/vdf_info_computation.py +156 -0
- chia/daemon/__init__.py +0 -0
- chia/daemon/client.py +252 -0
- chia/daemon/keychain_proxy.py +502 -0
- chia/daemon/keychain_server.py +365 -0
- chia/daemon/server.py +1606 -0
- chia/daemon/windows_signal.py +56 -0
- chia/data_layer/__init__.py +0 -0
- chia/data_layer/data_layer.py +1291 -0
- chia/data_layer/data_layer_api.py +33 -0
- chia/data_layer/data_layer_errors.py +50 -0
- chia/data_layer/data_layer_server.py +170 -0
- chia/data_layer/data_layer_util.py +985 -0
- chia/data_layer/data_layer_wallet.py +1311 -0
- chia/data_layer/data_store.py +2267 -0
- chia/data_layer/dl_wallet_store.py +407 -0
- chia/data_layer/download_data.py +389 -0
- chia/data_layer/puzzles/__init__.py +0 -0
- chia/data_layer/puzzles/graftroot_dl_offers.clsp +100 -0
- chia/data_layer/puzzles/graftroot_dl_offers.clsp.hex +1 -0
- chia/data_layer/s3_plugin_config.yml +33 -0
- chia/data_layer/s3_plugin_service.py +468 -0
- chia/data_layer/util/__init__.py +0 -0
- chia/data_layer/util/benchmark.py +107 -0
- chia/data_layer/util/plugin.py +40 -0
- chia/farmer/__init__.py +0 -0
- chia/farmer/farmer.py +923 -0
- chia/farmer/farmer_api.py +820 -0
- chia/full_node/__init__.py +0 -0
- chia/full_node/bitcoin_fee_estimator.py +85 -0
- chia/full_node/block_height_map.py +271 -0
- chia/full_node/block_store.py +576 -0
- chia/full_node/bundle_tools.py +19 -0
- chia/full_node/coin_store.py +647 -0
- chia/full_node/fee_estimate.py +54 -0
- chia/full_node/fee_estimate_store.py +24 -0
- chia/full_node/fee_estimation.py +92 -0
- chia/full_node/fee_estimator.py +90 -0
- chia/full_node/fee_estimator_constants.py +38 -0
- chia/full_node/fee_estimator_interface.py +42 -0
- chia/full_node/fee_history.py +25 -0
- chia/full_node/fee_tracker.py +564 -0
- chia/full_node/full_node.py +3327 -0
- chia/full_node/full_node_api.py +2025 -0
- chia/full_node/full_node_store.py +1033 -0
- chia/full_node/hint_management.py +56 -0
- chia/full_node/hint_store.py +93 -0
- chia/full_node/mempool.py +589 -0
- chia/full_node/mempool_check_conditions.py +146 -0
- chia/full_node/mempool_manager.py +853 -0
- chia/full_node/pending_tx_cache.py +112 -0
- chia/full_node/puzzles/__init__.py +0 -0
- chia/full_node/puzzles/block_program_zero.clsp +14 -0
- chia/full_node/puzzles/block_program_zero.clsp.hex +1 -0
- chia/full_node/puzzles/decompress_coin_spend_entry.clsp +5 -0
- chia/full_node/puzzles/decompress_coin_spend_entry.clsp.hex +1 -0
- chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp +7 -0
- chia/full_node/puzzles/decompress_coin_spend_entry_with_prefix.clsp.hex +1 -0
- chia/full_node/puzzles/decompress_puzzle.clsp +6 -0
- chia/full_node/puzzles/decompress_puzzle.clsp.hex +1 -0
- chia/full_node/signage_point.py +16 -0
- chia/full_node/subscriptions.py +247 -0
- chia/full_node/sync_store.py +146 -0
- chia/full_node/tx_processing_queue.py +78 -0
- chia/full_node/util/__init__.py +0 -0
- chia/full_node/weight_proof.py +1720 -0
- chia/harvester/__init__.py +0 -0
- chia/harvester/harvester.py +272 -0
- chia/harvester/harvester_api.py +380 -0
- chia/introducer/__init__.py +0 -0
- chia/introducer/introducer.py +122 -0
- chia/introducer/introducer_api.py +70 -0
- chia/legacy/__init__.py +0 -0
- chia/legacy/keyring.py +155 -0
- chia/plot_sync/__init__.py +0 -0
- chia/plot_sync/delta.py +61 -0
- chia/plot_sync/exceptions.py +56 -0
- chia/plot_sync/receiver.py +386 -0
- chia/plot_sync/sender.py +340 -0
- chia/plot_sync/util.py +43 -0
- chia/plotters/__init__.py +0 -0
- chia/plotters/bladebit.py +388 -0
- chia/plotters/chiapos.py +63 -0
- chia/plotters/madmax.py +224 -0
- chia/plotters/plotters.py +577 -0
- chia/plotters/plotters_util.py +133 -0
- chia/plotting/__init__.py +0 -0
- chia/plotting/cache.py +213 -0
- chia/plotting/check_plots.py +283 -0
- chia/plotting/create_plots.py +278 -0
- chia/plotting/manager.py +436 -0
- chia/plotting/util.py +336 -0
- chia/pools/__init__.py +0 -0
- chia/pools/pool_config.py +110 -0
- chia/pools/pool_puzzles.py +459 -0
- chia/pools/pool_wallet.py +933 -0
- chia/pools/pool_wallet_info.py +118 -0
- chia/pools/puzzles/__init__.py +0 -0
- chia/pools/puzzles/pool_member_innerpuz.clsp +70 -0
- chia/pools/puzzles/pool_member_innerpuz.clsp.hex +1 -0
- chia/pools/puzzles/pool_waitingroom_innerpuz.clsp +69 -0
- chia/pools/puzzles/pool_waitingroom_innerpuz.clsp.hex +1 -0
- chia/protocols/__init__.py +0 -0
- chia/protocols/farmer_protocol.py +102 -0
- chia/protocols/full_node_protocol.py +219 -0
- chia/protocols/harvester_protocol.py +216 -0
- chia/protocols/introducer_protocol.py +25 -0
- chia/protocols/pool_protocol.py +177 -0
- chia/protocols/protocol_message_types.py +139 -0
- chia/protocols/protocol_state_machine.py +87 -0
- chia/protocols/protocol_timing.py +8 -0
- chia/protocols/shared_protocol.py +86 -0
- chia/protocols/timelord_protocol.py +93 -0
- chia/protocols/wallet_protocol.py +401 -0
- chia/py.typed +0 -0
- chia/rpc/__init__.py +0 -0
- chia/rpc/crawler_rpc_api.py +80 -0
- chia/rpc/data_layer_rpc_api.py +644 -0
- chia/rpc/data_layer_rpc_client.py +188 -0
- chia/rpc/data_layer_rpc_util.py +58 -0
- chia/rpc/farmer_rpc_api.py +365 -0
- chia/rpc/farmer_rpc_client.py +86 -0
- chia/rpc/full_node_rpc_api.py +959 -0
- chia/rpc/full_node_rpc_client.py +292 -0
- chia/rpc/harvester_rpc_api.py +141 -0
- chia/rpc/harvester_rpc_client.py +54 -0
- chia/rpc/rpc_client.py +164 -0
- chia/rpc/rpc_server.py +521 -0
- chia/rpc/timelord_rpc_api.py +32 -0
- chia/rpc/util.py +93 -0
- chia/rpc/wallet_request_types.py +904 -0
- chia/rpc/wallet_rpc_api.py +4943 -0
- chia/rpc/wallet_rpc_client.py +1814 -0
- chia/seeder/__init__.py +0 -0
- chia/seeder/crawl_store.py +425 -0
- chia/seeder/crawler.py +410 -0
- chia/seeder/crawler_api.py +135 -0
- chia/seeder/dns_server.py +593 -0
- chia/seeder/peer_record.py +146 -0
- chia/seeder/start_crawler.py +92 -0
- chia/server/__init__.py +0 -0
- chia/server/address_manager.py +658 -0
- chia/server/address_manager_store.py +237 -0
- chia/server/api_protocol.py +116 -0
- chia/server/capabilities.py +24 -0
- chia/server/chia_policy.py +346 -0
- chia/server/introducer_peers.py +76 -0
- chia/server/node_discovery.py +714 -0
- chia/server/outbound_message.py +33 -0
- chia/server/rate_limit_numbers.py +214 -0
- chia/server/rate_limits.py +153 -0
- chia/server/server.py +741 -0
- chia/server/signal_handlers.py +120 -0
- chia/server/ssl_context.py +32 -0
- chia/server/start_data_layer.py +151 -0
- chia/server/start_farmer.py +98 -0
- chia/server/start_full_node.py +112 -0
- chia/server/start_harvester.py +93 -0
- chia/server/start_introducer.py +81 -0
- chia/server/start_service.py +316 -0
- chia/server/start_timelord.py +89 -0
- chia/server/start_wallet.py +113 -0
- chia/server/upnp.py +118 -0
- chia/server/ws_connection.py +766 -0
- chia/simulator/__init__.py +0 -0
- chia/simulator/add_blocks_in_batches.py +54 -0
- chia/simulator/block_tools.py +2054 -0
- chia/simulator/full_node_simulator.py +794 -0
- chia/simulator/keyring.py +128 -0
- chia/simulator/setup_services.py +506 -0
- chia/simulator/simulator_constants.py +13 -0
- chia/simulator/simulator_full_node_rpc_api.py +99 -0
- chia/simulator/simulator_full_node_rpc_client.py +60 -0
- chia/simulator/simulator_protocol.py +29 -0
- chia/simulator/simulator_test_tools.py +164 -0
- chia/simulator/socket.py +24 -0
- chia/simulator/ssl_certs.py +114 -0
- chia/simulator/ssl_certs_1.py +697 -0
- chia/simulator/ssl_certs_10.py +697 -0
- chia/simulator/ssl_certs_2.py +697 -0
- chia/simulator/ssl_certs_3.py +697 -0
- chia/simulator/ssl_certs_4.py +697 -0
- chia/simulator/ssl_certs_5.py +697 -0
- chia/simulator/ssl_certs_6.py +697 -0
- chia/simulator/ssl_certs_7.py +697 -0
- chia/simulator/ssl_certs_8.py +697 -0
- chia/simulator/ssl_certs_9.py +697 -0
- chia/simulator/start_simulator.py +143 -0
- chia/simulator/wallet_tools.py +246 -0
- chia/ssl/__init__.py +0 -0
- chia/ssl/chia_ca.crt +19 -0
- chia/ssl/chia_ca.key +28 -0
- chia/ssl/create_ssl.py +249 -0
- chia/ssl/dst_root_ca.pem +20 -0
- chia/timelord/__init__.py +0 -0
- chia/timelord/iters_from_block.py +50 -0
- chia/timelord/timelord.py +1226 -0
- chia/timelord/timelord_api.py +138 -0
- chia/timelord/timelord_launcher.py +190 -0
- chia/timelord/timelord_state.py +244 -0
- chia/timelord/types.py +22 -0
- chia/types/__init__.py +0 -0
- chia/types/aliases.py +35 -0
- chia/types/block_protocol.py +20 -0
- chia/types/blockchain_format/__init__.py +0 -0
- chia/types/blockchain_format/classgroup.py +5 -0
- chia/types/blockchain_format/coin.py +28 -0
- chia/types/blockchain_format/foliage.py +8 -0
- chia/types/blockchain_format/pool_target.py +5 -0
- chia/types/blockchain_format/program.py +269 -0
- chia/types/blockchain_format/proof_of_space.py +135 -0
- chia/types/blockchain_format/reward_chain_block.py +6 -0
- chia/types/blockchain_format/serialized_program.py +5 -0
- chia/types/blockchain_format/sized_bytes.py +11 -0
- chia/types/blockchain_format/slots.py +9 -0
- chia/types/blockchain_format/sub_epoch_summary.py +5 -0
- chia/types/blockchain_format/tree_hash.py +72 -0
- chia/types/blockchain_format/vdf.py +86 -0
- chia/types/clvm_cost.py +13 -0
- chia/types/coin_record.py +43 -0
- chia/types/coin_spend.py +115 -0
- chia/types/condition_opcodes.py +73 -0
- chia/types/condition_with_args.py +16 -0
- chia/types/eligible_coin_spends.py +365 -0
- chia/types/end_of_slot_bundle.py +5 -0
- chia/types/fee_rate.py +38 -0
- chia/types/full_block.py +5 -0
- chia/types/generator_types.py +13 -0
- chia/types/header_block.py +5 -0
- chia/types/internal_mempool_item.py +18 -0
- chia/types/mempool_inclusion_status.py +9 -0
- chia/types/mempool_item.py +85 -0
- chia/types/mempool_submission_status.py +30 -0
- chia/types/mojos.py +7 -0
- chia/types/peer_info.py +64 -0
- chia/types/signing_mode.py +29 -0
- chia/types/spend_bundle.py +30 -0
- chia/types/spend_bundle_conditions.py +7 -0
- chia/types/transaction_queue_entry.py +55 -0
- chia/types/unfinished_block.py +5 -0
- chia/types/unfinished_header_block.py +37 -0
- chia/types/validation_state.py +14 -0
- chia/types/weight_proof.py +49 -0
- chia/util/__init__.py +0 -0
- chia/util/action_scope.py +168 -0
- chia/util/async_pool.py +226 -0
- chia/util/augmented_chain.py +134 -0
- chia/util/batches.py +42 -0
- chia/util/bech32m.py +126 -0
- chia/util/beta_metrics.py +119 -0
- chia/util/block_cache.py +56 -0
- chia/util/byte_types.py +12 -0
- chia/util/check_fork_next_block.py +33 -0
- chia/util/chia_logging.py +144 -0
- chia/util/chia_version.py +33 -0
- chia/util/collection.py +17 -0
- chia/util/condition_tools.py +201 -0
- chia/util/config.py +367 -0
- chia/util/cpu.py +22 -0
- chia/util/db_synchronous.py +23 -0
- chia/util/db_version.py +32 -0
- chia/util/db_wrapper.py +430 -0
- chia/util/default_root.py +27 -0
- chia/util/dump_keyring.py +93 -0
- chia/util/english.txt +2048 -0
- chia/util/errors.py +353 -0
- chia/util/file_keyring.py +469 -0
- chia/util/files.py +97 -0
- chia/util/full_block_utils.py +345 -0
- chia/util/generator_tools.py +72 -0
- chia/util/hash.py +31 -0
- chia/util/initial-config.yaml +694 -0
- chia/util/inline_executor.py +26 -0
- chia/util/ints.py +19 -0
- chia/util/ip_address.py +39 -0
- chia/util/json_util.py +37 -0
- chia/util/keychain.py +676 -0
- chia/util/keyring_wrapper.py +327 -0
- chia/util/limited_semaphore.py +41 -0
- chia/util/lock.py +49 -0
- chia/util/log_exceptions.py +32 -0
- chia/util/logging.py +36 -0
- chia/util/lru_cache.py +31 -0
- chia/util/math.py +20 -0
- chia/util/network.py +182 -0
- chia/util/paginator.py +48 -0
- chia/util/path.py +31 -0
- chia/util/permissions.py +20 -0
- chia/util/prev_transaction_block.py +21 -0
- chia/util/priority_mutex.py +95 -0
- chia/util/profiler.py +197 -0
- chia/util/recursive_replace.py +24 -0
- chia/util/safe_cancel_task.py +16 -0
- chia/util/service_groups.py +47 -0
- chia/util/setproctitle.py +22 -0
- chia/util/significant_bits.py +32 -0
- chia/util/ssl_check.py +213 -0
- chia/util/streamable.py +642 -0
- chia/util/task_referencer.py +59 -0
- chia/util/task_timing.py +382 -0
- chia/util/timing.py +67 -0
- chia/util/vdf_prover.py +30 -0
- chia/util/virtual_project_analysis.py +540 -0
- chia/util/ws_message.py +66 -0
- chia/wallet/__init__.py +0 -0
- chia/wallet/cat_wallet/__init__.py +0 -0
- chia/wallet/cat_wallet/cat_constants.py +75 -0
- chia/wallet/cat_wallet/cat_info.py +47 -0
- chia/wallet/cat_wallet/cat_outer_puzzle.py +120 -0
- chia/wallet/cat_wallet/cat_utils.py +164 -0
- chia/wallet/cat_wallet/cat_wallet.py +855 -0
- chia/wallet/cat_wallet/dao_cat_info.py +28 -0
- chia/wallet/cat_wallet/dao_cat_wallet.py +669 -0
- chia/wallet/cat_wallet/lineage_store.py +74 -0
- chia/wallet/cat_wallet/puzzles/__init__.py +0 -0
- chia/wallet/cat_wallet/puzzles/cat_truths.clib +31 -0
- chia/wallet/cat_wallet/puzzles/cat_v2.clsp +397 -0
- chia/wallet/cat_wallet/puzzles/cat_v2.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/delegated_tail.clsp +25 -0
- chia/wallet/cat_wallet/puzzles/delegated_tail.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp +15 -0
- chia/wallet/cat_wallet/puzzles/everything_with_signature.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp +26 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp +42 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_coin_id_or_singleton.clsp.hex +1 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp +24 -0
- chia/wallet/cat_wallet/puzzles/genesis_by_puzzle_hash.clsp.hex +1 -0
- chia/wallet/coin_selection.py +188 -0
- chia/wallet/conditions.py +1512 -0
- chia/wallet/dao_wallet/__init__.py +0 -0
- chia/wallet/dao_wallet/dao_info.py +61 -0
- chia/wallet/dao_wallet/dao_utils.py +811 -0
- chia/wallet/dao_wallet/dao_wallet.py +2119 -0
- chia/wallet/db_wallet/__init__.py +0 -0
- chia/wallet/db_wallet/db_wallet_puzzles.py +111 -0
- chia/wallet/derivation_record.py +30 -0
- chia/wallet/derive_keys.py +146 -0
- chia/wallet/did_wallet/__init__.py +0 -0
- chia/wallet/did_wallet/did_info.py +39 -0
- chia/wallet/did_wallet/did_wallet.py +1494 -0
- chia/wallet/did_wallet/did_wallet_puzzles.py +221 -0
- chia/wallet/did_wallet/puzzles/__init__.py +0 -0
- chia/wallet/did_wallet/puzzles/did_innerpuz.clsp +135 -0
- chia/wallet/did_wallet/puzzles/did_innerpuz.clsp.hex +1 -0
- chia/wallet/driver_protocol.py +26 -0
- chia/wallet/key_val_store.py +55 -0
- chia/wallet/lineage_proof.py +58 -0
- chia/wallet/nft_wallet/__init__.py +0 -0
- chia/wallet/nft_wallet/metadata_outer_puzzle.py +92 -0
- chia/wallet/nft_wallet/nft_info.py +120 -0
- chia/wallet/nft_wallet/nft_puzzles.py +305 -0
- chia/wallet/nft_wallet/nft_wallet.py +1687 -0
- chia/wallet/nft_wallet/ownership_outer_puzzle.py +101 -0
- chia/wallet/nft_wallet/puzzles/__init__.py +0 -0
- chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp +6 -0
- chia/wallet/nft_wallet/puzzles/create_nft_launcher_from_did.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp +6 -0
- chia/wallet/nft_wallet/puzzles/nft_intermediate_launcher.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp +30 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_default.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp +28 -0
- chia/wallet/nft_wallet/puzzles/nft_metadata_updater_updateable.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp +100 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_layer.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp +78 -0
- chia/wallet/nft_wallet/puzzles/nft_ownership_transfer_program_one_way_claim_with_royalties.clsp.hex +1 -0
- chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp +74 -0
- chia/wallet/nft_wallet/puzzles/nft_state_layer.clsp.hex +1 -0
- chia/wallet/nft_wallet/singleton_outer_puzzle.py +101 -0
- chia/wallet/nft_wallet/transfer_program_puzzle.py +82 -0
- chia/wallet/nft_wallet/uncurry_nft.py +217 -0
- chia/wallet/notification_manager.py +117 -0
- chia/wallet/notification_store.py +178 -0
- chia/wallet/outer_puzzles.py +84 -0
- chia/wallet/payment.py +33 -0
- chia/wallet/puzzle_drivers.py +118 -0
- chia/wallet/puzzles/__init__.py +0 -0
- chia/wallet/puzzles/augmented_condition.clsp +13 -0
- chia/wallet/puzzles/augmented_condition.clsp.hex +1 -0
- chia/wallet/puzzles/clawback/__init__.py +0 -0
- chia/wallet/puzzles/clawback/drivers.py +188 -0
- chia/wallet/puzzles/clawback/metadata.py +38 -0
- chia/wallet/puzzles/clawback/puzzle_decorator.py +67 -0
- chia/wallet/puzzles/condition_codes.clib +77 -0
- chia/wallet/puzzles/curry-and-treehash.clib +102 -0
- chia/wallet/puzzles/curry.clib +135 -0
- chia/wallet/puzzles/curry_by_index.clib +16 -0
- chia/wallet/puzzles/dao_cat_eve.clsp +17 -0
- chia/wallet/puzzles/dao_cat_eve.clsp.hex +1 -0
- chia/wallet/puzzles/dao_cat_launcher.clsp +36 -0
- chia/wallet/puzzles/dao_cat_launcher.clsp.hex +1 -0
- chia/wallet/puzzles/dao_finished_state.clsp +35 -0
- chia/wallet/puzzles/dao_finished_state.clsp.hex +1 -0
- chia/wallet/puzzles/dao_finished_state.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_lockup.clsp +288 -0
- chia/wallet/puzzles/dao_lockup.clsp.hex +1 -0
- chia/wallet/puzzles/dao_lockup.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_proposal.clsp +377 -0
- chia/wallet/puzzles/dao_proposal.clsp.hex +1 -0
- chia/wallet/puzzles/dao_proposal.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_proposal_timer.clsp +78 -0
- chia/wallet/puzzles/dao_proposal_timer.clsp.hex +1 -0
- chia/wallet/puzzles/dao_proposal_timer.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_proposal_validator.clsp +87 -0
- chia/wallet/puzzles/dao_proposal_validator.clsp.hex +1 -0
- chia/wallet/puzzles/dao_proposal_validator.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp +240 -0
- chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex +1 -0
- chia/wallet/puzzles/dao_spend_p2_singleton_v2.clsp.hex.sha256tree +1 -0
- chia/wallet/puzzles/dao_treasury.clsp +115 -0
- chia/wallet/puzzles/dao_treasury.clsp.hex +1 -0
- chia/wallet/puzzles/dao_update_proposal.clsp +44 -0
- chia/wallet/puzzles/dao_update_proposal.clsp.hex +1 -0
- chia/wallet/puzzles/deployed_puzzle_hashes.json +67 -0
- chia/wallet/puzzles/json.clib +25 -0
- chia/wallet/puzzles/load_clvm.py +161 -0
- chia/wallet/puzzles/merkle_utils.clib +18 -0
- chia/wallet/puzzles/notification.clsp +7 -0
- chia/wallet/puzzles/notification.clsp.hex +1 -0
- chia/wallet/puzzles/p2_1_of_n.clsp +22 -0
- chia/wallet/puzzles/p2_1_of_n.clsp.hex +1 -0
- chia/wallet/puzzles/p2_conditions.clsp +3 -0
- chia/wallet/puzzles/p2_conditions.clsp.hex +1 -0
- chia/wallet/puzzles/p2_conditions.py +26 -0
- chia/wallet/puzzles/p2_delegated_conditions.clsp +18 -0
- chia/wallet/puzzles/p2_delegated_conditions.clsp.hex +1 -0
- chia/wallet/puzzles/p2_delegated_conditions.py +21 -0
- chia/wallet/puzzles/p2_delegated_puzzle.clsp +19 -0
- chia/wallet/puzzles/p2_delegated_puzzle.clsp.hex +1 -0
- chia/wallet/puzzles/p2_delegated_puzzle.py +34 -0
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp +91 -0
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.clsp.hex +1 -0
- chia/wallet/puzzles/p2_delegated_puzzle_or_hidden_puzzle.py +160 -0
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp +108 -0
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.clsp.hex +1 -0
- chia/wallet/puzzles/p2_m_of_n_delegate_direct.py +21 -0
- chia/wallet/puzzles/p2_parent.clsp +19 -0
- chia/wallet/puzzles/p2_parent.clsp.hex +1 -0
- chia/wallet/puzzles/p2_puzzle_hash.clsp +18 -0
- chia/wallet/puzzles/p2_puzzle_hash.clsp.hex +1 -0
- chia/wallet/puzzles/p2_puzzle_hash.py +27 -0
- chia/wallet/puzzles/p2_singleton.clsp +30 -0
- chia/wallet/puzzles/p2_singleton.clsp.hex +1 -0
- chia/wallet/puzzles/p2_singleton_aggregator.clsp +81 -0
- chia/wallet/puzzles/p2_singleton_aggregator.clsp.hex +1 -0
- chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp +50 -0
- chia/wallet/puzzles/p2_singleton_or_delayed_puzhash.clsp.hex +1 -0
- chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp +47 -0
- chia/wallet/puzzles/p2_singleton_via_delegated_puzzle.clsp.hex +1 -0
- chia/wallet/puzzles/puzzle_utils.py +34 -0
- chia/wallet/puzzles/settlement_payments.clsp +49 -0
- chia/wallet/puzzles/settlement_payments.clsp.hex +1 -0
- chia/wallet/puzzles/sha256tree.clib +11 -0
- chia/wallet/puzzles/singleton_launcher.clsp +16 -0
- chia/wallet/puzzles/singleton_launcher.clsp.hex +1 -0
- chia/wallet/puzzles/singleton_top_layer.clsp +177 -0
- chia/wallet/puzzles/singleton_top_layer.clsp.hex +1 -0
- chia/wallet/puzzles/singleton_top_layer.py +296 -0
- chia/wallet/puzzles/singleton_top_layer_v1_1.clsp +107 -0
- chia/wallet/puzzles/singleton_top_layer_v1_1.clsp.hex +1 -0
- chia/wallet/puzzles/singleton_top_layer_v1_1.py +345 -0
- chia/wallet/puzzles/singleton_truths.clib +21 -0
- chia/wallet/puzzles/tails.py +348 -0
- chia/wallet/puzzles/utility_macros.clib +48 -0
- chia/wallet/signer_protocol.py +125 -0
- chia/wallet/singleton.py +106 -0
- chia/wallet/singleton_record.py +30 -0
- chia/wallet/trade_manager.py +1102 -0
- chia/wallet/trade_record.py +67 -0
- chia/wallet/trading/__init__.py +0 -0
- chia/wallet/trading/offer.py +702 -0
- chia/wallet/trading/trade_status.py +13 -0
- chia/wallet/trading/trade_store.py +526 -0
- chia/wallet/transaction_record.py +158 -0
- chia/wallet/transaction_sorting.py +14 -0
- chia/wallet/uncurried_puzzle.py +17 -0
- chia/wallet/util/__init__.py +0 -0
- chia/wallet/util/address_type.py +55 -0
- chia/wallet/util/blind_signer_tl.py +164 -0
- chia/wallet/util/clvm_streamable.py +203 -0
- chia/wallet/util/compute_hints.py +66 -0
- chia/wallet/util/compute_memos.py +43 -0
- chia/wallet/util/curry_and_treehash.py +91 -0
- chia/wallet/util/debug_spend_bundle.py +232 -0
- chia/wallet/util/merkle_tree.py +100 -0
- chia/wallet/util/merkle_utils.py +102 -0
- chia/wallet/util/new_peak_queue.py +82 -0
- chia/wallet/util/notifications.py +12 -0
- chia/wallet/util/peer_request_cache.py +174 -0
- chia/wallet/util/pprint.py +39 -0
- chia/wallet/util/puzzle_compression.py +95 -0
- chia/wallet/util/puzzle_decorator.py +100 -0
- chia/wallet/util/puzzle_decorator_type.py +7 -0
- chia/wallet/util/query_filter.py +59 -0
- chia/wallet/util/transaction_type.py +23 -0
- chia/wallet/util/tx_config.py +158 -0
- chia/wallet/util/wallet_sync_utils.py +351 -0
- chia/wallet/util/wallet_types.py +72 -0
- chia/wallet/vc_wallet/__init__.py +0 -0
- chia/wallet/vc_wallet/cr_cat_drivers.py +664 -0
- chia/wallet/vc_wallet/cr_cat_wallet.py +877 -0
- chia/wallet/vc_wallet/cr_outer_puzzle.py +102 -0
- chia/wallet/vc_wallet/cr_puzzles/__init__.py +0 -0
- chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp +3 -0
- chia/wallet/vc_wallet/cr_puzzles/conditions_w_fee_announce.clsp.hex +1 -0
- chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp +304 -0
- chia/wallet/vc_wallet/cr_puzzles/credential_restriction.clsp.hex +1 -0
- chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp +45 -0
- chia/wallet/vc_wallet/cr_puzzles/flag_proofs_checker.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_drivers.py +838 -0
- chia/wallet/vc_wallet/vc_puzzles/__init__.py +0 -0
- chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp +30 -0
- chia/wallet/vc_wallet/vc_puzzles/covenant_layer.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp +75 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_covenant_morpher.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp +32 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_transfer_program_covenant_adapter.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp +80 -0
- chia/wallet/vc_wallet/vc_puzzles/eml_update_metadata_with_DID.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp +163 -0
- chia/wallet/vc_wallet/vc_puzzles/exigent_metadata_layer.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp +16 -0
- chia/wallet/vc_wallet/vc_puzzles/p2_announced_delegated_puzzle.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp +74 -0
- chia/wallet/vc_wallet/vc_puzzles/standard_vc_backdoor_puzzle.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp +23 -0
- chia/wallet/vc_wallet/vc_puzzles/std_parent_morpher.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp +64 -0
- chia/wallet/vc_wallet/vc_puzzles/viral_backdoor.clsp.hex +1 -0
- chia/wallet/vc_wallet/vc_store.py +263 -0
- chia/wallet/vc_wallet/vc_wallet.py +638 -0
- chia/wallet/wallet.py +698 -0
- chia/wallet/wallet_action_scope.py +96 -0
- chia/wallet/wallet_blockchain.py +244 -0
- chia/wallet/wallet_coin_record.py +72 -0
- chia/wallet/wallet_coin_store.py +351 -0
- chia/wallet/wallet_info.py +35 -0
- chia/wallet/wallet_interested_store.py +188 -0
- chia/wallet/wallet_nft_store.py +279 -0
- chia/wallet/wallet_node.py +1765 -0
- chia/wallet/wallet_node_api.py +207 -0
- chia/wallet/wallet_pool_store.py +119 -0
- chia/wallet/wallet_protocol.py +90 -0
- chia/wallet/wallet_puzzle_store.py +396 -0
- chia/wallet/wallet_retry_store.py +70 -0
- chia/wallet/wallet_singleton_store.py +259 -0
- chia/wallet/wallet_spend_bundle.py +25 -0
- chia/wallet/wallet_state_manager.py +2819 -0
- chia/wallet/wallet_transaction_store.py +496 -0
- chia/wallet/wallet_user_store.py +110 -0
- chia/wallet/wallet_weight_proof_handler.py +126 -0
- chia_blockchain-2.5.1rc1.dist-info/LICENSE +201 -0
- chia_blockchain-2.5.1rc1.dist-info/METADATA +156 -0
- chia_blockchain-2.5.1rc1.dist-info/RECORD +1042 -0
- chia_blockchain-2.5.1rc1.dist-info/WHEEL +4 -0
- chia_blockchain-2.5.1rc1.dist-info/entry_points.txt +17 -0
- mozilla-ca/cacert.pem +3611 -0
|
@@ -0,0 +1,702 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, BinaryIO, Optional, Union
|
|
5
|
+
|
|
6
|
+
from chia_rs import G2Element
|
|
7
|
+
from clvm_tools.binutils import disassemble
|
|
8
|
+
|
|
9
|
+
from chia.consensus.default_constants import DEFAULT_CONSTANTS
|
|
10
|
+
from chia.types.blockchain_format.coin import Coin, coin_as_list
|
|
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 CoinSpend, make_spend
|
|
14
|
+
from chia.util.bech32m import bech32_decode, bech32_encode, convertbits
|
|
15
|
+
from chia.util.errors import Err, ValidationError
|
|
16
|
+
from chia.util.ints import uint64
|
|
17
|
+
from chia.util.streamable import parse_rust
|
|
18
|
+
from chia.wallet.conditions import (
|
|
19
|
+
AssertCoinAnnouncement,
|
|
20
|
+
AssertPuzzleAnnouncement,
|
|
21
|
+
Condition,
|
|
22
|
+
ConditionValidTimes,
|
|
23
|
+
parse_conditions_non_consensus,
|
|
24
|
+
parse_timelock_info,
|
|
25
|
+
)
|
|
26
|
+
from chia.wallet.outer_puzzles import (
|
|
27
|
+
construct_puzzle,
|
|
28
|
+
create_asset_id,
|
|
29
|
+
get_inner_puzzle,
|
|
30
|
+
get_inner_solution,
|
|
31
|
+
match_puzzle,
|
|
32
|
+
solve_puzzle,
|
|
33
|
+
)
|
|
34
|
+
from chia.wallet.payment import Payment
|
|
35
|
+
from chia.wallet.puzzle_drivers import PuzzleInfo, Solver
|
|
36
|
+
from chia.wallet.puzzles.load_clvm import load_clvm_maybe_recompile
|
|
37
|
+
from chia.wallet.uncurried_puzzle import UncurriedPuzzle, uncurry_puzzle
|
|
38
|
+
from chia.wallet.util.compute_hints import compute_spend_hints_and_additions
|
|
39
|
+
from chia.wallet.util.puzzle_compression import (
|
|
40
|
+
compress_object_with_puzzles,
|
|
41
|
+
decompress_object_with_puzzles,
|
|
42
|
+
lowest_best_version,
|
|
43
|
+
)
|
|
44
|
+
from chia.wallet.wallet_spend_bundle import WalletSpendBundle
|
|
45
|
+
|
|
46
|
+
OFFER_MOD = load_clvm_maybe_recompile("settlement_payments.clsp")
|
|
47
|
+
OFFER_MOD_HASH = OFFER_MOD.get_tree_hash()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def detect_dependent_coin(
|
|
51
|
+
names: list[bytes32], deps: dict[bytes32, list[bytes32]], announcement_dict: dict[bytes32, list[bytes32]]
|
|
52
|
+
) -> Optional[tuple[bytes32, bytes32]]:
|
|
53
|
+
# First, we check for any dependencies on coins in the same bundle
|
|
54
|
+
for name in names:
|
|
55
|
+
for dependency in deps[name]:
|
|
56
|
+
for coin, announces in announcement_dict.items():
|
|
57
|
+
if dependency in announces and coin != name:
|
|
58
|
+
# We found one, now remove it and anything that depends on it (except the "provider")
|
|
59
|
+
return name, coin
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True)
|
|
64
|
+
class NotarizedPayment(Payment):
|
|
65
|
+
nonce: bytes32 = bytes32.zeros
|
|
66
|
+
|
|
67
|
+
@classmethod
|
|
68
|
+
def from_condition_and_nonce(cls, condition: Program, nonce: bytes32) -> NotarizedPayment:
|
|
69
|
+
with_opcode: Program = Program.to((51, condition)) # Gotta do this because the super class is expecting it
|
|
70
|
+
p = Payment.from_condition(with_opcode)
|
|
71
|
+
puzzle_hash, amount, memos = tuple(p.as_condition_args())
|
|
72
|
+
return cls(puzzle_hash, amount, memos, nonce)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass(frozen=True, eq=False)
|
|
76
|
+
class Offer:
|
|
77
|
+
requested_payments: dict[
|
|
78
|
+
Optional[bytes32], list[NotarizedPayment]
|
|
79
|
+
] # The key is the asset id of the asset being requested
|
|
80
|
+
_bundle: WalletSpendBundle
|
|
81
|
+
driver_dict: dict[bytes32, PuzzleInfo] # asset_id -> asset driver
|
|
82
|
+
|
|
83
|
+
# this is a cache of the coin additions made by the SpendBundle (_bundle)
|
|
84
|
+
# ordered by the coin being spent
|
|
85
|
+
_additions: dict[Coin, list[Coin]] = field(init=False, repr=False)
|
|
86
|
+
_hints: dict[bytes32, bytes32] = field(init=False)
|
|
87
|
+
_offered_coins: dict[Optional[bytes32], list[Coin]] = field(init=False, repr=False)
|
|
88
|
+
_final_spend_bundle: Optional[WalletSpendBundle] = field(init=False, repr=False)
|
|
89
|
+
_conditions: Optional[dict[Coin, list[Condition]]] = field(init=False)
|
|
90
|
+
|
|
91
|
+
@staticmethod
|
|
92
|
+
def ph() -> bytes32:
|
|
93
|
+
return OFFER_MOD_HASH
|
|
94
|
+
|
|
95
|
+
@staticmethod
|
|
96
|
+
def notarize_payments(
|
|
97
|
+
requested_payments: dict[Optional[bytes32], list[Payment]], # `None` means you are requesting XCH
|
|
98
|
+
coins: list[Coin],
|
|
99
|
+
) -> dict[Optional[bytes32], list[NotarizedPayment]]:
|
|
100
|
+
# This sort should be reproducible in CLVM with `>s`
|
|
101
|
+
sorted_coins: list[Coin] = sorted(coins, key=Coin.name)
|
|
102
|
+
sorted_coin_list: list[list[Union[bytes32, uint64]]] = [coin_as_list(c) for c in sorted_coins]
|
|
103
|
+
nonce: bytes32 = Program.to(sorted_coin_list).get_tree_hash()
|
|
104
|
+
|
|
105
|
+
notarized_payments: dict[Optional[bytes32], list[NotarizedPayment]] = {}
|
|
106
|
+
for asset_id, payments in requested_payments.items():
|
|
107
|
+
notarized_payments[asset_id] = []
|
|
108
|
+
for p in payments:
|
|
109
|
+
puzzle_hash, amount, memos = tuple(p.as_condition_args())
|
|
110
|
+
notarized_payments[asset_id].append(NotarizedPayment(puzzle_hash, amount, memos, nonce))
|
|
111
|
+
|
|
112
|
+
return notarized_payments
|
|
113
|
+
|
|
114
|
+
# The announcements returned from this function must be asserted in whatever spend bundle is created by the wallet
|
|
115
|
+
@staticmethod
|
|
116
|
+
def calculate_announcements(
|
|
117
|
+
notarized_payments: dict[Optional[bytes32], list[NotarizedPayment]],
|
|
118
|
+
driver_dict: dict[bytes32, PuzzleInfo],
|
|
119
|
+
) -> list[AssertPuzzleAnnouncement]:
|
|
120
|
+
announcements: list[AssertPuzzleAnnouncement] = []
|
|
121
|
+
for asset_id, payments in notarized_payments.items():
|
|
122
|
+
if asset_id is not None:
|
|
123
|
+
if asset_id not in driver_dict:
|
|
124
|
+
raise ValueError("Cannot calculate announcements without driver of requested item")
|
|
125
|
+
settlement_ph: bytes32 = construct_puzzle(driver_dict[asset_id], OFFER_MOD).get_tree_hash()
|
|
126
|
+
else:
|
|
127
|
+
settlement_ph = OFFER_MOD_HASH
|
|
128
|
+
|
|
129
|
+
msg: bytes32 = Program.to((payments[0].nonce, [p.as_condition_args() for p in payments])).get_tree_hash()
|
|
130
|
+
announcements.append(AssertPuzzleAnnouncement(asserted_ph=settlement_ph, asserted_msg=msg))
|
|
131
|
+
|
|
132
|
+
return announcements
|
|
133
|
+
|
|
134
|
+
def __post_init__(self) -> None:
|
|
135
|
+
# Verify that there are no duplicate payments
|
|
136
|
+
for payments in self.requested_payments.values():
|
|
137
|
+
payment_programs: list[bytes32] = [p.name() for p in payments]
|
|
138
|
+
if len(set(payment_programs)) != len(payment_programs):
|
|
139
|
+
raise ValueError("Bundle has duplicate requested payments")
|
|
140
|
+
|
|
141
|
+
# Verify we have a type for every kind of asset
|
|
142
|
+
for asset_id in self.requested_payments:
|
|
143
|
+
if asset_id is not None and asset_id not in self.driver_dict:
|
|
144
|
+
raise ValueError("Offer does not have enough driver information about the requested payments")
|
|
145
|
+
|
|
146
|
+
# populate the _additions cache
|
|
147
|
+
adds: dict[Coin, list[Coin]] = {}
|
|
148
|
+
hints: dict[bytes32, bytes32] = {}
|
|
149
|
+
max_cost = int(DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM)
|
|
150
|
+
for cs in self._bundle.coin_spends:
|
|
151
|
+
# you can't spend the same coin twice in the same SpendBundle
|
|
152
|
+
assert cs.coin not in adds
|
|
153
|
+
try:
|
|
154
|
+
hinted_coins, cost = compute_spend_hints_and_additions(cs)
|
|
155
|
+
max_cost -= cost
|
|
156
|
+
adds[cs.coin] = [hc.coin for hc in hinted_coins.values()]
|
|
157
|
+
hints = {**hints, **{id: hc.hint for id, hc in hinted_coins.items() if hc.hint is not None}}
|
|
158
|
+
except Exception:
|
|
159
|
+
continue
|
|
160
|
+
if max_cost < 0:
|
|
161
|
+
raise ValidationError(Err.BLOCK_COST_EXCEEDS_MAX, "compute_additions for CoinSpend")
|
|
162
|
+
object.__setattr__(self, "_additions", adds)
|
|
163
|
+
object.__setattr__(self, "_hints", hints)
|
|
164
|
+
object.__setattr__(self, "_conditions", None)
|
|
165
|
+
|
|
166
|
+
def conditions(self) -> dict[Coin, list[Condition]]:
|
|
167
|
+
if self._conditions is None:
|
|
168
|
+
conditions: dict[Coin, list[Condition]] = {}
|
|
169
|
+
max_cost = int(DEFAULT_CONSTANTS.MAX_BLOCK_COST_CLVM)
|
|
170
|
+
for cs in self._bundle.coin_spends:
|
|
171
|
+
try:
|
|
172
|
+
cost, conds = cs.puzzle_reveal.run_with_cost(max_cost, cs.solution)
|
|
173
|
+
max_cost -= cost
|
|
174
|
+
conditions[cs.coin] = parse_conditions_non_consensus(conds.as_iter())
|
|
175
|
+
except Exception: # pragma: no cover
|
|
176
|
+
continue
|
|
177
|
+
if max_cost < 0: # pragma: no cover
|
|
178
|
+
raise ValidationError(Err.BLOCK_COST_EXCEEDS_MAX, "computing conditions for CoinSpend")
|
|
179
|
+
object.__setattr__(self, "_conditions", conditions)
|
|
180
|
+
assert self._conditions is not None, "self._conditions is None"
|
|
181
|
+
return self._conditions
|
|
182
|
+
|
|
183
|
+
def valid_times(self) -> dict[Coin, ConditionValidTimes]:
|
|
184
|
+
return {coin: parse_timelock_info(conditions) for coin, conditions in self.conditions().items()}
|
|
185
|
+
|
|
186
|
+
def absolute_valid_times_ban_relatives(self) -> ConditionValidTimes:
|
|
187
|
+
valid_times: ConditionValidTimes = parse_timelock_info(
|
|
188
|
+
[c for conditions in self.conditions().values() for c in conditions]
|
|
189
|
+
)
|
|
190
|
+
if (
|
|
191
|
+
valid_times.max_secs_after_created is not None
|
|
192
|
+
or valid_times.min_secs_since_created is not None
|
|
193
|
+
or valid_times.max_blocks_after_created is not None
|
|
194
|
+
or valid_times.min_blocks_since_created is not None
|
|
195
|
+
):
|
|
196
|
+
raise ValueError("Offers with relative timelocks are not currently supported")
|
|
197
|
+
return valid_times
|
|
198
|
+
|
|
199
|
+
def hints(self) -> dict[bytes32, bytes32]:
|
|
200
|
+
return self._hints
|
|
201
|
+
|
|
202
|
+
def additions(self) -> list[Coin]:
|
|
203
|
+
return [c for additions in self._additions.values() for c in additions]
|
|
204
|
+
|
|
205
|
+
def removals(self) -> list[Coin]:
|
|
206
|
+
return self._bundle.removals()
|
|
207
|
+
|
|
208
|
+
def fees(self) -> int:
|
|
209
|
+
"""Unsafe to use for fees validation!!!"""
|
|
210
|
+
amount_in = sum(_.amount for _ in self.removals())
|
|
211
|
+
amount_out = sum(_.amount for _ in self.additions())
|
|
212
|
+
return int(amount_in - amount_out)
|
|
213
|
+
|
|
214
|
+
def coin_spends(self) -> list[CoinSpend]:
|
|
215
|
+
return self._bundle.coin_spends
|
|
216
|
+
|
|
217
|
+
def aggregated_signature(self) -> G2Element:
|
|
218
|
+
return self._bundle.aggregated_signature
|
|
219
|
+
|
|
220
|
+
# This method does not get every coin that is being offered, only the `settlement_payment` children
|
|
221
|
+
# It's also a little heuristic, but it should get most things
|
|
222
|
+
def _get_offered_coins(self) -> dict[Optional[bytes32], list[Coin]]:
|
|
223
|
+
offered_coins: dict[Optional[bytes32], list[Coin]] = {}
|
|
224
|
+
|
|
225
|
+
for parent_spend in self._bundle.coin_spends:
|
|
226
|
+
coins_for_this_spend: list[Coin] = []
|
|
227
|
+
|
|
228
|
+
parent_puzzle: UncurriedPuzzle = uncurry_puzzle(parent_spend.puzzle_reveal)
|
|
229
|
+
parent_solution: Program = parent_spend.solution.to_program()
|
|
230
|
+
additions: list[Coin] = self._additions[parent_spend.coin]
|
|
231
|
+
|
|
232
|
+
puzzle_driver = match_puzzle(parent_puzzle)
|
|
233
|
+
if puzzle_driver is not None:
|
|
234
|
+
asset_id = create_asset_id(puzzle_driver)
|
|
235
|
+
inner_puzzle: Optional[Program] = get_inner_puzzle(puzzle_driver, parent_puzzle)
|
|
236
|
+
inner_solution: Optional[Program] = get_inner_solution(puzzle_driver, parent_solution)
|
|
237
|
+
assert inner_puzzle is not None and inner_solution is not None
|
|
238
|
+
|
|
239
|
+
# We're going to look at the conditions created by the inner puzzle
|
|
240
|
+
conditions: Program = inner_puzzle.run(inner_solution)
|
|
241
|
+
expected_num_matches: int = 0
|
|
242
|
+
offered_amounts: list[int] = []
|
|
243
|
+
for condition in conditions.as_iter():
|
|
244
|
+
if condition.first() == 51 and condition.rest().first() == OFFER_MOD_HASH:
|
|
245
|
+
expected_num_matches += 1
|
|
246
|
+
offered_amounts.append(condition.rest().rest().first().as_int())
|
|
247
|
+
|
|
248
|
+
# Start by filtering additions that match the amount
|
|
249
|
+
matching_spend_additions = [a for a in additions if a.amount in offered_amounts]
|
|
250
|
+
|
|
251
|
+
if len(matching_spend_additions) == expected_num_matches:
|
|
252
|
+
coins_for_this_spend.extend(matching_spend_additions)
|
|
253
|
+
# We didn't quite get there so now lets narrow it down by puzzle hash
|
|
254
|
+
else:
|
|
255
|
+
# If we narrowed down too much, we can't trust the amounts so start over with all additions
|
|
256
|
+
if len(matching_spend_additions) < expected_num_matches:
|
|
257
|
+
matching_spend_additions = additions
|
|
258
|
+
matching_spend_additions = [
|
|
259
|
+
a
|
|
260
|
+
for a in matching_spend_additions
|
|
261
|
+
if a.puzzle_hash
|
|
262
|
+
== construct_puzzle(puzzle_driver, OFFER_MOD_HASH).get_tree_hash_precalc( # type: ignore
|
|
263
|
+
OFFER_MOD_HASH
|
|
264
|
+
)
|
|
265
|
+
]
|
|
266
|
+
if len(matching_spend_additions) == expected_num_matches:
|
|
267
|
+
coins_for_this_spend.extend(matching_spend_additions)
|
|
268
|
+
else:
|
|
269
|
+
raise ValueError("Could not properly guess offered coins from parent spend")
|
|
270
|
+
else:
|
|
271
|
+
# It's much easier if the asset is bare XCH
|
|
272
|
+
asset_id = None
|
|
273
|
+
coins_for_this_spend.extend([a for a in additions if a.puzzle_hash == OFFER_MOD_HASH])
|
|
274
|
+
|
|
275
|
+
# We only care about unspent coins
|
|
276
|
+
coins_for_this_spend = [c for c in coins_for_this_spend if c not in self._bundle.removals()]
|
|
277
|
+
|
|
278
|
+
if coins_for_this_spend != []:
|
|
279
|
+
offered_coins.setdefault(asset_id, [])
|
|
280
|
+
offered_coins[asset_id].extend(coins_for_this_spend)
|
|
281
|
+
return offered_coins
|
|
282
|
+
|
|
283
|
+
def get_offered_coins(self) -> dict[Optional[bytes32], list[Coin]]:
|
|
284
|
+
try:
|
|
285
|
+
if self._offered_coins is not None:
|
|
286
|
+
return self._offered_coins
|
|
287
|
+
except AttributeError:
|
|
288
|
+
object.__setattr__(self, "_offered_coins", self._get_offered_coins())
|
|
289
|
+
return self._offered_coins
|
|
290
|
+
|
|
291
|
+
def get_offered_amounts(self) -> dict[Optional[bytes32], int]:
|
|
292
|
+
offered_coins: dict[Optional[bytes32], list[Coin]] = self.get_offered_coins()
|
|
293
|
+
offered_amounts: dict[Optional[bytes32], int] = {}
|
|
294
|
+
for asset_id, coins in offered_coins.items():
|
|
295
|
+
offered_amounts[asset_id] = uint64(sum(c.amount for c in coins))
|
|
296
|
+
return offered_amounts
|
|
297
|
+
|
|
298
|
+
def get_requested_payments(self) -> dict[Optional[bytes32], list[NotarizedPayment]]:
|
|
299
|
+
return self.requested_payments
|
|
300
|
+
|
|
301
|
+
def get_requested_amounts(self) -> dict[Optional[bytes32], int]:
|
|
302
|
+
requested_amounts: dict[Optional[bytes32], int] = {}
|
|
303
|
+
for asset_id, coins in self.get_requested_payments().items():
|
|
304
|
+
requested_amounts[asset_id] = uint64(sum(c.amount for c in coins))
|
|
305
|
+
return requested_amounts
|
|
306
|
+
|
|
307
|
+
def arbitrage(self) -> dict[Optional[bytes32], int]:
|
|
308
|
+
"""
|
|
309
|
+
Returns a dictionary of the type of each asset and amount that is involved in the trade
|
|
310
|
+
With the amount being how much their offered amount within the offer
|
|
311
|
+
exceeds/falls short of their requested amount.
|
|
312
|
+
"""
|
|
313
|
+
offered_amounts: dict[Optional[bytes32], int] = self.get_offered_amounts()
|
|
314
|
+
requested_amounts: dict[Optional[bytes32], int] = self.get_requested_amounts()
|
|
315
|
+
|
|
316
|
+
arbitrage_dict: dict[Optional[bytes32], int] = {}
|
|
317
|
+
for asset_id in [*requested_amounts.keys(), *offered_amounts.keys()]:
|
|
318
|
+
arbitrage_dict[asset_id] = offered_amounts.get(asset_id, 0) - requested_amounts.get(asset_id, 0)
|
|
319
|
+
|
|
320
|
+
return arbitrage_dict
|
|
321
|
+
|
|
322
|
+
# This is a method mostly for the UI that creates a JSON summary of the offer
|
|
323
|
+
def summary(self) -> tuple[dict[str, int], dict[str, int], dict[str, dict[str, Any]], ConditionValidTimes]:
|
|
324
|
+
offered_amounts: dict[Optional[bytes32], int] = self.get_offered_amounts()
|
|
325
|
+
requested_amounts: dict[Optional[bytes32], int] = self.get_requested_amounts()
|
|
326
|
+
|
|
327
|
+
def keys_to_strings(dic: dict[Optional[bytes32], Any]) -> dict[str, Any]:
|
|
328
|
+
new_dic: dict[str, Any] = {}
|
|
329
|
+
for key, val in dic.items():
|
|
330
|
+
if key is None:
|
|
331
|
+
new_dic["xch"] = val
|
|
332
|
+
else:
|
|
333
|
+
new_dic[key.hex()] = val
|
|
334
|
+
return new_dic
|
|
335
|
+
|
|
336
|
+
driver_dict: dict[str, Any] = {}
|
|
337
|
+
for key, value in self.driver_dict.items():
|
|
338
|
+
driver_dict[key.hex()] = value.info
|
|
339
|
+
|
|
340
|
+
return (
|
|
341
|
+
keys_to_strings(offered_amounts),
|
|
342
|
+
keys_to_strings(requested_amounts),
|
|
343
|
+
driver_dict,
|
|
344
|
+
self.absolute_valid_times_ban_relatives(),
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
# Also mostly for the UI, returns a dictionary of assets and how much of them is pended for this offer
|
|
348
|
+
# This method is also imperfect for sufficiently complex spends
|
|
349
|
+
def get_pending_amounts(self) -> dict[str, int]:
|
|
350
|
+
all_additions: list[Coin] = self.additions()
|
|
351
|
+
all_removals: list[Coin] = self.removals()
|
|
352
|
+
non_ephemeral_removals: list[Coin] = list(filter(lambda c: c not in all_additions, all_removals))
|
|
353
|
+
|
|
354
|
+
pending_dict: dict[str, int] = {}
|
|
355
|
+
# First we add up the amounts of all coins that share an ancestor with the offered coins (i.e. a primary coin)
|
|
356
|
+
for asset_id, coins in self.get_offered_coins().items():
|
|
357
|
+
name = "xch" if asset_id is None else asset_id.hex()
|
|
358
|
+
pending_dict[name] = 0
|
|
359
|
+
for coin in coins:
|
|
360
|
+
root_removal: Coin = self.get_root_removal(coin)
|
|
361
|
+
|
|
362
|
+
for addition in filter(lambda c: c.parent_coin_info == root_removal.name(), all_additions):
|
|
363
|
+
pending_dict[name] += addition.amount
|
|
364
|
+
|
|
365
|
+
# Then we gather anything else as unknown
|
|
366
|
+
sum_of_additions_so_far: int = sum(pending_dict.values())
|
|
367
|
+
unknown: int = sum(c.amount for c in non_ephemeral_removals) - sum_of_additions_so_far
|
|
368
|
+
if unknown > 0:
|
|
369
|
+
pending_dict["unknown"] = unknown
|
|
370
|
+
|
|
371
|
+
return pending_dict
|
|
372
|
+
|
|
373
|
+
# This method returns all of the coins that are being used in the offer (without which it would be invalid)
|
|
374
|
+
def get_involved_coins(self) -> list[Coin]:
|
|
375
|
+
additions = self.additions()
|
|
376
|
+
return list(filter(lambda c: c not in additions, self.removals()))
|
|
377
|
+
|
|
378
|
+
# This returns the non-ephemeral removal that is an ancestor of the specified coin
|
|
379
|
+
# This should maybe move to the SpendBundle object at some point
|
|
380
|
+
def get_root_removal(self, coin: Coin) -> Coin:
|
|
381
|
+
all_removals: set[Coin] = set(self.removals())
|
|
382
|
+
all_removal_ids: set[bytes32] = {c.name() for c in all_removals}
|
|
383
|
+
non_ephemeral_removals: set[Coin] = {
|
|
384
|
+
c for c in all_removals if c.parent_coin_info not in {r.name() for r in all_removals}
|
|
385
|
+
}
|
|
386
|
+
if coin.name() not in all_removal_ids and coin.parent_coin_info not in all_removal_ids:
|
|
387
|
+
raise ValueError("The specified coin is not a coin in this bundle")
|
|
388
|
+
|
|
389
|
+
while coin not in non_ephemeral_removals:
|
|
390
|
+
coin = next(c for c in all_removals if c.name() == coin.parent_coin_info)
|
|
391
|
+
|
|
392
|
+
return coin
|
|
393
|
+
|
|
394
|
+
# This will only return coins that are ancestors of settlement payments
|
|
395
|
+
def get_primary_coins(self) -> list[Coin]:
|
|
396
|
+
primary_coins: set[Coin] = set()
|
|
397
|
+
for _, coins in self.get_offered_coins().items():
|
|
398
|
+
for coin in coins:
|
|
399
|
+
primary_coins.add(self.get_root_removal(coin))
|
|
400
|
+
return list(primary_coins)
|
|
401
|
+
|
|
402
|
+
# This returns the minimum coins that when spent will invalidate the rest of the bundle
|
|
403
|
+
def get_cancellation_coins(self) -> list[Coin]:
|
|
404
|
+
# First, we're going to gather:
|
|
405
|
+
dependencies: dict[bytes32, list[bytes32]] = {} # all of the hashes that each coin depends on
|
|
406
|
+
announcements: dict[bytes32, list[bytes32]] = {} # all of the hashes of the announcement that each coin makes
|
|
407
|
+
coin_names: list[bytes32] = [] # The names of all the coins
|
|
408
|
+
additions = self.additions()
|
|
409
|
+
for spend in [cs for cs in self._bundle.coin_spends if cs.coin not in additions]:
|
|
410
|
+
name = bytes32(spend.coin.name())
|
|
411
|
+
coin_names.append(name)
|
|
412
|
+
dependencies[name] = []
|
|
413
|
+
announcements[name] = []
|
|
414
|
+
conditions: Program = spend.puzzle_reveal.run_with_cost(INFINITE_COST, spend.solution)[1]
|
|
415
|
+
for condition in conditions.as_iter():
|
|
416
|
+
if condition.first() == 60: # create coin announcement
|
|
417
|
+
announcements[name].append(
|
|
418
|
+
AssertCoinAnnouncement(asserted_id=name, asserted_msg=condition.at("rf").as_python()).msg_calc
|
|
419
|
+
)
|
|
420
|
+
elif condition.first() == 61: # assert coin announcement
|
|
421
|
+
dependencies[name].append(bytes32(condition.at("rf").as_python()))
|
|
422
|
+
|
|
423
|
+
# We now enter a loop that is attempting to express the following logic:
|
|
424
|
+
# "If I am depending on another coin in the same bundle, you may as well cancel that coin instead of me"
|
|
425
|
+
# By the end of the loop, we should have filtered down the list of coin_names to include only those that will
|
|
426
|
+
# cancel everything else
|
|
427
|
+
while True:
|
|
428
|
+
removed = detect_dependent_coin(coin_names, dependencies, announcements)
|
|
429
|
+
if removed is None:
|
|
430
|
+
break
|
|
431
|
+
removed_coin, provider = removed
|
|
432
|
+
removed_announcements: list[bytes32] = announcements[removed_coin]
|
|
433
|
+
remove_these_keys: list[bytes32] = [removed_coin]
|
|
434
|
+
while True:
|
|
435
|
+
for coin, deps in dependencies.items():
|
|
436
|
+
if set(deps) & set(removed_announcements) and coin != provider:
|
|
437
|
+
remove_these_keys.append(coin)
|
|
438
|
+
removed_announcements = []
|
|
439
|
+
for coin in remove_these_keys:
|
|
440
|
+
dependencies.pop(coin)
|
|
441
|
+
removed_announcements.extend(announcements.pop(coin))
|
|
442
|
+
coin_names = [n for n in coin_names if n not in remove_these_keys]
|
|
443
|
+
if removed_announcements == []:
|
|
444
|
+
break
|
|
445
|
+
else:
|
|
446
|
+
remove_these_keys = []
|
|
447
|
+
|
|
448
|
+
return [cs.coin for cs in self._bundle.coin_spends if cs.coin.name() in coin_names]
|
|
449
|
+
|
|
450
|
+
@classmethod
|
|
451
|
+
def aggregate(cls, offers: list[Offer]) -> Offer:
|
|
452
|
+
total_requested_payments: dict[Optional[bytes32], list[NotarizedPayment]] = {}
|
|
453
|
+
total_bundle = WalletSpendBundle([], G2Element())
|
|
454
|
+
total_driver_dict: dict[bytes32, PuzzleInfo] = {}
|
|
455
|
+
for offer in offers:
|
|
456
|
+
# First check for any overlap in inputs
|
|
457
|
+
total_inputs: set[Coin] = {cs.coin for cs in total_bundle.coin_spends}
|
|
458
|
+
offer_inputs: set[Coin] = {cs.coin for cs in offer._bundle.coin_spends}
|
|
459
|
+
if total_inputs & offer_inputs:
|
|
460
|
+
raise ValueError("The aggregated offers overlap inputs")
|
|
461
|
+
|
|
462
|
+
# Next, do the aggregation
|
|
463
|
+
for asset_id, payments in offer.requested_payments.items():
|
|
464
|
+
if asset_id in total_requested_payments:
|
|
465
|
+
total_requested_payments[asset_id].extend(payments)
|
|
466
|
+
else:
|
|
467
|
+
total_requested_payments[asset_id] = payments
|
|
468
|
+
|
|
469
|
+
for key, value in offer.driver_dict.items():
|
|
470
|
+
if key in total_driver_dict and total_driver_dict[key] != value:
|
|
471
|
+
raise ValueError(f"The offers to aggregate disagree on the drivers for {key.hex()}")
|
|
472
|
+
|
|
473
|
+
total_bundle = WalletSpendBundle.aggregate([total_bundle, offer._bundle])
|
|
474
|
+
total_driver_dict.update(offer.driver_dict)
|
|
475
|
+
|
|
476
|
+
return cls(total_requested_payments, total_bundle, total_driver_dict)
|
|
477
|
+
|
|
478
|
+
# Validity is defined by having enough funds within the offer to satisfy both sides
|
|
479
|
+
def is_valid(self) -> bool:
|
|
480
|
+
return all([value >= 0 for value in self.arbitrage().values()])
|
|
481
|
+
|
|
482
|
+
# A "valid" spend means that this bundle can be pushed to the network and will succeed
|
|
483
|
+
# This differs from the `to_spend_bundle` method which deliberately creates an invalid SpendBundle
|
|
484
|
+
def to_valid_spend(self, arbitrage_ph: Optional[bytes32] = None, solver: Solver = Solver({})) -> WalletSpendBundle:
|
|
485
|
+
if not self.is_valid():
|
|
486
|
+
raise ValueError("Offer is currently incomplete")
|
|
487
|
+
|
|
488
|
+
completion_spends: list[CoinSpend] = []
|
|
489
|
+
all_offered_coins: dict[Optional[bytes32], list[Coin]] = self.get_offered_coins()
|
|
490
|
+
total_arbitrage_amount: dict[Optional[bytes32], int] = self.arbitrage()
|
|
491
|
+
for asset_id, payments in self.requested_payments.items():
|
|
492
|
+
offered_coins: list[Coin] = all_offered_coins[asset_id]
|
|
493
|
+
|
|
494
|
+
# Because of CAT supply laws, we must specify a place for the leftovers to go
|
|
495
|
+
arbitrage_amount: int = total_arbitrage_amount[asset_id]
|
|
496
|
+
all_payments: list[NotarizedPayment] = payments.copy()
|
|
497
|
+
if arbitrage_amount > 0:
|
|
498
|
+
assert arbitrage_amount is not None
|
|
499
|
+
assert arbitrage_ph is not None
|
|
500
|
+
all_payments.append(NotarizedPayment(arbitrage_ph, uint64(arbitrage_amount)))
|
|
501
|
+
|
|
502
|
+
# Some assets need to know about siblings so we need to collect all spends first to be able to use them
|
|
503
|
+
coin_to_spend_dict: dict[Coin, CoinSpend] = {}
|
|
504
|
+
coin_to_solution_dict: dict[Coin, Program] = {}
|
|
505
|
+
for coin in offered_coins:
|
|
506
|
+
parent_spend: CoinSpend = next(
|
|
507
|
+
filter(lambda cs: cs.coin.name() == coin.parent_coin_info, self._bundle.coin_spends)
|
|
508
|
+
)
|
|
509
|
+
coin_to_spend_dict[coin] = parent_spend
|
|
510
|
+
|
|
511
|
+
inner_solutions = []
|
|
512
|
+
if coin == offered_coins[0]:
|
|
513
|
+
nonces: list[bytes32] = [p.nonce for p in all_payments]
|
|
514
|
+
for nonce in list(dict.fromkeys(nonces)): # dedup without messing with order
|
|
515
|
+
nonce_payments: list[NotarizedPayment] = list(filter(lambda p: p.nonce == nonce, all_payments))
|
|
516
|
+
inner_solutions.append((nonce, [np.as_condition_args() for np in nonce_payments]))
|
|
517
|
+
coin_to_solution_dict[coin] = Program.to(inner_solutions)
|
|
518
|
+
|
|
519
|
+
for coin in offered_coins:
|
|
520
|
+
if asset_id:
|
|
521
|
+
siblings: str = "("
|
|
522
|
+
sibling_spends: str = "("
|
|
523
|
+
sibling_puzzles: str = "("
|
|
524
|
+
sibling_solutions: str = "("
|
|
525
|
+
disassembled_offer_mod: str = disassemble(OFFER_MOD)
|
|
526
|
+
for sibling_coin in offered_coins:
|
|
527
|
+
if sibling_coin != coin:
|
|
528
|
+
siblings += (
|
|
529
|
+
"0x"
|
|
530
|
+
+ sibling_coin.parent_coin_info.hex()
|
|
531
|
+
+ sibling_coin.puzzle_hash.hex()
|
|
532
|
+
+ uint64(sibling_coin.amount).stream_to_bytes().hex()
|
|
533
|
+
+ " "
|
|
534
|
+
)
|
|
535
|
+
sibling_spends += "0x" + bytes(coin_to_spend_dict[sibling_coin]).hex() + " "
|
|
536
|
+
sibling_puzzles += disassembled_offer_mod + " "
|
|
537
|
+
sibling_solutions += disassemble(coin_to_solution_dict[sibling_coin]) + " "
|
|
538
|
+
siblings += ")"
|
|
539
|
+
sibling_spends += ")"
|
|
540
|
+
sibling_puzzles += ")"
|
|
541
|
+
sibling_solutions += ")"
|
|
542
|
+
|
|
543
|
+
solution: Program = solve_puzzle(
|
|
544
|
+
self.driver_dict[asset_id],
|
|
545
|
+
Solver(
|
|
546
|
+
{
|
|
547
|
+
"coin": "0x"
|
|
548
|
+
+ coin.parent_coin_info.hex()
|
|
549
|
+
+ coin.puzzle_hash.hex()
|
|
550
|
+
+ uint64(coin.amount).stream_to_bytes().hex(),
|
|
551
|
+
"parent_spend": "0x" + bytes(coin_to_spend_dict[coin]).hex(),
|
|
552
|
+
"siblings": siblings,
|
|
553
|
+
"sibling_spends": sibling_spends,
|
|
554
|
+
"sibling_puzzles": sibling_puzzles,
|
|
555
|
+
"sibling_solutions": sibling_solutions,
|
|
556
|
+
**solver.info,
|
|
557
|
+
}
|
|
558
|
+
),
|
|
559
|
+
OFFER_MOD,
|
|
560
|
+
Program.to(coin_to_solution_dict[coin]),
|
|
561
|
+
)
|
|
562
|
+
else:
|
|
563
|
+
solution = Program.to(coin_to_solution_dict[coin])
|
|
564
|
+
|
|
565
|
+
completion_spends.append(
|
|
566
|
+
make_spend(
|
|
567
|
+
coin,
|
|
568
|
+
construct_puzzle(self.driver_dict[asset_id], OFFER_MOD) if asset_id else OFFER_MOD,
|
|
569
|
+
solution,
|
|
570
|
+
)
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
return WalletSpendBundle.aggregate([WalletSpendBundle(completion_spends, G2Element()), self._bundle])
|
|
574
|
+
|
|
575
|
+
def to_spend_bundle(self) -> WalletSpendBundle:
|
|
576
|
+
try:
|
|
577
|
+
if self._final_spend_bundle is not None:
|
|
578
|
+
return self._final_spend_bundle
|
|
579
|
+
except AttributeError:
|
|
580
|
+
pass
|
|
581
|
+
# Before we serialize this as a SpendBundle, we need to serialize the `requested_payments` as dummy CoinSpends
|
|
582
|
+
additional_coin_spends: list[CoinSpend] = []
|
|
583
|
+
for asset_id, payments in self.requested_payments.items():
|
|
584
|
+
puzzle_reveal: Program = construct_puzzle(self.driver_dict[asset_id], OFFER_MOD) if asset_id else OFFER_MOD
|
|
585
|
+
inner_solutions = []
|
|
586
|
+
nonces: list[bytes32] = [p.nonce for p in payments]
|
|
587
|
+
for nonce in list(dict.fromkeys(nonces)): # dedup without messing with order
|
|
588
|
+
nonce_payments: list[NotarizedPayment] = list(filter(lambda p: p.nonce == nonce, payments))
|
|
589
|
+
inner_solutions.append((nonce, [np.as_condition_args() for np in nonce_payments]))
|
|
590
|
+
|
|
591
|
+
additional_coin_spends.append(
|
|
592
|
+
make_spend(
|
|
593
|
+
Coin(
|
|
594
|
+
bytes32.zeros,
|
|
595
|
+
puzzle_reveal.get_tree_hash(),
|
|
596
|
+
uint64(0),
|
|
597
|
+
),
|
|
598
|
+
puzzle_reveal,
|
|
599
|
+
Program.to(inner_solutions),
|
|
600
|
+
)
|
|
601
|
+
)
|
|
602
|
+
|
|
603
|
+
sb = WalletSpendBundle.aggregate(
|
|
604
|
+
[
|
|
605
|
+
WalletSpendBundle(additional_coin_spends, G2Element()),
|
|
606
|
+
self._bundle,
|
|
607
|
+
]
|
|
608
|
+
)
|
|
609
|
+
object.__setattr__(self, "_final_spend_bundle", sb)
|
|
610
|
+
return sb
|
|
611
|
+
|
|
612
|
+
@classmethod
|
|
613
|
+
def from_spend_bundle(cls, bundle: WalletSpendBundle) -> Offer:
|
|
614
|
+
# Because of the `to_spend_bundle` method, we need to parse the dummy CoinSpends as `requested_payments`
|
|
615
|
+
requested_payments: dict[Optional[bytes32], list[NotarizedPayment]] = {}
|
|
616
|
+
driver_dict: dict[bytes32, PuzzleInfo] = {}
|
|
617
|
+
leftover_coin_spends: list[CoinSpend] = []
|
|
618
|
+
for coin_spend in bundle.coin_spends:
|
|
619
|
+
driver = match_puzzle(uncurry_puzzle(coin_spend.puzzle_reveal))
|
|
620
|
+
if driver is not None:
|
|
621
|
+
asset_id = create_asset_id(driver)
|
|
622
|
+
assert asset_id is not None
|
|
623
|
+
driver_dict[asset_id] = driver
|
|
624
|
+
else:
|
|
625
|
+
asset_id = None
|
|
626
|
+
if coin_spend.coin.parent_coin_info == bytes32.zeros:
|
|
627
|
+
notarized_payments: list[NotarizedPayment] = []
|
|
628
|
+
for payment_group in coin_spend.solution.to_program().as_iter():
|
|
629
|
+
nonce = bytes32(payment_group.first().as_atom())
|
|
630
|
+
payment_args_list = payment_group.rest().as_iter()
|
|
631
|
+
notarized_payments.extend(
|
|
632
|
+
[NotarizedPayment.from_condition_and_nonce(condition, nonce) for condition in payment_args_list]
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
requested_payments[asset_id] = notarized_payments
|
|
636
|
+
else:
|
|
637
|
+
leftover_coin_spends.append(coin_spend)
|
|
638
|
+
|
|
639
|
+
return cls(
|
|
640
|
+
requested_payments, WalletSpendBundle(leftover_coin_spends, bundle.aggregated_signature), driver_dict
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
def name(self) -> bytes32:
|
|
644
|
+
return self.to_spend_bundle().name()
|
|
645
|
+
|
|
646
|
+
def __eq__(self, other: object) -> bool:
|
|
647
|
+
if not isinstance(other, Offer):
|
|
648
|
+
return False # don't attempt to compare against unrelated types
|
|
649
|
+
return self.name() == other.name()
|
|
650
|
+
|
|
651
|
+
def compress(self, version: Optional[int] = None) -> bytes:
|
|
652
|
+
as_spend_bundle = self.to_spend_bundle()
|
|
653
|
+
if version is None:
|
|
654
|
+
mods: list[bytes] = [bytes(s.puzzle_reveal.to_program().uncurry()[0]) for s in as_spend_bundle.coin_spends]
|
|
655
|
+
version = max(lowest_best_version(mods), 6) # Clients lower than version 6 should not be able to parse
|
|
656
|
+
return compress_object_with_puzzles(bytes(as_spend_bundle), version)
|
|
657
|
+
|
|
658
|
+
@classmethod
|
|
659
|
+
def from_compressed(cls, compressed_bytes: bytes) -> Offer:
|
|
660
|
+
return Offer.from_bytes(decompress_object_with_puzzles(compressed_bytes))
|
|
661
|
+
|
|
662
|
+
@classmethod
|
|
663
|
+
def try_offer_decompression(cls, offer_bytes: bytes) -> Offer:
|
|
664
|
+
try:
|
|
665
|
+
return cls.from_compressed(offer_bytes)
|
|
666
|
+
except TypeError:
|
|
667
|
+
pass
|
|
668
|
+
return cls.from_bytes(offer_bytes)
|
|
669
|
+
|
|
670
|
+
def to_bech32(self, prefix: str = "offer", compression_version: Optional[int] = None) -> str:
|
|
671
|
+
offer_bytes = self.compress(version=compression_version)
|
|
672
|
+
encoded = bech32_encode(prefix, convertbits(list(offer_bytes), 8, 5))
|
|
673
|
+
return encoded
|
|
674
|
+
|
|
675
|
+
@classmethod
|
|
676
|
+
def from_bech32(cls, offer_bech32: str) -> Offer:
|
|
677
|
+
_hrpgot, data = bech32_decode(offer_bech32, max_length=len(offer_bech32))
|
|
678
|
+
if data is None:
|
|
679
|
+
raise ValueError("Invalid Offer")
|
|
680
|
+
decoded = convertbits(list(data), 5, 8, False)
|
|
681
|
+
decoded_bytes = bytes(decoded)
|
|
682
|
+
return cls.try_offer_decompression(decoded_bytes)
|
|
683
|
+
|
|
684
|
+
# Methods to make this a valid Streamable member
|
|
685
|
+
# We basically hijack the SpendBundle versions for most of it
|
|
686
|
+
@classmethod
|
|
687
|
+
def parse(cls, f: BinaryIO) -> Offer:
|
|
688
|
+
parsed_bundle = parse_rust(f, WalletSpendBundle)
|
|
689
|
+
return cls.from_bytes(bytes(parsed_bundle))
|
|
690
|
+
|
|
691
|
+
def stream(self, f: BinaryIO) -> None:
|
|
692
|
+
spend_bundle_bytes = self.to_spend_bundle().to_bytes()
|
|
693
|
+
f.write(spend_bundle_bytes)
|
|
694
|
+
|
|
695
|
+
def __bytes__(self) -> bytes:
|
|
696
|
+
return bytes(self.to_spend_bundle())
|
|
697
|
+
|
|
698
|
+
@classmethod
|
|
699
|
+
def from_bytes(cls, as_bytes: bytes) -> Offer:
|
|
700
|
+
# Because of the __bytes__ method, we need to parse the dummy CoinSpends as `requested_payments`
|
|
701
|
+
bundle = WalletSpendBundle.from_bytes(as_bytes)
|
|
702
|
+
return cls.from_spend_bundle(bundle)
|