flwr-nightly 1.9.0.dev20240502__tar.gz → 1.9.0.dev20240506__tar.gz
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.
Potentially problematic release.
This version of flwr-nightly might be problematic. Click here for more details.
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/PKG-INFO +1 -1
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/pyproject.toml +1 -1
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/message.py +33 -4
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/parametersrecord.py +0 -1
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/recordset.py +12 -1
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/app.py +13 -7
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_rere/server_interceptor.py +94 -53
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/state/in_memory_state.py +40 -8
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/state/sqlite_state.py +45 -7
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/state/state.py +9 -3
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/LICENSE +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/README.md +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/build.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/config_utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/example.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/new.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/.gitignore.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/README.md.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/__init__.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/client.numpy.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/client.pytorch.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/client.sklearn.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/server.numpy.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/server.pytorch.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/server.sklearn.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/task.pytorch.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/run/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/run/run.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/client.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/client_app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/dpfedavg_numpy_client.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/grpc_client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/grpc_client/connection.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/grpc_rere_client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/grpc_rere_client/client_interceptor.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/grpc_rere_client/connection.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/heartbeat.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/message_handler/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/message_handler/message_handler.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/message_handler/task_handler.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/centraldp_mods.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/comms_mods.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/localdp_mod.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/secure_aggregation/secagg_mod.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/secure_aggregation/secaggplus_mod.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/mod/utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/node_state.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/node_state_tests.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/numpy_client.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/rest_client/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/rest_client/connection.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/supernode/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/supernode/app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/typing.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/address.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/constant.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/context.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/date.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/differential_privacy.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/differential_privacy_constants.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/dp.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/exit_handlers.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/logger.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/object_ref.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/parameter.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/pyproject.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/configsrecord.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/conversion_utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/metricsrecord.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/record/typeddict.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/recordset_compat.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/retry_invoker.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/crypto/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/crypto/shamir.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/crypto/symmetric_encryption.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/ndarrays_arithmetic.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/quantization.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/secaggplus_constants.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/secure_aggregation/secaggplus_utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/serde.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/telemetry.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/typing.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/version.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/driver_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/driver_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/driver_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/driver_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/error_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/error_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/error_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/error_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/fleet_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/fleet_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/fleet_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/fleet_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/node_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/node_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/node_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/node_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/recordset_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/recordset_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/recordset_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/recordset_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/task_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/task_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/task_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/task_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/transport_pb2.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/transport_pb2.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/transport_pb2_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/proto/transport_pb2_grpc.pyi +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/py.typed +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/client_manager.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/compat/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/compat/app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/compat/app_utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/compat/driver_client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/compat/legacy_context.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/criterion.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/driver/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/driver/driver.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/driver/grpc_driver.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/history.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/run_serverapp.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/server.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/server_app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/server_config.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/aggregate.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/bulyan.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/dp_adaptive_clipping.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/dp_fixed_clipping.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/dpfedavg_adaptive.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/dpfedavg_fixed.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fault_tolerant_fedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedadagrad.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedadam.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedavg_android.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedavgm.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedmedian.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedopt.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedprox.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedtrimmedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedxgb_bagging.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedxgb_cyclic.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedxgb_nn_avg.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/fedyogi.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/krum.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/qfedavg.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/strategy/strategy.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/driver/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/driver/driver_grpc.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/driver/driver_servicer.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_bidi/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_rere/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/message_handler/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/message_handler/message_handler.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/rest_rere/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/rest_rere/rest_api.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/vce/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/vce/backend/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/vce/backend/backend.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/vce/backend/raybackend.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/fleet/vce/vce_api.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/state/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/state/state_factory.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/superlink/state/utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/typing.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/utils/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/utils/tensorboard.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/utils/validator.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/workflow/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/workflow/constant.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/workflow/default_workflows.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/workflow/secure_aggregation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/workflow/secure_aggregation/secagg_workflow.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/app.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/ray_transport/__init__.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/ray_transport/ray_actor.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/ray_transport/ray_client_proxy.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/ray_transport/utils.py +0 -0
- {flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/simulation/run_simulation.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
|
4
4
|
|
|
5
5
|
[tool.poetry]
|
|
6
6
|
name = "flwr-nightly"
|
|
7
|
-
version = "1.9.0.
|
|
7
|
+
version = "1.9.0.dev20240506"
|
|
8
8
|
description = "Flower: A Friendly Federated Learning Framework"
|
|
9
9
|
license = "Apache-2.0"
|
|
10
10
|
authors = ["The Flower Authors <hello@flower.ai>"]
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/common/message.py
RENAMED
|
@@ -18,7 +18,6 @@ from __future__ import annotations
|
|
|
18
18
|
|
|
19
19
|
import time
|
|
20
20
|
import warnings
|
|
21
|
-
from dataclasses import dataclass
|
|
22
21
|
from typing import Optional, cast
|
|
23
22
|
|
|
24
23
|
from .record import RecordSet
|
|
@@ -26,7 +25,6 @@ from .record import RecordSet
|
|
|
26
25
|
DEFAULT_TTL = 3600
|
|
27
26
|
|
|
28
27
|
|
|
29
|
-
@dataclass
|
|
30
28
|
class Metadata: # pylint: disable=too-many-instance-attributes
|
|
31
29
|
"""A dataclass holding metadata associated with the current message.
|
|
32
30
|
|
|
@@ -161,8 +159,18 @@ class Metadata: # pylint: disable=too-many-instance-attributes
|
|
|
161
159
|
"""Set partition_id."""
|
|
162
160
|
self.__dict__["_partition_id"] = value
|
|
163
161
|
|
|
162
|
+
def __repr__(self) -> str:
|
|
163
|
+
"""Return a string representation of this instance."""
|
|
164
|
+
view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
|
|
165
|
+
return f"{self.__class__.__qualname__}({view})"
|
|
166
|
+
|
|
167
|
+
def __eq__(self, other: object) -> bool:
|
|
168
|
+
"""Compare two instances of the class."""
|
|
169
|
+
if not isinstance(other, self.__class__):
|
|
170
|
+
raise NotImplementedError
|
|
171
|
+
return self.__dict__ == other.__dict__
|
|
172
|
+
|
|
164
173
|
|
|
165
|
-
@dataclass
|
|
166
174
|
class Error:
|
|
167
175
|
"""A dataclass that stores information about an error that occurred.
|
|
168
176
|
|
|
@@ -191,8 +199,18 @@ class Error:
|
|
|
191
199
|
"""Reason reported about the error."""
|
|
192
200
|
return cast(Optional[str], self.__dict__["_reason"])
|
|
193
201
|
|
|
202
|
+
def __repr__(self) -> str:
|
|
203
|
+
"""Return a string representation of this instance."""
|
|
204
|
+
view = ", ".join([f"{k.lstrip('_')}={v!r}" for k, v in self.__dict__.items()])
|
|
205
|
+
return f"{self.__class__.__qualname__}({view})"
|
|
206
|
+
|
|
207
|
+
def __eq__(self, other: object) -> bool:
|
|
208
|
+
"""Compare two instances of the class."""
|
|
209
|
+
if not isinstance(other, self.__class__):
|
|
210
|
+
raise NotImplementedError
|
|
211
|
+
return self.__dict__ == other.__dict__
|
|
212
|
+
|
|
194
213
|
|
|
195
|
-
@dataclass
|
|
196
214
|
class Message:
|
|
197
215
|
"""State of your application from the viewpoint of the entity using it.
|
|
198
216
|
|
|
@@ -357,6 +375,17 @@ class Message:
|
|
|
357
375
|
|
|
358
376
|
return message
|
|
359
377
|
|
|
378
|
+
def __repr__(self) -> str:
|
|
379
|
+
"""Return a string representation of this instance."""
|
|
380
|
+
view = ", ".join(
|
|
381
|
+
[
|
|
382
|
+
f"{k.lstrip('_')}={v!r}"
|
|
383
|
+
for k, v in self.__dict__.items()
|
|
384
|
+
if v is not None
|
|
385
|
+
]
|
|
386
|
+
)
|
|
387
|
+
return f"{self.__class__.__qualname__}({view})"
|
|
388
|
+
|
|
360
389
|
|
|
361
390
|
def _create_reply_metadata(msg: Message, ttl: float) -> Metadata:
|
|
362
391
|
"""Construct metadata for a reply message."""
|
|
@@ -83,7 +83,6 @@ class RecordSetData:
|
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
@dataclass
|
|
87
86
|
class RecordSet:
|
|
88
87
|
"""RecordSet stores groups of parameters, metrics and configs."""
|
|
89
88
|
|
|
@@ -117,3 +116,15 @@ class RecordSet:
|
|
|
117
116
|
"""Dictionary holding ConfigsRecord instances."""
|
|
118
117
|
data = cast(RecordSetData, self.__dict__["_data"])
|
|
119
118
|
return data.configs_records
|
|
119
|
+
|
|
120
|
+
def __repr__(self) -> str:
|
|
121
|
+
"""Return a string representation of this instance."""
|
|
122
|
+
flds = ("parameters_records", "metrics_records", "configs_records")
|
|
123
|
+
view = ", ".join([f"{fld}={getattr(self, fld)!r}" for fld in flds])
|
|
124
|
+
return f"{self.__class__.__qualname__}({view})"
|
|
125
|
+
|
|
126
|
+
def __eq__(self, other: object) -> bool:
|
|
127
|
+
"""Compare two instances of the class."""
|
|
128
|
+
if not isinstance(other, self.__class__):
|
|
129
|
+
raise NotImplementedError
|
|
130
|
+
return self.__dict__ == other.__dict__
|
|
@@ -43,6 +43,7 @@ from flwr.common.constant import (
|
|
|
43
43
|
from flwr.common.exit_handlers import register_exit_handlers
|
|
44
44
|
from flwr.common.logger import log
|
|
45
45
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
|
46
|
+
private_key_to_bytes,
|
|
46
47
|
public_key_to_bytes,
|
|
47
48
|
ssh_types_to_elliptic_curve,
|
|
48
49
|
)
|
|
@@ -374,13 +375,18 @@ def run_superlink() -> None:
|
|
|
374
375
|
server_private_key,
|
|
375
376
|
server_public_key,
|
|
376
377
|
) = maybe_keys
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
378
|
+
state = state_factory.state()
|
|
379
|
+
state.store_client_public_keys(client_public_keys)
|
|
380
|
+
state.store_server_private_public_key(
|
|
381
|
+
private_key_to_bytes(server_private_key),
|
|
382
|
+
public_key_to_bytes(server_public_key),
|
|
383
|
+
)
|
|
384
|
+
log(
|
|
385
|
+
INFO,
|
|
386
|
+
"Client authentication enabled with %d known public keys",
|
|
387
|
+
len(client_public_keys),
|
|
388
|
+
)
|
|
389
|
+
interceptors = [AuthenticateServerInterceptor(state)]
|
|
384
390
|
|
|
385
391
|
fleet_server = _run_fleet_api_grpc_rere(
|
|
386
392
|
address=address,
|
|
@@ -16,17 +16,17 @@
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
import base64
|
|
19
|
-
from logging import
|
|
20
|
-
from typing import Any, Callable,
|
|
19
|
+
from logging import WARNING
|
|
20
|
+
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
|
21
21
|
|
|
22
22
|
import grpc
|
|
23
23
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
24
24
|
|
|
25
25
|
from flwr.common.logger import log
|
|
26
26
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
|
27
|
+
bytes_to_private_key,
|
|
27
28
|
bytes_to_public_key,
|
|
28
29
|
generate_shared_key,
|
|
29
|
-
public_key_to_bytes,
|
|
30
30
|
verify_hmac,
|
|
31
31
|
)
|
|
32
32
|
from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
@@ -43,6 +43,8 @@ from flwr.proto.fleet_pb2 import ( # pylint: disable=E0611
|
|
|
43
43
|
PushTaskResRequest,
|
|
44
44
|
PushTaskResResponse,
|
|
45
45
|
)
|
|
46
|
+
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
|
47
|
+
from flwr.server.superlink.state import State
|
|
46
48
|
|
|
47
49
|
_PUBLIC_KEY_HEADER = "public-key"
|
|
48
50
|
_AUTH_TOKEN_HEADER = "auth-token"
|
|
@@ -79,22 +81,21 @@ def _get_value_from_tuples(
|
|
|
79
81
|
class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
80
82
|
"""Server interceptor for client authentication."""
|
|
81
83
|
|
|
82
|
-
def __init__(
|
|
83
|
-
self
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
84
|
+
def __init__(self, state: State):
|
|
85
|
+
self.state = state
|
|
86
|
+
|
|
87
|
+
self.client_public_keys = state.get_client_public_keys()
|
|
88
|
+
if len(self.client_public_keys) == 0:
|
|
89
|
+
log(WARNING, "Authentication enabled, but no known public keys configured")
|
|
90
|
+
|
|
91
|
+
private_key = self.state.get_server_private_key()
|
|
92
|
+
public_key = self.state.get_server_public_key()
|
|
93
|
+
|
|
94
|
+
if private_key is None or public_key is None:
|
|
95
|
+
raise ValueError("Error loading authentication keys")
|
|
96
|
+
|
|
97
|
+
self.server_private_key = bytes_to_private_key(private_key)
|
|
98
|
+
self.encoded_server_public_key = base64.urlsafe_b64encode(public_key)
|
|
98
99
|
|
|
99
100
|
def intercept_service(
|
|
100
101
|
self,
|
|
@@ -124,45 +125,29 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
124
125
|
_PUBLIC_KEY_HEADER, context.invocation_metadata()
|
|
125
126
|
)
|
|
126
127
|
)
|
|
127
|
-
|
|
128
|
-
if not is_public_key_known:
|
|
128
|
+
if client_public_key_bytes not in self.client_public_keys:
|
|
129
129
|
context.abort(grpc.StatusCode.UNAUTHENTICATED, "Access denied")
|
|
130
130
|
|
|
131
131
|
if isinstance(request, CreateNodeRequest):
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
(
|
|
135
|
-
_PUBLIC_KEY_HEADER,
|
|
136
|
-
self.encoded_server_public_key,
|
|
137
|
-
),
|
|
138
|
-
)
|
|
132
|
+
return self._create_authenticated_node(
|
|
133
|
+
client_public_key_bytes, request, context
|
|
139
134
|
)
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
PushTaskResRequest,
|
|
146
|
-
GetRunRequest,
|
|
147
|
-
PingRequest,
|
|
148
|
-
),
|
|
149
|
-
):
|
|
150
|
-
hmac_value = base64.urlsafe_b64decode(
|
|
151
|
-
_get_value_from_tuples(
|
|
152
|
-
_AUTH_TOKEN_HEADER, context.invocation_metadata()
|
|
153
|
-
)
|
|
154
|
-
)
|
|
155
|
-
client_public_key = bytes_to_public_key(client_public_key_bytes)
|
|
156
|
-
shared_secret = generate_shared_key(
|
|
157
|
-
self.server_private_key,
|
|
158
|
-
client_public_key,
|
|
159
|
-
)
|
|
160
|
-
verify = verify_hmac(
|
|
161
|
-
shared_secret, request.SerializeToString(True), hmac_value
|
|
135
|
+
|
|
136
|
+
# Verify hmac value
|
|
137
|
+
hmac_value = base64.urlsafe_b64decode(
|
|
138
|
+
_get_value_from_tuples(
|
|
139
|
+
_AUTH_TOKEN_HEADER, context.invocation_metadata()
|
|
162
140
|
)
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
141
|
+
)
|
|
142
|
+
public_key = bytes_to_public_key(client_public_key_bytes)
|
|
143
|
+
|
|
144
|
+
if not self._verify_hmac(public_key, request, hmac_value):
|
|
145
|
+
context.abort(grpc.StatusCode.UNAUTHENTICATED, "Access denied")
|
|
146
|
+
|
|
147
|
+
# Verify node_id
|
|
148
|
+
node_id = self.state.get_node_id(client_public_key_bytes)
|
|
149
|
+
|
|
150
|
+
if not self._verify_node_id(node_id, request):
|
|
166
151
|
context.abort(grpc.StatusCode.UNAUTHENTICATED, "Access denied")
|
|
167
152
|
|
|
168
153
|
return method_handler.unary_unary(request, context) # type: ignore
|
|
@@ -172,3 +157,59 @@ class AuthenticateServerInterceptor(grpc.ServerInterceptor): # type: ignore
|
|
|
172
157
|
request_deserializer=method_handler.request_deserializer,
|
|
173
158
|
response_serializer=method_handler.response_serializer,
|
|
174
159
|
)
|
|
160
|
+
|
|
161
|
+
def _verify_node_id(
|
|
162
|
+
self,
|
|
163
|
+
node_id: Optional[int],
|
|
164
|
+
request: Union[
|
|
165
|
+
DeleteNodeRequest,
|
|
166
|
+
PullTaskInsRequest,
|
|
167
|
+
PushTaskResRequest,
|
|
168
|
+
GetRunRequest,
|
|
169
|
+
PingRequest,
|
|
170
|
+
],
|
|
171
|
+
) -> bool:
|
|
172
|
+
if node_id is None:
|
|
173
|
+
return False
|
|
174
|
+
if isinstance(request, PushTaskResRequest):
|
|
175
|
+
if len(request.task_res_list) == 0:
|
|
176
|
+
return False
|
|
177
|
+
return request.task_res_list[0].task.producer.node_id == node_id
|
|
178
|
+
if isinstance(request, GetRunRequest):
|
|
179
|
+
return node_id in self.state.get_nodes(request.run_id)
|
|
180
|
+
return request.node.node_id == node_id
|
|
181
|
+
|
|
182
|
+
def _verify_hmac(
|
|
183
|
+
self, public_key: ec.EllipticCurvePublicKey, request: Request, hmac_value: bytes
|
|
184
|
+
) -> bool:
|
|
185
|
+
shared_secret = generate_shared_key(self.server_private_key, public_key)
|
|
186
|
+
return verify_hmac(shared_secret, request.SerializeToString(True), hmac_value)
|
|
187
|
+
|
|
188
|
+
def _create_authenticated_node(
|
|
189
|
+
self,
|
|
190
|
+
public_key_bytes: bytes,
|
|
191
|
+
request: CreateNodeRequest,
|
|
192
|
+
context: grpc.ServicerContext,
|
|
193
|
+
) -> CreateNodeResponse:
|
|
194
|
+
context.send_initial_metadata(
|
|
195
|
+
(
|
|
196
|
+
(
|
|
197
|
+
_PUBLIC_KEY_HEADER,
|
|
198
|
+
self.encoded_server_public_key,
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
node_id = self.state.get_node_id(public_key_bytes)
|
|
204
|
+
|
|
205
|
+
# Handle `CreateNode` here instead of calling the default method handler
|
|
206
|
+
# Return previously assigned `node_id` for the provided `public_key`
|
|
207
|
+
if node_id is not None:
|
|
208
|
+
self.state.acknowledge_ping(node_id, request.ping_interval)
|
|
209
|
+
return CreateNodeResponse(node=Node(node_id=node_id, anonymous=False))
|
|
210
|
+
|
|
211
|
+
# No `node_id` exists for the provided `public_key`
|
|
212
|
+
# Handle `CreateNode` here instead of calling the default method handler
|
|
213
|
+
# Note: the innermost `CreateNode` method will never be called
|
|
214
|
+
node_id = self.state.create_node(request.ping_interval, public_key_bytes)
|
|
215
|
+
return CreateNodeResponse(node=Node(node_id=node_id, anonymous=False))
|
|
@@ -30,19 +30,24 @@ from flwr.server.utils import validate_task_ins_or_res
|
|
|
30
30
|
from .utils import make_node_unavailable_taskres
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
class InMemoryState(State): # pylint: disable=R0902
|
|
33
|
+
class InMemoryState(State): # pylint: disable=R0902,R0904
|
|
34
34
|
"""In-memory State implementation."""
|
|
35
35
|
|
|
36
36
|
def __init__(self) -> None:
|
|
37
|
+
|
|
37
38
|
# Map node_id to (online_until, ping_interval)
|
|
38
39
|
self.node_ids: Dict[int, Tuple[float, float]] = {}
|
|
40
|
+
self.public_key_to_node_id: Dict[bytes, int] = {}
|
|
41
|
+
|
|
39
42
|
# Map run_id to (fab_id, fab_version)
|
|
40
43
|
self.run_ids: Dict[int, Tuple[str, str]] = {}
|
|
41
44
|
self.task_ins_store: Dict[UUID, TaskIns] = {}
|
|
42
45
|
self.task_res_store: Dict[UUID, TaskRes] = {}
|
|
46
|
+
|
|
43
47
|
self.client_public_keys: Set[bytes] = set()
|
|
44
48
|
self.server_public_key: Optional[bytes] = None
|
|
45
49
|
self.server_private_key: Optional[bytes] = None
|
|
50
|
+
|
|
46
51
|
self.lock = threading.Lock()
|
|
47
52
|
|
|
48
53
|
def store_task_ins(self, task_ins: TaskIns) -> Optional[UUID]:
|
|
@@ -205,23 +210,46 @@ class InMemoryState(State): # pylint: disable=R0902
|
|
|
205
210
|
"""
|
|
206
211
|
return len(self.task_res_store)
|
|
207
212
|
|
|
208
|
-
def create_node(
|
|
213
|
+
def create_node(
|
|
214
|
+
self, ping_interval: float, public_key: Optional[bytes] = None
|
|
215
|
+
) -> int:
|
|
209
216
|
"""Create, store in state, and return `node_id`."""
|
|
210
217
|
# Sample a random int64 as node_id
|
|
211
218
|
node_id: int = int.from_bytes(os.urandom(8), "little", signed=True)
|
|
212
219
|
|
|
213
220
|
with self.lock:
|
|
214
|
-
if node_id
|
|
215
|
-
|
|
216
|
-
return
|
|
217
|
-
log(ERROR, "Unexpected node registration failure.")
|
|
218
|
-
return 0
|
|
221
|
+
if node_id in self.node_ids:
|
|
222
|
+
log(ERROR, "Unexpected node registration failure.")
|
|
223
|
+
return 0
|
|
219
224
|
|
|
220
|
-
|
|
225
|
+
if public_key is not None:
|
|
226
|
+
if (
|
|
227
|
+
public_key in self.public_key_to_node_id
|
|
228
|
+
or node_id in self.public_key_to_node_id.values()
|
|
229
|
+
):
|
|
230
|
+
log(ERROR, "Unexpected node registration failure.")
|
|
231
|
+
return 0
|
|
232
|
+
|
|
233
|
+
self.public_key_to_node_id[public_key] = node_id
|
|
234
|
+
|
|
235
|
+
self.node_ids[node_id] = (time.time() + ping_interval, ping_interval)
|
|
236
|
+
return node_id
|
|
237
|
+
|
|
238
|
+
def delete_node(self, node_id: int, public_key: Optional[bytes] = None) -> None:
|
|
221
239
|
"""Delete a client node."""
|
|
222
240
|
with self.lock:
|
|
223
241
|
if node_id not in self.node_ids:
|
|
224
242
|
raise ValueError(f"Node {node_id} not found")
|
|
243
|
+
|
|
244
|
+
if public_key is not None:
|
|
245
|
+
if (
|
|
246
|
+
public_key not in self.public_key_to_node_id
|
|
247
|
+
or node_id not in self.public_key_to_node_id.values()
|
|
248
|
+
):
|
|
249
|
+
raise ValueError("Public key or node_id not found")
|
|
250
|
+
|
|
251
|
+
del self.public_key_to_node_id[public_key]
|
|
252
|
+
|
|
225
253
|
del self.node_ids[node_id]
|
|
226
254
|
|
|
227
255
|
def get_nodes(self, run_id: int) -> Set[int]:
|
|
@@ -242,6 +270,10 @@ class InMemoryState(State): # pylint: disable=R0902
|
|
|
242
270
|
if online_until > current_time
|
|
243
271
|
}
|
|
244
272
|
|
|
273
|
+
def get_node_id(self, client_public_key: bytes) -> Optional[int]:
|
|
274
|
+
"""Retrieve stored `node_id` filtered by `client_public_keys`."""
|
|
275
|
+
return self.public_key_to_node_id.get(client_public_key)
|
|
276
|
+
|
|
245
277
|
def create_run(self, fab_id: str, fab_version: str) -> int:
|
|
246
278
|
"""Create a new run for the specified `fab_id` and `fab_version`."""
|
|
247
279
|
# Sample a random int64 as run_id
|
|
@@ -36,7 +36,8 @@ SQL_CREATE_TABLE_NODE = """
|
|
|
36
36
|
CREATE TABLE IF NOT EXISTS node(
|
|
37
37
|
node_id INTEGER UNIQUE,
|
|
38
38
|
online_until REAL,
|
|
39
|
-
ping_interval REAL
|
|
39
|
+
ping_interval REAL,
|
|
40
|
+
public_key BLOB
|
|
40
41
|
);
|
|
41
42
|
"""
|
|
42
43
|
|
|
@@ -534,26 +535,54 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
534
535
|
|
|
535
536
|
return None
|
|
536
537
|
|
|
537
|
-
def create_node(
|
|
538
|
+
def create_node(
|
|
539
|
+
self, ping_interval: float, public_key: Optional[bytes] = None
|
|
540
|
+
) -> int:
|
|
538
541
|
"""Create, store in state, and return `node_id`."""
|
|
539
542
|
# Sample a random int64 as node_id
|
|
540
543
|
node_id: int = int.from_bytes(os.urandom(8), "little", signed=True)
|
|
541
544
|
|
|
545
|
+
query = "SELECT node_id FROM node WHERE public_key = :public_key;"
|
|
546
|
+
row = self.query(query, {"public_key": public_key})
|
|
547
|
+
|
|
548
|
+
if len(row) > 0:
|
|
549
|
+
log(ERROR, "Unexpected node registration failure.")
|
|
550
|
+
return 0
|
|
551
|
+
|
|
542
552
|
query = (
|
|
543
|
-
"INSERT INTO node
|
|
553
|
+
"INSERT INTO node "
|
|
554
|
+
"(node_id, online_until, ping_interval, public_key) "
|
|
555
|
+
"VALUES (?, ?, ?, ?)"
|
|
544
556
|
)
|
|
545
557
|
|
|
546
558
|
try:
|
|
547
|
-
self.query(
|
|
559
|
+
self.query(
|
|
560
|
+
query, (node_id, time.time() + ping_interval, ping_interval, public_key)
|
|
561
|
+
)
|
|
548
562
|
except sqlite3.IntegrityError:
|
|
549
563
|
log(ERROR, "Unexpected node registration failure.")
|
|
550
564
|
return 0
|
|
551
565
|
return node_id
|
|
552
566
|
|
|
553
|
-
def delete_node(self, node_id: int) -> None:
|
|
567
|
+
def delete_node(self, node_id: int, public_key: Optional[bytes] = None) -> None:
|
|
554
568
|
"""Delete a client node."""
|
|
555
|
-
query = "DELETE FROM node WHERE node_id =
|
|
556
|
-
|
|
569
|
+
query = "DELETE FROM node WHERE node_id = ?"
|
|
570
|
+
params = (node_id,)
|
|
571
|
+
|
|
572
|
+
if public_key is not None:
|
|
573
|
+
query += " AND public_key = ?"
|
|
574
|
+
params += (public_key,) # type: ignore
|
|
575
|
+
|
|
576
|
+
if self.conn is None:
|
|
577
|
+
raise AttributeError("State is not initialized.")
|
|
578
|
+
|
|
579
|
+
try:
|
|
580
|
+
with self.conn:
|
|
581
|
+
rows = self.conn.execute(query, params)
|
|
582
|
+
if rows.rowcount < 1:
|
|
583
|
+
raise ValueError("Public key or node_id not found")
|
|
584
|
+
except KeyError as exc:
|
|
585
|
+
log(ERROR, {"query": query, "data": params, "exception": exc})
|
|
557
586
|
|
|
558
587
|
def get_nodes(self, run_id: int) -> Set[int]:
|
|
559
588
|
"""Retrieve all currently stored node IDs as a set.
|
|
@@ -574,6 +603,15 @@ class SqliteState(State): # pylint: disable=R0904
|
|
|
574
603
|
result: Set[int] = {row["node_id"] for row in rows}
|
|
575
604
|
return result
|
|
576
605
|
|
|
606
|
+
def get_node_id(self, client_public_key: bytes) -> Optional[int]:
|
|
607
|
+
"""Retrieve stored `node_id` filtered by `client_public_keys`."""
|
|
608
|
+
query = "SELECT node_id FROM node WHERE public_key = :public_key;"
|
|
609
|
+
row = self.query(query, {"public_key": client_public_key})
|
|
610
|
+
if len(row) > 0:
|
|
611
|
+
node_id: int = row[0]["node_id"]
|
|
612
|
+
return node_id
|
|
613
|
+
return None
|
|
614
|
+
|
|
577
615
|
def create_run(self, fab_id: str, fab_version: str) -> int:
|
|
578
616
|
"""Create a new run for the specified `fab_id` and `fab_version`."""
|
|
579
617
|
# Sample a random int64 as run_id
|
|
@@ -22,7 +22,7 @@ from uuid import UUID
|
|
|
22
22
|
from flwr.proto.task_pb2 import TaskIns, TaskRes # pylint: disable=E0611
|
|
23
23
|
|
|
24
24
|
|
|
25
|
-
class State(abc.ABC):
|
|
25
|
+
class State(abc.ABC): # pylint: disable=R0904
|
|
26
26
|
"""Abstract State."""
|
|
27
27
|
|
|
28
28
|
@abc.abstractmethod
|
|
@@ -132,11 +132,13 @@ class State(abc.ABC):
|
|
|
132
132
|
"""Delete all delivered TaskIns/TaskRes pairs."""
|
|
133
133
|
|
|
134
134
|
@abc.abstractmethod
|
|
135
|
-
def create_node(
|
|
135
|
+
def create_node(
|
|
136
|
+
self, ping_interval: float, public_key: Optional[bytes] = None
|
|
137
|
+
) -> int:
|
|
136
138
|
"""Create, store in state, and return `node_id`."""
|
|
137
139
|
|
|
138
140
|
@abc.abstractmethod
|
|
139
|
-
def delete_node(self, node_id: int) -> None:
|
|
141
|
+
def delete_node(self, node_id: int, public_key: Optional[bytes] = None) -> None:
|
|
140
142
|
"""Remove `node_id` from state."""
|
|
141
143
|
|
|
142
144
|
@abc.abstractmethod
|
|
@@ -149,6 +151,10 @@ class State(abc.ABC):
|
|
|
149
151
|
an empty `Set` MUST be returned.
|
|
150
152
|
"""
|
|
151
153
|
|
|
154
|
+
@abc.abstractmethod
|
|
155
|
+
def get_node_id(self, client_public_key: bytes) -> Optional[int]:
|
|
156
|
+
"""Retrieve stored `node_id` filtered by `client_public_keys`."""
|
|
157
|
+
|
|
152
158
|
@abc.abstractmethod
|
|
153
159
|
def create_run(self, fab_id: str, fab_version: str) -> int:
|
|
154
160
|
"""Create a new run for the specified `fab_id` and `fab_version`."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/config_utils.py
RENAMED
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/example.py
RENAMED
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/__init__.py
RENAMED
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/new/new.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/run/__init__.py
RENAMED
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/cli/run/run.py
RENAMED
|
File without changes
|
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{flwr_nightly-1.9.0.dev20240502 → flwr_nightly-1.9.0.dev20240506}/src/py/flwr/client/client.py
RENAMED
|
File without changes
|