flwr 1.22.0__py3-none-any.whl → 1.24.0__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.
Files changed (301) hide show
  1. flwr/__init__.py +16 -5
  2. flwr/app/error.py +2 -2
  3. flwr/app/exception.py +3 -3
  4. flwr/cli/app.py +34 -1
  5. flwr/cli/app_cmd/__init__.py +23 -0
  6. flwr/cli/app_cmd/publish.py +285 -0
  7. flwr/cli/app_cmd/review.py +252 -0
  8. flwr/cli/auth_plugin/__init__.py +15 -6
  9. flwr/cli/auth_plugin/auth_plugin.py +94 -0
  10. flwr/cli/auth_plugin/noop_auth_plugin.py +101 -0
  11. flwr/cli/auth_plugin/oidc_cli_plugin.py +46 -32
  12. flwr/cli/build.py +166 -53
  13. flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +29 -11
  14. flwr/cli/config_utils.py +101 -13
  15. flwr/cli/federation/__init__.py +24 -0
  16. flwr/cli/federation/ls.py +140 -0
  17. flwr/cli/federation/show.py +317 -0
  18. flwr/cli/install.py +91 -13
  19. flwr/cli/log.py +54 -11
  20. flwr/cli/login/login.py +41 -27
  21. flwr/cli/ls.py +177 -133
  22. flwr/cli/new/new.py +175 -40
  23. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +1 -0
  24. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +1 -1
  25. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +1 -1
  26. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +1 -1
  27. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  28. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +1 -1
  29. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  30. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
  31. flwr/cli/new/templates/app/pyproject.pytorch_legacy_api.toml.tpl +1 -1
  32. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  33. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +2 -2
  34. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +1 -1
  35. flwr/cli/pull.py +12 -7
  36. flwr/cli/run/run.py +82 -31
  37. flwr/cli/run_utils.py +130 -0
  38. flwr/cli/stop.py +27 -9
  39. flwr/cli/supernode/__init__.py +25 -0
  40. flwr/cli/supernode/ls.py +268 -0
  41. flwr/cli/supernode/register.py +190 -0
  42. flwr/cli/supernode/unregister.py +140 -0
  43. flwr/cli/utils.py +464 -81
  44. flwr/client/__init__.py +2 -1
  45. flwr/client/dpfedavg_numpy_client.py +4 -1
  46. flwr/client/grpc_adapter_client/connection.py +12 -15
  47. flwr/client/grpc_rere_client/connection.py +68 -41
  48. flwr/client/grpc_rere_client/grpc_adapter.py +34 -14
  49. flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +5 -7
  50. flwr/client/message_handler/message_handler.py +2 -2
  51. flwr/client/mod/secure_aggregation/secaggplus_mod.py +10 -8
  52. flwr/client/numpy_client.py +1 -1
  53. flwr/client/rest_client/connection.py +94 -51
  54. flwr/client/run_info_store.py +4 -5
  55. flwr/client/typing.py +1 -1
  56. flwr/clientapp/__init__.py +1 -2
  57. flwr/{client → clientapp}/client_app.py +9 -10
  58. flwr/clientapp/mod/centraldp_mods.py +16 -17
  59. flwr/clientapp/mod/localdp_mod.py +8 -9
  60. flwr/clientapp/typing.py +1 -1
  61. flwr/{client/clientapp → clientapp}/utils.py +4 -4
  62. flwr/common/address.py +1 -2
  63. flwr/common/args.py +3 -4
  64. flwr/common/config.py +13 -16
  65. flwr/common/constant.py +56 -13
  66. flwr/common/differential_privacy.py +3 -4
  67. flwr/common/event_log_plugin/event_log_plugin.py +3 -4
  68. flwr/common/exit/exit.py +15 -2
  69. flwr/common/exit/exit_code.py +39 -10
  70. flwr/common/exit/exit_handler.py +6 -2
  71. flwr/common/exit/signal_handler.py +5 -5
  72. flwr/common/grpc.py +6 -6
  73. flwr/common/inflatable_protobuf_utils.py +1 -1
  74. flwr/common/inflatable_utils.py +48 -31
  75. flwr/common/logger.py +19 -19
  76. flwr/common/message.py +4 -4
  77. flwr/common/object_ref.py +7 -7
  78. flwr/common/record/array.py +6 -6
  79. flwr/common/record/arrayrecord.py +18 -21
  80. flwr/common/record/configrecord.py +3 -3
  81. flwr/common/record/recorddict.py +5 -5
  82. flwr/common/record/typeddict.py +9 -2
  83. flwr/common/recorddict_compat.py +7 -10
  84. flwr/common/retry_invoker.py +20 -20
  85. flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
  86. flwr/common/secure_aggregation/ndarrays_arithmetic.py +3 -3
  87. flwr/common/serde.py +9 -6
  88. flwr/common/serde_utils.py +2 -2
  89. flwr/common/telemetry.py +9 -5
  90. flwr/common/typing.py +59 -43
  91. flwr/compat/client/app.py +39 -38
  92. flwr/compat/client/grpc_client/connection.py +13 -13
  93. flwr/compat/server/app.py +5 -6
  94. flwr/proto/appio_pb2.py +13 -3
  95. flwr/proto/appio_pb2.pyi +134 -65
  96. flwr/proto/appio_pb2_grpc.py +20 -0
  97. flwr/proto/appio_pb2_grpc.pyi +27 -0
  98. flwr/proto/clientappio_pb2.py +17 -7
  99. flwr/proto/clientappio_pb2.pyi +15 -0
  100. flwr/proto/clientappio_pb2_grpc.py +206 -40
  101. flwr/proto/clientappio_pb2_grpc.pyi +168 -53
  102. flwr/proto/control_pb2.py +72 -40
  103. flwr/proto/control_pb2.pyi +319 -87
  104. flwr/proto/control_pb2_grpc.py +339 -28
  105. flwr/proto/control_pb2_grpc.pyi +209 -37
  106. flwr/proto/error_pb2.py +13 -3
  107. flwr/proto/error_pb2.pyi +24 -6
  108. flwr/proto/error_pb2_grpc.py +20 -0
  109. flwr/proto/error_pb2_grpc.pyi +27 -0
  110. flwr/proto/fab_pb2.py +24 -10
  111. flwr/proto/fab_pb2.pyi +68 -20
  112. flwr/proto/fab_pb2_grpc.py +20 -0
  113. flwr/proto/fab_pb2_grpc.pyi +27 -0
  114. flwr/proto/federation_pb2.py +38 -0
  115. flwr/proto/federation_pb2.pyi +56 -0
  116. flwr/proto/federation_pb2_grpc.py +24 -0
  117. flwr/proto/federation_pb2_grpc.pyi +31 -0
  118. flwr/proto/fleet_pb2.py +45 -27
  119. flwr/proto/fleet_pb2.pyi +186 -70
  120. flwr/proto/fleet_pb2_grpc.py +277 -66
  121. flwr/proto/fleet_pb2_grpc.pyi +201 -55
  122. flwr/proto/grpcadapter_pb2.py +14 -4
  123. flwr/proto/grpcadapter_pb2.pyi +38 -16
  124. flwr/proto/grpcadapter_pb2_grpc.py +35 -4
  125. flwr/proto/grpcadapter_pb2_grpc.pyi +38 -7
  126. flwr/proto/heartbeat_pb2.py +17 -7
  127. flwr/proto/heartbeat_pb2.pyi +51 -22
  128. flwr/proto/heartbeat_pb2_grpc.py +20 -0
  129. flwr/proto/heartbeat_pb2_grpc.pyi +27 -0
  130. flwr/proto/log_pb2.py +13 -3
  131. flwr/proto/log_pb2.pyi +34 -11
  132. flwr/proto/log_pb2_grpc.py +20 -0
  133. flwr/proto/log_pb2_grpc.pyi +27 -0
  134. flwr/proto/message_pb2.py +15 -5
  135. flwr/proto/message_pb2.pyi +154 -86
  136. flwr/proto/message_pb2_grpc.py +20 -0
  137. flwr/proto/message_pb2_grpc.pyi +27 -0
  138. flwr/proto/node_pb2.py +16 -4
  139. flwr/proto/node_pb2.pyi +77 -4
  140. flwr/proto/node_pb2_grpc.py +20 -0
  141. flwr/proto/node_pb2_grpc.pyi +27 -0
  142. flwr/proto/recorddict_pb2.py +13 -3
  143. flwr/proto/recorddict_pb2.pyi +184 -107
  144. flwr/proto/recorddict_pb2_grpc.py +20 -0
  145. flwr/proto/recorddict_pb2_grpc.pyi +27 -0
  146. flwr/proto/run_pb2.py +40 -31
  147. flwr/proto/run_pb2.pyi +149 -84
  148. flwr/proto/run_pb2_grpc.py +20 -0
  149. flwr/proto/run_pb2_grpc.pyi +27 -0
  150. flwr/proto/serverappio_pb2.py +13 -3
  151. flwr/proto/serverappio_pb2.pyi +32 -8
  152. flwr/proto/serverappio_pb2_grpc.py +246 -65
  153. flwr/proto/serverappio_pb2_grpc.pyi +221 -85
  154. flwr/proto/simulationio_pb2.py +16 -8
  155. flwr/proto/simulationio_pb2.pyi +15 -0
  156. flwr/proto/simulationio_pb2_grpc.py +162 -41
  157. flwr/proto/simulationio_pb2_grpc.pyi +149 -55
  158. flwr/proto/transport_pb2.py +20 -10
  159. flwr/proto/transport_pb2.pyi +249 -160
  160. flwr/proto/transport_pb2_grpc.py +35 -4
  161. flwr/proto/transport_pb2_grpc.pyi +38 -8
  162. flwr/server/app.py +173 -127
  163. flwr/server/client_manager.py +4 -5
  164. flwr/server/client_proxy.py +10 -11
  165. flwr/server/compat/app.py +4 -5
  166. flwr/server/compat/app_utils.py +2 -1
  167. flwr/server/compat/grid_client_proxy.py +10 -12
  168. flwr/server/compat/legacy_context.py +3 -4
  169. flwr/server/fleet_event_log_interceptor.py +2 -1
  170. flwr/server/grid/grid.py +2 -3
  171. flwr/server/grid/grpc_grid.py +10 -8
  172. flwr/server/grid/inmemory_grid.py +4 -4
  173. flwr/server/run_serverapp.py +2 -3
  174. flwr/server/server.py +34 -39
  175. flwr/server/server_app.py +7 -8
  176. flwr/server/server_config.py +1 -2
  177. flwr/server/serverapp/app.py +34 -28
  178. flwr/server/serverapp_components.py +4 -5
  179. flwr/server/strategy/aggregate.py +9 -8
  180. flwr/server/strategy/bulyan.py +13 -11
  181. flwr/server/strategy/dp_adaptive_clipping.py +16 -20
  182. flwr/server/strategy/dp_fixed_clipping.py +12 -17
  183. flwr/server/strategy/dpfedavg_adaptive.py +3 -4
  184. flwr/server/strategy/dpfedavg_fixed.py +6 -10
  185. flwr/server/strategy/fault_tolerant_fedavg.py +14 -13
  186. flwr/server/strategy/fedadagrad.py +18 -14
  187. flwr/server/strategy/fedadam.py +16 -14
  188. flwr/server/strategy/fedavg.py +16 -17
  189. flwr/server/strategy/fedavg_android.py +15 -15
  190. flwr/server/strategy/fedavgm.py +21 -18
  191. flwr/server/strategy/fedmedian.py +2 -3
  192. flwr/server/strategy/fedopt.py +11 -10
  193. flwr/server/strategy/fedprox.py +10 -9
  194. flwr/server/strategy/fedtrimmedavg.py +12 -11
  195. flwr/server/strategy/fedxgb_bagging.py +13 -11
  196. flwr/server/strategy/fedxgb_cyclic.py +6 -6
  197. flwr/server/strategy/fedxgb_nn_avg.py +4 -4
  198. flwr/server/strategy/fedyogi.py +16 -14
  199. flwr/server/strategy/krum.py +12 -11
  200. flwr/server/strategy/qfedavg.py +16 -15
  201. flwr/server/strategy/strategy.py +6 -9
  202. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +19 -8
  203. flwr/server/superlink/fleet/grpc_bidi/flower_service_servicer.py +1 -2
  204. flwr/server/superlink/fleet/grpc_bidi/grpc_bridge.py +3 -4
  205. flwr/server/superlink/fleet/grpc_bidi/grpc_client_proxy.py +10 -12
  206. flwr/server/superlink/fleet/grpc_bidi/grpc_server.py +1 -3
  207. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +136 -42
  208. flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +28 -51
  209. flwr/server/superlink/fleet/message_handler/message_handler.py +100 -49
  210. flwr/server/superlink/fleet/rest_rere/rest_api.py +54 -33
  211. flwr/server/superlink/fleet/vce/backend/backend.py +2 -2
  212. flwr/server/superlink/fleet/vce/backend/raybackend.py +6 -6
  213. flwr/server/superlink/fleet/vce/vce_api.py +32 -13
  214. flwr/server/superlink/linkstate/in_memory_linkstate.py +266 -207
  215. flwr/server/superlink/linkstate/linkstate.py +161 -62
  216. flwr/server/superlink/linkstate/linkstate_factory.py +24 -6
  217. flwr/server/superlink/linkstate/sqlite_linkstate.py +698 -638
  218. flwr/server/superlink/linkstate/utils.py +9 -60
  219. flwr/server/superlink/serverappio/serverappio_grpc.py +1 -2
  220. flwr/server/superlink/serverappio/serverappio_servicer.py +28 -23
  221. flwr/server/superlink/simulation/simulationio_grpc.py +1 -2
  222. flwr/server/superlink/simulation/simulationio_servicer.py +19 -14
  223. flwr/server/superlink/utils.py +4 -6
  224. flwr/server/typing.py +1 -1
  225. flwr/server/utils/tensorboard.py +15 -8
  226. flwr/server/utils/validator.py +2 -3
  227. flwr/server/workflow/default_workflows.py +5 -5
  228. flwr/server/workflow/secure_aggregation/secagg_workflow.py +2 -4
  229. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +12 -10
  230. flwr/serverapp/strategy/bulyan.py +16 -15
  231. flwr/serverapp/strategy/dp_adaptive_clipping.py +12 -11
  232. flwr/serverapp/strategy/dp_fixed_clipping.py +11 -14
  233. flwr/serverapp/strategy/fedadagrad.py +10 -11
  234. flwr/serverapp/strategy/fedadam.py +10 -11
  235. flwr/serverapp/strategy/fedavg.py +9 -10
  236. flwr/serverapp/strategy/fedavgm.py +17 -16
  237. flwr/serverapp/strategy/fedmedian.py +2 -2
  238. flwr/serverapp/strategy/fedopt.py +10 -11
  239. flwr/serverapp/strategy/fedprox.py +7 -8
  240. flwr/serverapp/strategy/fedtrimmedavg.py +9 -9
  241. flwr/serverapp/strategy/fedxgb_bagging.py +3 -3
  242. flwr/serverapp/strategy/fedxgb_cyclic.py +9 -9
  243. flwr/serverapp/strategy/fedyogi.py +9 -11
  244. flwr/serverapp/strategy/krum.py +7 -7
  245. flwr/serverapp/strategy/multikrum.py +9 -9
  246. flwr/serverapp/strategy/qfedavg.py +17 -16
  247. flwr/serverapp/strategy/strategy.py +6 -9
  248. flwr/serverapp/strategy/strategy_utils.py +7 -8
  249. flwr/simulation/app.py +46 -42
  250. flwr/simulation/legacy_app.py +12 -12
  251. flwr/simulation/ray_transport/ray_actor.py +11 -12
  252. flwr/simulation/ray_transport/ray_client_proxy.py +12 -13
  253. flwr/simulation/run_simulation.py +44 -43
  254. flwr/simulation/simulationio_connection.py +4 -4
  255. flwr/supercore/cli/flower_superexec.py +3 -4
  256. flwr/supercore/constant.py +52 -0
  257. flwr/supercore/corestate/corestate.py +24 -3
  258. flwr/supercore/corestate/in_memory_corestate.py +138 -0
  259. flwr/supercore/corestate/sqlite_corestate.py +157 -0
  260. flwr/supercore/ffs/disk_ffs.py +1 -2
  261. flwr/supercore/ffs/ffs.py +1 -2
  262. flwr/supercore/ffs/ffs_factory.py +1 -2
  263. flwr/{common → supercore}/heartbeat.py +20 -25
  264. flwr/supercore/object_store/in_memory_object_store.py +1 -6
  265. flwr/supercore/object_store/object_store.py +1 -2
  266. flwr/supercore/object_store/object_store_factory.py +27 -8
  267. flwr/supercore/object_store/sqlite_object_store.py +253 -0
  268. flwr/{client/clientapp → supercore/primitives}/__init__.py +1 -1
  269. flwr/supercore/primitives/asymmetric.py +117 -0
  270. flwr/supercore/primitives/asymmetric_ed25519.py +175 -0
  271. flwr/supercore/sqlite_mixin.py +159 -0
  272. flwr/supercore/superexec/plugin/base_exec_plugin.py +1 -2
  273. flwr/supercore/superexec/plugin/exec_plugin.py +3 -3
  274. flwr/supercore/superexec/run_superexec.py +9 -13
  275. flwr/supercore/utils.py +20 -0
  276. flwr/superlink/artifact_provider/artifact_provider.py +1 -2
  277. flwr/{common → superlink}/auth_plugin/__init__.py +6 -6
  278. flwr/superlink/auth_plugin/auth_plugin.py +88 -0
  279. flwr/superlink/auth_plugin/noop_auth_plugin.py +84 -0
  280. flwr/superlink/federation/__init__.py +24 -0
  281. flwr/superlink/federation/federation_manager.py +64 -0
  282. flwr/superlink/federation/noop_federation_manager.py +71 -0
  283. flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +41 -32
  284. flwr/superlink/servicer/control/control_event_log_interceptor.py +7 -7
  285. flwr/superlink/servicer/control/control_grpc.py +18 -17
  286. flwr/superlink/servicer/control/control_license_interceptor.py +3 -3
  287. flwr/superlink/servicer/control/control_servicer.py +239 -63
  288. flwr/supernode/cli/flower_supernode.py +74 -26
  289. flwr/supernode/nodestate/in_memory_nodestate.py +60 -49
  290. flwr/supernode/nodestate/nodestate.py +7 -8
  291. flwr/supernode/nodestate/nodestate_factory.py +7 -4
  292. flwr/supernode/runtime/run_clientapp.py +43 -24
  293. flwr/supernode/servicer/clientappio/clientappio_servicer.py +40 -10
  294. flwr/supernode/start_client_internal.py +175 -51
  295. {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/METADATA +8 -8
  296. flwr-1.24.0.dist-info/RECORD +454 -0
  297. flwr/common/auth_plugin/auth_plugin.py +0 -149
  298. flwr/supercore/object_store/utils.py +0 -43
  299. flwr-1.22.0.dist-info/RECORD +0 -428
  300. {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/WHEEL +0 -0
  301. {flwr-1.22.0.dist-info → flwr-1.24.0.dist-info}/entry_points.txt +0 -0
@@ -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(request_iterator, target, '/flwr.proto.FlowerService/Join',
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, channel_credentials,
66
- insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
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(self,
20
- request_iterator: typing.Iterator[flwr.proto.transport_pb2.ClientMessage],
21
- context: grpc.ServicerContext,
22
- ) -> typing.Iterator[flwr.proto.transport_pb2.ServerMessage]: ...
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,30 +16,26 @@
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 DEBUG, INFO, WARN
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 Any, Callable, Optional, TypeVar
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
34
  from flwr.common.address import parse_address
38
35
  from flwr.common.args import try_obtain_server_certificates
39
- from flwr.common.auth_plugin import ControlAuthPlugin, ControlAuthzPlugin
40
36
  from flwr.common.config import get_flwr_dir
41
37
  from flwr.common.constant import (
42
- AUTH_TYPE_YAML_KEY,
38
+ AUTHN_TYPE_YAML_KEY,
43
39
  AUTHZ_TYPE_YAML_KEY,
44
40
  CLIENT_OCTET,
45
41
  CONTROL_API_DEFAULT_SERVER_ADDRESS,
@@ -53,6 +49,8 @@ from flwr.common.constant import (
53
49
  TRANSPORT_TYPE_GRPC_ADAPTER,
54
50
  TRANSPORT_TYPE_GRPC_RERE,
55
51
  TRANSPORT_TYPE_REST,
52
+ AuthnType,
53
+ AuthzType,
56
54
  EventLogWriterType,
57
55
  ExecPluginType,
58
56
  )
@@ -60,39 +58,47 @@ from flwr.common.event_log_plugin import EventLogWriterPlugin
60
58
  from flwr.common.exit import ExitCode, flwr_exit, register_signal_handlers
61
59
  from flwr.common.grpc import generic_create_grpc_server
62
60
  from flwr.common.logger import log
63
- from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
64
- public_key_to_bytes,
65
- )
61
+ from flwr.common.version import package_version
66
62
  from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611
67
63
  add_FleetServicer_to_server,
68
64
  )
69
65
  from flwr.proto.grpcadapter_pb2_grpc import add_GrpcAdapterServicer_to_server
70
66
  from flwr.server.fleet_event_log_interceptor import FleetEventLogInterceptor
67
+ from flwr.supercore.constant import FLWR_IN_MEMORY_DB_NAME
71
68
  from flwr.supercore.ffs import FfsFactory
72
69
  from flwr.supercore.grpc_health import add_args_health, run_health_server_grpc_no_tls
73
70
  from flwr.supercore.object_store import ObjectStoreFactory
74
71
  from flwr.superlink.artifact_provider import ArtifactProvider
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.server_interceptor import AuthenticateServerInterceptor
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", ControlAuthPlugin, ControlAuthzPlugin)
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
- get_control_auth_plugins,
93
- get_control_authz_plugins,
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 user auth TLS check if args.disable_oidc_tls_cert_verification is
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
- auth_plugin: Optional[ControlAuthPlugin] = None
197
- authz_plugin: Optional[ControlAuthzPlugin] = None
198
- event_log_plugin: Optional[EventLogWriterPlugin] = None
199
- # Load the auth plugin if the args.user_auth_config is provided
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
- auth_plugin, authz_plugin = _try_obtain_control_auth_plugins(
202
- Path(cfg_path), verify_tls_cert
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(args.database)
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,7 +320,7 @@ def run_superlink() -> None:
229
320
  objectstore_factory=objectstore_factory,
230
321
  certificates=certificates,
231
322
  is_simulation=is_simulation,
232
- auth_plugin=auth_plugin,
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,
@@ -306,22 +397,8 @@ def run_superlink() -> None:
306
397
  fleet_thread.start()
307
398
  bckg_threads.append(fleet_thread)
308
399
  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
400
 
324
- interceptors = [AuthenticateServerInterceptor(state_factory, auto_auth)]
401
+ interceptors = [NodeAuthServerInterceptor(state_factory)]
325
402
  if getattr(args, "enable_event_log", None):
326
403
  fleet_log_plugin = _try_obtain_fleet_event_log_writer_plugin()
327
404
  if fleet_log_plugin is not None:
@@ -333,6 +410,7 @@ def run_superlink() -> None:
333
410
  state_factory=state_factory,
334
411
  ffs_factory=ffs_factory,
335
412
  objectstore_factory=objectstore_factory,
413
+ enable_supernode_auth=enable_supernode_auth,
336
414
  certificates=certificates,
337
415
  interceptors=interceptors,
338
416
  )
@@ -400,55 +478,21 @@ def _format_address(address: str) -> tuple[str, str, int]:
400
478
  return (f"[{host}]:{port}" if is_v6 else f"{host}:{port}", host, port)
401
479
 
402
480
 
403
- def _try_load_public_keys_node_authentication(
404
- args: argparse.Namespace,
405
- ) -> Optional[set[bytes]]:
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]:
481
+ def _load_control_auth_plugins(
482
+ config_path: str | None, verify_tls_cert: bool
483
+ ) -> tuple[ControlAuthnPlugin, ControlAuthzPlugin]:
448
484
  """Obtain Control API authentication and authorization plugins."""
485
+ # Load NoOp plugins if no config path is provided
486
+ if config_path is None:
487
+ config_path = ""
488
+ config = {
489
+ "authentication": {AUTHN_TYPE_YAML_KEY: AuthnType.NOOP},
490
+ "authorization": {AUTHZ_TYPE_YAML_KEY: AuthzType.NOOP},
491
+ }
449
492
  # Load YAML file
450
- with config_path.open("r", encoding="utf-8") as file:
451
- config: dict[str, Any] = yaml.safe_load(file)
493
+ else:
494
+ with Path(config_path).open("r", encoding="utf-8") as file:
495
+ config = yaml.safe_load(file)
452
496
 
453
497
  def _load_plugin(
454
498
  section: str, yaml_key: str, loader: Callable[[], dict[str, type[P]]]
@@ -458,9 +502,7 @@ def _try_obtain_control_auth_plugins(
458
502
  try:
459
503
  plugins: dict[str, type[P]] = loader()
460
504
  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
- )
505
+ return plugin_cls(Path(cast(str, config_path)), verify_tls_cert)
464
506
  except KeyError:
465
507
  if auth_plugin_name:
466
508
  sys.exit(
@@ -468,14 +510,22 @@ def _try_obtain_control_auth_plugins(
468
510
  f"Please provide a valid {section} type in the configuration."
469
511
  )
470
512
  sys.exit(f"No {section} type is provided in the configuration.")
471
- except NotImplementedError:
472
- sys.exit(f"No {section} plugins are currently supported.")
513
+
514
+ # Warn deprecated auth_type key
515
+ if authn_type := config["authentication"].pop("auth_type", None):
516
+ log(
517
+ WARN,
518
+ "The `auth_type` key in the authentication configuration is deprecated. "
519
+ "Use `%s` instead.",
520
+ AUTHN_TYPE_YAML_KEY,
521
+ )
522
+ config["authentication"][AUTHN_TYPE_YAML_KEY] = authn_type
473
523
 
474
524
  # Load authentication plugin
475
- auth_plugin = _load_plugin(
525
+ authn_plugin = _load_plugin(
476
526
  section="authentication",
477
- yaml_key=AUTH_TYPE_YAML_KEY,
478
- loader=get_control_auth_plugins,
527
+ yaml_key=AUTHN_TYPE_YAML_KEY,
528
+ loader=get_control_authn_plugins,
479
529
  )
480
530
 
481
531
  # Load authorization plugin
@@ -485,10 +535,10 @@ def _try_obtain_control_auth_plugins(
485
535
  loader=get_control_authz_plugins,
486
536
  )
487
537
 
488
- return auth_plugin, authz_plugin
538
+ return authn_plugin, authz_plugin
489
539
 
490
540
 
491
- def _try_obtain_control_event_log_writer_plugin() -> Optional[EventLogWriterPlugin]:
541
+ def _try_obtain_control_event_log_writer_plugin() -> EventLogWriterPlugin | None:
492
542
  """Return an instance of the event log writer plugin."""
493
543
  try:
494
544
  all_plugins: dict[str, type[EventLogWriterPlugin]] = (
@@ -502,7 +552,7 @@ def _try_obtain_control_event_log_writer_plugin() -> Optional[EventLogWriterPlug
502
552
  sys.exit("No event log writer plugins are currently supported.")
503
553
 
504
554
 
505
- def _try_obtain_fleet_event_log_writer_plugin() -> Optional[EventLogWriterPlugin]:
555
+ def _try_obtain_fleet_event_log_writer_plugin() -> EventLogWriterPlugin | None:
506
556
  """Return an instance of the Fleet Servicer event log writer plugin."""
507
557
  try:
508
558
  all_plugins: dict[str, type[EventLogWriterPlugin]] = (
@@ -521,8 +571,9 @@ def _run_fleet_api_grpc_rere( # pylint: disable=R0913, R0917
521
571
  state_factory: LinkStateFactory,
522
572
  ffs_factory: FfsFactory,
523
573
  objectstore_factory: ObjectStoreFactory,
524
- certificates: Optional[tuple[bytes, bytes, bytes]],
525
- interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None,
574
+ enable_supernode_auth: bool,
575
+ certificates: tuple[bytes, bytes, bytes] | None,
576
+ interceptors: Sequence[grpc.ServerInterceptor] | None = None,
526
577
  ) -> grpc.Server:
527
578
  """Run Fleet API (gRPC, request-response)."""
528
579
  # Create Fleet API gRPC server
@@ -530,6 +581,7 @@ def _run_fleet_api_grpc_rere( # pylint: disable=R0913, R0917
530
581
  state_factory=state_factory,
531
582
  ffs_factory=ffs_factory,
532
583
  objectstore_factory=objectstore_factory,
584
+ enable_supernode_auth=enable_supernode_auth,
533
585
  )
534
586
  fleet_add_servicer_to_server_fn = add_FleetServicer_to_server
535
587
  fleet_grpc_server = generic_create_grpc_server(
@@ -548,12 +600,13 @@ def _run_fleet_api_grpc_rere( # pylint: disable=R0913, R0917
548
600
  return fleet_grpc_server
549
601
 
550
602
 
603
+ # pylint: disable=R0913, R0917
551
604
  def _run_fleet_api_grpc_adapter(
552
605
  address: str,
553
606
  state_factory: LinkStateFactory,
554
607
  ffs_factory: FfsFactory,
555
608
  objectstore_factory: ObjectStoreFactory,
556
- certificates: Optional[tuple[bytes, bytes, bytes]],
609
+ certificates: tuple[bytes, bytes, bytes] | None,
557
610
  ) -> grpc.Server:
558
611
  """Run Fleet API (GrpcAdapter)."""
559
612
  # Create Fleet API gRPC server
@@ -561,6 +614,7 @@ def _run_fleet_api_grpc_adapter(
561
614
  state_factory=state_factory,
562
615
  ffs_factory=ffs_factory,
563
616
  objectstore_factory=objectstore_factory,
617
+ enable_supernode_auth=False,
564
618
  )
565
619
  fleet_add_servicer_to_server_fn = add_GrpcAdapterServicer_to_server
566
620
  fleet_grpc_server = generic_create_grpc_server(
@@ -585,8 +639,8 @@ def _run_fleet_api_grpc_adapter(
585
639
  def _run_fleet_api_rest(
586
640
  host: str,
587
641
  port: int,
588
- ssl_keyfile: Optional[str],
589
- ssl_certfile: Optional[str],
642
+ ssl_keyfile: str | None,
643
+ ssl_certfile: str | None,
590
644
  state_factory: LinkStateFactory,
591
645
  ffs_factory: FfsFactory,
592
646
  objectstore_factory: ObjectStoreFactory,
@@ -691,11 +745,9 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
691
745
  parser.add_argument(
692
746
  "--database",
693
747
  help="A string representing the path to the database "
694
- "file that will be opened. Note that passing ':memory:' "
695
- "will open a connection to a database that is in RAM, "
696
- "instead of on disk. If nothing is provided, "
748
+ "file that will be opened. If nothing is provided, "
697
749
  "Flower will just create a state in memory.",
698
- default=DATABASE,
750
+ default=FLWR_IN_MEMORY_DB_NAME,
699
751
  )
700
752
  parser.add_argument(
701
753
  "--storage-dir",
@@ -705,18 +757,12 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
705
757
  parser.add_argument(
706
758
  "--auth-list-public-keys",
707
759
  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
760
  help="This argument is deprecated and will be removed in a future release.",
715
761
  )
716
762
  parser.add_argument(
717
- "--auth-superlink-public-key",
718
- type=str,
719
- help="This argument is deprecated and will be removed in a future release.",
763
+ "--enable-supernode-auth",
764
+ action="store_true",
765
+ help="Enable supernode authentication.",
720
766
  )
721
767
 
722
768
 
@@ -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: Optional[int] = None,
84
- criterion: Optional[Criterion] = None,
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: Optional[int] = None,
183
- criterion: Optional[Criterion] = None,
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.