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,593 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
import signal
|
|
6
|
+
import sys
|
|
7
|
+
import traceback
|
|
8
|
+
from collections.abc import AsyncIterator, Awaitable
|
|
9
|
+
from contextlib import asynccontextmanager
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from ipaddress import IPv4Address, IPv6Address, ip_address
|
|
12
|
+
from multiprocessing import freeze_support
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from types import FrameType
|
|
15
|
+
from typing import Any, Callable, Optional
|
|
16
|
+
|
|
17
|
+
import aiosqlite
|
|
18
|
+
import dns.asyncresolver
|
|
19
|
+
from dnslib import AAAA, EDNS0, NS, QTYPE, RCODE, RD, RR, SOA, A, DNSError, DNSHeader, DNSQuestion, DNSRecord
|
|
20
|
+
|
|
21
|
+
from chia.seeder.crawl_store import CrawlStore
|
|
22
|
+
from chia.server.signal_handlers import SignalHandlers
|
|
23
|
+
from chia.util.chia_logging import initialize_service_logging
|
|
24
|
+
from chia.util.config import load_config, load_config_cli
|
|
25
|
+
from chia.util.default_root import resolve_root_path
|
|
26
|
+
from chia.util.path import path_from_root
|
|
27
|
+
from chia.util.task_referencer import create_referenced_task
|
|
28
|
+
|
|
29
|
+
SERVICE_NAME = "seeder"
|
|
30
|
+
log = logging.getLogger(__name__)
|
|
31
|
+
DnsCallback = Callable[[DNSRecord], Awaitable[DNSRecord]]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# DNS snippet taken from: https://gist.github.com/pklaus/b5a7876d4d2cf7271873
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class DomainName(str):
|
|
38
|
+
def __getattr__(self, item: str) -> DomainName:
|
|
39
|
+
return DomainName(f"{item}.{self}") # DomainName.NS becomes DomainName("NS.DomainName")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class PeerList:
|
|
44
|
+
ipv4: list[IPv4Address]
|
|
45
|
+
ipv6: list[IPv6Address]
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def no_peers(self) -> bool:
|
|
49
|
+
return not self.ipv4 and not self.ipv6
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass
|
|
53
|
+
class UDPDNSServerProtocol(asyncio.DatagramProtocol):
|
|
54
|
+
"""
|
|
55
|
+
This is a really simple UDP Server, that converts all requests to DNSRecord objects and passes them to the callback.
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
callback: DnsCallback
|
|
59
|
+
transport: Optional[asyncio.DatagramTransport] = field(init=False, default=None)
|
|
60
|
+
data_queue: asyncio.Queue[tuple[DNSRecord, tuple[str, int]]] = field(default_factory=asyncio.Queue)
|
|
61
|
+
queue_task: Optional[asyncio.Task[None]] = field(init=False, default=None)
|
|
62
|
+
|
|
63
|
+
def start(self) -> None:
|
|
64
|
+
self.queue_task = create_referenced_task(self.respond()) # This starts the dns respond loop.
|
|
65
|
+
|
|
66
|
+
async def stop(self) -> None:
|
|
67
|
+
if self.queue_task is not None:
|
|
68
|
+
self.queue_task.cancel()
|
|
69
|
+
try:
|
|
70
|
+
await self.queue_task
|
|
71
|
+
except asyncio.CancelledError: # we dont care
|
|
72
|
+
pass
|
|
73
|
+
if self.transport is not None:
|
|
74
|
+
self.transport.close()
|
|
75
|
+
|
|
76
|
+
def connection_made(self, transport: asyncio.BaseTransport) -> None:
|
|
77
|
+
# we use the #ignore because transport is a subclass of BaseTransport, but we need the real type.
|
|
78
|
+
self.transport = transport # type: ignore[assignment]
|
|
79
|
+
|
|
80
|
+
def datagram_received(self, data: bytes, addr: tuple[str, int]) -> None:
|
|
81
|
+
log.debug(f"Received UDP DNS request from {addr}.")
|
|
82
|
+
dns_request: Optional[DNSRecord] = parse_dns_request(data)
|
|
83
|
+
if dns_request is None: # Invalid Request, we can just drop it and move on.
|
|
84
|
+
return
|
|
85
|
+
create_referenced_task(self.handler(dns_request, addr), known_unreferenced=True)
|
|
86
|
+
|
|
87
|
+
async def respond(self) -> None:
|
|
88
|
+
log.info("UDP DNS responder started.")
|
|
89
|
+
# TODO: switch to event driven code
|
|
90
|
+
while self.transport is None: # we wait for the transport to be set. # noqa: ASYNC110
|
|
91
|
+
await asyncio.sleep(0.1)
|
|
92
|
+
while not self.transport.is_closing():
|
|
93
|
+
try:
|
|
94
|
+
edns_max_size = 0
|
|
95
|
+
reply, caller = await self.data_queue.get()
|
|
96
|
+
if len(reply.ar) > 0 and reply.ar[0].rtype == QTYPE.OPT:
|
|
97
|
+
edns_max_size = reply.ar[0].edns_len
|
|
98
|
+
|
|
99
|
+
reply_packed = reply.pack()
|
|
100
|
+
|
|
101
|
+
if len(reply_packed) > max(512, edns_max_size): # 512 is the default max size for DNS:
|
|
102
|
+
log.debug(f"DNS response to {caller} is too large, truncating.")
|
|
103
|
+
reply_packed = reply.truncate().pack()
|
|
104
|
+
|
|
105
|
+
self.transport.sendto(reply_packed, caller)
|
|
106
|
+
log.debug(f"Sent UDP DNS response to {caller}, of size {len(reply_packed)}.")
|
|
107
|
+
except Exception as e:
|
|
108
|
+
log.error(f"Exception while responding to UDP DNS request: {e}. Traceback: {traceback.format_exc()}.")
|
|
109
|
+
log.info("UDP DNS responder stopped.")
|
|
110
|
+
|
|
111
|
+
async def handler(self, data: DNSRecord, caller: tuple[str, int]) -> None:
|
|
112
|
+
r_data = await get_dns_reply(self.callback, data) # process the request, returning a DNSRecord response.
|
|
113
|
+
await self.data_queue.put((r_data, caller))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@dataclass
|
|
117
|
+
class TCPDNSServerProtocol(asyncio.BufferedProtocol):
|
|
118
|
+
"""
|
|
119
|
+
This TCP server is a little more complicated, because we need to handle the length field, however it still
|
|
120
|
+
converts all requests to DNSRecord objects and passes them to the callback, after receiving the full message.
|
|
121
|
+
"""
|
|
122
|
+
|
|
123
|
+
callback: DnsCallback
|
|
124
|
+
transport: Optional[asyncio.Transport] = field(init=False, default=None)
|
|
125
|
+
peer_info: str = field(init=False, default="")
|
|
126
|
+
expected_length: int = 0
|
|
127
|
+
buffer: bytearray = field(init=False, default_factory=lambda: bytearray(2))
|
|
128
|
+
futures: list[asyncio.Future[None]] = field(init=False, default_factory=list)
|
|
129
|
+
|
|
130
|
+
def connection_made(self, transport: asyncio.BaseTransport) -> None:
|
|
131
|
+
"""
|
|
132
|
+
This is called whenever we get a new connection.
|
|
133
|
+
"""
|
|
134
|
+
# we use the #ignore because transport is a subclass of BaseTransport, but we need the real type.
|
|
135
|
+
self.transport = transport # type: ignore[assignment]
|
|
136
|
+
peer_info = transport.get_extra_info("peername")
|
|
137
|
+
self.peer_info = f"{peer_info[0]}:{peer_info[1]}"
|
|
138
|
+
log.debug(f"TCP connection established with {self.peer_info}.")
|
|
139
|
+
|
|
140
|
+
def connection_lost(self, exc: Optional[Exception]) -> None:
|
|
141
|
+
"""
|
|
142
|
+
This is called whenever a connection is lost, or closed.
|
|
143
|
+
"""
|
|
144
|
+
if exc is not None:
|
|
145
|
+
log.debug(f"TCP DNS connection lost with {self.peer_info}. Exception: {exc}.")
|
|
146
|
+
else:
|
|
147
|
+
log.debug(f"TCP DNS connection closed with {self.peer_info}.")
|
|
148
|
+
# reset the state of the protocol.
|
|
149
|
+
for future in self.futures:
|
|
150
|
+
future.cancel()
|
|
151
|
+
self.futures = []
|
|
152
|
+
self.buffer = bytearray(2)
|
|
153
|
+
self.expected_length = 0
|
|
154
|
+
|
|
155
|
+
def get_buffer(self, sizehint: int) -> memoryview:
|
|
156
|
+
"""
|
|
157
|
+
This is the first function called after connection_made, it returns a buffer that the tcp server will write to.
|
|
158
|
+
Once a buffer is written to, buffer_updated is called.
|
|
159
|
+
"""
|
|
160
|
+
return memoryview(self.buffer)
|
|
161
|
+
|
|
162
|
+
def buffer_updated(self, nbytes: int) -> None:
|
|
163
|
+
"""
|
|
164
|
+
This is called whenever the buffer is written to, and it loops through the buffer, grouping them into messages
|
|
165
|
+
and then dns records.
|
|
166
|
+
"""
|
|
167
|
+
while not len(self.buffer) == 0 and self.transport is not None:
|
|
168
|
+
if not self.expected_length:
|
|
169
|
+
# Length field received (This is the first part of the message)
|
|
170
|
+
self.expected_length = int.from_bytes(self.buffer, byteorder="big")
|
|
171
|
+
self.buffer = self.buffer[2:] # Remove the length field from the buffer.
|
|
172
|
+
|
|
173
|
+
if len(self.buffer) >= self.expected_length:
|
|
174
|
+
# This is the rest of the message (after the length field)
|
|
175
|
+
message = self.buffer[: self.expected_length]
|
|
176
|
+
self.buffer = self.buffer[self.expected_length :] # Remove the message from the buffer
|
|
177
|
+
self.expected_length = 0 # Reset the expected length
|
|
178
|
+
|
|
179
|
+
dns_request: Optional[DNSRecord] = parse_dns_request(message)
|
|
180
|
+
if dns_request is None: # Invalid Request, so we disconnect and don't send anything back.
|
|
181
|
+
self.transport.close()
|
|
182
|
+
return
|
|
183
|
+
self.futures.append(create_referenced_task(self.handle_and_respond(dns_request)))
|
|
184
|
+
|
|
185
|
+
self.buffer = bytearray(2 if self.expected_length == 0 else self.expected_length) # Reset the buffer if empty.
|
|
186
|
+
|
|
187
|
+
def eof_received(self) -> Optional[bool]:
|
|
188
|
+
"""
|
|
189
|
+
This is called when the client closes the connection, False or None means we close the connection.
|
|
190
|
+
True means we keep the connection open.
|
|
191
|
+
"""
|
|
192
|
+
if len(self.futures) > 0: # Successful requests
|
|
193
|
+
if self.expected_length != 0: # Incomplete requests
|
|
194
|
+
log.warning(
|
|
195
|
+
f"Received incomplete TCP DNS request of length {self.expected_length} from {self.peer_info}, "
|
|
196
|
+
f"closing connection after dns replies are sent."
|
|
197
|
+
)
|
|
198
|
+
create_referenced_task(self.wait_for_futures(), known_unreferenced=True)
|
|
199
|
+
return True # Keep connection open, until the futures are done.
|
|
200
|
+
log.info(f"Received early EOF from {self.peer_info}, closing connection.")
|
|
201
|
+
return False
|
|
202
|
+
|
|
203
|
+
async def wait_for_futures(self) -> None:
|
|
204
|
+
"""
|
|
205
|
+
Waits for all the futures to complete, and then closes the connection.
|
|
206
|
+
"""
|
|
207
|
+
try:
|
|
208
|
+
await asyncio.wait_for(asyncio.gather(*self.futures), timeout=10)
|
|
209
|
+
except asyncio.TimeoutError:
|
|
210
|
+
log.warning(f"Timed out waiting for DNS replies to be sent to {self.peer_info}.")
|
|
211
|
+
if self.transport is not None:
|
|
212
|
+
self.transport.close()
|
|
213
|
+
|
|
214
|
+
async def handle_and_respond(self, data: DNSRecord) -> None:
|
|
215
|
+
r_data = await get_dns_reply(self.callback, data) # process the request, returning a DNSRecord response.
|
|
216
|
+
try:
|
|
217
|
+
# If the client closed the connection, we don't want to send anything.
|
|
218
|
+
if self.transport is not None and not self.transport.is_closing():
|
|
219
|
+
self.transport.write(dns_response_to_tcp(r_data)) # send data back to the client
|
|
220
|
+
log.debug(f"Sent DNS response for {data.q.qname}, to {self.peer_info}.")
|
|
221
|
+
except Exception as e:
|
|
222
|
+
log.error(f"Exception while responding to TCP DNS request: {e}. Traceback: {traceback.format_exc()}.")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def dns_response_to_tcp(data: DNSRecord) -> bytes:
|
|
226
|
+
"""
|
|
227
|
+
Converts a DNSRecord response to a TCP DNS response, by adding a 2 byte length field to the start.
|
|
228
|
+
"""
|
|
229
|
+
dns_response = data.pack()
|
|
230
|
+
dns_response_length = len(dns_response).to_bytes(2, byteorder="big")
|
|
231
|
+
return bytes(dns_response_length + dns_response)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def create_dns_reply(dns_request: DNSRecord) -> DNSRecord:
|
|
235
|
+
"""
|
|
236
|
+
Creates a DNS response with the correct header and section flags set.
|
|
237
|
+
"""
|
|
238
|
+
# QR means query response, AA means authoritative answer, RA means recursion available
|
|
239
|
+
return DNSRecord(DNSHeader(id=dns_request.header.id, qr=1, aa=1, ra=0), q=dns_request.q)
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
def parse_dns_request(data: bytes) -> Optional[DNSRecord]:
|
|
243
|
+
"""
|
|
244
|
+
Parses the DNS request, and returns a DNSRecord object, or None if the request is invalid.
|
|
245
|
+
"""
|
|
246
|
+
dns_request: Optional[DNSRecord] = None
|
|
247
|
+
try:
|
|
248
|
+
dns_request = DNSRecord.parse(data)
|
|
249
|
+
except DNSError as e:
|
|
250
|
+
log.warning(f"Received invalid DNS request: {e}. Traceback: {traceback.format_exc()}.")
|
|
251
|
+
return dns_request
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
async def get_dns_reply(callback: DnsCallback, dns_request: DNSRecord) -> DNSRecord:
|
|
255
|
+
"""
|
|
256
|
+
This function calls the callback, and returns SERVFAIL if the callback raises an exception.
|
|
257
|
+
"""
|
|
258
|
+
try:
|
|
259
|
+
dns_reply = await callback(dns_request)
|
|
260
|
+
except Exception as e:
|
|
261
|
+
log.error(f"Exception during DNS record processing: {e}. Traceback: {traceback.format_exc()}.")
|
|
262
|
+
# we return an empty response with an error code
|
|
263
|
+
dns_reply = create_dns_reply(dns_request) # This is an empty response, with only the header set.
|
|
264
|
+
dns_reply.header.rcode = RCODE.SERVFAIL
|
|
265
|
+
return dns_reply
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
@dataclass
|
|
269
|
+
class DNSServer:
|
|
270
|
+
config: dict[str, Any]
|
|
271
|
+
root_path: Path
|
|
272
|
+
lock: asyncio.Lock = field(default_factory=asyncio.Lock)
|
|
273
|
+
shutdown_event: asyncio.Event = field(default_factory=asyncio.Event)
|
|
274
|
+
crawl_store: Optional[CrawlStore] = field(init=False, default=None)
|
|
275
|
+
reliable_task: Optional[asyncio.Task[None]] = field(init=False, default=None)
|
|
276
|
+
shutting_down: bool = field(init=False, default=False)
|
|
277
|
+
udp_transport_ipv4: Optional[asyncio.DatagramTransport] = field(init=False, default=None)
|
|
278
|
+
udp_protocol_ipv4: Optional[UDPDNSServerProtocol] = field(init=False, default=None)
|
|
279
|
+
udp_transport_ipv6: Optional[asyncio.DatagramTransport] = field(init=False, default=None)
|
|
280
|
+
udp_protocol_ipv6: Optional[UDPDNSServerProtocol] = field(init=False, default=None)
|
|
281
|
+
# TODO: After 3.10 is dropped change to asyncio.Server
|
|
282
|
+
tcp_server: Optional[asyncio.base_events.Server] = field(init=False, default=None)
|
|
283
|
+
# these are all set in __post_init__
|
|
284
|
+
tcp_dns_port: int = field(init=False)
|
|
285
|
+
udp_dns_port: int = field(init=False)
|
|
286
|
+
db_path: Path = field(init=False)
|
|
287
|
+
domain: DomainName = field(init=False)
|
|
288
|
+
ns1: DomainName = field(init=False)
|
|
289
|
+
ns_records: list[RR] = field(init=False)
|
|
290
|
+
ttl: int = field(init=False)
|
|
291
|
+
soa_record: RR = field(init=False)
|
|
292
|
+
reliable_peers_v4: list[IPv4Address] = field(default_factory=list)
|
|
293
|
+
reliable_peers_v6: list[IPv6Address] = field(default_factory=list)
|
|
294
|
+
static_peers_v4: list[IPv4Address] = field(default_factory=list)
|
|
295
|
+
static_peers_v6: list[IPv6Address] = field(default_factory=list)
|
|
296
|
+
resolver: Optional[dns.asyncresolver.Resolver] = field(init=False)
|
|
297
|
+
pointer_v4: int = 0
|
|
298
|
+
pointer_v6: int = 0
|
|
299
|
+
|
|
300
|
+
def __post_init__(self) -> None:
|
|
301
|
+
"""
|
|
302
|
+
We initialize all the variables set to field(init=False) here.
|
|
303
|
+
"""
|
|
304
|
+
# From Config:
|
|
305
|
+
# The dns ports should only really be different if testing.
|
|
306
|
+
self.tcp_dns_port: int = self.config.get("dns_port", 53)
|
|
307
|
+
self.udp_dns_port: int = self.config.get("dns_port", 53)
|
|
308
|
+
# DB Path:
|
|
309
|
+
crawler_db_path: str = self.config.get("crawler_db_path", "crawler.db")
|
|
310
|
+
self.db_path: Path = path_from_root(self.root_path, crawler_db_path)
|
|
311
|
+
self.db_path.parent.mkdir(parents=True, exist_ok=True)
|
|
312
|
+
# DNS info:
|
|
313
|
+
self.domain: DomainName = DomainName(self.config["domain_name"])
|
|
314
|
+
if not self.domain.endswith("."):
|
|
315
|
+
self.domain = DomainName(self.domain + ".") # Make sure the domain ends with a period, as per RFC 1035.
|
|
316
|
+
self.ns1: DomainName = DomainName(self.config["nameserver"])
|
|
317
|
+
self.ns_records: list[NS] = [NS(self.ns1)]
|
|
318
|
+
self.ttl: int = self.config["ttl"]
|
|
319
|
+
self.soa_record: SOA = SOA(
|
|
320
|
+
mname=self.ns1, # primary name server
|
|
321
|
+
rname=self.config["soa"]["rname"], # email of the domain administrator
|
|
322
|
+
times=(
|
|
323
|
+
self.config["soa"]["serial_number"],
|
|
324
|
+
self.config["soa"]["refresh"],
|
|
325
|
+
self.config["soa"]["retry"],
|
|
326
|
+
self.config["soa"]["expire"],
|
|
327
|
+
self.config["soa"]["minimum"],
|
|
328
|
+
),
|
|
329
|
+
)
|
|
330
|
+
try:
|
|
331
|
+
self.resolver: Optional[dns.asyncresolver.Resolver] = dns.asyncresolver.Resolver()
|
|
332
|
+
except Exception:
|
|
333
|
+
self.resolver = None
|
|
334
|
+
log.exception("Error initializing asyncresolver for dns_server")
|
|
335
|
+
|
|
336
|
+
@asynccontextmanager
|
|
337
|
+
async def run(self) -> AsyncIterator[None]:
|
|
338
|
+
log.warning("Starting DNS server.")
|
|
339
|
+
# Get a reference to the event loop as we plan to use low-level APIs.
|
|
340
|
+
loop = asyncio.get_running_loop()
|
|
341
|
+
|
|
342
|
+
# Set up the crawl store and the peer update task.
|
|
343
|
+
self.crawl_store = await CrawlStore.create(await aiosqlite.connect(self.db_path, timeout=120))
|
|
344
|
+
self.reliable_task = create_referenced_task(self.periodically_get_reliable_peers())
|
|
345
|
+
|
|
346
|
+
# One protocol instance will be created for each udp transport, so that we can accept ipv4 and ipv6
|
|
347
|
+
self.udp_transport_ipv6, self.udp_protocol_ipv6 = await loop.create_datagram_endpoint(
|
|
348
|
+
lambda: UDPDNSServerProtocol(self.dns_response), local_addr=("::0", self.udp_dns_port)
|
|
349
|
+
)
|
|
350
|
+
self.udp_protocol_ipv6.start() # start ipv6 udp transmit task
|
|
351
|
+
|
|
352
|
+
# in case the port is 0, we get the real port
|
|
353
|
+
self.udp_dns_port = self.udp_transport_ipv6.get_extra_info("sockname")[1] # get the port we bound to
|
|
354
|
+
|
|
355
|
+
if sys.platform.startswith("win32") or sys.platform.startswith("cygwin"):
|
|
356
|
+
# Windows does not support dual stack sockets, so we need to create a new socket for ipv4.
|
|
357
|
+
self.udp_transport_ipv4, self.udp_protocol_ipv4 = await loop.create_datagram_endpoint(
|
|
358
|
+
lambda: UDPDNSServerProtocol(self.dns_response), local_addr=("0.0.0.0", self.udp_dns_port)
|
|
359
|
+
)
|
|
360
|
+
self.udp_protocol_ipv4.start() # start ipv4 udp transmit task
|
|
361
|
+
|
|
362
|
+
# One tcp server will handle both ipv4 and ipv6 on both linux and windows.
|
|
363
|
+
self.tcp_server = await loop.create_server(
|
|
364
|
+
lambda: TCPDNSServerProtocol(self.dns_response), ["::0", "0.0.0.0"], self.tcp_dns_port
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
log.warning("DNS server started.")
|
|
368
|
+
try:
|
|
369
|
+
yield
|
|
370
|
+
finally: # catches any errors and properly shuts down the server
|
|
371
|
+
await self.stop()
|
|
372
|
+
log.warning("DNS server stopped.")
|
|
373
|
+
|
|
374
|
+
async def setup_process_global_state(self, signal_handlers: SignalHandlers) -> None:
|
|
375
|
+
signal_handlers.setup_async_signal_handler(handler=self._accept_signal)
|
|
376
|
+
|
|
377
|
+
async def _accept_signal(
|
|
378
|
+
self,
|
|
379
|
+
signal_: signal.Signals,
|
|
380
|
+
stack_frame: Optional[FrameType],
|
|
381
|
+
loop: asyncio.AbstractEventLoop,
|
|
382
|
+
) -> None: # pragma: no cover
|
|
383
|
+
log.info("Received signal %s (%s), shutting down.", signal_.name, signal_.value)
|
|
384
|
+
await self.stop()
|
|
385
|
+
|
|
386
|
+
async def stop(self) -> None:
|
|
387
|
+
log.warning("Stopping DNS server...")
|
|
388
|
+
if self.shutting_down:
|
|
389
|
+
return
|
|
390
|
+
self.shutting_down = True
|
|
391
|
+
if self.reliable_task is not None:
|
|
392
|
+
self.reliable_task.cancel() # cancel the peer update task
|
|
393
|
+
if self.crawl_store is not None:
|
|
394
|
+
await self.crawl_store.crawl_db.close()
|
|
395
|
+
if self.udp_protocol_ipv6 is not None:
|
|
396
|
+
await self.udp_protocol_ipv6.stop() # stop responding to and accepting udp requests (ipv6) & ipv4 if linux.
|
|
397
|
+
if self.udp_protocol_ipv4 is not None:
|
|
398
|
+
await self.udp_protocol_ipv4.stop() # stop responding to and accepting udp requests (ipv4) if windows.
|
|
399
|
+
if self.tcp_server is not None:
|
|
400
|
+
self.tcp_server.close() # stop accepting new tcp requests (ipv4 and ipv6)
|
|
401
|
+
await self.tcp_server.wait_closed() # wait for existing TCP requests to finish (ipv4 and ipv6)
|
|
402
|
+
self.shutdown_event.set()
|
|
403
|
+
|
|
404
|
+
async def periodically_get_reliable_peers(self) -> None:
|
|
405
|
+
sleep_interval = 0
|
|
406
|
+
while not self.shutdown_event.is_set() and self.crawl_store is not None:
|
|
407
|
+
await self.refresh_reliable_peers()
|
|
408
|
+
sleep_interval = min(15, sleep_interval + 1)
|
|
409
|
+
await asyncio.sleep(sleep_interval * 60)
|
|
410
|
+
|
|
411
|
+
async def refresh_reliable_peers(self) -> None:
|
|
412
|
+
if self.crawl_store is None:
|
|
413
|
+
return
|
|
414
|
+
new_reliable_peers: list[str] = []
|
|
415
|
+
while not self.shutdown_event.is_set():
|
|
416
|
+
try:
|
|
417
|
+
new_reliable_peers = await self.crawl_store.get_good_peers()
|
|
418
|
+
except Exception as e:
|
|
419
|
+
log.error(f"Error loading reliable peers from database: {e}. Traceback: {traceback.format_exc()}.")
|
|
420
|
+
await asyncio.sleep(2)
|
|
421
|
+
continue
|
|
422
|
+
|
|
423
|
+
static_peers = self.config.get("static_peers", [])
|
|
424
|
+
if len(static_peers) > 0:
|
|
425
|
+
log.warning("have static peers, resolving ip addresses")
|
|
426
|
+
for static_peer in static_peers:
|
|
427
|
+
try:
|
|
428
|
+
log.warning(f"Handling static peer {static_peer}")
|
|
429
|
+
# Attempt to parse as an IP address
|
|
430
|
+
# If this doesn't throw, we can just add to the list
|
|
431
|
+
# Otherwise, we have to resolve the hostname
|
|
432
|
+
ip_address(static_peer)
|
|
433
|
+
new_reliable_peers.append(static_peer)
|
|
434
|
+
except ValueError:
|
|
435
|
+
# Wasn't an IP address, so resolve the hostname
|
|
436
|
+
log.warning(f"Not an IP address, trying to resolve {static_peer} to an IP address")
|
|
437
|
+
if self.resolver is not None:
|
|
438
|
+
for rdtype in ["A", "AAAA"]:
|
|
439
|
+
result = await self.resolver.resolve(qname=static_peer, rdtype=rdtype, lifetime=30)
|
|
440
|
+
for ip in result:
|
|
441
|
+
try:
|
|
442
|
+
ip_as_string = ip.to_text()
|
|
443
|
+
ip_address(ip_as_string)
|
|
444
|
+
new_reliable_peers.append(ip_as_string)
|
|
445
|
+
except ValueError:
|
|
446
|
+
pass
|
|
447
|
+
|
|
448
|
+
if len(new_reliable_peers) > 0:
|
|
449
|
+
break
|
|
450
|
+
|
|
451
|
+
log.warning("No reliable peers found in database, waiting for db to be populated.")
|
|
452
|
+
await asyncio.sleep(2) # sleep for 2 seconds, because the db has not been populated yet.
|
|
453
|
+
|
|
454
|
+
async with self.lock:
|
|
455
|
+
self.reliable_peers_v4 = []
|
|
456
|
+
self.reliable_peers_v6 = []
|
|
457
|
+
self.pointer_v4 = 0
|
|
458
|
+
self.pointer_v6 = 0
|
|
459
|
+
for peer in new_reliable_peers:
|
|
460
|
+
try:
|
|
461
|
+
validated_peer = ip_address(peer)
|
|
462
|
+
if validated_peer.version == 4:
|
|
463
|
+
self.reliable_peers_v4.append(validated_peer)
|
|
464
|
+
elif validated_peer.version == 6:
|
|
465
|
+
self.reliable_peers_v6.append(validated_peer)
|
|
466
|
+
except ValueError:
|
|
467
|
+
log.error(f"Invalid peer: {peer}")
|
|
468
|
+
continue
|
|
469
|
+
log.warning(
|
|
470
|
+
f"Number of reliable peers discovered in dns server:"
|
|
471
|
+
f" IPv4 count - {len(self.reliable_peers_v4)}"
|
|
472
|
+
f" IPv6 count - {len(self.reliable_peers_v6)}"
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
async def get_peers_to_respond(self, ipv4_count: int, ipv6_count: int) -> PeerList:
|
|
476
|
+
async with self.lock:
|
|
477
|
+
# Append IPv4.
|
|
478
|
+
ipv4_peers: list[IPv4Address] = []
|
|
479
|
+
size = len(self.reliable_peers_v4)
|
|
480
|
+
if ipv4_count > 0 and size <= ipv4_count:
|
|
481
|
+
ipv4_peers = self.reliable_peers_v4
|
|
482
|
+
elif ipv4_count > 0:
|
|
483
|
+
ipv4_peers = [
|
|
484
|
+
self.reliable_peers_v4[i % size] for i in range(self.pointer_v4, self.pointer_v4 + ipv4_count)
|
|
485
|
+
]
|
|
486
|
+
self.pointer_v4 = (self.pointer_v4 + ipv4_count) % size # mark where we left off
|
|
487
|
+
# Append IPv6.
|
|
488
|
+
ipv6_peers: list[IPv6Address] = []
|
|
489
|
+
size = len(self.reliable_peers_v6)
|
|
490
|
+
if ipv6_count > 0 and size <= ipv6_count:
|
|
491
|
+
ipv6_peers = self.reliable_peers_v6
|
|
492
|
+
elif ipv6_count > 0:
|
|
493
|
+
ipv6_peers = [
|
|
494
|
+
self.reliable_peers_v6[i % size] for i in range(self.pointer_v6, self.pointer_v6 + ipv6_count)
|
|
495
|
+
]
|
|
496
|
+
self.pointer_v6 = (self.pointer_v6 + ipv6_count) % size # mark where we left off
|
|
497
|
+
return PeerList(ipv4_peers, ipv6_peers)
|
|
498
|
+
|
|
499
|
+
async def dns_response(self, request: DNSRecord) -> DNSRecord:
|
|
500
|
+
"""
|
|
501
|
+
This function is called when a DNS request is received, and it returns a DNS response.
|
|
502
|
+
It does not catch any errors as it is called from within a try-except block.
|
|
503
|
+
"""
|
|
504
|
+
reply = create_dns_reply(request)
|
|
505
|
+
dns_question: DNSQuestion = request.q # this is the question / request
|
|
506
|
+
question_type: int = dns_question.qtype # the type of the record being requested
|
|
507
|
+
qname = dns_question.qname # the name being queried / requested
|
|
508
|
+
# ADD EDNS0 to response if supported
|
|
509
|
+
if len(request.ar) > 0 and request.ar[0].rtype == QTYPE.OPT: # OPT Means EDNS
|
|
510
|
+
udp_len = min(4096, request.ar[0].edns_len)
|
|
511
|
+
edns_reply = EDNS0(udp_len=udp_len)
|
|
512
|
+
reply.add_ar(edns_reply)
|
|
513
|
+
# DNS labels are mixed case with DNS resolvers that implement the use of bit 0x20 to improve
|
|
514
|
+
# transaction identity. See https://datatracker.ietf.org/doc/html/draft-vixie-dnsext-dns0x20-00
|
|
515
|
+
qname_str = str(qname).lower()
|
|
516
|
+
if qname_str != self.domain and not qname_str.endswith(f".{self.domain}"):
|
|
517
|
+
# we don't answer for other domains (we have the not recursive bit set)
|
|
518
|
+
log.warning(f"Invalid request for {qname_str}, returning REFUSED.")
|
|
519
|
+
reply.header.rcode = RCODE.REFUSED
|
|
520
|
+
return reply
|
|
521
|
+
|
|
522
|
+
ttl: int = self.ttl
|
|
523
|
+
# we add these to the list as it will allow us to respond to ns and soa requests
|
|
524
|
+
ips: list[RD] = [self.soa_record, *self.ns_records]
|
|
525
|
+
ipv4_count = 0
|
|
526
|
+
ipv6_count = 0
|
|
527
|
+
if question_type is QTYPE.A:
|
|
528
|
+
ipv4_count = 32
|
|
529
|
+
elif question_type is QTYPE.AAAA:
|
|
530
|
+
ipv6_count = 32
|
|
531
|
+
elif question_type is QTYPE.ANY:
|
|
532
|
+
ipv4_count = 16
|
|
533
|
+
ipv6_count = 16
|
|
534
|
+
else:
|
|
535
|
+
ipv4_count = 32
|
|
536
|
+
peers: PeerList = await self.get_peers_to_respond(ipv4_count, ipv6_count)
|
|
537
|
+
if peers.no_peers:
|
|
538
|
+
log.error("No peers found, returning SOA and NS records only.")
|
|
539
|
+
ttl = 60 # 1 minute as we should have some peers very soon
|
|
540
|
+
# we always return the SOA and NS records, so we continue even if there are no peers
|
|
541
|
+
ips.extend([A(str(peer)) for peer in peers.ipv4])
|
|
542
|
+
ips.extend([AAAA(str(peer)) for peer in peers.ipv6])
|
|
543
|
+
|
|
544
|
+
records: dict[DomainName, list[RD]] = { # this is where we can add other records we want to serve
|
|
545
|
+
self.domain: ips,
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
valid_domain = False
|
|
549
|
+
for domain_name, domain_responses in records.items():
|
|
550
|
+
if domain_name == qname_str: # if the dns name is the same as the requested name
|
|
551
|
+
valid_domain = True
|
|
552
|
+
for response in domain_responses:
|
|
553
|
+
rqt: int = getattr(QTYPE, response.__class__.__name__)
|
|
554
|
+
if question_type in {rqt, QTYPE.ANY}:
|
|
555
|
+
reply.add_answer(RR(rname=qname, rtype=rqt, rclass=1, ttl=ttl, rdata=response))
|
|
556
|
+
if not valid_domain and len(reply.rr) == 0: # if we didn't find any records to return
|
|
557
|
+
reply.header.rcode = RCODE.NXDOMAIN
|
|
558
|
+
# always put nameservers and the SOA records
|
|
559
|
+
for nameserver in self.ns_records:
|
|
560
|
+
reply.add_auth(RR(rname=self.domain, rtype=QTYPE.NS, rclass=1, ttl=ttl, rdata=nameserver))
|
|
561
|
+
reply.add_auth(RR(rname=self.domain, rtype=QTYPE.SOA, rclass=1, ttl=ttl, rdata=self.soa_record))
|
|
562
|
+
return reply
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
async def run_dns_server(dns_server: DNSServer) -> None: # pragma: no cover
|
|
566
|
+
async with SignalHandlers.manage() as signal_handlers:
|
|
567
|
+
await dns_server.setup_process_global_state(signal_handlers=signal_handlers)
|
|
568
|
+
async with dns_server.run():
|
|
569
|
+
await dns_server.shutdown_event.wait() # this is released on SIGINT or SIGTERM or any unhandled exception
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
def create_dns_server_service(config: dict[str, Any], root_path: Path) -> DNSServer:
|
|
573
|
+
service_config = config[SERVICE_NAME]
|
|
574
|
+
|
|
575
|
+
return DNSServer(service_config, root_path)
|
|
576
|
+
|
|
577
|
+
|
|
578
|
+
def main() -> None: # pragma: no cover
|
|
579
|
+
freeze_support()
|
|
580
|
+
root_path = resolve_root_path(override=None)
|
|
581
|
+
|
|
582
|
+
# TODO: refactor to avoid the double load
|
|
583
|
+
config = load_config(root_path, "config.yaml")
|
|
584
|
+
service_config = load_config_cli(root_path, "config.yaml", SERVICE_NAME)
|
|
585
|
+
config[SERVICE_NAME] = service_config
|
|
586
|
+
initialize_service_logging(service_name=SERVICE_NAME, config=config, root_path=root_path)
|
|
587
|
+
|
|
588
|
+
dns_server = create_dns_server_service(config, root_path)
|
|
589
|
+
asyncio.run(run_dns_server(dns_server))
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
if __name__ == "__main__":
|
|
593
|
+
main()
|