flwr-nightly 1.23.0.dev20250930__py3-none-any.whl → 1.26.0.dev20260121__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.
- flwr/__init__.py +17 -6
- flwr/app/__init__.py +4 -1
- flwr/app/error.py +2 -2
- flwr/app/exception.py +3 -3
- flwr/app/message_type.py +29 -0
- flwr/app/metadata.py +5 -2
- flwr/app/user_config.py +19 -0
- flwr/cli/app.py +62 -9
- flwr/cli/{new/templates/app/code → app_cmd}/__init__.py +9 -1
- flwr/cli/app_cmd/publish.py +285 -0
- flwr/cli/app_cmd/review.py +262 -0
- flwr/cli/auth_plugin/__init__.py +13 -6
- flwr/cli/auth_plugin/auth_plugin.py +26 -15
- flwr/cli/auth_plugin/noop_auth_plugin.py +101 -0
- flwr/cli/auth_plugin/oidc_cli_plugin.py +52 -32
- flwr/cli/build.py +166 -53
- flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +27 -10
- flwr/cli/config/__init__.py +21 -0
- flwr/cli/config/ls.py +104 -0
- flwr/cli/config_migration.py +300 -0
- flwr/cli/config_utils.py +154 -13
- flwr/cli/constant.py +67 -0
- flwr/cli/{new/templates/app/code/flwr_tune → federation}/__init__.py +8 -1
- flwr/cli/federation/ls.py +361 -0
- flwr/cli/flower_config.py +447 -0
- flwr/cli/install.py +91 -13
- flwr/cli/log.py +65 -36
- flwr/cli/login/login.py +41 -27
- flwr/cli/ls.py +232 -158
- flwr/cli/new/new.py +188 -244
- flwr/cli/pull.py +25 -34
- flwr/cli/run/run.py +106 -74
- flwr/cli/run_utils.py +148 -0
- flwr/cli/stop.py +46 -37
- flwr/cli/supernode/__init__.py +25 -0
- flwr/cli/supernode/ls.py +273 -0
- flwr/cli/supernode/register.py +190 -0
- flwr/cli/supernode/unregister.py +140 -0
- flwr/cli/typing.py +211 -0
- flwr/cli/utils.py +428 -80
- flwr/client/__init__.py +2 -1
- flwr/client/dpfedavg_numpy_client.py +4 -1
- flwr/client/grpc_adapter_client/connection.py +14 -17
- flwr/client/grpc_rere_client/connection.py +73 -43
- flwr/client/grpc_rere_client/grpc_adapter.py +35 -15
- flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +5 -7
- flwr/client/message_handler/message_handler.py +4 -3
- flwr/client/mod/centraldp_mods.py +1 -1
- flwr/client/mod/localdp_mod.py +1 -1
- flwr/client/mod/secure_aggregation/secaggplus_mod.py +11 -9
- flwr/client/numpy_client.py +1 -1
- flwr/client/rest_client/connection.py +99 -54
- flwr/client/run_info_store.py +6 -6
- flwr/client/typing.py +1 -1
- flwr/clientapp/__init__.py +1 -2
- flwr/{client → clientapp}/client_app.py +11 -11
- flwr/clientapp/mod/centraldp_mods.py +16 -17
- flwr/clientapp/mod/localdp_mod.py +8 -9
- flwr/clientapp/typing.py +1 -1
- flwr/{client/clientapp → clientapp}/utils.py +4 -4
- flwr/common/__init__.py +3 -2
- flwr/common/args.py +3 -4
- flwr/common/config.py +15 -17
- flwr/common/constant.py +56 -28
- flwr/common/context.py +2 -1
- flwr/common/differential_privacy.py +3 -4
- flwr/common/event_log_plugin/event_log_plugin.py +3 -4
- flwr/common/exit/exit.py +16 -3
- flwr/common/exit/exit_code.py +39 -10
- flwr/common/exit/exit_handler.py +6 -2
- flwr/common/exit/signal_handler.py +5 -5
- flwr/common/grpc.py +8 -7
- flwr/common/inflatable_protobuf_utils.py +1 -1
- flwr/common/inflatable_utils.py +48 -31
- flwr/common/logger.py +19 -19
- flwr/common/message.py +5 -5
- flwr/common/object_ref.py +7 -7
- flwr/common/record/array.py +6 -6
- flwr/common/record/arrayrecord.py +18 -21
- flwr/common/record/configrecord.py +3 -3
- flwr/common/record/recorddict.py +5 -5
- flwr/common/record/typeddict.py +9 -2
- flwr/common/recorddict_compat.py +7 -10
- flwr/common/retry_invoker.py +20 -20
- flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
- flwr/common/secure_aggregation/ndarrays_arithmetic.py +8 -5
- flwr/common/serde.py +22 -11
- flwr/common/serde_utils.py +2 -2
- flwr/common/telemetry.py +10 -6
- flwr/common/typing.py +65 -44
- flwr/compat/client/app.py +45 -47
- flwr/compat/client/grpc_client/connection.py +15 -14
- flwr/compat/common/constant.py +29 -0
- flwr/compat/server/app.py +6 -7
- flwr/proto/appio_pb2.py +13 -3
- flwr/proto/appio_pb2.pyi +134 -65
- flwr/proto/appio_pb2_grpc.py +20 -0
- flwr/proto/appio_pb2_grpc.pyi +27 -0
- flwr/proto/clientappio_pb2.py +17 -7
- flwr/proto/clientappio_pb2.pyi +15 -0
- flwr/proto/clientappio_pb2_grpc.py +206 -40
- flwr/proto/clientappio_pb2_grpc.pyi +168 -53
- flwr/proto/control_pb2.py +72 -40
- flwr/proto/control_pb2.pyi +319 -87
- flwr/proto/control_pb2_grpc.py +339 -28
- flwr/proto/control_pb2_grpc.pyi +209 -37
- flwr/proto/error_pb2.py +13 -3
- flwr/proto/error_pb2.pyi +24 -6
- flwr/proto/error_pb2_grpc.py +20 -0
- flwr/proto/error_pb2_grpc.pyi +27 -0
- flwr/proto/fab_pb2.py +24 -10
- flwr/proto/fab_pb2.pyi +68 -20
- flwr/proto/fab_pb2_grpc.py +20 -0
- flwr/proto/fab_pb2_grpc.pyi +27 -0
- flwr/proto/federation_pb2.py +38 -0
- flwr/proto/federation_pb2.pyi +56 -0
- flwr/proto/federation_pb2_grpc.py +24 -0
- flwr/proto/federation_pb2_grpc.pyi +31 -0
- flwr/proto/fleet_pb2.py +45 -27
- flwr/proto/fleet_pb2.pyi +190 -70
- flwr/proto/fleet_pb2_grpc.py +277 -66
- flwr/proto/fleet_pb2_grpc.pyi +201 -55
- flwr/proto/grpcadapter_pb2.py +14 -4
- flwr/proto/grpcadapter_pb2.pyi +38 -16
- flwr/proto/grpcadapter_pb2_grpc.py +35 -4
- flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
- flwr/proto/heartbeat_pb2.py +17 -7
- flwr/proto/heartbeat_pb2.pyi +51 -22
- flwr/proto/heartbeat_pb2_grpc.py +20 -0
- flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
- flwr/proto/log_pb2.py +13 -3
- flwr/proto/log_pb2.pyi +34 -11
- flwr/proto/log_pb2_grpc.py +20 -0
- flwr/proto/log_pb2_grpc.pyi +27 -0
- flwr/proto/message_pb2.py +15 -5
- flwr/proto/message_pb2.pyi +154 -86
- flwr/proto/message_pb2_grpc.py +20 -0
- flwr/proto/message_pb2_grpc.pyi +27 -0
- flwr/proto/node_pb2.py +16 -4
- flwr/proto/node_pb2.pyi +77 -4
- flwr/proto/node_pb2_grpc.py +20 -0
- flwr/proto/node_pb2_grpc.pyi +27 -0
- flwr/proto/recorddict_pb2.py +13 -3
- flwr/proto/recorddict_pb2.pyi +184 -107
- flwr/proto/recorddict_pb2_grpc.py +20 -0
- flwr/proto/recorddict_pb2_grpc.pyi +27 -0
- flwr/proto/run_pb2.py +40 -31
- flwr/proto/run_pb2.pyi +158 -84
- flwr/proto/run_pb2_grpc.py +20 -0
- flwr/proto/run_pb2_grpc.pyi +27 -0
- flwr/proto/serverappio_pb2.py +13 -3
- flwr/proto/serverappio_pb2.pyi +32 -8
- flwr/proto/serverappio_pb2_grpc.py +246 -65
- flwr/proto/serverappio_pb2_grpc.pyi +221 -85
- flwr/proto/simulationio_pb2.py +16 -8
- flwr/proto/simulationio_pb2.pyi +15 -0
- flwr/proto/simulationio_pb2_grpc.py +162 -41
- flwr/proto/simulationio_pb2_grpc.pyi +149 -55
- flwr/proto/transport_pb2.py +20 -10
- flwr/proto/transport_pb2.pyi +249 -160
- flwr/proto/transport_pb2_grpc.py +35 -4
- flwr/proto/transport_pb2_grpc.pyi +38 -8
- flwr/server/app.py +175 -128
- flwr/server/client_manager.py +4 -5
- flwr/server/client_proxy.py +10 -11
- flwr/server/compat/app.py +4 -5
- flwr/server/compat/app_utils.py +2 -1
- flwr/server/compat/grid_client_proxy.py +12 -13
- flwr/server/compat/legacy_context.py +3 -4
- flwr/server/fleet_event_log_interceptor.py +2 -1
- flwr/server/grid/grid.py +2 -3
- flwr/server/grid/grpc_grid.py +12 -10
- flwr/server/grid/inmemory_grid.py +4 -4
- flwr/server/run_serverapp.py +2 -3
- flwr/server/server.py +34 -39
- flwr/server/server_app.py +7 -8
- flwr/server/server_config.py +1 -2
- flwr/server/serverapp/app.py +34 -28
- flwr/server/serverapp_components.py +4 -5
- flwr/server/strategy/aggregate.py +9 -8
- flwr/server/strategy/bulyan.py +13 -11
- flwr/server/strategy/dp_adaptive_clipping.py +16 -20
- flwr/server/strategy/dp_fixed_clipping.py +12 -17
- flwr/server/strategy/dpfedavg_adaptive.py +3 -4
- flwr/server/strategy/dpfedavg_fixed.py +6 -10
- flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
- flwr/server/strategy/fedadagrad.py +18 -14
- flwr/server/strategy/fedadam.py +16 -14
- flwr/server/strategy/fedavg.py +16 -17
- flwr/server/strategy/fedavg_android.py +15 -15
- flwr/server/strategy/fedavgm.py +21 -18
- flwr/server/strategy/fedmedian.py +2 -3
- flwr/server/strategy/fedopt.py +11 -10
- flwr/server/strategy/fedprox.py +10 -9
- flwr/server/strategy/fedtrimmedavg.py +12 -11
- flwr/server/strategy/fedxgb_bagging.py +13 -11
- flwr/server/strategy/fedxgb_cyclic.py +6 -6
- flwr/server/strategy/fedxgb_nn_avg.py +4 -4
- flwr/server/strategy/fedyogi.py +16 -14
- flwr/server/strategy/krum.py +12 -11
- flwr/server/strategy/qfedavg.py +16 -15
- flwr/server/strategy/strategy.py +6 -9
- flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +20 -9
- flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
- flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
- flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
- flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
- flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +136 -42
- flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +28 -50
- flwr/server/superlink/fleet/message_handler/message_handler.py +141 -51
- flwr/server/superlink/fleet/rest_rere/rest_api.py +54 -33
- flwr/server/superlink/fleet/vce/backend/backend.py +2 -2
- flwr/server/superlink/fleet/vce/backend/raybackend.py +6 -6
- flwr/server/superlink/fleet/vce/vce_api.py +32 -13
- flwr/server/superlink/linkstate/__init__.py +2 -0
- flwr/server/superlink/linkstate/in_memory_linkstate.py +293 -208
- flwr/server/superlink/linkstate/linkstate.py +176 -64
- flwr/server/superlink/linkstate/linkstate_factory.py +24 -6
- flwr/server/superlink/linkstate/sql_linkstate.py +221 -0
- flwr/server/superlink/linkstate/sqlite_linkstate.py +743 -648
- flwr/server/superlink/linkstate/utils.py +11 -62
- flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
- flwr/server/superlink/serverappio/serverappio_servicer.py +28 -23
- flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
- flwr/server/superlink/simulation/simulationio_servicer.py +19 -14
- flwr/server/superlink/utils.py +4 -6
- flwr/server/typing.py +1 -1
- flwr/server/utils/tensorboard.py +15 -8
- flwr/server/utils/validator.py +2 -3
- flwr/server/workflow/default_workflows.py +7 -6
- flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
- flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +13 -11
- flwr/serverapp/strategy/bulyan.py +16 -15
- flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
- flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
- flwr/serverapp/strategy/fedadagrad.py +10 -11
- flwr/serverapp/strategy/fedadam.py +10 -11
- flwr/serverapp/strategy/fedavg.py +10 -11
- flwr/serverapp/strategy/fedavgm.py +17 -16
- flwr/serverapp/strategy/fedmedian.py +2 -2
- flwr/serverapp/strategy/fedopt.py +10 -11
- flwr/serverapp/strategy/fedprox.py +7 -8
- flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
- flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
- flwr/serverapp/strategy/fedxgb_cyclic.py +10 -10
- flwr/serverapp/strategy/fedyogi.py +9 -11
- flwr/serverapp/strategy/krum.py +7 -7
- flwr/serverapp/strategy/multikrum.py +9 -9
- flwr/serverapp/strategy/qfedavg.py +17 -16
- flwr/serverapp/strategy/strategy.py +6 -9
- flwr/serverapp/strategy/strategy_utils.py +7 -8
- flwr/simulation/app.py +46 -42
- flwr/simulation/legacy_app.py +12 -12
- flwr/simulation/ray_transport/ray_actor.py +11 -12
- flwr/simulation/ray_transport/ray_client_proxy.py +14 -19
- flwr/simulation/run_simulation.py +46 -44
- flwr/simulation/simulationio_connection.py +4 -4
- flwr/{common → supercore}/address.py +1 -37
- flwr/supercore/cli/flower_superexec.py +3 -4
- flwr/supercore/constant.py +69 -0
- flwr/supercore/corestate/corestate.py +24 -3
- flwr/supercore/corestate/in_memory_corestate.py +138 -0
- flwr/supercore/corestate/sql_corestate.py +153 -0
- flwr/supercore/corestate/sqlite_corestate.py +157 -0
- flwr/supercore/credential_store/__init__.py +33 -0
- flwr/supercore/credential_store/credential_store.py +34 -0
- flwr/supercore/credential_store/file_credential_store.py +76 -0
- flwr/{common → supercore}/date.py +0 -11
- flwr/supercore/ffs/disk_ffs.py +1 -2
- flwr/supercore/ffs/ffs.py +1 -2
- flwr/supercore/ffs/ffs_factory.py +1 -2
- flwr/{common → supercore}/heartbeat.py +20 -25
- flwr/supercore/object_store/in_memory_object_store.py +1 -6
- flwr/supercore/object_store/object_store.py +1 -2
- flwr/supercore/object_store/object_store_factory.py +27 -8
- flwr/supercore/object_store/sqlite_object_store.py +253 -0
- flwr/{cli/new/templates/app → supercore/primitives}/__init__.py +1 -1
- flwr/supercore/primitives/asymmetric.py +117 -0
- flwr/supercore/primitives/asymmetric_ed25519.py +175 -0
- flwr/supercore/sql_mixin.py +292 -0
- flwr/supercore/sqlite_mixin.py +156 -0
- flwr/{client/clientapp → supercore/state}/__init__.py +2 -2
- flwr/supercore/state/schema/README.md +125 -0
- flwr/{cli/new/templates → supercore/state/schema}/__init__.py +2 -2
- flwr/supercore/state/schema/corestate_tables.py +36 -0
- flwr/supercore/state/schema/linkstate_tables.py +152 -0
- flwr/supercore/state/schema/objectstore_tables.py +90 -0
- flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
- flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
- flwr/supercore/superexec/run_superexec.py +9 -13
- flwr/supercore/utils.py +224 -0
- flwr/superlink/artifact_provider/artifact_provider.py +1 -2
- flwr/superlink/auth_plugin/__init__.py +5 -2
- flwr/superlink/auth_plugin/auth_plugin.py +20 -19
- flwr/superlink/auth_plugin/noop_auth_plugin.py +84 -0
- flwr/superlink/federation/__init__.py +24 -0
- flwr/superlink/federation/federation_manager.py +64 -0
- flwr/superlink/federation/noop_federation_manager.py +71 -0
- flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +41 -32
- flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
- flwr/superlink/servicer/control/control_grpc.py +20 -17
- flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
- flwr/superlink/servicer/control/control_servicer.py +328 -68
- flwr/supernode/cli/flower_supernode.py +74 -26
- flwr/supernode/nodestate/in_memory_nodestate.py +121 -49
- flwr/supernode/nodestate/nodestate.py +52 -8
- flwr/supernode/nodestate/nodestate_factory.py +7 -4
- flwr/supernode/runtime/run_clientapp.py +43 -24
- flwr/supernode/servicer/clientappio/clientappio_servicer.py +48 -10
- flwr/supernode/start_client_internal.py +185 -57
- {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/METADATA +10 -11
- flwr_nightly-1.26.0.dev20260121.dist-info/RECORD +411 -0
- flwr/cli/new/templates/app/.gitignore.tpl +0 -163
- flwr/cli/new/templates/app/LICENSE.tpl +0 -202
- flwr/cli/new/templates/app/README.baseline.md.tpl +0 -127
- flwr/cli/new/templates/app/README.flowertune.md.tpl +0 -68
- flwr/cli/new/templates/app/README.md.tpl +0 -37
- flwr/cli/new/templates/app/code/__init__.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/code/__init__.py.tpl +0 -1
- flwr/cli/new/templates/app/code/__init__.pytorch_legacy_api.py.tpl +0 -1
- flwr/cli/new/templates/app/code/client.baseline.py.tpl +0 -75
- flwr/cli/new/templates/app/code/client.huggingface.py.tpl +0 -93
- flwr/cli/new/templates/app/code/client.jax.py.tpl +0 -71
- flwr/cli/new/templates/app/code/client.mlx.py.tpl +0 -102
- flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -46
- flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -80
- flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +0 -55
- flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -108
- flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -82
- flwr/cli/new/templates/app/code/client.xgboost.py.tpl +0 -110
- flwr/cli/new/templates/app/code/dataset.baseline.py.tpl +0 -36
- flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +0 -92
- flwr/cli/new/templates/app/code/flwr_tune/dataset.py.tpl +0 -87
- flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +0 -56
- flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +0 -73
- flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +0 -78
- flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -66
- flwr/cli/new/templates/app/code/server.baseline.py.tpl +0 -43
- flwr/cli/new/templates/app/code/server.huggingface.py.tpl +0 -42
- flwr/cli/new/templates/app/code/server.jax.py.tpl +0 -39
- flwr/cli/new/templates/app/code/server.mlx.py.tpl +0 -41
- flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -38
- flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -41
- flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +0 -31
- flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -44
- flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -38
- flwr/cli/new/templates/app/code/server.xgboost.py.tpl +0 -56
- flwr/cli/new/templates/app/code/strategy.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/code/task.huggingface.py.tpl +0 -98
- flwr/cli/new/templates/app/code/task.jax.py.tpl +0 -57
- flwr/cli/new/templates/app/code/task.mlx.py.tpl +0 -102
- flwr/cli/new/templates/app/code/task.numpy.py.tpl +0 -7
- flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -98
- flwr/cli/new/templates/app/code/task.pytorch_legacy_api.py.tpl +0 -111
- flwr/cli/new/templates/app/code/task.sklearn.py.tpl +0 -67
- flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -52
- flwr/cli/new/templates/app/code/task.xgboost.py.tpl +0 -67
- flwr/cli/new/templates/app/code/utils.baseline.py.tpl +0 -1
- flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +0 -146
- flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +0 -80
- flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +0 -65
- flwr/cli/new/templates/app/pyproject.jax.toml.tpl +0 -52
- flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +0 -56
- flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -49
- flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -52
- flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -53
- flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +0 -61
- flwr/common/pyproject.py +0 -42
- flwr/supercore/object_store/utils.py +0 -43
- flwr_nightly-1.23.0.dev20250930.dist-info/RECORD +0 -429
- /flwr/{common → supercore}/version.py +0 -0
- {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.23.0.dev20250930.dist-info → flwr_nightly-1.26.0.dev20260121.dist-info}/entry_points.txt +0 -0
flwr/proto/transport_pb2_grpc.py
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
1
|
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
2
|
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
3
|
import grpc
|
|
4
|
+
import warnings
|
|
4
5
|
|
|
5
6
|
from flwr.proto import transport_pb2 as flwr_dot_proto_dot_transport__pb2
|
|
6
7
|
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.70.0'
|
|
9
|
+
GRPC_VERSION = grpc.__version__
|
|
10
|
+
_version_not_supported = False
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from grpc._utilities import first_version_is_lower
|
|
14
|
+
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
|
15
|
+
except ImportError:
|
|
16
|
+
_version_not_supported = True
|
|
17
|
+
|
|
18
|
+
if _version_not_supported:
|
|
19
|
+
raise RuntimeError(
|
|
20
|
+
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
+
+ f' but the generated code in flwr/proto/transport_pb2_grpc.py depends on'
|
|
22
|
+
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
|
+
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
|
+
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
25
|
+
)
|
|
26
|
+
|
|
7
27
|
|
|
8
28
|
class FlowerServiceStub(object):
|
|
9
29
|
"""Missing associated documentation comment in .proto file."""
|
|
@@ -18,7 +38,7 @@ class FlowerServiceStub(object):
|
|
|
18
38
|
'/flwr.proto.FlowerService/Join',
|
|
19
39
|
request_serializer=flwr_dot_proto_dot_transport__pb2.ClientMessage.SerializeToString,
|
|
20
40
|
response_deserializer=flwr_dot_proto_dot_transport__pb2.ServerMessage.FromString,
|
|
21
|
-
)
|
|
41
|
+
_registered_method=True)
|
|
22
42
|
|
|
23
43
|
|
|
24
44
|
class FlowerServiceServicer(object):
|
|
@@ -42,6 +62,7 @@ def add_FlowerServiceServicer_to_server(servicer, server):
|
|
|
42
62
|
generic_handler = grpc.method_handlers_generic_handler(
|
|
43
63
|
'flwr.proto.FlowerService', rpc_method_handlers)
|
|
44
64
|
server.add_generic_rpc_handlers((generic_handler,))
|
|
65
|
+
server.add_registered_method_handlers('flwr.proto.FlowerService', rpc_method_handlers)
|
|
45
66
|
|
|
46
67
|
|
|
47
68
|
# This class is part of an EXPERIMENTAL API.
|
|
@@ -59,8 +80,18 @@ class FlowerService(object):
|
|
|
59
80
|
wait_for_ready=None,
|
|
60
81
|
timeout=None,
|
|
61
82
|
metadata=None):
|
|
62
|
-
return grpc.experimental.stream_stream(
|
|
83
|
+
return grpc.experimental.stream_stream(
|
|
84
|
+
request_iterator,
|
|
85
|
+
target,
|
|
86
|
+
'/flwr.proto.FlowerService/Join',
|
|
63
87
|
flwr_dot_proto_dot_transport__pb2.ClientMessage.SerializeToString,
|
|
64
88
|
flwr_dot_proto_dot_transport__pb2.ServerMessage.FromString,
|
|
65
|
-
options,
|
|
66
|
-
|
|
89
|
+
options,
|
|
90
|
+
channel_credentials,
|
|
91
|
+
insecure,
|
|
92
|
+
call_credentials,
|
|
93
|
+
compression,
|
|
94
|
+
wait_for_ready,
|
|
95
|
+
timeout,
|
|
96
|
+
metadata,
|
|
97
|
+
_registered_method=True)
|
|
@@ -1,25 +1,55 @@
|
|
|
1
1
|
"""
|
|
2
2
|
@generated by mypy-protobuf. Do not edit manually!
|
|
3
3
|
isort:skip_file
|
|
4
|
+
Copyright 2020 Flower Labs GmbH. All Rights Reserved.
|
|
5
|
+
|
|
6
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
you may not use this file except in compliance with the License.
|
|
8
|
+
You may obtain a copy of the License at
|
|
9
|
+
|
|
10
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
|
|
12
|
+
Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
See the License for the specific language governing permissions and
|
|
16
|
+
limitations under the License.
|
|
17
|
+
==============================================================================
|
|
4
18
|
"""
|
|
19
|
+
|
|
5
20
|
import abc
|
|
21
|
+
import collections.abc
|
|
6
22
|
import flwr.proto.transport_pb2
|
|
7
23
|
import grpc
|
|
24
|
+
import grpc.aio
|
|
8
25
|
import typing
|
|
9
26
|
|
|
27
|
+
_T = typing.TypeVar("_T")
|
|
28
|
+
|
|
29
|
+
class _MaybeAsyncIterator(collections.abc.AsyncIterator[_T], collections.abc.Iterator[_T], metaclass=abc.ABCMeta): ...
|
|
30
|
+
|
|
31
|
+
class _ServicerContext(grpc.ServicerContext, grpc.aio.ServicerContext): # type: ignore[misc, type-arg]
|
|
32
|
+
...
|
|
33
|
+
|
|
10
34
|
class FlowerServiceStub:
|
|
11
|
-
def __init__(self, channel: grpc.Channel) -> None: ...
|
|
35
|
+
def __init__(self, channel: typing.Union[grpc.Channel, grpc.aio.Channel]) -> None: ...
|
|
12
36
|
Join: grpc.StreamStreamMultiCallable[
|
|
13
37
|
flwr.proto.transport_pb2.ClientMessage,
|
|
14
|
-
flwr.proto.transport_pb2.ServerMessage
|
|
38
|
+
flwr.proto.transport_pb2.ServerMessage,
|
|
39
|
+
]
|
|
15
40
|
|
|
41
|
+
class FlowerServiceAsyncStub:
|
|
42
|
+
Join: grpc.aio.StreamStreamMultiCallable[
|
|
43
|
+
flwr.proto.transport_pb2.ClientMessage,
|
|
44
|
+
flwr.proto.transport_pb2.ServerMessage,
|
|
45
|
+
]
|
|
16
46
|
|
|
17
47
|
class FlowerServiceServicer(metaclass=abc.ABCMeta):
|
|
18
48
|
@abc.abstractmethod
|
|
19
|
-
def Join(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
49
|
+
def Join(
|
|
50
|
+
self,
|
|
51
|
+
request_iterator: _MaybeAsyncIterator[flwr.proto.transport_pb2.ClientMessage],
|
|
52
|
+
context: _ServicerContext,
|
|
53
|
+
) -> typing.Union[collections.abc.Iterator[flwr.proto.transport_pb2.ServerMessage], collections.abc.AsyncIterator[flwr.proto.transport_pb2.ServerMessage]]: ...
|
|
24
54
|
|
|
25
|
-
def add_FlowerServiceServicer_to_server(servicer: FlowerServiceServicer, server: grpc.Server) -> None: ...
|
|
55
|
+
def add_FlowerServiceServicer_to_server(servicer: FlowerServiceServicer, server: typing.Union[grpc.Server, grpc.aio.Server]) -> None: ...
|
flwr/server/app.py
CHANGED
|
@@ -16,29 +16,25 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
|
-
import csv
|
|
20
19
|
import importlib.util
|
|
21
20
|
import os
|
|
22
21
|
import subprocess
|
|
23
22
|
import sys
|
|
24
23
|
import threading
|
|
25
|
-
from collections.abc import Sequence
|
|
26
|
-
from logging import
|
|
24
|
+
from collections.abc import Callable, Sequence
|
|
25
|
+
from logging import INFO, WARN
|
|
27
26
|
from pathlib import Path
|
|
28
27
|
from time import sleep
|
|
29
|
-
from typing import
|
|
28
|
+
from typing import TypeVar, cast
|
|
30
29
|
|
|
31
30
|
import grpc
|
|
32
31
|
import yaml
|
|
33
|
-
from cryptography.hazmat.primitives.asymmetric import ec
|
|
34
|
-
from cryptography.hazmat.primitives.serialization import load_ssh_public_key
|
|
35
32
|
|
|
36
33
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event
|
|
37
|
-
from flwr.common.address import parse_address
|
|
38
34
|
from flwr.common.args import try_obtain_server_certificates
|
|
39
35
|
from flwr.common.config import get_flwr_dir
|
|
40
36
|
from flwr.common.constant import (
|
|
41
|
-
|
|
37
|
+
AUTHN_TYPE_YAML_KEY,
|
|
42
38
|
AUTHZ_TYPE_YAML_KEY,
|
|
43
39
|
CLIENT_OCTET,
|
|
44
40
|
CONTROL_API_DEFAULT_SERVER_ADDRESS,
|
|
@@ -52,6 +48,8 @@ from flwr.common.constant import (
|
|
|
52
48
|
TRANSPORT_TYPE_GRPC_ADAPTER,
|
|
53
49
|
TRANSPORT_TYPE_GRPC_RERE,
|
|
54
50
|
TRANSPORT_TYPE_REST,
|
|
51
|
+
AuthnType,
|
|
52
|
+
AuthzType,
|
|
55
53
|
EventLogWriterType,
|
|
56
54
|
ExecPluginType,
|
|
57
55
|
)
|
|
@@ -59,40 +57,48 @@ from flwr.common.event_log_plugin import EventLogWriterPlugin
|
|
|
59
57
|
from flwr.common.exit import ExitCode, flwr_exit, register_signal_handlers
|
|
60
58
|
from flwr.common.grpc import generic_create_grpc_server
|
|
61
59
|
from flwr.common.logger import log
|
|
62
|
-
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
|
63
|
-
public_key_to_bytes,
|
|
64
|
-
)
|
|
65
60
|
from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611
|
|
66
61
|
add_FleetServicer_to_server,
|
|
67
62
|
)
|
|
68
63
|
from flwr.proto.grpcadapter_pb2_grpc import add_GrpcAdapterServicer_to_server
|
|
69
64
|
from flwr.server.fleet_event_log_interceptor import FleetEventLogInterceptor
|
|
65
|
+
from flwr.supercore.address import parse_address
|
|
66
|
+
from flwr.supercore.constant import FLWR_IN_MEMORY_DB_NAME
|
|
70
67
|
from flwr.supercore.ffs import FfsFactory
|
|
71
68
|
from flwr.supercore.grpc_health import add_args_health, run_health_server_grpc_no_tls
|
|
72
69
|
from flwr.supercore.object_store import ObjectStoreFactory
|
|
70
|
+
from flwr.supercore.version import package_version
|
|
73
71
|
from flwr.superlink.artifact_provider import ArtifactProvider
|
|
74
|
-
from flwr.superlink.auth_plugin import
|
|
72
|
+
from flwr.superlink.auth_plugin import (
|
|
73
|
+
ControlAuthnPlugin,
|
|
74
|
+
ControlAuthzPlugin,
|
|
75
|
+
NoOpControlAuthnPlugin,
|
|
76
|
+
NoOpControlAuthzPlugin,
|
|
77
|
+
)
|
|
78
|
+
from flwr.superlink.federation import FederationManager, NoOpFederationManager
|
|
75
79
|
from flwr.superlink.servicer.control import run_control_api_grpc
|
|
76
80
|
|
|
77
81
|
from .superlink.fleet.grpc_adapter.grpc_adapter_servicer import GrpcAdapterServicer
|
|
78
82
|
from .superlink.fleet.grpc_rere.fleet_servicer import FleetServicer
|
|
79
|
-
from .superlink.fleet.grpc_rere.
|
|
83
|
+
from .superlink.fleet.grpc_rere.node_auth_server_interceptor import (
|
|
84
|
+
NodeAuthServerInterceptor,
|
|
85
|
+
)
|
|
80
86
|
from .superlink.linkstate import LinkStateFactory
|
|
81
87
|
from .superlink.serverappio.serverappio_grpc import run_serverappio_api_grpc
|
|
82
88
|
from .superlink.simulation.simulationio_grpc import run_simulationio_api_grpc
|
|
83
89
|
|
|
84
|
-
DATABASE = ":flwr-in-memory-state:"
|
|
85
90
|
BASE_DIR = get_flwr_dir() / "superlink" / "ffs"
|
|
86
|
-
P = TypeVar("P",
|
|
91
|
+
P = TypeVar("P", ControlAuthnPlugin, ControlAuthzPlugin)
|
|
87
92
|
|
|
88
93
|
|
|
89
94
|
try:
|
|
90
95
|
from flwr.ee import (
|
|
91
96
|
add_ee_args_superlink,
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
get_control_authn_ee_plugins,
|
|
98
|
+
get_control_authz_ee_plugins,
|
|
94
99
|
get_control_event_log_writer_plugins,
|
|
95
100
|
get_ee_artifact_provider,
|
|
101
|
+
get_ee_federation_manager,
|
|
96
102
|
get_fleet_event_log_writer_plugins,
|
|
97
103
|
)
|
|
98
104
|
except ImportError:
|
|
@@ -101,14 +107,6 @@ except ImportError:
|
|
|
101
107
|
def add_ee_args_superlink(parser: argparse.ArgumentParser) -> None:
|
|
102
108
|
"""Add EE-specific arguments to the parser."""
|
|
103
109
|
|
|
104
|
-
def get_control_auth_plugins() -> dict[str, type[ControlAuthPlugin]]:
|
|
105
|
-
"""Return all Control API authentication plugins."""
|
|
106
|
-
raise NotImplementedError("No authentication plugins are currently supported.")
|
|
107
|
-
|
|
108
|
-
def get_control_authz_plugins() -> dict[str, type[ControlAuthzPlugin]]:
|
|
109
|
-
"""Return all Control API authorization plugins."""
|
|
110
|
-
raise NotImplementedError("No authorization plugins are currently supported.")
|
|
111
|
-
|
|
112
110
|
def get_control_event_log_writer_plugins() -> dict[str, type[EventLogWriterPlugin]]:
|
|
113
111
|
"""Return all Control API event log writer plugins."""
|
|
114
112
|
raise NotImplementedError(
|
|
@@ -125,6 +123,39 @@ except ImportError:
|
|
|
125
123
|
"No event log writer plugins are currently supported."
|
|
126
124
|
)
|
|
127
125
|
|
|
126
|
+
def get_control_authn_ee_plugins() -> dict[str, type[ControlAuthnPlugin]]:
|
|
127
|
+
"""Return all Control API authentication plugins for EE."""
|
|
128
|
+
return {}
|
|
129
|
+
|
|
130
|
+
def get_control_authz_ee_plugins() -> dict[str, type[ControlAuthzPlugin]]:
|
|
131
|
+
"""Return all Control API authorization plugins for EE."""
|
|
132
|
+
return {}
|
|
133
|
+
|
|
134
|
+
# pylint: disable-next=unused-argument
|
|
135
|
+
def get_ee_federation_manager(config_path: str) -> FederationManager:
|
|
136
|
+
"""Return the EE FederationManager."""
|
|
137
|
+
raise NotImplementedError("No federation manager is currently supported.")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def get_control_authn_plugins() -> dict[str, type[ControlAuthnPlugin]]:
|
|
141
|
+
"""Return all Control API authentication plugins."""
|
|
142
|
+
ee_dict: dict[str, type[ControlAuthnPlugin]] = get_control_authn_ee_plugins()
|
|
143
|
+
return ee_dict | {AuthnType.NOOP: NoOpControlAuthnPlugin}
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def get_control_authz_plugins() -> dict[str, type[ControlAuthzPlugin]]:
|
|
147
|
+
"""Return all Control API authorization plugins."""
|
|
148
|
+
ee_dict: dict[str, type[ControlAuthzPlugin]] = get_control_authz_ee_plugins()
|
|
149
|
+
return ee_dict | {AuthzType.NOOP: NoOpControlAuthzPlugin}
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def get_federation_manager(config_path: str | None = None) -> FederationManager:
|
|
153
|
+
"""Return the FederationManager."""
|
|
154
|
+
if config_path is None:
|
|
155
|
+
return NoOpFederationManager()
|
|
156
|
+
federation_manager: FederationManager = get_ee_federation_manager(config_path)
|
|
157
|
+
return federation_manager
|
|
158
|
+
|
|
128
159
|
|
|
129
160
|
# pylint: disable=too-many-branches, too-many-locals, too-many-statements
|
|
130
161
|
def run_superlink() -> None:
|
|
@@ -189,18 +220,24 @@ def run_superlink() -> None:
|
|
|
189
220
|
# Obtain certificates
|
|
190
221
|
certificates = try_obtain_server_certificates(args)
|
|
191
222
|
|
|
192
|
-
# Disable the
|
|
223
|
+
# Disable the account auth TLS check if args.disable_oidc_tls_cert_verification is
|
|
193
224
|
# provided
|
|
194
225
|
verify_tls_cert = not getattr(args, "disable_oidc_tls_cert_verification", None)
|
|
195
226
|
|
|
196
|
-
|
|
197
|
-
authz_plugin:
|
|
198
|
-
event_log_plugin:
|
|
199
|
-
# Load the auth plugin if the args.
|
|
227
|
+
authn_plugin: ControlAuthnPlugin | None = None
|
|
228
|
+
authz_plugin: ControlAuthzPlugin | None = None
|
|
229
|
+
event_log_plugin: EventLogWriterPlugin | None = None
|
|
230
|
+
# Load the auth plugin if the args.account_auth_config is provided
|
|
200
231
|
if cfg_path := getattr(args, "user_auth_config", None):
|
|
201
|
-
|
|
202
|
-
|
|
232
|
+
log(
|
|
233
|
+
WARN,
|
|
234
|
+
"The `--user-auth-config` flag is deprecated and will be removed in a "
|
|
235
|
+
"future release. Please use `--account-auth-config` instead.",
|
|
203
236
|
)
|
|
237
|
+
args.account_auth_config = cfg_path
|
|
238
|
+
cfg_path = getattr(args, "account_auth_config", None)
|
|
239
|
+
authn_plugin, authz_plugin = _load_control_auth_plugins(cfg_path, verify_tls_cert)
|
|
240
|
+
if cfg_path is not None:
|
|
204
241
|
# Enable event logging if the args.enable_event_log is True
|
|
205
242
|
if args.enable_event_log:
|
|
206
243
|
event_log_plugin = _try_obtain_control_event_log_writer_plugin()
|
|
@@ -211,15 +248,69 @@ def run_superlink() -> None:
|
|
|
211
248
|
log(WARN, "The `--artifact-provider-config` flag is highly experimental.")
|
|
212
249
|
artifact_provider = get_ee_artifact_provider(cfg_path)
|
|
213
250
|
|
|
251
|
+
# Check for incompatible args with SuperNode authentication
|
|
252
|
+
enable_supernode_auth: bool = args.enable_supernode_auth
|
|
253
|
+
if enable_supernode_auth:
|
|
254
|
+
if args.insecure:
|
|
255
|
+
url_v = f"https://flower.ai/docs/framework/v{package_version}/en/"
|
|
256
|
+
page = "how-to-authenticate-supernodes.html"
|
|
257
|
+
flwr_exit(
|
|
258
|
+
ExitCode.SUPERLINK_INVALID_ARGS,
|
|
259
|
+
"The `--enable-supernode-auth` flag requires encrypted TLS "
|
|
260
|
+
"communications. Please provide TLS certificates using the "
|
|
261
|
+
"`--ssl-certfile`, `--ssl-keyfile` and `--ssl-ca-certfile` "
|
|
262
|
+
"arguments to your SuperLink. Please refer to the Flower "
|
|
263
|
+
f"documentation for more information: {url_v}{page}",
|
|
264
|
+
)
|
|
265
|
+
if args.fleet_api_type != TRANSPORT_TYPE_GRPC_RERE:
|
|
266
|
+
flwr_exit(
|
|
267
|
+
ExitCode.SUPERLINK_INVALID_ARGS,
|
|
268
|
+
"The `--enable-supernode-auth` flag is only supported "
|
|
269
|
+
"with the gRPC-rere Fleet API transport. Please set "
|
|
270
|
+
f"`--fleet-api-type` to `{TRANSPORT_TYPE_GRPC_RERE}`.",
|
|
271
|
+
)
|
|
272
|
+
if args.simulation:
|
|
273
|
+
log(
|
|
274
|
+
WARN,
|
|
275
|
+
"SuperNode authentication is not applicable with the simulation, "
|
|
276
|
+
"runtime as no SuperNodes can connect to this SuperLink. "
|
|
277
|
+
"Proceeding...",
|
|
278
|
+
)
|
|
279
|
+
# If supernode authentication is disabled, warn users
|
|
280
|
+
else:
|
|
281
|
+
log(
|
|
282
|
+
WARN,
|
|
283
|
+
"SuperNode authentication is disabled. The SuperLink will accept "
|
|
284
|
+
"connections from any SuperNode.",
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
if args.auth_list_public_keys:
|
|
288
|
+
url_v = f"https://flower.ai/docs/framework/v{package_version}/en/"
|
|
289
|
+
page = "how-to-authenticate-supernodes.html"
|
|
290
|
+
flwr_exit(
|
|
291
|
+
ExitCode.SUPERLINK_INVALID_ARGS,
|
|
292
|
+
"The `--auth-list-public-keys` "
|
|
293
|
+
"argument is no longer supported. To enable SuperNode authentication, "
|
|
294
|
+
"use the `--enable-supernode-auth` flag and use the Flower CLI to register "
|
|
295
|
+
"SuperNodes by supplying their public keys. Please refer"
|
|
296
|
+
f" to the Flower documentation for more information: {url_v}{page}",
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# Load Federation Manager
|
|
300
|
+
fed_config_path = getattr(args, "federations_config", None)
|
|
301
|
+
federation_manager = get_federation_manager(fed_config_path)
|
|
302
|
+
|
|
303
|
+
# Initialize ObjectStoreFactory
|
|
304
|
+
objectstore_factory = ObjectStoreFactory(args.database)
|
|
305
|
+
|
|
214
306
|
# Initialize StateFactory
|
|
215
|
-
state_factory = LinkStateFactory(
|
|
307
|
+
state_factory = LinkStateFactory(
|
|
308
|
+
args.database, federation_manager, objectstore_factory
|
|
309
|
+
)
|
|
216
310
|
|
|
217
311
|
# Initialize FfsFactory
|
|
218
312
|
ffs_factory = FfsFactory(args.storage_dir)
|
|
219
313
|
|
|
220
|
-
# Initialize ObjectStoreFactory
|
|
221
|
-
objectstore_factory = ObjectStoreFactory()
|
|
222
|
-
|
|
223
314
|
# Start Control API
|
|
224
315
|
is_simulation = args.simulation
|
|
225
316
|
control_server: grpc.Server = run_control_api_grpc(
|
|
@@ -229,10 +320,11 @@ def run_superlink() -> None:
|
|
|
229
320
|
objectstore_factory=objectstore_factory,
|
|
230
321
|
certificates=certificates,
|
|
231
322
|
is_simulation=is_simulation,
|
|
232
|
-
|
|
323
|
+
authn_plugin=authn_plugin,
|
|
233
324
|
authz_plugin=authz_plugin,
|
|
234
325
|
event_log_plugin=event_log_plugin,
|
|
235
326
|
artifact_provider=artifact_provider,
|
|
327
|
+
fleet_api_type=args.fleet_api_type,
|
|
236
328
|
)
|
|
237
329
|
grpc_servers = [control_server]
|
|
238
330
|
bckg_threads: list[threading.Thread] = []
|
|
@@ -306,22 +398,8 @@ def run_superlink() -> None:
|
|
|
306
398
|
fleet_thread.start()
|
|
307
399
|
bckg_threads.append(fleet_thread)
|
|
308
400
|
elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE:
|
|
309
|
-
node_public_keys = _try_load_public_keys_node_authentication(args)
|
|
310
|
-
auto_auth = True
|
|
311
|
-
if node_public_keys is not None:
|
|
312
|
-
auto_auth = False
|
|
313
|
-
state = state_factory.state()
|
|
314
|
-
state.clear_supernode_auth_keys()
|
|
315
|
-
state.store_node_public_keys(node_public_keys)
|
|
316
|
-
log(
|
|
317
|
-
INFO,
|
|
318
|
-
"Node authentication enabled with %d known public keys",
|
|
319
|
-
len(node_public_keys),
|
|
320
|
-
)
|
|
321
|
-
else:
|
|
322
|
-
log(DEBUG, "Automatic node authentication enabled")
|
|
323
401
|
|
|
324
|
-
interceptors = [
|
|
402
|
+
interceptors = [NodeAuthServerInterceptor(state_factory)]
|
|
325
403
|
if getattr(args, "enable_event_log", None):
|
|
326
404
|
fleet_log_plugin = _try_obtain_fleet_event_log_writer_plugin()
|
|
327
405
|
if fleet_log_plugin is not None:
|
|
@@ -333,6 +411,7 @@ def run_superlink() -> None:
|
|
|
333
411
|
state_factory=state_factory,
|
|
334
412
|
ffs_factory=ffs_factory,
|
|
335
413
|
objectstore_factory=objectstore_factory,
|
|
414
|
+
enable_supernode_auth=enable_supernode_auth,
|
|
336
415
|
certificates=certificates,
|
|
337
416
|
interceptors=interceptors,
|
|
338
417
|
)
|
|
@@ -400,55 +479,21 @@ def _format_address(address: str) -> tuple[str, str, int]:
|
|
|
400
479
|
return (f"[{host}]:{port}" if is_v6 else f"{host}:{port}", host, port)
|
|
401
480
|
|
|
402
481
|
|
|
403
|
-
def
|
|
404
|
-
|
|
405
|
-
) ->
|
|
406
|
-
"""Return a set of node public keys."""
|
|
407
|
-
if args.auth_superlink_private_key or args.auth_superlink_public_key:
|
|
408
|
-
log(
|
|
409
|
-
WARN,
|
|
410
|
-
"The `--auth-superlink-private-key` and `--auth-superlink-public-key` "
|
|
411
|
-
"arguments are deprecated and will be removed in a future release. Node "
|
|
412
|
-
"authentication no longer requires these arguments.",
|
|
413
|
-
)
|
|
414
|
-
|
|
415
|
-
if not args.auth_list_public_keys:
|
|
416
|
-
return None
|
|
417
|
-
|
|
418
|
-
node_keys_file_path = Path(args.auth_list_public_keys)
|
|
419
|
-
if not node_keys_file_path.exists():
|
|
420
|
-
sys.exit(
|
|
421
|
-
"The provided path to the known public keys CSV file does not exist: "
|
|
422
|
-
f"{node_keys_file_path}. "
|
|
423
|
-
"Please provide the CSV file path containing known public keys "
|
|
424
|
-
"to '--auth-list-public-keys'."
|
|
425
|
-
)
|
|
426
|
-
|
|
427
|
-
node_public_keys: set[bytes] = set()
|
|
428
|
-
|
|
429
|
-
with open(node_keys_file_path, newline="", encoding="utf-8") as csvfile:
|
|
430
|
-
reader = csv.reader(csvfile)
|
|
431
|
-
for row in reader:
|
|
432
|
-
for element in row:
|
|
433
|
-
public_key = load_ssh_public_key(element.encode())
|
|
434
|
-
if isinstance(public_key, ec.EllipticCurvePublicKey):
|
|
435
|
-
node_public_keys.add(public_key_to_bytes(public_key))
|
|
436
|
-
else:
|
|
437
|
-
sys.exit(
|
|
438
|
-
"Error: Unable to parse the public keys in the CSV "
|
|
439
|
-
"file. Please ensure that the CSV file path points to a valid "
|
|
440
|
-
"known SSH public keys files and try again."
|
|
441
|
-
)
|
|
442
|
-
return node_public_keys
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
def _try_obtain_control_auth_plugins(
|
|
446
|
-
config_path: Path, verify_tls_cert: bool
|
|
447
|
-
) -> tuple[ControlAuthPlugin, ControlAuthzPlugin]:
|
|
482
|
+
def _load_control_auth_plugins(
|
|
483
|
+
config_path: str | None, verify_tls_cert: bool
|
|
484
|
+
) -> tuple[ControlAuthnPlugin, ControlAuthzPlugin]:
|
|
448
485
|
"""Obtain Control API authentication and authorization plugins."""
|
|
486
|
+
# Load NoOp plugins if no config path is provided
|
|
487
|
+
if config_path is None:
|
|
488
|
+
config_path = ""
|
|
489
|
+
config = {
|
|
490
|
+
"authentication": {AUTHN_TYPE_YAML_KEY: AuthnType.NOOP},
|
|
491
|
+
"authorization": {AUTHZ_TYPE_YAML_KEY: AuthzType.NOOP},
|
|
492
|
+
}
|
|
449
493
|
# Load YAML file
|
|
450
|
-
|
|
451
|
-
|
|
494
|
+
else:
|
|
495
|
+
with Path(config_path).open("r", encoding="utf-8") as file:
|
|
496
|
+
config = yaml.safe_load(file)
|
|
452
497
|
|
|
453
498
|
def _load_plugin(
|
|
454
499
|
section: str, yaml_key: str, loader: Callable[[], dict[str, type[P]]]
|
|
@@ -458,9 +503,7 @@ def _try_obtain_control_auth_plugins(
|
|
|
458
503
|
try:
|
|
459
504
|
plugins: dict[str, type[P]] = loader()
|
|
460
505
|
plugin_cls: type[P] = plugins[auth_plugin_name]
|
|
461
|
-
return plugin_cls(
|
|
462
|
-
user_auth_config_path=config_path, verify_tls_cert=verify_tls_cert
|
|
463
|
-
)
|
|
506
|
+
return plugin_cls(Path(cast(str, config_path)), verify_tls_cert)
|
|
464
507
|
except KeyError:
|
|
465
508
|
if auth_plugin_name:
|
|
466
509
|
sys.exit(
|
|
@@ -468,14 +511,22 @@ def _try_obtain_control_auth_plugins(
|
|
|
468
511
|
f"Please provide a valid {section} type in the configuration."
|
|
469
512
|
)
|
|
470
513
|
sys.exit(f"No {section} type is provided in the configuration.")
|
|
471
|
-
|
|
472
|
-
|
|
514
|
+
|
|
515
|
+
# Warn deprecated auth_type key
|
|
516
|
+
if authn_type := config["authentication"].pop("auth_type", None):
|
|
517
|
+
log(
|
|
518
|
+
WARN,
|
|
519
|
+
"The `auth_type` key in the authentication configuration is deprecated. "
|
|
520
|
+
"Use `%s` instead.",
|
|
521
|
+
AUTHN_TYPE_YAML_KEY,
|
|
522
|
+
)
|
|
523
|
+
config["authentication"][AUTHN_TYPE_YAML_KEY] = authn_type
|
|
473
524
|
|
|
474
525
|
# Load authentication plugin
|
|
475
|
-
|
|
526
|
+
authn_plugin = _load_plugin(
|
|
476
527
|
section="authentication",
|
|
477
|
-
yaml_key=
|
|
478
|
-
loader=
|
|
528
|
+
yaml_key=AUTHN_TYPE_YAML_KEY,
|
|
529
|
+
loader=get_control_authn_plugins,
|
|
479
530
|
)
|
|
480
531
|
|
|
481
532
|
# Load authorization plugin
|
|
@@ -485,10 +536,10 @@ def _try_obtain_control_auth_plugins(
|
|
|
485
536
|
loader=get_control_authz_plugins,
|
|
486
537
|
)
|
|
487
538
|
|
|
488
|
-
return
|
|
539
|
+
return authn_plugin, authz_plugin
|
|
489
540
|
|
|
490
541
|
|
|
491
|
-
def _try_obtain_control_event_log_writer_plugin() ->
|
|
542
|
+
def _try_obtain_control_event_log_writer_plugin() -> EventLogWriterPlugin | None:
|
|
492
543
|
"""Return an instance of the event log writer plugin."""
|
|
493
544
|
try:
|
|
494
545
|
all_plugins: dict[str, type[EventLogWriterPlugin]] = (
|
|
@@ -502,7 +553,7 @@ def _try_obtain_control_event_log_writer_plugin() -> Optional[EventLogWriterPlug
|
|
|
502
553
|
sys.exit("No event log writer plugins are currently supported.")
|
|
503
554
|
|
|
504
555
|
|
|
505
|
-
def _try_obtain_fleet_event_log_writer_plugin() ->
|
|
556
|
+
def _try_obtain_fleet_event_log_writer_plugin() -> EventLogWriterPlugin | None:
|
|
506
557
|
"""Return an instance of the Fleet Servicer event log writer plugin."""
|
|
507
558
|
try:
|
|
508
559
|
all_plugins: dict[str, type[EventLogWriterPlugin]] = (
|
|
@@ -521,8 +572,9 @@ def _run_fleet_api_grpc_rere( # pylint: disable=R0913, R0917
|
|
|
521
572
|
state_factory: LinkStateFactory,
|
|
522
573
|
ffs_factory: FfsFactory,
|
|
523
574
|
objectstore_factory: ObjectStoreFactory,
|
|
524
|
-
|
|
525
|
-
|
|
575
|
+
enable_supernode_auth: bool,
|
|
576
|
+
certificates: tuple[bytes, bytes, bytes] | None,
|
|
577
|
+
interceptors: Sequence[grpc.ServerInterceptor] | None = None,
|
|
526
578
|
) -> grpc.Server:
|
|
527
579
|
"""Run Fleet API (gRPC, request-response)."""
|
|
528
580
|
# Create Fleet API gRPC server
|
|
@@ -530,6 +582,7 @@ def _run_fleet_api_grpc_rere( # pylint: disable=R0913, R0917
|
|
|
530
582
|
state_factory=state_factory,
|
|
531
583
|
ffs_factory=ffs_factory,
|
|
532
584
|
objectstore_factory=objectstore_factory,
|
|
585
|
+
enable_supernode_auth=enable_supernode_auth,
|
|
533
586
|
)
|
|
534
587
|
fleet_add_servicer_to_server_fn = add_FleetServicer_to_server
|
|
535
588
|
fleet_grpc_server = generic_create_grpc_server(
|
|
@@ -548,12 +601,13 @@ def _run_fleet_api_grpc_rere( # pylint: disable=R0913, R0917
|
|
|
548
601
|
return fleet_grpc_server
|
|
549
602
|
|
|
550
603
|
|
|
604
|
+
# pylint: disable=R0913, R0917
|
|
551
605
|
def _run_fleet_api_grpc_adapter(
|
|
552
606
|
address: str,
|
|
553
607
|
state_factory: LinkStateFactory,
|
|
554
608
|
ffs_factory: FfsFactory,
|
|
555
609
|
objectstore_factory: ObjectStoreFactory,
|
|
556
|
-
certificates:
|
|
610
|
+
certificates: tuple[bytes, bytes, bytes] | None,
|
|
557
611
|
) -> grpc.Server:
|
|
558
612
|
"""Run Fleet API (GrpcAdapter)."""
|
|
559
613
|
# Create Fleet API gRPC server
|
|
@@ -561,6 +615,7 @@ def _run_fleet_api_grpc_adapter(
|
|
|
561
615
|
state_factory=state_factory,
|
|
562
616
|
ffs_factory=ffs_factory,
|
|
563
617
|
objectstore_factory=objectstore_factory,
|
|
618
|
+
enable_supernode_auth=False,
|
|
564
619
|
)
|
|
565
620
|
fleet_add_servicer_to_server_fn = add_GrpcAdapterServicer_to_server
|
|
566
621
|
fleet_grpc_server = generic_create_grpc_server(
|
|
@@ -585,8 +640,8 @@ def _run_fleet_api_grpc_adapter(
|
|
|
585
640
|
def _run_fleet_api_rest(
|
|
586
641
|
host: str,
|
|
587
642
|
port: int,
|
|
588
|
-
ssl_keyfile:
|
|
589
|
-
ssl_certfile:
|
|
643
|
+
ssl_keyfile: str | None,
|
|
644
|
+
ssl_certfile: str | None,
|
|
590
645
|
state_factory: LinkStateFactory,
|
|
591
646
|
ffs_factory: FfsFactory,
|
|
592
647
|
objectstore_factory: ObjectStoreFactory,
|
|
@@ -691,11 +746,9 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
|
|
|
691
746
|
parser.add_argument(
|
|
692
747
|
"--database",
|
|
693
748
|
help="A string representing the path to the database "
|
|
694
|
-
"file that will be opened.
|
|
695
|
-
"will open a connection to a database that is in RAM, "
|
|
696
|
-
"instead of on disk. If nothing is provided, "
|
|
749
|
+
"file that will be opened. If nothing is provided, "
|
|
697
750
|
"Flower will just create a state in memory.",
|
|
698
|
-
default=
|
|
751
|
+
default=FLWR_IN_MEMORY_DB_NAME,
|
|
699
752
|
)
|
|
700
753
|
parser.add_argument(
|
|
701
754
|
"--storage-dir",
|
|
@@ -705,18 +758,12 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
|
|
|
705
758
|
parser.add_argument(
|
|
706
759
|
"--auth-list-public-keys",
|
|
707
760
|
type=str,
|
|
708
|
-
help="A CSV file (as a path str) containing a list of known public "
|
|
709
|
-
"keys to enable authentication.",
|
|
710
|
-
)
|
|
711
|
-
parser.add_argument(
|
|
712
|
-
"--auth-superlink-private-key",
|
|
713
|
-
type=str,
|
|
714
761
|
help="This argument is deprecated and will be removed in a future release.",
|
|
715
762
|
)
|
|
716
763
|
parser.add_argument(
|
|
717
|
-
"--
|
|
718
|
-
|
|
719
|
-
help="
|
|
764
|
+
"--enable-supernode-auth",
|
|
765
|
+
action="store_true",
|
|
766
|
+
help="Enable supernode authentication.",
|
|
720
767
|
)
|
|
721
768
|
|
|
722
769
|
|
flwr/server/client_manager.py
CHANGED
|
@@ -19,7 +19,6 @@ import random
|
|
|
19
19
|
import threading
|
|
20
20
|
from abc import ABC, abstractmethod
|
|
21
21
|
from logging import INFO
|
|
22
|
-
from typing import Optional
|
|
23
22
|
|
|
24
23
|
from flwr.common.logger import log
|
|
25
24
|
|
|
@@ -80,8 +79,8 @@ class ClientManager(ABC):
|
|
|
80
79
|
def sample(
|
|
81
80
|
self,
|
|
82
81
|
num_clients: int,
|
|
83
|
-
min_num_clients:
|
|
84
|
-
criterion:
|
|
82
|
+
min_num_clients: int | None = None,
|
|
83
|
+
criterion: Criterion | None = None,
|
|
85
84
|
) -> list[ClientProxy]:
|
|
86
85
|
"""Sample a number of Flower ClientProxy instances."""
|
|
87
86
|
|
|
@@ -179,8 +178,8 @@ class SimpleClientManager(ClientManager):
|
|
|
179
178
|
def sample(
|
|
180
179
|
self,
|
|
181
180
|
num_clients: int,
|
|
182
|
-
min_num_clients:
|
|
183
|
-
criterion:
|
|
181
|
+
min_num_clients: int | None = None,
|
|
182
|
+
criterion: Criterion | None = None,
|
|
184
183
|
) -> list[ClientProxy]:
|
|
185
184
|
"""Sample a number of Flower ClientProxy instances."""
|
|
186
185
|
# Block until at least num_clients are connected.
|