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,1494 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
import re
|
|
7
|
+
import time
|
|
8
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Optional, cast
|
|
9
|
+
|
|
10
|
+
from chia_rs import AugSchemeMPL, G1Element, G2Element
|
|
11
|
+
|
|
12
|
+
from chia.protocols.wallet_protocol import CoinState
|
|
13
|
+
from chia.server.ws_connection import WSChiaConnection
|
|
14
|
+
from chia.types.blockchain_format.coin import Coin
|
|
15
|
+
from chia.types.blockchain_format.program import Program
|
|
16
|
+
from chia.types.blockchain_format.sized_bytes import bytes32
|
|
17
|
+
from chia.types.coin_spend import CoinSpend, make_spend
|
|
18
|
+
from chia.types.signing_mode import CHIP_0002_SIGN_MESSAGE_PREFIX, SigningMode
|
|
19
|
+
from chia.util.ints import uint16, uint32, uint64, uint128
|
|
20
|
+
from chia.wallet.conditions import (
|
|
21
|
+
AssertCoinAnnouncement,
|
|
22
|
+
Condition,
|
|
23
|
+
ConditionValidTimes,
|
|
24
|
+
CreateCoinAnnouncement,
|
|
25
|
+
parse_timelock_info,
|
|
26
|
+
)
|
|
27
|
+
from chia.wallet.derivation_record import DerivationRecord
|
|
28
|
+
from chia.wallet.did_wallet import did_wallet_puzzles
|
|
29
|
+
from chia.wallet.did_wallet.did_info import DIDCoinData, DIDInfo
|
|
30
|
+
from chia.wallet.did_wallet.did_wallet_puzzles import match_did_puzzle, uncurry_innerpuz
|
|
31
|
+
from chia.wallet.lineage_proof import LineageProof
|
|
32
|
+
from chia.wallet.payment import Payment
|
|
33
|
+
from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import (
|
|
34
|
+
DEFAULT_HIDDEN_PUZZLE_HASH,
|
|
35
|
+
calculate_synthetic_secret_key,
|
|
36
|
+
puzzle_for_pk,
|
|
37
|
+
puzzle_hash_for_pk,
|
|
38
|
+
)
|
|
39
|
+
from chia.wallet.singleton import (
|
|
40
|
+
SINGLETON_LAUNCHER_PUZZLE,
|
|
41
|
+
create_singleton_puzzle,
|
|
42
|
+
create_singleton_puzzle_hash,
|
|
43
|
+
get_inner_puzzle_from_singleton,
|
|
44
|
+
)
|
|
45
|
+
from chia.wallet.transaction_record import TransactionRecord
|
|
46
|
+
from chia.wallet.uncurried_puzzle import uncurry_puzzle
|
|
47
|
+
from chia.wallet.util.compute_memos import compute_memos
|
|
48
|
+
from chia.wallet.util.curry_and_treehash import NIL_TREEHASH, shatree_int, shatree_pair
|
|
49
|
+
from chia.wallet.util.transaction_type import TransactionType
|
|
50
|
+
from chia.wallet.util.wallet_sync_utils import fetch_coin_spend, fetch_coin_spend_for_coin_state
|
|
51
|
+
from chia.wallet.util.wallet_types import WalletType
|
|
52
|
+
from chia.wallet.wallet import Wallet
|
|
53
|
+
from chia.wallet.wallet_action_scope import WalletActionScope
|
|
54
|
+
from chia.wallet.wallet_coin_record import WalletCoinRecord
|
|
55
|
+
from chia.wallet.wallet_info import WalletInfo
|
|
56
|
+
from chia.wallet.wallet_protocol import WalletProtocol
|
|
57
|
+
from chia.wallet.wallet_spend_bundle import WalletSpendBundle
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class DIDWallet:
|
|
61
|
+
if TYPE_CHECKING:
|
|
62
|
+
if TYPE_CHECKING:
|
|
63
|
+
_protocol_check: ClassVar[WalletProtocol[DIDCoinData]] = cast("DIDWallet", None)
|
|
64
|
+
|
|
65
|
+
wallet_state_manager: Any
|
|
66
|
+
log: logging.Logger
|
|
67
|
+
wallet_info: WalletInfo
|
|
68
|
+
did_info: DIDInfo
|
|
69
|
+
standard_wallet: Wallet
|
|
70
|
+
base_puzzle_program: Optional[bytes]
|
|
71
|
+
base_inner_puzzle_hash: Optional[bytes32]
|
|
72
|
+
wallet_id: int
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
async def create_new_did_wallet(
|
|
76
|
+
wallet_state_manager: Any,
|
|
77
|
+
wallet: Wallet,
|
|
78
|
+
amount: uint64,
|
|
79
|
+
action_scope: WalletActionScope,
|
|
80
|
+
backups_ids: list[bytes32] = [],
|
|
81
|
+
num_of_backup_ids_needed: uint64 = None,
|
|
82
|
+
metadata: dict[str, str] = {},
|
|
83
|
+
name: Optional[str] = None,
|
|
84
|
+
fee: uint64 = uint64(0),
|
|
85
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
86
|
+
):
|
|
87
|
+
"""
|
|
88
|
+
Create a brand new DID wallet
|
|
89
|
+
This must be called under the wallet state manager lock
|
|
90
|
+
:param wallet_state_manager: Wallet state manager
|
|
91
|
+
:param wallet: Standard wallet
|
|
92
|
+
:param amount: Amount of the DID coin
|
|
93
|
+
:param backups_ids: A list of DIDs used for recovery this DID
|
|
94
|
+
:param num_of_backup_ids_needed: Needs how many recovery DIDs at least
|
|
95
|
+
:param metadata: Metadata saved in the DID
|
|
96
|
+
:param name: Wallet name
|
|
97
|
+
:param fee: transaction fee
|
|
98
|
+
:return: DID wallet
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
self = DIDWallet()
|
|
102
|
+
self.wallet_state_manager = wallet_state_manager
|
|
103
|
+
if name is None:
|
|
104
|
+
name = self.generate_wallet_name()
|
|
105
|
+
self.base_puzzle_program = None
|
|
106
|
+
self.base_inner_puzzle_hash = None
|
|
107
|
+
self.standard_wallet = wallet
|
|
108
|
+
self.log = logging.getLogger(name if name else __name__)
|
|
109
|
+
std_wallet_id = self.standard_wallet.wallet_id
|
|
110
|
+
bal = await wallet_state_manager.get_confirmed_balance_for_wallet(std_wallet_id)
|
|
111
|
+
if amount > bal:
|
|
112
|
+
raise ValueError("Not enough balance")
|
|
113
|
+
if amount & 1 == 0:
|
|
114
|
+
raise ValueError("DID amount must be odd number")
|
|
115
|
+
|
|
116
|
+
if num_of_backup_ids_needed is None:
|
|
117
|
+
num_of_backup_ids_needed = uint64(len(backups_ids))
|
|
118
|
+
if num_of_backup_ids_needed > len(backups_ids):
|
|
119
|
+
raise ValueError("Cannot require more IDs than are known.")
|
|
120
|
+
self.did_info = DIDInfo(
|
|
121
|
+
origin_coin=None,
|
|
122
|
+
backup_ids=backups_ids,
|
|
123
|
+
num_of_backup_ids_needed=num_of_backup_ids_needed,
|
|
124
|
+
parent_info=[],
|
|
125
|
+
current_inner=None,
|
|
126
|
+
temp_coin=None,
|
|
127
|
+
temp_puzhash=None,
|
|
128
|
+
temp_pubkey=None,
|
|
129
|
+
sent_recovery_transaction=False,
|
|
130
|
+
metadata=json.dumps(metadata),
|
|
131
|
+
)
|
|
132
|
+
info_as_string = json.dumps(self.did_info.to_json_dict())
|
|
133
|
+
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
|
134
|
+
name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
|
|
135
|
+
)
|
|
136
|
+
self.wallet_id = self.wallet_info.id
|
|
137
|
+
std_wallet_id = self.standard_wallet.wallet_id
|
|
138
|
+
bal = await wallet_state_manager.get_confirmed_balance_for_wallet(std_wallet_id)
|
|
139
|
+
if amount > bal:
|
|
140
|
+
raise ValueError("Not enough balance")
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
await self.generate_new_decentralised_id(amount, action_scope, fee, extra_conditions)
|
|
144
|
+
except Exception:
|
|
145
|
+
await wallet_state_manager.delete_wallet(self.id())
|
|
146
|
+
raise
|
|
147
|
+
|
|
148
|
+
await self.wallet_state_manager.add_new_wallet(self)
|
|
149
|
+
|
|
150
|
+
return self
|
|
151
|
+
|
|
152
|
+
@staticmethod
|
|
153
|
+
async def create_new_did_wallet_from_recovery(
|
|
154
|
+
wallet_state_manager: Any,
|
|
155
|
+
wallet: Wallet,
|
|
156
|
+
backup_data: str,
|
|
157
|
+
name: Optional[str] = None,
|
|
158
|
+
):
|
|
159
|
+
"""
|
|
160
|
+
Create a DID wallet from a backup file
|
|
161
|
+
:param wallet_state_manager: Wallet state manager
|
|
162
|
+
:param wallet: Standard wallet
|
|
163
|
+
:param backup_data: A serialized backup data
|
|
164
|
+
:param name: Wallet name
|
|
165
|
+
:return: DID wallet
|
|
166
|
+
"""
|
|
167
|
+
self = DIDWallet()
|
|
168
|
+
self.wallet_state_manager = wallet_state_manager
|
|
169
|
+
if name is None:
|
|
170
|
+
name = self.generate_wallet_name()
|
|
171
|
+
self.base_puzzle_program = None
|
|
172
|
+
self.base_inner_puzzle_hash = None
|
|
173
|
+
self.standard_wallet = wallet
|
|
174
|
+
self.log = logging.getLogger(name if name else __name__)
|
|
175
|
+
self.log.info("Creating DID wallet from recovery file ...")
|
|
176
|
+
# load backup will also set our DIDInfo
|
|
177
|
+
self.did_info = DIDWallet.deserialize_backup_data(backup_data)
|
|
178
|
+
self.check_existed_did()
|
|
179
|
+
info_as_string = json.dumps(self.did_info.to_json_dict())
|
|
180
|
+
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
|
181
|
+
name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
|
|
182
|
+
)
|
|
183
|
+
await self.wallet_state_manager.add_new_wallet(self)
|
|
184
|
+
await self.save_info(self.did_info)
|
|
185
|
+
await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
|
|
186
|
+
await self.load_parent(self.did_info)
|
|
187
|
+
if self.wallet_info is None:
|
|
188
|
+
raise ValueError("Internal Error")
|
|
189
|
+
self.wallet_id = self.wallet_info.id
|
|
190
|
+
return self
|
|
191
|
+
|
|
192
|
+
@staticmethod
|
|
193
|
+
async def create_new_did_wallet_from_coin_spend(
|
|
194
|
+
wallet_state_manager: Any,
|
|
195
|
+
wallet: Wallet,
|
|
196
|
+
launch_coin: Coin,
|
|
197
|
+
inner_puzzle: Program,
|
|
198
|
+
coin_spend: CoinSpend,
|
|
199
|
+
name: Optional[str] = None,
|
|
200
|
+
):
|
|
201
|
+
"""
|
|
202
|
+
Create a DID wallet from a transfer
|
|
203
|
+
:param wallet_state_manager: Wallet state manager
|
|
204
|
+
:param wallet: Main wallet
|
|
205
|
+
:param launch_coin: The launch coin of the DID
|
|
206
|
+
:param inner_puzzle: DID inner puzzle
|
|
207
|
+
:param coin_spend: DID transfer spend
|
|
208
|
+
:param name: Wallet name
|
|
209
|
+
:return: DID wallet
|
|
210
|
+
"""
|
|
211
|
+
self = DIDWallet()
|
|
212
|
+
self.wallet_state_manager = wallet_state_manager
|
|
213
|
+
if name is None:
|
|
214
|
+
name = self.generate_wallet_name()
|
|
215
|
+
self.base_puzzle_program = None
|
|
216
|
+
self.base_inner_puzzle_hash = None
|
|
217
|
+
self.standard_wallet = wallet
|
|
218
|
+
self.log = logging.getLogger(name if name else __name__)
|
|
219
|
+
|
|
220
|
+
self.log.info(f"Creating DID wallet from a coin spend {launch_coin} ...")
|
|
221
|
+
# Create did info from the coin spend
|
|
222
|
+
args = did_wallet_puzzles.uncurry_innerpuz(inner_puzzle)
|
|
223
|
+
if args is None:
|
|
224
|
+
raise ValueError("Cannot uncurry the DID puzzle.")
|
|
225
|
+
_, recovery_list_hash, num_verification, _, metadata = args
|
|
226
|
+
full_solution: Program = Program.from_bytes(bytes(coin_spend.solution))
|
|
227
|
+
inner_solution: Program = full_solution.rest().rest().first()
|
|
228
|
+
recovery_list: list[bytes32] = []
|
|
229
|
+
backup_required: int = num_verification.as_int()
|
|
230
|
+
if recovery_list_hash != NIL_TREEHASH:
|
|
231
|
+
try:
|
|
232
|
+
for did in inner_solution.rest().rest().rest().rest().rest().as_python():
|
|
233
|
+
recovery_list.append(bytes32(did[0]))
|
|
234
|
+
except Exception:
|
|
235
|
+
self.log.warning(
|
|
236
|
+
f"DID {launch_coin.name().hex()} has a recovery list hash but missing a reveal,"
|
|
237
|
+
" you may need to reset the recovery info."
|
|
238
|
+
)
|
|
239
|
+
self.did_info = DIDInfo(
|
|
240
|
+
origin_coin=launch_coin,
|
|
241
|
+
backup_ids=recovery_list,
|
|
242
|
+
num_of_backup_ids_needed=uint64(backup_required),
|
|
243
|
+
parent_info=[],
|
|
244
|
+
current_inner=inner_puzzle,
|
|
245
|
+
temp_coin=None,
|
|
246
|
+
temp_puzhash=None,
|
|
247
|
+
temp_pubkey=None,
|
|
248
|
+
sent_recovery_transaction=False,
|
|
249
|
+
metadata=json.dumps(did_wallet_puzzles.did_program_to_metadata(metadata)),
|
|
250
|
+
)
|
|
251
|
+
self.check_existed_did()
|
|
252
|
+
info_as_string = json.dumps(self.did_info.to_json_dict())
|
|
253
|
+
|
|
254
|
+
self.wallet_info = await wallet_state_manager.user_store.create_wallet(
|
|
255
|
+
name=name, wallet_type=WalletType.DECENTRALIZED_ID.value, data=info_as_string
|
|
256
|
+
)
|
|
257
|
+
await self.wallet_state_manager.add_new_wallet(self)
|
|
258
|
+
await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
|
|
259
|
+
await self.load_parent(self.did_info)
|
|
260
|
+
self.log.info(f"New DID wallet created {info_as_string}.")
|
|
261
|
+
if self.wallet_info is None:
|
|
262
|
+
raise ValueError("Internal Error")
|
|
263
|
+
self.wallet_id = self.wallet_info.id
|
|
264
|
+
return self
|
|
265
|
+
|
|
266
|
+
@staticmethod
|
|
267
|
+
async def create(
|
|
268
|
+
wallet_state_manager: Any,
|
|
269
|
+
wallet: Wallet,
|
|
270
|
+
wallet_info: WalletInfo,
|
|
271
|
+
name: Optional[str] = None,
|
|
272
|
+
):
|
|
273
|
+
"""
|
|
274
|
+
Create a DID wallet based on the local database
|
|
275
|
+
:param wallet_state_manager: Wallet state manager
|
|
276
|
+
:param wallet: Standard wallet
|
|
277
|
+
:param wallet_info: Serialized WalletInfo
|
|
278
|
+
:param name: Wallet name
|
|
279
|
+
:return:
|
|
280
|
+
"""
|
|
281
|
+
self = DIDWallet()
|
|
282
|
+
self.log = logging.getLogger(name if name else __name__)
|
|
283
|
+
self.wallet_state_manager = wallet_state_manager
|
|
284
|
+
self.wallet_info = wallet_info
|
|
285
|
+
self.wallet_id = wallet_info.id
|
|
286
|
+
self.standard_wallet = wallet
|
|
287
|
+
self.wallet_info = wallet_info
|
|
288
|
+
self.did_info = DIDInfo.from_json_dict(json.loads(wallet_info.data))
|
|
289
|
+
self.base_puzzle_program = None
|
|
290
|
+
self.base_inner_puzzle_hash = None
|
|
291
|
+
return self
|
|
292
|
+
|
|
293
|
+
@classmethod
|
|
294
|
+
def type(cls) -> WalletType:
|
|
295
|
+
return WalletType.DECENTRALIZED_ID
|
|
296
|
+
|
|
297
|
+
def id(self) -> uint32:
|
|
298
|
+
return self.wallet_info.id
|
|
299
|
+
|
|
300
|
+
async def get_confirmed_balance(self, record_list=None) -> uint128:
|
|
301
|
+
if record_list is None:
|
|
302
|
+
record_list = await self.wallet_state_manager.coin_store.get_unspent_coins_for_wallet(self.id())
|
|
303
|
+
|
|
304
|
+
amount: uint128 = uint128(0)
|
|
305
|
+
for record in record_list:
|
|
306
|
+
parent = self.get_parent_for_coin(record.coin)
|
|
307
|
+
if parent is not None:
|
|
308
|
+
amount = uint128(amount + record.coin.amount)
|
|
309
|
+
|
|
310
|
+
self.log.info(f"Confirmed balance for did wallet is {amount}")
|
|
311
|
+
return uint128(amount)
|
|
312
|
+
|
|
313
|
+
async def get_pending_change_balance(self) -> uint64:
|
|
314
|
+
unconfirmed_tx = await self.wallet_state_manager.tx_store.get_unconfirmed_for_wallet(self.id())
|
|
315
|
+
addition_amount = 0
|
|
316
|
+
|
|
317
|
+
for record in unconfirmed_tx:
|
|
318
|
+
our_spend = False
|
|
319
|
+
# Need to check belonging with hint_dict
|
|
320
|
+
for coin in record.removals:
|
|
321
|
+
if await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id()):
|
|
322
|
+
our_spend = True
|
|
323
|
+
break
|
|
324
|
+
|
|
325
|
+
if our_spend is not True:
|
|
326
|
+
continue
|
|
327
|
+
|
|
328
|
+
for coin in record.additions:
|
|
329
|
+
hint_dict = {
|
|
330
|
+
coin_id: bytes32(memos[0])
|
|
331
|
+
for coin_id, memos in record.memos
|
|
332
|
+
if len(memos) > 0 and len(memos[0]) == 32
|
|
333
|
+
}
|
|
334
|
+
if (await self.wallet_state_manager.does_coin_belong_to_wallet(coin, self.id(), hint_dict)) and (
|
|
335
|
+
coin not in record.removals
|
|
336
|
+
):
|
|
337
|
+
addition_amount += coin.amount
|
|
338
|
+
|
|
339
|
+
return uint64(addition_amount)
|
|
340
|
+
|
|
341
|
+
async def get_unconfirmed_balance(self, record_list=None) -> uint128:
|
|
342
|
+
return await self.wallet_state_manager.get_unconfirmed_balance(self.id(), record_list)
|
|
343
|
+
|
|
344
|
+
async def select_coins(
|
|
345
|
+
self,
|
|
346
|
+
amount: uint64,
|
|
347
|
+
action_scope: WalletActionScope,
|
|
348
|
+
) -> set[Coin]:
|
|
349
|
+
try:
|
|
350
|
+
async with action_scope.use() as interface:
|
|
351
|
+
coin = await self.get_coin()
|
|
352
|
+
interface.side_effects.selected_coins.append(coin)
|
|
353
|
+
return {coin}
|
|
354
|
+
except RuntimeError:
|
|
355
|
+
return set()
|
|
356
|
+
|
|
357
|
+
def _coin_is_first_singleton(self, coin: Coin) -> bool:
|
|
358
|
+
parent = self.get_parent_for_coin(coin)
|
|
359
|
+
if parent is None:
|
|
360
|
+
return False
|
|
361
|
+
assert self.did_info.origin_coin
|
|
362
|
+
return parent.parent_name == self.did_info.origin_coin.name()
|
|
363
|
+
|
|
364
|
+
# This will be used in the recovery case where we don't have the parent info already
|
|
365
|
+
# But it is also called whenever a Singleton coin from this wallet is spent
|
|
366
|
+
# We can improve this interface by passing in the CoinSpend, as well
|
|
367
|
+
# We need to change DID Wallet coin_added to expect p2 spends as well as recovery spends,
|
|
368
|
+
# or only call it in the recovery spend case
|
|
369
|
+
async def coin_added(self, coin: Coin, _: uint32, peer: WSChiaConnection, parent_coin_data: Optional[DIDCoinData]):
|
|
370
|
+
"""Notification from wallet state manager that wallet has been received."""
|
|
371
|
+
parent = self.get_parent_for_coin(coin)
|
|
372
|
+
if parent_coin_data is not None:
|
|
373
|
+
assert isinstance(parent_coin_data, DIDCoinData)
|
|
374
|
+
did_data: DIDCoinData = parent_coin_data
|
|
375
|
+
else:
|
|
376
|
+
parent_state: CoinState = (
|
|
377
|
+
await self.wallet_state_manager.wallet_node.get_coin_state(
|
|
378
|
+
coin_names=[coin.parent_coin_info], peer=peer
|
|
379
|
+
)
|
|
380
|
+
)[0]
|
|
381
|
+
coin_spend = await fetch_coin_spend_for_coin_state(parent_state, peer)
|
|
382
|
+
uncurried = uncurry_puzzle(coin_spend.puzzle_reveal)
|
|
383
|
+
did_curried_args = match_did_puzzle(uncurried.mod, uncurried.args)
|
|
384
|
+
assert did_curried_args is not None
|
|
385
|
+
p2_puzzle, recovery_list_hash, num_verification, singleton_struct, metadata = did_curried_args
|
|
386
|
+
did_data = DIDCoinData(
|
|
387
|
+
p2_puzzle=p2_puzzle,
|
|
388
|
+
recovery_list_hash=bytes32(recovery_list_hash.as_atom()),
|
|
389
|
+
num_verification=uint16(num_verification.as_int()),
|
|
390
|
+
singleton_struct=singleton_struct,
|
|
391
|
+
metadata=metadata,
|
|
392
|
+
inner_puzzle=get_inner_puzzle_from_singleton(coin_spend.puzzle_reveal),
|
|
393
|
+
coin_state=parent_state,
|
|
394
|
+
)
|
|
395
|
+
if parent is None:
|
|
396
|
+
# this is the first time we received it, check it's a DID coin
|
|
397
|
+
parent_innerpuz = did_data.inner_puzzle
|
|
398
|
+
if parent_innerpuz:
|
|
399
|
+
parent_info = LineageProof(
|
|
400
|
+
parent_name=did_data.coin_state.coin.parent_coin_info,
|
|
401
|
+
inner_puzzle_hash=parent_innerpuz.get_tree_hash(),
|
|
402
|
+
amount=uint64(did_data.coin_state.coin.amount),
|
|
403
|
+
)
|
|
404
|
+
await self.add_parent(coin.parent_coin_info, parent_info)
|
|
405
|
+
else:
|
|
406
|
+
self.log.warning("Parent coin is not a DID, skipping: %s -> %s", coin.name(), coin)
|
|
407
|
+
return
|
|
408
|
+
self.log.info(f"DID wallet has been notified that coin was added: {coin.name()}:{coin}")
|
|
409
|
+
inner_puzzle = await self.inner_puzzle_for_did_puzzle(coin.puzzle_hash)
|
|
410
|
+
# Check inner puzzle consistency
|
|
411
|
+
assert self.did_info.origin_coin is not None
|
|
412
|
+
|
|
413
|
+
# TODO: if not the first singleton, and solution mode == recovery
|
|
414
|
+
if not self._coin_is_first_singleton(coin):
|
|
415
|
+
full_puzzle = create_singleton_puzzle(inner_puzzle, self.did_info.origin_coin.name())
|
|
416
|
+
assert full_puzzle.get_tree_hash() == coin.puzzle_hash
|
|
417
|
+
if self.did_info.temp_coin is not None:
|
|
418
|
+
self.wallet_state_manager.state_changed("did_coin_added", self.wallet_info.id)
|
|
419
|
+
new_info = DIDInfo(
|
|
420
|
+
origin_coin=self.did_info.origin_coin,
|
|
421
|
+
backup_ids=self.did_info.backup_ids,
|
|
422
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
423
|
+
parent_info=self.did_info.parent_info,
|
|
424
|
+
current_inner=inner_puzzle,
|
|
425
|
+
temp_coin=None,
|
|
426
|
+
temp_puzhash=None,
|
|
427
|
+
temp_pubkey=None,
|
|
428
|
+
sent_recovery_transaction=False,
|
|
429
|
+
metadata=json.dumps(did_wallet_puzzles.did_program_to_metadata(did_data.metadata)),
|
|
430
|
+
)
|
|
431
|
+
await self.save_info(new_info)
|
|
432
|
+
|
|
433
|
+
future_parent = LineageProof(
|
|
434
|
+
parent_name=coin.parent_coin_info,
|
|
435
|
+
inner_puzzle_hash=inner_puzzle.get_tree_hash(),
|
|
436
|
+
amount=uint64(coin.amount),
|
|
437
|
+
)
|
|
438
|
+
|
|
439
|
+
await self.add_parent(coin.name(), future_parent)
|
|
440
|
+
await self.wallet_state_manager.add_interested_coin_ids([coin.name()])
|
|
441
|
+
|
|
442
|
+
def create_backup(self) -> str:
|
|
443
|
+
"""
|
|
444
|
+
Create a serialized backup data for DIDInfo
|
|
445
|
+
:return: Serialized backup data
|
|
446
|
+
"""
|
|
447
|
+
assert self.did_info.current_inner is not None
|
|
448
|
+
assert self.did_info.origin_coin is not None
|
|
449
|
+
output_str = f"{self.did_info.origin_coin.parent_coin_info.hex()}:"
|
|
450
|
+
output_str += f"{self.did_info.origin_coin.puzzle_hash.hex()}:"
|
|
451
|
+
output_str += f"{self.did_info.origin_coin.amount}:"
|
|
452
|
+
if len(self.did_info.backup_ids) > 0:
|
|
453
|
+
for did in self.did_info.backup_ids:
|
|
454
|
+
output_str = output_str + did.hex() + ","
|
|
455
|
+
output_str = output_str[:-1]
|
|
456
|
+
output_str += f":{bytes(self.did_info.current_inner).hex()}:{self.did_info.num_of_backup_ids_needed}"
|
|
457
|
+
output_str += f":{self.did_info.metadata}"
|
|
458
|
+
return output_str
|
|
459
|
+
|
|
460
|
+
async def load_parent(self, did_info: DIDInfo):
|
|
461
|
+
"""
|
|
462
|
+
Load the parent info when importing a DID
|
|
463
|
+
:param did_info: DID info
|
|
464
|
+
:return:
|
|
465
|
+
"""
|
|
466
|
+
# full_puz = did_wallet_puzzles.create_fullpuz(innerpuz, origin.name())
|
|
467
|
+
# All additions in this block here:
|
|
468
|
+
|
|
469
|
+
new_puzhash = await self.wallet_state_manager.main_wallet.get_puzzle_hash(new=False)
|
|
470
|
+
new_pubkey = await self.wallet_state_manager.get_public_key(new_puzhash)
|
|
471
|
+
parent_info = None
|
|
472
|
+
assert did_info.origin_coin is not None
|
|
473
|
+
assert did_info.current_inner is not None
|
|
474
|
+
new_did_inner_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2(
|
|
475
|
+
p2_puzhash=new_puzhash,
|
|
476
|
+
recovery_list=did_info.backup_ids,
|
|
477
|
+
num_of_backup_ids_needed=did_info.num_of_backup_ids_needed,
|
|
478
|
+
launcher_id=did_info.origin_coin.name(),
|
|
479
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
480
|
+
)
|
|
481
|
+
wallet_node = self.wallet_state_manager.wallet_node
|
|
482
|
+
parent_coin: Coin = did_info.origin_coin
|
|
483
|
+
while True:
|
|
484
|
+
peer = wallet_node.get_full_node_peer()
|
|
485
|
+
children = await wallet_node.fetch_children(parent_coin.name(), peer)
|
|
486
|
+
if len(children) == 0:
|
|
487
|
+
break
|
|
488
|
+
|
|
489
|
+
children_state: CoinState = children[0]
|
|
490
|
+
child_coin = children_state.coin
|
|
491
|
+
future_parent = LineageProof(
|
|
492
|
+
parent_name=child_coin.parent_coin_info,
|
|
493
|
+
inner_puzzle_hash=did_info.current_inner.get_tree_hash(),
|
|
494
|
+
amount=uint64(child_coin.amount),
|
|
495
|
+
)
|
|
496
|
+
await self.add_parent(child_coin.name(), future_parent)
|
|
497
|
+
if children_state.spent_height != children_state.created_height:
|
|
498
|
+
did_info = DIDInfo(
|
|
499
|
+
origin_coin=did_info.origin_coin,
|
|
500
|
+
backup_ids=did_info.backup_ids,
|
|
501
|
+
num_of_backup_ids_needed=did_info.num_of_backup_ids_needed,
|
|
502
|
+
parent_info=self.did_info.parent_info,
|
|
503
|
+
current_inner=did_info.current_inner,
|
|
504
|
+
temp_coin=child_coin,
|
|
505
|
+
temp_puzhash=new_did_inner_puzhash,
|
|
506
|
+
temp_pubkey=bytes(new_pubkey),
|
|
507
|
+
sent_recovery_transaction=did_info.sent_recovery_transaction,
|
|
508
|
+
metadata=did_info.metadata,
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
await self.save_info(did_info)
|
|
512
|
+
assert children_state.created_height
|
|
513
|
+
parent_spend = await fetch_coin_spend(uint32(children_state.created_height), parent_coin, peer)
|
|
514
|
+
assert parent_spend is not None
|
|
515
|
+
parent_innerpuz = get_inner_puzzle_from_singleton(parent_spend.puzzle_reveal)
|
|
516
|
+
assert parent_innerpuz is not None
|
|
517
|
+
parent_info = LineageProof(
|
|
518
|
+
parent_name=parent_coin.parent_coin_info,
|
|
519
|
+
inner_puzzle_hash=parent_innerpuz.get_tree_hash(),
|
|
520
|
+
amount=uint64(parent_coin.amount),
|
|
521
|
+
)
|
|
522
|
+
await self.add_parent(child_coin.parent_coin_info, parent_info)
|
|
523
|
+
parent_coin = child_coin
|
|
524
|
+
assert parent_info is not None
|
|
525
|
+
|
|
526
|
+
def puzzle_for_pk(self, pubkey: G1Element) -> Program:
|
|
527
|
+
if self.did_info.origin_coin is not None:
|
|
528
|
+
innerpuz = did_wallet_puzzles.create_innerpuz(
|
|
529
|
+
p2_puzzle_or_hash=puzzle_for_pk(pubkey),
|
|
530
|
+
recovery_list=self.did_info.backup_ids,
|
|
531
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
532
|
+
launcher_id=self.did_info.origin_coin.name(),
|
|
533
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
534
|
+
)
|
|
535
|
+
return create_singleton_puzzle(innerpuz, self.did_info.origin_coin.name())
|
|
536
|
+
else:
|
|
537
|
+
innerpuz = Program.to((8, 0))
|
|
538
|
+
return create_singleton_puzzle(innerpuz, bytes32.zeros)
|
|
539
|
+
|
|
540
|
+
def puzzle_hash_for_pk(self, pubkey: G1Element) -> bytes32:
|
|
541
|
+
if self.did_info.origin_coin is None:
|
|
542
|
+
# TODO: this seem dumb. Why bother with this case? Is it ever used?
|
|
543
|
+
# inner puzzle: (8 . 0)
|
|
544
|
+
innerpuz_hash = shatree_pair(shatree_int(8), NIL_TREEHASH)
|
|
545
|
+
return create_singleton_puzzle_hash(innerpuz_hash, bytes32.zeros)
|
|
546
|
+
origin_coin_name = self.did_info.origin_coin.name()
|
|
547
|
+
innerpuz_hash = did_wallet_puzzles.get_inner_puzhash_by_p2(
|
|
548
|
+
p2_puzhash=puzzle_hash_for_pk(pubkey),
|
|
549
|
+
recovery_list=self.did_info.backup_ids,
|
|
550
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
551
|
+
launcher_id=origin_coin_name,
|
|
552
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
553
|
+
)
|
|
554
|
+
return create_singleton_puzzle_hash(innerpuz_hash, origin_coin_name)
|
|
555
|
+
|
|
556
|
+
def get_my_DID(self) -> str:
|
|
557
|
+
assert self.did_info.origin_coin is not None
|
|
558
|
+
core = self.did_info.origin_coin.name()
|
|
559
|
+
assert core is not None
|
|
560
|
+
return core.hex()
|
|
561
|
+
|
|
562
|
+
async def set_name(self, new_name: str):
|
|
563
|
+
new_info = dataclasses.replace(self.wallet_info, name=new_name)
|
|
564
|
+
self.wallet_info = new_info
|
|
565
|
+
await self.wallet_state_manager.user_store.update_wallet(self.wallet_info)
|
|
566
|
+
|
|
567
|
+
def get_name(self):
|
|
568
|
+
return self.wallet_info.name
|
|
569
|
+
|
|
570
|
+
async def create_update_spend(
|
|
571
|
+
self,
|
|
572
|
+
action_scope: WalletActionScope,
|
|
573
|
+
fee: uint64 = uint64(0),
|
|
574
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
575
|
+
) -> None:
|
|
576
|
+
assert self.did_info.current_inner is not None
|
|
577
|
+
assert self.did_info.origin_coin is not None
|
|
578
|
+
coin = await self.get_coin()
|
|
579
|
+
new_inner_puzzle = await self.get_did_innerpuz(new=not action_scope.config.tx_config.reuse_puzhash)
|
|
580
|
+
uncurried = did_wallet_puzzles.uncurry_innerpuz(new_inner_puzzle)
|
|
581
|
+
assert uncurried is not None
|
|
582
|
+
p2_puzzle = uncurried[0]
|
|
583
|
+
# innerpuz solution is (mode, p2_solution)
|
|
584
|
+
p2_solution = self.standard_wallet.make_solution(
|
|
585
|
+
primaries=[
|
|
586
|
+
Payment(
|
|
587
|
+
puzzle_hash=new_inner_puzzle.get_tree_hash(),
|
|
588
|
+
amount=uint64(coin.amount),
|
|
589
|
+
memos=[p2_puzzle.get_tree_hash()],
|
|
590
|
+
)
|
|
591
|
+
],
|
|
592
|
+
conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())),
|
|
593
|
+
)
|
|
594
|
+
innersol: Program = Program.to([1, p2_solution])
|
|
595
|
+
# full solution is (corehash parent_info my_amount innerpuz_reveal solution)
|
|
596
|
+
innerpuz: Program = self.did_info.current_inner
|
|
597
|
+
|
|
598
|
+
full_puzzle: Program = create_singleton_puzzle(
|
|
599
|
+
innerpuz,
|
|
600
|
+
self.did_info.origin_coin.name(),
|
|
601
|
+
)
|
|
602
|
+
parent_info = self.get_parent_for_coin(coin)
|
|
603
|
+
assert parent_info is not None
|
|
604
|
+
fullsol = Program.to(
|
|
605
|
+
[
|
|
606
|
+
[
|
|
607
|
+
parent_info.parent_name,
|
|
608
|
+
parent_info.inner_puzzle_hash,
|
|
609
|
+
parent_info.amount,
|
|
610
|
+
],
|
|
611
|
+
coin.amount,
|
|
612
|
+
innersol,
|
|
613
|
+
]
|
|
614
|
+
)
|
|
615
|
+
# Create an additional spend to confirm the change on-chain
|
|
616
|
+
new_full_puzzle: Program = create_singleton_puzzle(
|
|
617
|
+
new_inner_puzzle,
|
|
618
|
+
self.did_info.origin_coin.name(),
|
|
619
|
+
)
|
|
620
|
+
new_full_sol = Program.to(
|
|
621
|
+
[
|
|
622
|
+
[
|
|
623
|
+
coin.parent_coin_info,
|
|
624
|
+
innerpuz.get_tree_hash(),
|
|
625
|
+
coin.amount,
|
|
626
|
+
],
|
|
627
|
+
coin.amount,
|
|
628
|
+
innersol,
|
|
629
|
+
]
|
|
630
|
+
)
|
|
631
|
+
new_coin = Coin(coin.name(), new_full_puzzle.get_tree_hash(), coin.amount)
|
|
632
|
+
list_of_coinspends = [
|
|
633
|
+
make_spend(coin, full_puzzle, fullsol),
|
|
634
|
+
make_spend(new_coin, new_full_puzzle, new_full_sol),
|
|
635
|
+
]
|
|
636
|
+
spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
|
|
637
|
+
if fee > 0:
|
|
638
|
+
coin_name = coin.name()
|
|
639
|
+
await self.standard_wallet.create_tandem_xch_tx(
|
|
640
|
+
fee,
|
|
641
|
+
action_scope,
|
|
642
|
+
extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),),
|
|
643
|
+
)
|
|
644
|
+
did_record = TransactionRecord(
|
|
645
|
+
confirmed_at_height=uint32(0),
|
|
646
|
+
created_at_time=uint64(int(time.time())),
|
|
647
|
+
to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
|
|
648
|
+
amount=uint64(coin.amount),
|
|
649
|
+
fee_amount=uint64(0),
|
|
650
|
+
confirmed=False,
|
|
651
|
+
sent=uint32(0),
|
|
652
|
+
spend_bundle=spend_bundle,
|
|
653
|
+
additions=spend_bundle.additions(),
|
|
654
|
+
removals=spend_bundle.removals(),
|
|
655
|
+
wallet_id=self.wallet_info.id,
|
|
656
|
+
sent_to=[],
|
|
657
|
+
trade_id=None,
|
|
658
|
+
type=uint32(TransactionType.OUTGOING_TX.value),
|
|
659
|
+
name=bytes32.secret(),
|
|
660
|
+
memos=list(compute_memos(spend_bundle).items()),
|
|
661
|
+
valid_times=parse_timelock_info(extra_conditions),
|
|
662
|
+
)
|
|
663
|
+
|
|
664
|
+
async with action_scope.use() as interface:
|
|
665
|
+
interface.side_effects.transactions.append(did_record)
|
|
666
|
+
|
|
667
|
+
async def transfer_did(
|
|
668
|
+
self,
|
|
669
|
+
new_puzhash: bytes32,
|
|
670
|
+
fee: uint64,
|
|
671
|
+
with_recovery: bool,
|
|
672
|
+
action_scope: WalletActionScope,
|
|
673
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
674
|
+
) -> None:
|
|
675
|
+
"""
|
|
676
|
+
Transfer the current DID to another owner
|
|
677
|
+
:param new_puzhash: New owner's p2_puzzle
|
|
678
|
+
:param fee: Transaction fee
|
|
679
|
+
:param with_recovery: A boolean indicates if the recovery info will be sent through the blockchain
|
|
680
|
+
:return: Spend bundle
|
|
681
|
+
"""
|
|
682
|
+
assert self.did_info.current_inner is not None
|
|
683
|
+
assert self.did_info.origin_coin is not None
|
|
684
|
+
coin = await self.get_coin()
|
|
685
|
+
backup_ids = []
|
|
686
|
+
backup_required = uint64(0)
|
|
687
|
+
if with_recovery:
|
|
688
|
+
backup_ids = self.did_info.backup_ids
|
|
689
|
+
backup_required = self.did_info.num_of_backup_ids_needed
|
|
690
|
+
new_did_puzhash = did_wallet_puzzles.get_inner_puzhash_by_p2(
|
|
691
|
+
p2_puzhash=new_puzhash,
|
|
692
|
+
recovery_list=backup_ids,
|
|
693
|
+
num_of_backup_ids_needed=backup_required,
|
|
694
|
+
launcher_id=self.did_info.origin_coin.name(),
|
|
695
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
696
|
+
)
|
|
697
|
+
p2_solution = self.standard_wallet.make_solution(
|
|
698
|
+
primaries=[Payment(new_did_puzhash, uint64(coin.amount), [new_puzhash])],
|
|
699
|
+
conditions=(*extra_conditions, CreateCoinAnnouncement(coin.name())),
|
|
700
|
+
)
|
|
701
|
+
# Need to include backup list reveal here, even we are don't recover
|
|
702
|
+
# innerpuz solution is
|
|
703
|
+
# (mode, p2_solution)
|
|
704
|
+
innersol: Program = Program.to([2, p2_solution])
|
|
705
|
+
if with_recovery:
|
|
706
|
+
innersol = Program.to([2, p2_solution, [], [], [], self.did_info.backup_ids])
|
|
707
|
+
# full solution is (corehash parent_info my_amount innerpuz_reveal solution)
|
|
708
|
+
|
|
709
|
+
full_puzzle: Program = create_singleton_puzzle(
|
|
710
|
+
self.did_info.current_inner,
|
|
711
|
+
self.did_info.origin_coin.name(),
|
|
712
|
+
)
|
|
713
|
+
parent_info = self.get_parent_for_coin(coin)
|
|
714
|
+
assert parent_info is not None
|
|
715
|
+
fullsol = Program.to(
|
|
716
|
+
[
|
|
717
|
+
[
|
|
718
|
+
parent_info.parent_name,
|
|
719
|
+
parent_info.inner_puzzle_hash,
|
|
720
|
+
parent_info.amount,
|
|
721
|
+
],
|
|
722
|
+
coin.amount,
|
|
723
|
+
innersol,
|
|
724
|
+
]
|
|
725
|
+
)
|
|
726
|
+
list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
|
|
727
|
+
spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
|
|
728
|
+
if fee > 0:
|
|
729
|
+
coin_name = coin.name()
|
|
730
|
+
await self.standard_wallet.create_tandem_xch_tx(
|
|
731
|
+
fee,
|
|
732
|
+
action_scope,
|
|
733
|
+
extra_conditions=(AssertCoinAnnouncement(asserted_id=coin_name, asserted_msg=coin_name),),
|
|
734
|
+
)
|
|
735
|
+
did_record = TransactionRecord(
|
|
736
|
+
confirmed_at_height=uint32(0),
|
|
737
|
+
created_at_time=uint64(int(time.time())),
|
|
738
|
+
to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
|
|
739
|
+
amount=uint64(coin.amount),
|
|
740
|
+
fee_amount=fee,
|
|
741
|
+
confirmed=False,
|
|
742
|
+
sent=uint32(0),
|
|
743
|
+
spend_bundle=spend_bundle,
|
|
744
|
+
additions=spend_bundle.additions(),
|
|
745
|
+
removals=spend_bundle.removals(),
|
|
746
|
+
wallet_id=self.wallet_info.id,
|
|
747
|
+
sent_to=[],
|
|
748
|
+
trade_id=None,
|
|
749
|
+
type=uint32(TransactionType.OUTGOING_TX.value),
|
|
750
|
+
name=spend_bundle.name(),
|
|
751
|
+
memos=list(compute_memos(spend_bundle).items()),
|
|
752
|
+
valid_times=parse_timelock_info(extra_conditions),
|
|
753
|
+
)
|
|
754
|
+
|
|
755
|
+
async with action_scope.use() as interface:
|
|
756
|
+
interface.side_effects.transactions.append(did_record)
|
|
757
|
+
|
|
758
|
+
# The message spend can tests\wallet\rpc\test_wallet_rpc.py send messages and also change your innerpuz
|
|
759
|
+
async def create_message_spend(
|
|
760
|
+
self,
|
|
761
|
+
action_scope: WalletActionScope,
|
|
762
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
763
|
+
) -> None:
|
|
764
|
+
assert self.did_info.current_inner is not None
|
|
765
|
+
assert self.did_info.origin_coin is not None
|
|
766
|
+
coin = await self.get_coin()
|
|
767
|
+
innerpuz: Program = self.did_info.current_inner
|
|
768
|
+
# Quote message puzzle & solution
|
|
769
|
+
if action_scope.config.tx_config.reuse_puzhash:
|
|
770
|
+
new_innerpuzzle_hash = innerpuz.get_tree_hash()
|
|
771
|
+
uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
|
|
772
|
+
assert uncurried is not None
|
|
773
|
+
p2_ph = uncurried[0].get_tree_hash()
|
|
774
|
+
else:
|
|
775
|
+
p2_ph = await self.standard_wallet.get_puzzle_hash(new=True)
|
|
776
|
+
new_innerpuzzle_hash = did_wallet_puzzles.get_inner_puzhash_by_p2(
|
|
777
|
+
p2_puzhash=p2_ph,
|
|
778
|
+
recovery_list=self.did_info.backup_ids,
|
|
779
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
780
|
+
launcher_id=self.did_info.origin_coin.name(),
|
|
781
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
782
|
+
)
|
|
783
|
+
p2_solution = self.standard_wallet.make_solution(
|
|
784
|
+
primaries=[Payment(puzzle_hash=new_innerpuzzle_hash, amount=uint64(coin.amount), memos=[p2_ph])],
|
|
785
|
+
conditions=extra_conditions,
|
|
786
|
+
)
|
|
787
|
+
# innerpuz solution is (mode p2_solution)
|
|
788
|
+
innersol: Program = Program.to([1, p2_solution])
|
|
789
|
+
|
|
790
|
+
# full solution is (corehash parent_info my_amount innerpuz_reveal solution)
|
|
791
|
+
full_puzzle: Program = create_singleton_puzzle(
|
|
792
|
+
innerpuz,
|
|
793
|
+
self.did_info.origin_coin.name(),
|
|
794
|
+
)
|
|
795
|
+
parent_info = self.get_parent_for_coin(coin)
|
|
796
|
+
assert parent_info is not None
|
|
797
|
+
fullsol = Program.to(
|
|
798
|
+
[
|
|
799
|
+
[
|
|
800
|
+
parent_info.parent_name,
|
|
801
|
+
parent_info.inner_puzzle_hash,
|
|
802
|
+
parent_info.amount,
|
|
803
|
+
],
|
|
804
|
+
coin.amount,
|
|
805
|
+
innersol,
|
|
806
|
+
]
|
|
807
|
+
)
|
|
808
|
+
list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
|
|
809
|
+
unsigned_spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
|
|
810
|
+
tx = TransactionRecord(
|
|
811
|
+
confirmed_at_height=uint32(0),
|
|
812
|
+
created_at_time=uint64(int(time.time())),
|
|
813
|
+
to_puzzle_hash=p2_ph,
|
|
814
|
+
amount=uint64(coin.amount),
|
|
815
|
+
fee_amount=uint64(0),
|
|
816
|
+
confirmed=False,
|
|
817
|
+
sent=uint32(0),
|
|
818
|
+
spend_bundle=unsigned_spend_bundle,
|
|
819
|
+
additions=unsigned_spend_bundle.additions(),
|
|
820
|
+
removals=[coin],
|
|
821
|
+
wallet_id=self.id(),
|
|
822
|
+
sent_to=[],
|
|
823
|
+
trade_id=None,
|
|
824
|
+
type=uint32(TransactionType.OUTGOING_TX.value),
|
|
825
|
+
name=unsigned_spend_bundle.name(),
|
|
826
|
+
memos=list(compute_memos(unsigned_spend_bundle).items()),
|
|
827
|
+
valid_times=parse_timelock_info(extra_conditions),
|
|
828
|
+
)
|
|
829
|
+
async with action_scope.use() as interface:
|
|
830
|
+
interface.side_effects.transactions.append(tx)
|
|
831
|
+
|
|
832
|
+
# This is used to cash out, or update the id_list
|
|
833
|
+
async def create_exit_spend(self, puzhash: bytes32, action_scope: WalletActionScope) -> None:
|
|
834
|
+
assert self.did_info.current_inner is not None
|
|
835
|
+
assert self.did_info.origin_coin is not None
|
|
836
|
+
coin = await self.get_coin()
|
|
837
|
+
message_puz = Program.to((1, [[51, puzhash, coin.amount - 1, [puzhash]], [51, 0x00, -113]]))
|
|
838
|
+
|
|
839
|
+
# innerpuz solution is (mode p2_solution)
|
|
840
|
+
innersol: Program = Program.to([1, [[], message_puz, []]])
|
|
841
|
+
# full solution is (corehash parent_info my_amount innerpuz_reveal solution)
|
|
842
|
+
innerpuz: Program = self.did_info.current_inner
|
|
843
|
+
|
|
844
|
+
full_puzzle: Program = create_singleton_puzzle(
|
|
845
|
+
innerpuz,
|
|
846
|
+
self.did_info.origin_coin.name(),
|
|
847
|
+
)
|
|
848
|
+
parent_info = self.get_parent_for_coin(coin)
|
|
849
|
+
assert parent_info is not None
|
|
850
|
+
fullsol = Program.to(
|
|
851
|
+
[
|
|
852
|
+
[
|
|
853
|
+
parent_info.parent_name,
|
|
854
|
+
parent_info.inner_puzzle_hash,
|
|
855
|
+
parent_info.amount,
|
|
856
|
+
],
|
|
857
|
+
coin.amount,
|
|
858
|
+
innersol,
|
|
859
|
+
]
|
|
860
|
+
)
|
|
861
|
+
list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
|
|
862
|
+
spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
|
|
863
|
+
|
|
864
|
+
async with action_scope.use() as interface:
|
|
865
|
+
interface.side_effects.transactions.append(
|
|
866
|
+
TransactionRecord(
|
|
867
|
+
confirmed_at_height=uint32(0),
|
|
868
|
+
created_at_time=uint64(int(time.time())),
|
|
869
|
+
to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
|
|
870
|
+
amount=uint64(coin.amount),
|
|
871
|
+
fee_amount=uint64(0),
|
|
872
|
+
confirmed=False,
|
|
873
|
+
sent=uint32(0),
|
|
874
|
+
spend_bundle=spend_bundle,
|
|
875
|
+
additions=spend_bundle.additions(),
|
|
876
|
+
removals=spend_bundle.removals(),
|
|
877
|
+
wallet_id=self.wallet_info.id,
|
|
878
|
+
sent_to=[],
|
|
879
|
+
trade_id=None,
|
|
880
|
+
type=uint32(TransactionType.OUTGOING_TX.value),
|
|
881
|
+
name=bytes32.secret(),
|
|
882
|
+
memos=list(compute_memos(spend_bundle).items()),
|
|
883
|
+
valid_times=ConditionValidTimes(),
|
|
884
|
+
)
|
|
885
|
+
)
|
|
886
|
+
|
|
887
|
+
# Pushes a spend bundle to create a message coin on the blockchain
|
|
888
|
+
# Returns a spend bundle for the recoverer to spend the message coin
|
|
889
|
+
async def create_attestment(
|
|
890
|
+
self,
|
|
891
|
+
recovering_coin_name: bytes32,
|
|
892
|
+
newpuz: bytes32,
|
|
893
|
+
pubkey: G1Element,
|
|
894
|
+
action_scope: WalletActionScope,
|
|
895
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
896
|
+
) -> tuple[WalletSpendBundle, str]:
|
|
897
|
+
"""
|
|
898
|
+
Create an attestment
|
|
899
|
+
TODO:
|
|
900
|
+
1. We should use/respect `action_scope.config.tx_config` (reuse_puzhash and co)
|
|
901
|
+
2. We should take a fee as it's a requirement for every transaction function to do so
|
|
902
|
+
:param recovering_coin_name: Coin ID of the DID
|
|
903
|
+
:param newpuz: New puzzle hash
|
|
904
|
+
:param pubkey: New wallet pubkey
|
|
905
|
+
:return: (Spend bundle, attest string)
|
|
906
|
+
"""
|
|
907
|
+
assert self.did_info.current_inner is not None
|
|
908
|
+
assert self.did_info.origin_coin is not None
|
|
909
|
+
coin = await self.get_coin()
|
|
910
|
+
message = did_wallet_puzzles.create_recovery_message_puzzle(recovering_coin_name, newpuz, pubkey)
|
|
911
|
+
innermessage = message.get_tree_hash()
|
|
912
|
+
innerpuz: Program = self.did_info.current_inner
|
|
913
|
+
uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
|
|
914
|
+
assert uncurried is not None
|
|
915
|
+
p2_puzzle = uncurried[0]
|
|
916
|
+
# innerpuz solution is (mode, p2_solution)
|
|
917
|
+
p2_solution = self.standard_wallet.make_solution(
|
|
918
|
+
primaries=[
|
|
919
|
+
Payment(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()]),
|
|
920
|
+
Payment(innermessage, uint64(0)),
|
|
921
|
+
],
|
|
922
|
+
conditions=extra_conditions,
|
|
923
|
+
)
|
|
924
|
+
innersol = Program.to([1, p2_solution])
|
|
925
|
+
|
|
926
|
+
# full solution is (corehash parent_info my_amount innerpuz_reveal solution)
|
|
927
|
+
full_puzzle: Program = create_singleton_puzzle(
|
|
928
|
+
innerpuz,
|
|
929
|
+
self.did_info.origin_coin.name(),
|
|
930
|
+
)
|
|
931
|
+
parent_info = self.get_parent_for_coin(coin)
|
|
932
|
+
assert parent_info is not None
|
|
933
|
+
|
|
934
|
+
fullsol = Program.to(
|
|
935
|
+
[
|
|
936
|
+
[
|
|
937
|
+
parent_info.parent_name,
|
|
938
|
+
parent_info.inner_puzzle_hash,
|
|
939
|
+
parent_info.amount,
|
|
940
|
+
],
|
|
941
|
+
coin.amount,
|
|
942
|
+
innersol,
|
|
943
|
+
]
|
|
944
|
+
)
|
|
945
|
+
list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
|
|
946
|
+
message_spend = did_wallet_puzzles.create_spend_for_message(coin.name(), recovering_coin_name, newpuz, pubkey)
|
|
947
|
+
message_spend_bundle = WalletSpendBundle([message_spend], AugSchemeMPL.aggregate([]))
|
|
948
|
+
spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
|
|
949
|
+
did_record = TransactionRecord(
|
|
950
|
+
confirmed_at_height=uint32(0),
|
|
951
|
+
created_at_time=uint64(int(time.time())),
|
|
952
|
+
to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
|
|
953
|
+
amount=uint64(coin.amount),
|
|
954
|
+
fee_amount=uint64(0),
|
|
955
|
+
confirmed=False,
|
|
956
|
+
sent=uint32(0),
|
|
957
|
+
spend_bundle=spend_bundle,
|
|
958
|
+
additions=spend_bundle.additions(),
|
|
959
|
+
removals=spend_bundle.removals(),
|
|
960
|
+
wallet_id=self.wallet_info.id,
|
|
961
|
+
sent_to=[],
|
|
962
|
+
trade_id=None,
|
|
963
|
+
type=uint32(TransactionType.INCOMING_TX.value),
|
|
964
|
+
name=bytes32.secret(),
|
|
965
|
+
memos=list(compute_memos(spend_bundle).items()),
|
|
966
|
+
valid_times=parse_timelock_info(extra_conditions),
|
|
967
|
+
)
|
|
968
|
+
async with action_scope.use() as interface:
|
|
969
|
+
interface.side_effects.transactions.append(did_record)
|
|
970
|
+
attest_str: str = f"{self.get_my_DID()}:{bytes(message_spend_bundle).hex()}:{coin.parent_coin_info.hex()}:"
|
|
971
|
+
attest_str += f"{self.did_info.current_inner.get_tree_hash().hex()}:{coin.amount}"
|
|
972
|
+
return message_spend_bundle, attest_str
|
|
973
|
+
|
|
974
|
+
async def get_info_for_recovery(self) -> Optional[tuple[bytes32, bytes32, uint64]]:
|
|
975
|
+
assert self.did_info.current_inner is not None
|
|
976
|
+
assert self.did_info.origin_coin is not None
|
|
977
|
+
try:
|
|
978
|
+
coin = await self.get_coin()
|
|
979
|
+
except RuntimeError:
|
|
980
|
+
return None
|
|
981
|
+
parent = coin.parent_coin_info
|
|
982
|
+
innerpuzhash = self.did_info.current_inner.get_tree_hash()
|
|
983
|
+
amount = uint64(coin.amount)
|
|
984
|
+
return (parent, innerpuzhash, amount)
|
|
985
|
+
|
|
986
|
+
async def load_attest_files_for_recovery_spend(self, attest_data: list[str]) -> tuple[list, WalletSpendBundle]:
|
|
987
|
+
spend_bundle_list = []
|
|
988
|
+
info_dict = {}
|
|
989
|
+
for attest in attest_data:
|
|
990
|
+
info = attest.split(":")
|
|
991
|
+
info_dict[info[0]] = [
|
|
992
|
+
bytes.fromhex(info[2]),
|
|
993
|
+
bytes.fromhex(info[3]),
|
|
994
|
+
uint64(info[4]),
|
|
995
|
+
]
|
|
996
|
+
new_sb = WalletSpendBundle.from_bytes(bytes.fromhex(info[1]))
|
|
997
|
+
spend_bundle_list.append(new_sb)
|
|
998
|
+
# info_dict {0xidentity: "(0xparent_info 0xinnerpuz amount)"}
|
|
999
|
+
my_recovery_list: list[bytes32] = self.did_info.backup_ids
|
|
1000
|
+
|
|
1001
|
+
# convert info dict into recovery list - same order as wallet
|
|
1002
|
+
info_list = []
|
|
1003
|
+
for entry in my_recovery_list:
|
|
1004
|
+
if entry.hex() in info_dict:
|
|
1005
|
+
info_list.append(
|
|
1006
|
+
[
|
|
1007
|
+
info_dict[entry.hex()][0],
|
|
1008
|
+
info_dict[entry.hex()][1],
|
|
1009
|
+
info_dict[entry.hex()][2],
|
|
1010
|
+
]
|
|
1011
|
+
)
|
|
1012
|
+
else:
|
|
1013
|
+
info_list.append([])
|
|
1014
|
+
message_spend_bundle = WalletSpendBundle.aggregate(spend_bundle_list)
|
|
1015
|
+
return info_list, message_spend_bundle
|
|
1016
|
+
|
|
1017
|
+
async def recovery_spend(
|
|
1018
|
+
self,
|
|
1019
|
+
coin: Coin,
|
|
1020
|
+
puzhash: bytes32,
|
|
1021
|
+
parent_innerpuzhash_amounts_for_recovery_ids: list[tuple[bytes, bytes, int]],
|
|
1022
|
+
pubkey: G1Element,
|
|
1023
|
+
spend_bundle: WalletSpendBundle,
|
|
1024
|
+
action_scope: WalletActionScope,
|
|
1025
|
+
) -> None:
|
|
1026
|
+
assert self.did_info.origin_coin is not None
|
|
1027
|
+
|
|
1028
|
+
# innersol is mode new_amount_or_p2_solution new_inner_puzhash parent_innerpuzhash_amounts_for_recovery_ids pubkey recovery_list_reveal my_id) # noqa
|
|
1029
|
+
innersol: Program = Program.to(
|
|
1030
|
+
[
|
|
1031
|
+
0,
|
|
1032
|
+
coin.amount,
|
|
1033
|
+
puzhash,
|
|
1034
|
+
parent_innerpuzhash_amounts_for_recovery_ids,
|
|
1035
|
+
bytes(pubkey),
|
|
1036
|
+
self.did_info.backup_ids,
|
|
1037
|
+
coin.name(),
|
|
1038
|
+
]
|
|
1039
|
+
)
|
|
1040
|
+
# full solution is (parent_info my_amount solution)
|
|
1041
|
+
assert self.did_info.current_inner is not None
|
|
1042
|
+
innerpuz: Program = self.did_info.current_inner
|
|
1043
|
+
full_puzzle: Program = create_singleton_puzzle(
|
|
1044
|
+
innerpuz,
|
|
1045
|
+
self.did_info.origin_coin.name(),
|
|
1046
|
+
)
|
|
1047
|
+
parent_info = self.get_parent_for_coin(coin)
|
|
1048
|
+
assert parent_info is not None
|
|
1049
|
+
fullsol = Program.to(
|
|
1050
|
+
[
|
|
1051
|
+
[
|
|
1052
|
+
parent_info.parent_name,
|
|
1053
|
+
parent_info.inner_puzzle_hash,
|
|
1054
|
+
parent_info.amount,
|
|
1055
|
+
],
|
|
1056
|
+
coin.amount,
|
|
1057
|
+
innersol,
|
|
1058
|
+
]
|
|
1059
|
+
)
|
|
1060
|
+
list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
|
|
1061
|
+
|
|
1062
|
+
spend_bundle = spend_bundle.aggregate([spend_bundle, WalletSpendBundle(list_of_coinspends, G2Element())])
|
|
1063
|
+
|
|
1064
|
+
async with action_scope.use() as interface:
|
|
1065
|
+
interface.side_effects.transactions.append(
|
|
1066
|
+
TransactionRecord(
|
|
1067
|
+
confirmed_at_height=uint32(0),
|
|
1068
|
+
created_at_time=uint64(int(time.time())),
|
|
1069
|
+
to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
|
|
1070
|
+
amount=uint64(coin.amount),
|
|
1071
|
+
fee_amount=uint64(0),
|
|
1072
|
+
confirmed=False,
|
|
1073
|
+
sent=uint32(0),
|
|
1074
|
+
spend_bundle=spend_bundle,
|
|
1075
|
+
additions=spend_bundle.additions(),
|
|
1076
|
+
removals=spend_bundle.removals(),
|
|
1077
|
+
wallet_id=self.wallet_info.id,
|
|
1078
|
+
sent_to=[],
|
|
1079
|
+
trade_id=None,
|
|
1080
|
+
type=uint32(TransactionType.OUTGOING_TX.value),
|
|
1081
|
+
name=bytes32.secret(),
|
|
1082
|
+
memos=list(compute_memos(spend_bundle).items()),
|
|
1083
|
+
valid_times=ConditionValidTimes(),
|
|
1084
|
+
)
|
|
1085
|
+
)
|
|
1086
|
+
new_did_info = DIDInfo(
|
|
1087
|
+
origin_coin=self.did_info.origin_coin,
|
|
1088
|
+
backup_ids=self.did_info.backup_ids,
|
|
1089
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
1090
|
+
parent_info=self.did_info.parent_info,
|
|
1091
|
+
current_inner=self.did_info.current_inner,
|
|
1092
|
+
temp_coin=self.did_info.temp_coin,
|
|
1093
|
+
temp_puzhash=self.did_info.temp_puzhash,
|
|
1094
|
+
temp_pubkey=self.did_info.temp_pubkey,
|
|
1095
|
+
sent_recovery_transaction=True,
|
|
1096
|
+
metadata=self.did_info.metadata,
|
|
1097
|
+
)
|
|
1098
|
+
await self.save_info(new_did_info)
|
|
1099
|
+
|
|
1100
|
+
async def get_p2_inner_hash(self, new: bool) -> bytes32:
|
|
1101
|
+
return await self.standard_wallet.get_puzzle_hash(new=new)
|
|
1102
|
+
|
|
1103
|
+
async def get_p2_inner_puzzle(self, new: bool) -> Program:
|
|
1104
|
+
return await self.standard_wallet.get_puzzle(new=new)
|
|
1105
|
+
|
|
1106
|
+
async def get_did_innerpuz(self, new: bool, origin_id: Optional[bytes32] = None) -> Program:
|
|
1107
|
+
if self.did_info.origin_coin is not None:
|
|
1108
|
+
launcher_id = self.did_info.origin_coin.name()
|
|
1109
|
+
elif origin_id is not None:
|
|
1110
|
+
launcher_id = origin_id
|
|
1111
|
+
else:
|
|
1112
|
+
raise ValueError("must have origin coin")
|
|
1113
|
+
return did_wallet_puzzles.create_innerpuz(
|
|
1114
|
+
p2_puzzle_or_hash=await self.get_p2_inner_puzzle(new=new),
|
|
1115
|
+
recovery_list=self.did_info.backup_ids,
|
|
1116
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
1117
|
+
launcher_id=launcher_id,
|
|
1118
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
1119
|
+
)
|
|
1120
|
+
|
|
1121
|
+
async def get_did_inner_hash(self, new: bool) -> bytes32:
|
|
1122
|
+
innerpuz = await self.get_did_innerpuz(new=new)
|
|
1123
|
+
return innerpuz.get_tree_hash()
|
|
1124
|
+
|
|
1125
|
+
async def get_innerpuz_for_new_innerhash(self, pubkey: G1Element):
|
|
1126
|
+
"""
|
|
1127
|
+
Get the inner puzzle for a new owner
|
|
1128
|
+
:param pubkey: Pubkey
|
|
1129
|
+
:return: Inner puzzle
|
|
1130
|
+
"""
|
|
1131
|
+
# Note: the recovery list will be kept.
|
|
1132
|
+
# In a selling case, the seller should clean the recovery list then transfer to the new owner.
|
|
1133
|
+
assert self.did_info.origin_coin is not None
|
|
1134
|
+
return did_wallet_puzzles.create_innerpuz(
|
|
1135
|
+
p2_puzzle_or_hash=puzzle_for_pk(pubkey),
|
|
1136
|
+
recovery_list=self.did_info.backup_ids,
|
|
1137
|
+
num_of_backup_ids_needed=uint64(self.did_info.num_of_backup_ids_needed),
|
|
1138
|
+
launcher_id=self.did_info.origin_coin.name(),
|
|
1139
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
1140
|
+
)
|
|
1141
|
+
|
|
1142
|
+
async def inner_puzzle_for_did_puzzle(self, did_hash: bytes32) -> Program:
|
|
1143
|
+
record: DerivationRecord = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
|
|
1144
|
+
did_hash
|
|
1145
|
+
)
|
|
1146
|
+
assert self.did_info.origin_coin is not None
|
|
1147
|
+
assert self.did_info.current_inner is not None
|
|
1148
|
+
uncurried_args = uncurry_innerpuz(self.did_info.current_inner)
|
|
1149
|
+
assert uncurried_args is not None
|
|
1150
|
+
old_recovery_list_hash: Optional[Program] = None
|
|
1151
|
+
p2_puzzle, old_recovery_list_hash, _, _, _ = uncurried_args
|
|
1152
|
+
if record is None:
|
|
1153
|
+
record = await self.wallet_state_manager.puzzle_store.get_derivation_record_for_puzzle_hash(
|
|
1154
|
+
p2_puzzle.get_tree_hash()
|
|
1155
|
+
)
|
|
1156
|
+
if not (self.did_info.num_of_backup_ids_needed > 0 and len(self.did_info.backup_ids) == 0):
|
|
1157
|
+
# We have the recovery list, don't reset it
|
|
1158
|
+
old_recovery_list_hash = None
|
|
1159
|
+
|
|
1160
|
+
inner_puzzle: Program = did_wallet_puzzles.create_innerpuz(
|
|
1161
|
+
p2_puzzle_or_hash=puzzle_for_pk(record.pubkey),
|
|
1162
|
+
recovery_list=self.did_info.backup_ids,
|
|
1163
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
1164
|
+
launcher_id=self.did_info.origin_coin.name(),
|
|
1165
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
1166
|
+
recovery_list_hash=old_recovery_list_hash,
|
|
1167
|
+
)
|
|
1168
|
+
return inner_puzzle
|
|
1169
|
+
|
|
1170
|
+
def get_parent_for_coin(self, coin) -> Optional[LineageProof]:
|
|
1171
|
+
parent_info = None
|
|
1172
|
+
for name, ccparent in self.did_info.parent_info:
|
|
1173
|
+
if name == coin.parent_coin_info:
|
|
1174
|
+
parent_info = ccparent
|
|
1175
|
+
|
|
1176
|
+
return parent_info
|
|
1177
|
+
|
|
1178
|
+
async def sign_message(self, message: str, mode: SigningMode) -> tuple[G1Element, G2Element]:
|
|
1179
|
+
if self.did_info.current_inner is None:
|
|
1180
|
+
raise ValueError("Missing DID inner puzzle.")
|
|
1181
|
+
puzzle_args = did_wallet_puzzles.uncurry_innerpuz(self.did_info.current_inner)
|
|
1182
|
+
if puzzle_args is not None:
|
|
1183
|
+
p2_puzzle, _, _, _, _ = puzzle_args
|
|
1184
|
+
puzzle_hash = p2_puzzle.get_tree_hash()
|
|
1185
|
+
private = await self.wallet_state_manager.get_private_key(puzzle_hash)
|
|
1186
|
+
synthetic_secret_key = calculate_synthetic_secret_key(private, DEFAULT_HIDDEN_PUZZLE_HASH)
|
|
1187
|
+
synthetic_pk = synthetic_secret_key.get_g1()
|
|
1188
|
+
if mode == SigningMode.CHIP_0002_HEX_INPUT:
|
|
1189
|
+
hex_message: bytes = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, bytes.fromhex(message))).get_tree_hash()
|
|
1190
|
+
elif mode == SigningMode.BLS_MESSAGE_AUGMENTATION_UTF8_INPUT:
|
|
1191
|
+
hex_message = bytes(message, "utf-8")
|
|
1192
|
+
elif mode == SigningMode.BLS_MESSAGE_AUGMENTATION_HEX_INPUT:
|
|
1193
|
+
hex_message = bytes.fromhex(message)
|
|
1194
|
+
else:
|
|
1195
|
+
hex_message = Program.to((CHIP_0002_SIGN_MESSAGE_PREFIX, message)).get_tree_hash()
|
|
1196
|
+
return synthetic_pk, AugSchemeMPL.sign(synthetic_secret_key, hex_message)
|
|
1197
|
+
else:
|
|
1198
|
+
raise ValueError("Invalid inner DID puzzle.")
|
|
1199
|
+
|
|
1200
|
+
async def generate_new_decentralised_id(
|
|
1201
|
+
self,
|
|
1202
|
+
amount: uint64,
|
|
1203
|
+
action_scope: WalletActionScope,
|
|
1204
|
+
fee: uint64 = uint64(0),
|
|
1205
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
1206
|
+
) -> None:
|
|
1207
|
+
"""
|
|
1208
|
+
This must be called under the wallet state manager lock
|
|
1209
|
+
"""
|
|
1210
|
+
|
|
1211
|
+
coins = await self.standard_wallet.select_coins(uint64(amount + fee), action_scope)
|
|
1212
|
+
|
|
1213
|
+
origin = coins.copy().pop()
|
|
1214
|
+
genesis_launcher_puz = SINGLETON_LAUNCHER_PUZZLE
|
|
1215
|
+
launcher_coin = Coin(origin.name(), genesis_launcher_puz.get_tree_hash(), amount)
|
|
1216
|
+
|
|
1217
|
+
did_inner: Program = await self.get_did_innerpuz(
|
|
1218
|
+
new=not action_scope.config.tx_config.reuse_puzhash, origin_id=launcher_coin.name()
|
|
1219
|
+
)
|
|
1220
|
+
did_inner_hash = did_inner.get_tree_hash()
|
|
1221
|
+
did_full_puz = create_singleton_puzzle(did_inner, launcher_coin.name())
|
|
1222
|
+
did_puzzle_hash = did_full_puz.get_tree_hash()
|
|
1223
|
+
|
|
1224
|
+
announcement_message = Program.to([did_puzzle_hash, amount, bytes(0x80)]).get_tree_hash()
|
|
1225
|
+
|
|
1226
|
+
await self.standard_wallet.generate_signed_transaction(
|
|
1227
|
+
amount=amount,
|
|
1228
|
+
puzzle_hash=genesis_launcher_puz.get_tree_hash(),
|
|
1229
|
+
action_scope=action_scope,
|
|
1230
|
+
fee=fee,
|
|
1231
|
+
coins=coins,
|
|
1232
|
+
primaries=None,
|
|
1233
|
+
origin_id=origin.name(),
|
|
1234
|
+
extra_conditions=(
|
|
1235
|
+
AssertCoinAnnouncement(asserted_id=launcher_coin.name(), asserted_msg=announcement_message),
|
|
1236
|
+
*extra_conditions,
|
|
1237
|
+
),
|
|
1238
|
+
)
|
|
1239
|
+
|
|
1240
|
+
genesis_launcher_solution = Program.to([did_puzzle_hash, amount, bytes(0x80)])
|
|
1241
|
+
|
|
1242
|
+
launcher_cs = make_spend(launcher_coin, genesis_launcher_puz, genesis_launcher_solution)
|
|
1243
|
+
launcher_sb = WalletSpendBundle([launcher_cs], AugSchemeMPL.aggregate([]))
|
|
1244
|
+
eve_coin = Coin(launcher_coin.name(), did_puzzle_hash, amount)
|
|
1245
|
+
future_parent = LineageProof(
|
|
1246
|
+
parent_name=eve_coin.parent_coin_info,
|
|
1247
|
+
inner_puzzle_hash=did_inner_hash,
|
|
1248
|
+
amount=uint64(eve_coin.amount),
|
|
1249
|
+
)
|
|
1250
|
+
eve_parent = LineageProof(
|
|
1251
|
+
parent_name=launcher_coin.parent_coin_info,
|
|
1252
|
+
inner_puzzle_hash=launcher_coin.puzzle_hash,
|
|
1253
|
+
amount=uint64(launcher_coin.amount),
|
|
1254
|
+
)
|
|
1255
|
+
await self.add_parent(eve_coin.parent_coin_info, eve_parent)
|
|
1256
|
+
await self.add_parent(eve_coin.name(), future_parent)
|
|
1257
|
+
|
|
1258
|
+
# Only want to save this information if the transaction is valid
|
|
1259
|
+
did_info = DIDInfo(
|
|
1260
|
+
origin_coin=launcher_coin,
|
|
1261
|
+
backup_ids=self.did_info.backup_ids,
|
|
1262
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
1263
|
+
parent_info=self.did_info.parent_info,
|
|
1264
|
+
current_inner=did_inner,
|
|
1265
|
+
temp_coin=None,
|
|
1266
|
+
temp_puzhash=None,
|
|
1267
|
+
temp_pubkey=None,
|
|
1268
|
+
sent_recovery_transaction=False,
|
|
1269
|
+
metadata=self.did_info.metadata,
|
|
1270
|
+
)
|
|
1271
|
+
await self.save_info(did_info)
|
|
1272
|
+
eve_spend = await self.generate_eve_spend(eve_coin, did_full_puz, did_inner)
|
|
1273
|
+
full_spend = WalletSpendBundle.aggregate([eve_spend, launcher_sb])
|
|
1274
|
+
assert self.did_info.origin_coin is not None
|
|
1275
|
+
assert self.did_info.current_inner is not None
|
|
1276
|
+
|
|
1277
|
+
did_record = TransactionRecord(
|
|
1278
|
+
confirmed_at_height=uint32(0),
|
|
1279
|
+
created_at_time=uint64(int(time.time())),
|
|
1280
|
+
amount=uint64(amount),
|
|
1281
|
+
to_puzzle_hash=await self.standard_wallet.get_puzzle_hash(False),
|
|
1282
|
+
fee_amount=fee,
|
|
1283
|
+
confirmed=False,
|
|
1284
|
+
sent=uint32(0),
|
|
1285
|
+
spend_bundle=full_spend,
|
|
1286
|
+
additions=full_spend.additions(),
|
|
1287
|
+
removals=full_spend.removals(),
|
|
1288
|
+
wallet_id=self.id(),
|
|
1289
|
+
sent_to=[],
|
|
1290
|
+
trade_id=None,
|
|
1291
|
+
type=uint32(TransactionType.INCOMING_TX.value),
|
|
1292
|
+
name=full_spend.name(),
|
|
1293
|
+
memos=[],
|
|
1294
|
+
valid_times=ConditionValidTimes(),
|
|
1295
|
+
)
|
|
1296
|
+
async with action_scope.use() as interface:
|
|
1297
|
+
interface.side_effects.transactions.append(did_record)
|
|
1298
|
+
|
|
1299
|
+
async def generate_eve_spend(
|
|
1300
|
+
self,
|
|
1301
|
+
coin: Coin,
|
|
1302
|
+
full_puzzle: Program,
|
|
1303
|
+
innerpuz: Program,
|
|
1304
|
+
extra_conditions: tuple[Condition, ...] = tuple(),
|
|
1305
|
+
):
|
|
1306
|
+
assert self.did_info.origin_coin is not None
|
|
1307
|
+
uncurried = did_wallet_puzzles.uncurry_innerpuz(innerpuz)
|
|
1308
|
+
assert uncurried is not None
|
|
1309
|
+
p2_puzzle = uncurried[0]
|
|
1310
|
+
# innerpuz solution is (mode p2_solution)
|
|
1311
|
+
p2_solution = self.standard_wallet.make_solution(
|
|
1312
|
+
primaries=[Payment(innerpuz.get_tree_hash(), uint64(coin.amount), [p2_puzzle.get_tree_hash()])],
|
|
1313
|
+
conditions=extra_conditions,
|
|
1314
|
+
)
|
|
1315
|
+
innersol = Program.to([1, p2_solution])
|
|
1316
|
+
# full solution is (lineage_proof my_amount inner_solution)
|
|
1317
|
+
fullsol = Program.to(
|
|
1318
|
+
[
|
|
1319
|
+
[self.did_info.origin_coin.parent_coin_info, self.did_info.origin_coin.amount],
|
|
1320
|
+
coin.amount,
|
|
1321
|
+
innersol,
|
|
1322
|
+
]
|
|
1323
|
+
)
|
|
1324
|
+
list_of_coinspends = [make_spend(coin, full_puzzle, fullsol)]
|
|
1325
|
+
unsigned_spend_bundle = WalletSpendBundle(list_of_coinspends, G2Element())
|
|
1326
|
+
return unsigned_spend_bundle
|
|
1327
|
+
|
|
1328
|
+
async def get_spendable_balance(self, unspent_records=None) -> uint128:
|
|
1329
|
+
spendable_am = await self.wallet_state_manager.get_confirmed_spendable_balance_for_wallet(
|
|
1330
|
+
self.wallet_info.id, unspent_records
|
|
1331
|
+
)
|
|
1332
|
+
return spendable_am
|
|
1333
|
+
|
|
1334
|
+
async def get_max_send_amount(self, records: Optional[set[WalletCoinRecord]] = None):
|
|
1335
|
+
spendable: list[WalletCoinRecord] = list(
|
|
1336
|
+
await self.wallet_state_manager.get_spendable_coins_for_wallet(self.id(), records)
|
|
1337
|
+
)
|
|
1338
|
+
max_send_amount = sum(cr.coin.amount for cr in spendable)
|
|
1339
|
+
return max_send_amount
|
|
1340
|
+
|
|
1341
|
+
async def add_parent(self, name: bytes32, parent: Optional[LineageProof]):
|
|
1342
|
+
self.log.info(f"Adding parent {name}: {parent}")
|
|
1343
|
+
current_list = self.did_info.parent_info.copy()
|
|
1344
|
+
current_list.append((name, parent))
|
|
1345
|
+
did_info = DIDInfo(
|
|
1346
|
+
origin_coin=self.did_info.origin_coin,
|
|
1347
|
+
backup_ids=self.did_info.backup_ids,
|
|
1348
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
1349
|
+
parent_info=current_list,
|
|
1350
|
+
current_inner=self.did_info.current_inner,
|
|
1351
|
+
temp_coin=self.did_info.temp_coin,
|
|
1352
|
+
temp_puzhash=self.did_info.temp_puzhash,
|
|
1353
|
+
temp_pubkey=self.did_info.temp_pubkey,
|
|
1354
|
+
sent_recovery_transaction=self.did_info.sent_recovery_transaction,
|
|
1355
|
+
metadata=self.did_info.metadata,
|
|
1356
|
+
)
|
|
1357
|
+
await self.save_info(did_info)
|
|
1358
|
+
|
|
1359
|
+
async def update_recovery_list(self, recover_list: list[bytes32], num_of_backup_ids_needed: uint64) -> bool:
|
|
1360
|
+
if num_of_backup_ids_needed > len(recover_list):
|
|
1361
|
+
return False
|
|
1362
|
+
did_info = DIDInfo(
|
|
1363
|
+
origin_coin=self.did_info.origin_coin,
|
|
1364
|
+
backup_ids=recover_list,
|
|
1365
|
+
num_of_backup_ids_needed=num_of_backup_ids_needed,
|
|
1366
|
+
parent_info=self.did_info.parent_info,
|
|
1367
|
+
current_inner=self.did_info.current_inner,
|
|
1368
|
+
temp_coin=self.did_info.temp_coin,
|
|
1369
|
+
temp_puzhash=self.did_info.temp_puzhash,
|
|
1370
|
+
temp_pubkey=self.did_info.temp_pubkey,
|
|
1371
|
+
sent_recovery_transaction=self.did_info.sent_recovery_transaction,
|
|
1372
|
+
metadata=self.did_info.metadata,
|
|
1373
|
+
)
|
|
1374
|
+
await self.save_info(did_info)
|
|
1375
|
+
await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
|
|
1376
|
+
return True
|
|
1377
|
+
|
|
1378
|
+
async def update_metadata(self, metadata: dict[str, str]) -> bool:
|
|
1379
|
+
# validate metadata
|
|
1380
|
+
if not all(isinstance(k, str) and isinstance(v, str) for k, v in metadata.items()):
|
|
1381
|
+
raise ValueError("Metadata key value pairs must be strings.")
|
|
1382
|
+
did_info = DIDInfo(
|
|
1383
|
+
origin_coin=self.did_info.origin_coin,
|
|
1384
|
+
backup_ids=self.did_info.backup_ids,
|
|
1385
|
+
num_of_backup_ids_needed=self.did_info.num_of_backup_ids_needed,
|
|
1386
|
+
parent_info=self.did_info.parent_info,
|
|
1387
|
+
current_inner=self.did_info.current_inner,
|
|
1388
|
+
temp_coin=self.did_info.temp_coin,
|
|
1389
|
+
temp_puzhash=self.did_info.temp_puzhash,
|
|
1390
|
+
temp_pubkey=self.did_info.temp_pubkey,
|
|
1391
|
+
sent_recovery_transaction=self.did_info.sent_recovery_transaction,
|
|
1392
|
+
metadata=json.dumps(metadata),
|
|
1393
|
+
)
|
|
1394
|
+
await self.save_info(did_info)
|
|
1395
|
+
await self.wallet_state_manager.update_wallet_puzzle_hashes(self.wallet_info.id)
|
|
1396
|
+
return True
|
|
1397
|
+
|
|
1398
|
+
async def save_info(self, did_info: DIDInfo):
|
|
1399
|
+
self.did_info = did_info
|
|
1400
|
+
current_info = self.wallet_info
|
|
1401
|
+
data_str = json.dumps(did_info.to_json_dict())
|
|
1402
|
+
wallet_info = WalletInfo(current_info.id, current_info.name, current_info.type, data_str)
|
|
1403
|
+
self.wallet_info = wallet_info
|
|
1404
|
+
await self.wallet_state_manager.user_store.update_wallet(wallet_info)
|
|
1405
|
+
|
|
1406
|
+
def generate_wallet_name(self) -> str:
|
|
1407
|
+
"""
|
|
1408
|
+
Generate a new DID wallet name
|
|
1409
|
+
:return: wallet name
|
|
1410
|
+
"""
|
|
1411
|
+
max_num = 0
|
|
1412
|
+
for wallet in self.wallet_state_manager.wallets.values():
|
|
1413
|
+
if wallet.type() == WalletType.DECENTRALIZED_ID:
|
|
1414
|
+
matched = re.search(r"^Profile (\d+)$", wallet.get_name())
|
|
1415
|
+
if matched and int(matched.group(1)) > max_num:
|
|
1416
|
+
max_num = int(matched.group(1))
|
|
1417
|
+
return f"Profile {max_num + 1}"
|
|
1418
|
+
|
|
1419
|
+
def check_existed_did(self):
|
|
1420
|
+
"""
|
|
1421
|
+
Check if the current DID is existed
|
|
1422
|
+
:return: None
|
|
1423
|
+
"""
|
|
1424
|
+
for wallet in self.wallet_state_manager.wallets.values():
|
|
1425
|
+
if (
|
|
1426
|
+
wallet.type() == WalletType.DECENTRALIZED_ID
|
|
1427
|
+
and self.did_info.origin_coin.name() == wallet.did_info.origin_coin.name()
|
|
1428
|
+
):
|
|
1429
|
+
self.log.warning(f"DID {self.did_info.origin_coin} already existed, ignore the wallet creation.")
|
|
1430
|
+
raise ValueError("Wallet already exists")
|
|
1431
|
+
|
|
1432
|
+
@staticmethod
|
|
1433
|
+
def deserialize_backup_data(backup_data: str) -> DIDInfo:
|
|
1434
|
+
"""
|
|
1435
|
+
Get a DIDInfo from a serialized string
|
|
1436
|
+
:param backup_data: serialized
|
|
1437
|
+
:return: DIDInfo
|
|
1438
|
+
"""
|
|
1439
|
+
details = backup_data.split(":")
|
|
1440
|
+
origin = Coin(bytes32.fromhex(details[0]), bytes32.fromhex(details[1]), uint64(int(details[2])))
|
|
1441
|
+
backup_ids = []
|
|
1442
|
+
if len(details[3]) > 0:
|
|
1443
|
+
for d in details[3].split(","):
|
|
1444
|
+
backup_ids.append(bytes32.from_hexstr(d))
|
|
1445
|
+
num_of_backup_ids_needed = uint64(int(details[5]))
|
|
1446
|
+
if num_of_backup_ids_needed > len(backup_ids):
|
|
1447
|
+
raise Exception
|
|
1448
|
+
innerpuz: Program = Program.from_bytes(bytes.fromhex(details[4]))
|
|
1449
|
+
metadata: str = ""
|
|
1450
|
+
for d in details[6:]:
|
|
1451
|
+
metadata = metadata + d + ":"
|
|
1452
|
+
if len(metadata) > 0:
|
|
1453
|
+
metadata = metadata[:-1]
|
|
1454
|
+
did_info = DIDInfo(
|
|
1455
|
+
origin_coin=origin,
|
|
1456
|
+
backup_ids=backup_ids,
|
|
1457
|
+
num_of_backup_ids_needed=num_of_backup_ids_needed,
|
|
1458
|
+
parent_info=[],
|
|
1459
|
+
current_inner=innerpuz,
|
|
1460
|
+
temp_coin=None,
|
|
1461
|
+
temp_puzhash=None,
|
|
1462
|
+
temp_pubkey=None,
|
|
1463
|
+
sent_recovery_transaction=True,
|
|
1464
|
+
metadata=metadata,
|
|
1465
|
+
)
|
|
1466
|
+
return did_info
|
|
1467
|
+
|
|
1468
|
+
def require_derivation_paths(self) -> bool:
|
|
1469
|
+
return True
|
|
1470
|
+
|
|
1471
|
+
async def get_coin(self) -> Coin:
|
|
1472
|
+
spendable_coins: set[WalletCoinRecord] = await self.wallet_state_manager.get_spendable_coins_for_wallet(
|
|
1473
|
+
self.wallet_info.id
|
|
1474
|
+
)
|
|
1475
|
+
if len(spendable_coins) == 0:
|
|
1476
|
+
raise RuntimeError("DID is not currently spendable")
|
|
1477
|
+
return sorted(list(spendable_coins), key=lambda c: c.confirmed_block_height, reverse=True)[0].coin
|
|
1478
|
+
|
|
1479
|
+
async def match_hinted_coin(self, coin: Coin, hint: bytes32) -> bool:
|
|
1480
|
+
if self.did_info.origin_coin is None:
|
|
1481
|
+
return False # pragma: no cover
|
|
1482
|
+
return (
|
|
1483
|
+
create_singleton_puzzle(
|
|
1484
|
+
did_wallet_puzzles.create_innerpuz(
|
|
1485
|
+
p2_puzzle_or_hash=hint,
|
|
1486
|
+
recovery_list=self.did_info.backup_ids,
|
|
1487
|
+
num_of_backup_ids_needed=uint64(self.did_info.num_of_backup_ids_needed),
|
|
1488
|
+
launcher_id=self.did_info.origin_coin.name(),
|
|
1489
|
+
metadata=did_wallet_puzzles.metadata_to_program(json.loads(self.did_info.metadata)),
|
|
1490
|
+
),
|
|
1491
|
+
self.did_info.origin_coin.name(),
|
|
1492
|
+
).get_tree_hash_precalc(hint)
|
|
1493
|
+
== coin.puzzle_hash
|
|
1494
|
+
)
|