flwr-nightly 1.15.0.dev20250123__py3-none-any.whl → 1.15.0.dev20250125__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flwr/cli/config_utils.py +1 -1
- flwr/cli/log.py +1 -1
- flwr/cli/login/login.py +15 -1
- flwr/cli/ls.py +1 -1
- flwr/cli/run/run.py +1 -1
- flwr/cli/stop.py +1 -1
- flwr/cli/utils.py +29 -12
- flwr/server/app.py +18 -79
- flwr/server/driver/grpc_driver.py +22 -21
- flwr/server/superlink/linkstate/in_memory_linkstate.py +2 -25
- flwr/server/superlink/linkstate/linkstate.py +2 -16
- flwr/server/superlink/linkstate/sqlite_linkstate.py +3 -48
- {flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/METADATA +1 -1
- {flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/RECORD +17 -17
- {flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/LICENSE +0 -0
- {flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/WHEEL +0 -0
- {flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/entry_points.txt +0 -0
flwr/cli/config_utils.py
CHANGED
@@ -182,7 +182,7 @@ def validate_certificate_in_federation_config(
|
|
182
182
|
root_certificates_bytes = (app / root_certificates).read_bytes()
|
183
183
|
if insecure := bool(insecure_str):
|
184
184
|
typer.secho(
|
185
|
-
"❌ `
|
185
|
+
"❌ `root-certificates` were provided but the `insecure` parameter "
|
186
186
|
"is set to `True`.",
|
187
187
|
fg=typer.colors.RED,
|
188
188
|
bold=True,
|
flwr/cli/log.py
CHANGED
@@ -187,7 +187,7 @@ def _log_with_exec_api(
|
|
187
187
|
run_id: int,
|
188
188
|
stream: bool,
|
189
189
|
) -> None:
|
190
|
-
auth_plugin = try_obtain_cli_auth_plugin(app, federation)
|
190
|
+
auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
|
191
191
|
channel = init_channel(app, federation_config, auth_plugin)
|
192
192
|
|
193
193
|
if stream:
|
flwr/cli/login/login.py
CHANGED
@@ -65,6 +65,18 @@ def login( # pylint: disable=R0914
|
|
65
65
|
federation, config, federation_config_overrides
|
66
66
|
)
|
67
67
|
exit_if_no_address(federation_config, "login")
|
68
|
+
|
69
|
+
# Check if `enable-user-auth` is set to `true`
|
70
|
+
if not federation_config.get("enable-user-auth", False):
|
71
|
+
typer.secho(
|
72
|
+
f"❌ User authentication is not enabled for the federation '{federation}'. "
|
73
|
+
"To enable it, set `enable-user-auth = true` in the federation "
|
74
|
+
"configuration.",
|
75
|
+
fg=typer.colors.RED,
|
76
|
+
bold=True,
|
77
|
+
)
|
78
|
+
raise typer.Exit(code=1)
|
79
|
+
|
68
80
|
channel = init_channel(app, federation_config, None)
|
69
81
|
stub = ExecStub(channel)
|
70
82
|
|
@@ -73,7 +85,9 @@ def login( # pylint: disable=R0914
|
|
73
85
|
|
74
86
|
# Get the auth plugin
|
75
87
|
auth_type = login_response.auth_type
|
76
|
-
auth_plugin = try_obtain_cli_auth_plugin(
|
88
|
+
auth_plugin = try_obtain_cli_auth_plugin(
|
89
|
+
app, federation, federation_config, auth_type
|
90
|
+
)
|
77
91
|
if auth_plugin is None:
|
78
92
|
typer.secho(
|
79
93
|
f'❌ Authentication type "{auth_type}" not found',
|
flwr/cli/ls.py
CHANGED
@@ -123,7 +123,7 @@ def ls( # pylint: disable=too-many-locals, too-many-branches, R0913, R0917
|
|
123
123
|
raise ValueError(
|
124
124
|
"The options '--runs' and '--run-id' are mutually exclusive."
|
125
125
|
)
|
126
|
-
auth_plugin = try_obtain_cli_auth_plugin(app, federation)
|
126
|
+
auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
|
127
127
|
channel = init_channel(app, federation_config, auth_plugin)
|
128
128
|
stub = ExecStub(channel)
|
129
129
|
|
flwr/cli/run/run.py
CHANGED
@@ -158,7 +158,7 @@ def _run_with_exec_api(
|
|
158
158
|
stream: bool,
|
159
159
|
output_format: str,
|
160
160
|
) -> None:
|
161
|
-
auth_plugin = try_obtain_cli_auth_plugin(app, federation)
|
161
|
+
auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
|
162
162
|
channel = init_channel(app, federation_config, auth_plugin)
|
163
163
|
stub = ExecStub(channel)
|
164
164
|
|
flwr/cli/stop.py
CHANGED
@@ -86,7 +86,7 @@ def stop( # pylint: disable=R0914
|
|
86
86
|
exit_if_no_address(federation_config, "stop")
|
87
87
|
|
88
88
|
try:
|
89
|
-
auth_plugin = try_obtain_cli_auth_plugin(app, federation)
|
89
|
+
auth_plugin = try_obtain_cli_auth_plugin(app, federation, federation_config)
|
90
90
|
channel = init_channel(app, federation_config, auth_plugin)
|
91
91
|
stub = ExecStub(channel) # pylint: disable=unused-variable # noqa: F841
|
92
92
|
|
flwr/cli/utils.py
CHANGED
@@ -217,25 +217,42 @@ def get_user_auth_config_path(root_dir: Path, federation: str) -> Path:
|
|
217
217
|
def try_obtain_cli_auth_plugin(
|
218
218
|
root_dir: Path,
|
219
219
|
federation: str,
|
220
|
+
federation_config: dict[str, Any],
|
220
221
|
auth_type: Optional[str] = None,
|
221
222
|
) -> Optional[CliAuthPlugin]:
|
222
223
|
"""Load the CLI-side user auth plugin for the given auth type."""
|
223
|
-
|
224
|
-
|
225
|
-
# Load the config file if it exists
|
226
|
-
json_file: dict[str, Any] = {}
|
227
|
-
if config_path.exists():
|
228
|
-
with config_path.open("r", encoding="utf-8") as file:
|
229
|
-
json_file = json.load(file)
|
230
|
-
# This is the case when the user auth is not enabled
|
231
|
-
elif auth_type is None:
|
224
|
+
# Check if user auth is enabled
|
225
|
+
if not federation_config.get("enable-user-auth", False):
|
232
226
|
return None
|
233
227
|
|
228
|
+
# Check if TLS is enabled. If not, raise an error
|
229
|
+
if federation_config.get("root-certificates") is None:
|
230
|
+
typer.secho(
|
231
|
+
"❌ User authentication requires TLS to be enabled. "
|
232
|
+
"Please provide 'root-certificates' in the federation"
|
233
|
+
" configuration.",
|
234
|
+
fg=typer.colors.RED,
|
235
|
+
bold=True,
|
236
|
+
)
|
237
|
+
raise typer.Exit(code=1)
|
238
|
+
|
239
|
+
config_path = get_user_auth_config_path(root_dir, federation)
|
240
|
+
|
234
241
|
# Get the auth type from the config if not provided
|
242
|
+
# auth_type will be None for all CLI commands except login
|
235
243
|
if auth_type is None:
|
236
|
-
|
237
|
-
|
238
|
-
|
244
|
+
try:
|
245
|
+
with config_path.open("r", encoding="utf-8") as file:
|
246
|
+
json_file = json.load(file)
|
247
|
+
auth_type = json_file[AUTH_TYPE]
|
248
|
+
except (FileNotFoundError, KeyError):
|
249
|
+
typer.secho(
|
250
|
+
"❌ Missing or invalid credentials for user authentication. "
|
251
|
+
"Please run `flwr login` to authenticate.",
|
252
|
+
fg=typer.colors.RED,
|
253
|
+
bold=True,
|
254
|
+
)
|
255
|
+
raise typer.Exit(code=1) from None
|
239
256
|
|
240
257
|
# Retrieve auth plugin class and instantiate it
|
241
258
|
try:
|
flwr/server/app.py
CHANGED
@@ -31,12 +31,8 @@ from typing import Any, Optional
|
|
31
31
|
|
32
32
|
import grpc
|
33
33
|
import yaml
|
34
|
-
from cryptography.exceptions import UnsupportedAlgorithm
|
35
34
|
from cryptography.hazmat.primitives.asymmetric import ec
|
36
|
-
from cryptography.hazmat.primitives.serialization import
|
37
|
-
load_ssh_private_key,
|
38
|
-
load_ssh_public_key,
|
39
|
-
)
|
35
|
+
from cryptography.hazmat.primitives.serialization import load_ssh_public_key
|
40
36
|
|
41
37
|
from flwr.common import GRPC_MAX_MESSAGE_LENGTH, EventType, event
|
42
38
|
from flwr.common.address import parse_address
|
@@ -64,7 +60,6 @@ from flwr.common.exit_handlers import register_exit_handlers
|
|
64
60
|
from flwr.common.grpc import generic_create_grpc_server
|
65
61
|
from flwr.common.logger import log, warn_deprecated_feature
|
66
62
|
from flwr.common.secure_aggregation.crypto.symmetric_encryption import (
|
67
|
-
private_key_to_bytes,
|
68
63
|
public_key_to_bytes,
|
69
64
|
)
|
70
65
|
from flwr.proto.fleet_pb2_grpc import ( # pylint: disable=E0611
|
@@ -378,21 +373,12 @@ def run_superlink() -> None:
|
|
378
373
|
fleet_thread.start()
|
379
374
|
bckg_threads.append(fleet_thread)
|
380
375
|
elif args.fleet_api_type == TRANSPORT_TYPE_GRPC_RERE:
|
381
|
-
|
376
|
+
node_public_keys = _try_load_public_keys_node_authentication(args)
|
382
377
|
interceptors: Optional[Sequence[grpc.ServerInterceptor]] = None
|
383
|
-
if
|
384
|
-
(
|
385
|
-
node_public_keys,
|
386
|
-
server_private_key,
|
387
|
-
server_public_key,
|
388
|
-
) = maybe_keys
|
378
|
+
if node_public_keys is not None:
|
389
379
|
state = state_factory.state()
|
390
|
-
state.
|
380
|
+
state.clear_supernode_auth_keys()
|
391
381
|
state.store_node_public_keys(node_public_keys)
|
392
|
-
state.store_server_private_public_key(
|
393
|
-
private_key_to_bytes(server_private_key),
|
394
|
-
public_key_to_bytes(server_public_key),
|
395
|
-
)
|
396
382
|
log(
|
397
383
|
INFO,
|
398
384
|
"Node authentication enabled with %d known public keys",
|
@@ -541,34 +527,20 @@ def _format_address(address: str) -> tuple[str, str, int]:
|
|
541
527
|
return (f"[{host}]:{port}" if is_v6 else f"{host}:{port}", host, port)
|
542
528
|
|
543
529
|
|
544
|
-
def
|
530
|
+
def _try_load_public_keys_node_authentication(
|
545
531
|
args: argparse.Namespace,
|
546
|
-
|
547
|
-
|
548
|
-
if
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
if (
|
556
|
-
not args.auth_list_public_keys
|
557
|
-
or not args.auth_superlink_private_key
|
558
|
-
or not args.auth_superlink_public_key
|
559
|
-
):
|
560
|
-
sys.exit(
|
561
|
-
"Authentication requires providing file paths for "
|
562
|
-
"'--auth-list-public-keys', '--auth-superlink-private-key' and "
|
563
|
-
"'--auth-superlink-public-key'. Provide all three to enable authentication."
|
532
|
+
) -> Optional[set[bytes]]:
|
533
|
+
"""Return a set of node public keys."""
|
534
|
+
if args.auth_superlink_private_key or args.auth_superlink_public_key:
|
535
|
+
log(
|
536
|
+
WARN,
|
537
|
+
"The `--auth-superlink-private-key` and `--auth-superlink-public-key` "
|
538
|
+
"arguments are deprecated and will be removed in a future release. Node "
|
539
|
+
"authentication no longer requires these arguments.",
|
564
540
|
)
|
565
541
|
|
566
|
-
if
|
567
|
-
|
568
|
-
"Authentication requires secure connections. "
|
569
|
-
"Please provide certificate paths to `--ssl-certfile`, "
|
570
|
-
"`--ssl-keyfile`, and `—-ssl-ca-certfile` and try again."
|
571
|
-
)
|
542
|
+
if not args.auth_list_public_keys:
|
543
|
+
return None
|
572
544
|
|
573
545
|
node_keys_file_path = Path(args.auth_list_public_keys)
|
574
546
|
if not node_keys_file_path.exists():
|
@@ -581,35 +553,6 @@ def _try_setup_node_authentication(
|
|
581
553
|
|
582
554
|
node_public_keys: set[bytes] = set()
|
583
555
|
|
584
|
-
try:
|
585
|
-
ssh_private_key = load_ssh_private_key(
|
586
|
-
Path(args.auth_superlink_private_key).read_bytes(),
|
587
|
-
None,
|
588
|
-
)
|
589
|
-
if not isinstance(ssh_private_key, ec.EllipticCurvePrivateKey):
|
590
|
-
raise ValueError()
|
591
|
-
except (ValueError, UnsupportedAlgorithm):
|
592
|
-
sys.exit(
|
593
|
-
"Error: Unable to parse the private key file in "
|
594
|
-
"'--auth-superlink-private-key'. Authentication requires elliptic "
|
595
|
-
"curve private and public key pair. Please ensure that the file "
|
596
|
-
"path points to a valid private key file and try again."
|
597
|
-
)
|
598
|
-
|
599
|
-
try:
|
600
|
-
ssh_public_key = load_ssh_public_key(
|
601
|
-
Path(args.auth_superlink_public_key).read_bytes()
|
602
|
-
)
|
603
|
-
if not isinstance(ssh_public_key, ec.EllipticCurvePublicKey):
|
604
|
-
raise ValueError()
|
605
|
-
except (ValueError, UnsupportedAlgorithm):
|
606
|
-
sys.exit(
|
607
|
-
"Error: Unable to parse the public key file in "
|
608
|
-
"'--auth-superlink-public-key'. Authentication requires elliptic "
|
609
|
-
"curve private and public key pair. Please ensure that the file "
|
610
|
-
"path points to a valid public key file and try again."
|
611
|
-
)
|
612
|
-
|
613
556
|
with open(node_keys_file_path, newline="", encoding="utf-8") as csvfile:
|
614
557
|
reader = csv.reader(csvfile)
|
615
558
|
for row in reader:
|
@@ -623,11 +566,7 @@ def _try_setup_node_authentication(
|
|
623
566
|
"file. Please ensure that the CSV file path points to a valid "
|
624
567
|
"known SSH public keys files and try again."
|
625
568
|
)
|
626
|
-
|
627
|
-
node_public_keys,
|
628
|
-
ssh_private_key,
|
629
|
-
ssh_public_key,
|
630
|
-
)
|
569
|
+
return node_public_keys
|
631
570
|
|
632
571
|
|
633
572
|
def _try_obtain_exec_auth_plugin(
|
@@ -840,12 +779,12 @@ def _add_args_common(parser: argparse.ArgumentParser) -> None:
|
|
840
779
|
parser.add_argument(
|
841
780
|
"--auth-superlink-private-key",
|
842
781
|
type=str,
|
843
|
-
help="
|
782
|
+
help="This argument is deprecated and will be removed in a future release.",
|
844
783
|
)
|
845
784
|
parser.add_argument(
|
846
785
|
"--auth-superlink-public-key",
|
847
786
|
type=str,
|
848
|
-
help="
|
787
|
+
help="This argument is deprecated and will be removed in a future release.",
|
849
788
|
)
|
850
789
|
|
851
790
|
|
@@ -31,20 +31,20 @@ from flwr.common.constant import (
|
|
31
31
|
from flwr.common.grpc import create_channel
|
32
32
|
from flwr.common.logger import log
|
33
33
|
from flwr.common.retry_invoker import _make_simple_grpc_retry_invoker, _wrap_stub
|
34
|
-
from flwr.common.serde import
|
34
|
+
from flwr.common.serde import message_from_proto, message_to_proto, run_from_proto
|
35
35
|
from flwr.common.typing import Run
|
36
|
+
from flwr.proto.message_pb2 import Message as ProtoMessage # pylint: disable=E0611
|
36
37
|
from flwr.proto.node_pb2 import Node # pylint: disable=E0611
|
37
38
|
from flwr.proto.run_pb2 import GetRunRequest, GetRunResponse # pylint: disable=E0611
|
38
39
|
from flwr.proto.serverappio_pb2 import ( # pylint: disable=E0611
|
39
40
|
GetNodesRequest,
|
40
41
|
GetNodesResponse,
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
PullResMessagesRequest,
|
43
|
+
PullResMessagesResponse,
|
44
|
+
PushInsMessagesRequest,
|
45
|
+
PushInsMessagesResponse,
|
45
46
|
)
|
46
47
|
from flwr.proto.serverappio_pb2_grpc import ServerAppIoStub # pylint: disable=E0611
|
47
|
-
from flwr.proto.task_pb2 import TaskIns # pylint: disable=E0611
|
48
48
|
|
49
49
|
from .driver import Driver
|
50
50
|
|
@@ -196,22 +196,22 @@ class GrpcDriver(Driver):
|
|
196
196
|
This method takes an iterable of messages and sends each message
|
197
197
|
to the node specified in `dst_node_id`.
|
198
198
|
"""
|
199
|
-
# Construct
|
200
|
-
|
199
|
+
# Construct Messages
|
200
|
+
message_proto_list: list[ProtoMessage] = []
|
201
201
|
for msg in messages:
|
202
202
|
# Check message
|
203
203
|
self._check_message(msg)
|
204
|
-
# Convert
|
205
|
-
|
204
|
+
# Convert to proto
|
205
|
+
msg_proto = message_to_proto(msg)
|
206
206
|
# Add to list
|
207
|
-
|
207
|
+
message_proto_list.append(msg_proto)
|
208
208
|
# Call GrpcDriverStub method
|
209
|
-
res:
|
210
|
-
|
211
|
-
|
209
|
+
res: PushInsMessagesResponse = self._stub.PushMessages(
|
210
|
+
PushInsMessagesRequest(
|
211
|
+
messages_list=message_proto_list, run_id=cast(Run, self._run).run_id
|
212
212
|
)
|
213
213
|
)
|
214
|
-
return list(res.
|
214
|
+
return list(res.message_ids)
|
215
215
|
|
216
216
|
def pull_messages(self, message_ids: Iterable[str]) -> Iterable[Message]:
|
217
217
|
"""Pull messages based on message IDs.
|
@@ -219,14 +219,15 @@ class GrpcDriver(Driver):
|
|
219
219
|
This method is used to collect messages from the SuperLink that correspond to a
|
220
220
|
set of given message IDs.
|
221
221
|
"""
|
222
|
-
# Pull
|
223
|
-
res:
|
224
|
-
|
225
|
-
|
222
|
+
# Pull Messages
|
223
|
+
res: PullResMessagesResponse = self._stub.PullMessages(
|
224
|
+
PullResMessagesRequest(
|
225
|
+
message_ids=message_ids,
|
226
|
+
run_id=cast(Run, self._run).run_id,
|
226
227
|
)
|
227
228
|
)
|
228
|
-
# Convert
|
229
|
-
msgs = [
|
229
|
+
# Convert Message from Protobuf representation
|
230
|
+
msgs = [message_from_proto(msg_proto) for msg_proto in res.messages_list]
|
230
231
|
return msgs
|
231
232
|
|
232
233
|
def send_and_receive(
|
@@ -74,8 +74,6 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
74
74
|
self.task_ins_id_to_task_res_id: dict[UUID, UUID] = {}
|
75
75
|
|
76
76
|
self.node_public_keys: set[bytes] = set()
|
77
|
-
self.server_public_key: Optional[bytes] = None
|
78
|
-
self.server_private_key: Optional[bytes] = None
|
79
77
|
|
80
78
|
self.lock = threading.RLock()
|
81
79
|
|
@@ -403,30 +401,9 @@ class InMemoryLinkState(LinkState): # pylint: disable=R0902,R0904
|
|
403
401
|
log(ERROR, "Unexpected run creation failure.")
|
404
402
|
return 0
|
405
403
|
|
406
|
-
def
|
407
|
-
|
408
|
-
) -> None:
|
409
|
-
"""Store `server_private_key` and `server_public_key` in the link state."""
|
404
|
+
def clear_supernode_auth_keys(self) -> None:
|
405
|
+
"""Clear stored `node_public_keys` in the link state if any."""
|
410
406
|
with self.lock:
|
411
|
-
if self.server_private_key is None and self.server_public_key is None:
|
412
|
-
self.server_private_key = private_key
|
413
|
-
self.server_public_key = public_key
|
414
|
-
else:
|
415
|
-
raise RuntimeError("Server private and public key already set")
|
416
|
-
|
417
|
-
def get_server_private_key(self) -> Optional[bytes]:
|
418
|
-
"""Retrieve `server_private_key` in urlsafe bytes."""
|
419
|
-
return self.server_private_key
|
420
|
-
|
421
|
-
def get_server_public_key(self) -> Optional[bytes]:
|
422
|
-
"""Retrieve `server_public_key` in urlsafe bytes."""
|
423
|
-
return self.server_public_key
|
424
|
-
|
425
|
-
def clear_supernode_auth_keys_and_credentials(self) -> None:
|
426
|
-
"""Clear stored `node_public_keys` and credentials in the link state if any."""
|
427
|
-
with self.lock:
|
428
|
-
self.server_private_key = None
|
429
|
-
self.server_public_key = None
|
430
407
|
self.node_public_keys.clear()
|
431
408
|
|
432
409
|
def store_node_public_keys(self, public_keys: set[bytes]) -> None:
|
@@ -264,22 +264,8 @@ class LinkState(abc.ABC): # pylint: disable=R0904
|
|
264
264
|
"""
|
265
265
|
|
266
266
|
@abc.abstractmethod
|
267
|
-
def
|
268
|
-
|
269
|
-
) -> None:
|
270
|
-
"""Store `server_private_key` and `server_public_key` in the link state."""
|
271
|
-
|
272
|
-
@abc.abstractmethod
|
273
|
-
def get_server_private_key(self) -> Optional[bytes]:
|
274
|
-
"""Retrieve `server_private_key` in urlsafe bytes."""
|
275
|
-
|
276
|
-
@abc.abstractmethod
|
277
|
-
def get_server_public_key(self) -> Optional[bytes]:
|
278
|
-
"""Retrieve `server_public_key` in urlsafe bytes."""
|
279
|
-
|
280
|
-
@abc.abstractmethod
|
281
|
-
def clear_supernode_auth_keys_and_credentials(self) -> None:
|
282
|
-
"""Clear stored `node_public_keys` and credentials in the link state if any."""
|
267
|
+
def clear_supernode_auth_keys(self) -> None:
|
268
|
+
"""Clear stored `node_public_keys` in the link state if any."""
|
283
269
|
|
284
270
|
@abc.abstractmethod
|
285
271
|
def store_node_public_keys(self, public_keys: set[bytes]) -> None:
|
@@ -71,13 +71,6 @@ CREATE TABLE IF NOT EXISTS node(
|
|
71
71
|
);
|
72
72
|
"""
|
73
73
|
|
74
|
-
SQL_CREATE_TABLE_CREDENTIAL = """
|
75
|
-
CREATE TABLE IF NOT EXISTS credential(
|
76
|
-
private_key BLOB PRIMARY KEY,
|
77
|
-
public_key BLOB
|
78
|
-
);
|
79
|
-
"""
|
80
|
-
|
81
74
|
SQL_CREATE_TABLE_PUBLIC_KEY = """
|
82
75
|
CREATE TABLE IF NOT EXISTS public_key(
|
83
76
|
public_key BLOB PRIMARY KEY
|
@@ -208,7 +201,6 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
208
201
|
cur.execute(SQL_CREATE_TABLE_TASK_INS)
|
209
202
|
cur.execute(SQL_CREATE_TABLE_TASK_RES)
|
210
203
|
cur.execute(SQL_CREATE_TABLE_NODE)
|
211
|
-
cur.execute(SQL_CREATE_TABLE_CREDENTIAL)
|
212
204
|
cur.execute(SQL_CREATE_TABLE_PUBLIC_KEY)
|
213
205
|
cur.execute(SQL_CREATE_INDEX_ONLINE_UNTIL)
|
214
206
|
res = cur.execute("SELECT name FROM sqlite_schema;")
|
@@ -773,46 +765,9 @@ class SqliteLinkState(LinkState): # pylint: disable=R0904
|
|
773
765
|
log(ERROR, "Unexpected run creation failure.")
|
774
766
|
return 0
|
775
767
|
|
776
|
-
def
|
777
|
-
|
778
|
-
|
779
|
-
"""Store `server_private_key` and `server_public_key` in the link state."""
|
780
|
-
query = "SELECT COUNT(*) FROM credential"
|
781
|
-
count = self.query(query)[0]["COUNT(*)"]
|
782
|
-
if count < 1:
|
783
|
-
query = (
|
784
|
-
"INSERT OR REPLACE INTO credential (private_key, public_key) "
|
785
|
-
"VALUES (:private_key, :public_key)"
|
786
|
-
)
|
787
|
-
self.query(query, {"private_key": private_key, "public_key": public_key})
|
788
|
-
else:
|
789
|
-
raise RuntimeError("Server private and public key already set")
|
790
|
-
|
791
|
-
def get_server_private_key(self) -> Optional[bytes]:
|
792
|
-
"""Retrieve `server_private_key` in urlsafe bytes."""
|
793
|
-
query = "SELECT private_key FROM credential"
|
794
|
-
rows = self.query(query)
|
795
|
-
try:
|
796
|
-
private_key: Optional[bytes] = rows[0]["private_key"]
|
797
|
-
except IndexError:
|
798
|
-
private_key = None
|
799
|
-
return private_key
|
800
|
-
|
801
|
-
def get_server_public_key(self) -> Optional[bytes]:
|
802
|
-
"""Retrieve `server_public_key` in urlsafe bytes."""
|
803
|
-
query = "SELECT public_key FROM credential"
|
804
|
-
rows = self.query(query)
|
805
|
-
try:
|
806
|
-
public_key: Optional[bytes] = rows[0]["public_key"]
|
807
|
-
except IndexError:
|
808
|
-
public_key = None
|
809
|
-
return public_key
|
810
|
-
|
811
|
-
def clear_supernode_auth_keys_and_credentials(self) -> None:
|
812
|
-
"""Clear stored `node_public_keys` and credentials in the link state if any."""
|
813
|
-
queries = ["DELETE FROM public_key;", "DELETE FROM credential;"]
|
814
|
-
for query in queries:
|
815
|
-
self.query(query)
|
768
|
+
def clear_supernode_auth_keys(self) -> None:
|
769
|
+
"""Clear stored `node_public_keys` in the link state if any."""
|
770
|
+
self.query("DELETE FROM public_key;")
|
816
771
|
|
817
772
|
def store_node_public_keys(self, public_keys: set[bytes]) -> None:
|
818
773
|
"""Store a set of `node_public_keys` in the link state."""
|
{flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/RECORD
RENAMED
@@ -3,14 +3,14 @@ flwr/cli/__init__.py,sha256=cZJVgozlkC6Ni2Hd_FAIrqefrkCGOV18fikToq-6iLw,720
|
|
3
3
|
flwr/cli/app.py,sha256=UeXrW5gxrUnFViDjAMIxGNZZKwu3a1oAj83v53IWIWM,1382
|
4
4
|
flwr/cli/build.py,sha256=4P70i_FnUs0P21aTwjTXtFQSAfY-C04hUDF-2npfJdo,6345
|
5
5
|
flwr/cli/cli_user_auth_interceptor.py,sha256=aZepPA298s-HjGmkJGMvI_uZe72O5aLC3jri-ilG53o,3126
|
6
|
-
flwr/cli/config_utils.py,sha256=
|
6
|
+
flwr/cli/config_utils.py,sha256=LelRR960I36n1IPw7BIu79fKoOh0JePA58kAtoXSTH0,7518
|
7
7
|
flwr/cli/constant.py,sha256=g7Ad7o3DJDkJNrWS0T3SSJETWSTkkVJWGpLM8zlbpcY,1289
|
8
8
|
flwr/cli/example.py,sha256=uk5CoD0ZITgpY_ffsTbEKf8XOOCSUzByjHPcMSPqV18,2216
|
9
9
|
flwr/cli/install.py,sha256=-RnrYGejN_zyXXp_CoddSQwoQfRTWWyt9WYlxphJzyU,8180
|
10
|
-
flwr/cli/log.py,sha256=
|
10
|
+
flwr/cli/log.py,sha256=vcO-r5EIc127mOQ26uxKVITX-w_Zib7AxSVuuN70_JY,6671
|
11
11
|
flwr/cli/login/__init__.py,sha256=6_9zOzbPOAH72K2wX3-9dXTAbS7Mjpa5sEn2lA6eHHI,800
|
12
|
-
flwr/cli/login/login.py,sha256=
|
13
|
-
flwr/cli/ls.py,sha256=
|
12
|
+
flwr/cli/login/login.py,sha256=EOU1E-89VPn5Ns7ytaDdGNVVeOoC4ULFjtNPogjXGGQ,3783
|
13
|
+
flwr/cli/ls.py,sha256=5KCHdctN5f5GkCAkbZSC1OuKdhmLzobINpltsdtDtQU,11383
|
14
14
|
flwr/cli/new/__init__.py,sha256=pOQtPT9W4kCIttcKne5m-FtJbvTqdjTVJxzQ9AUYK8I,790
|
15
15
|
flwr/cli/new/new.py,sha256=scyyKt8mzkc3El1bypgkHjKwVQEc2-q4I50PxriPFdI,9922
|
16
16
|
flwr/cli/new/templates/__init__.py,sha256=4luU8RL-CK8JJCstQ_ON809W9bNTkY1l9zSaPKBkgwY,725
|
@@ -66,9 +66,9 @@ flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl,sha256=PA_dEtWkY6Wf3Ektc9D
|
|
66
66
|
flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl,sha256=d7TwWH-QJN0j-9rs9zHnng_bHeHV7mk138KXqdv5BoE,686
|
67
67
|
flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl,sha256=r0SZnvoR5a5mEWKJIvQ3rW8C6-2DkhaC8A1fTA0avm0,710
|
68
68
|
flwr/cli/run/__init__.py,sha256=cCsKVB0SFzh2b3QmGba6BHckB85xlhjh3mh4pBpACtY,790
|
69
|
-
flwr/cli/run/run.py,sha256=
|
70
|
-
flwr/cli/stop.py,sha256=
|
71
|
-
flwr/cli/utils.py,sha256=
|
69
|
+
flwr/cli/run/run.py,sha256=kEOYKin9qPJy8SODxcAvIWk-OskKPsxvcbvhDhf2VD4,8299
|
70
|
+
flwr/cli/stop.py,sha256=DBCKg9AhB1WcJsyqfkHKR1_V_yT7D32zqa9QhmX9IAU,4926
|
71
|
+
flwr/cli/utils.py,sha256=z5WFbh2RwMirFcv6QtV_4rJlK7ad2XrUJUsinNhqE28,11310
|
72
72
|
flwr/client/__init__.py,sha256=DGDoO0AEAfz-0CUFmLdyUUweAS64-07AOnmDfWUefK4,1192
|
73
73
|
flwr/client/app.py,sha256=tNnef5wGVfqMiiGiWzAuULyy1QpvCKukiRmNi_a2cQc,34261
|
74
74
|
flwr/client/client.py,sha256=8o58nd9o6ZFcMIaVYPGcV4MSjBG4H0oFgWiv8ZEO3oA,7895
|
@@ -215,7 +215,7 @@ flwr/proto/transport_pb2_grpc.py,sha256=Nvn7oxzm1g1fPiGCGhyKxILDZHYG0CcgjySTzxq-
|
|
215
215
|
flwr/proto/transport_pb2_grpc.pyi,sha256=AGXf8RiIiW2J5IKMlm_3qT3AzcDa4F3P5IqUjve_esA,766
|
216
216
|
flwr/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
217
217
|
flwr/server/__init__.py,sha256=cEg1oecBu4cKB69iJCqWEylC8b5XW47bl7rQiJsdTvM,1528
|
218
|
-
flwr/server/app.py,sha256=
|
218
|
+
flwr/server/app.py,sha256=4AYewApWSvYTJZcLzKGrcvT8AvHUXzwY0ROBXgmFlPU,30598
|
219
219
|
flwr/server/client_manager.py,sha256=7Ese0tgrH-i-ms363feYZJKwB8gWnXSmg_hYF2Bju4U,6227
|
220
220
|
flwr/server/client_proxy.py,sha256=4G-oTwhb45sfWLx2uZdcXD98IZwdTS6F88xe3akCdUg,2399
|
221
221
|
flwr/server/compat/__init__.py,sha256=VxnJtJyOjNFQXMNi9hIuzNlZM5n0Hj1p3aq_Pm2udw4,892
|
@@ -226,7 +226,7 @@ flwr/server/compat/legacy_context.py,sha256=wBzBcfV6YO6IQGriM_FdJ5XZfiBBEEJdS_Od
|
|
226
226
|
flwr/server/criterion.py,sha256=ypbAexbztzGUxNen9RCHF91QeqiEQix4t4Ih3E-42MM,1061
|
227
227
|
flwr/server/driver/__init__.py,sha256=bikRv6CjTwSvYh7tf10gziU5o2YotOWhhftz2tr3KDc,886
|
228
228
|
flwr/server/driver/driver.py,sha256=u_fMfqLYTroTafGCNwKPHI4lttRL-Z5CqeT3_FHSq-Q,5701
|
229
|
-
flwr/server/driver/grpc_driver.py,sha256=
|
229
|
+
flwr/server/driver/grpc_driver.py,sha256=VYIbYavkJO2m6TcqStHr-pQLiyEoWlX8lsOsWfljZRQ,9758
|
230
230
|
flwr/server/driver/inmemory_driver.py,sha256=b1U1PrB_Vpn--vav8SX-sn0THD9BTlV9UFIpuWTWLro,6665
|
231
231
|
flwr/server/history.py,sha256=qSb5_pPTrwofpSYGsZWzMPkl_4uJ4mJFWesxXDrEvDU,5026
|
232
232
|
flwr/server/run_serverapp.py,sha256=vIPhvJx0i5sEZO4IKM6ruCXmx4ncat76rh0B4KhdhhM,2446
|
@@ -289,10 +289,10 @@ flwr/server/superlink/fleet/vce/backend/backend.py,sha256=LBAQxnbfPAphVOVIvYMj0Q
|
|
289
289
|
flwr/server/superlink/fleet/vce/backend/raybackend.py,sha256=jsUkFEVQTnrucK1jNQ_cUM8YwL7W4MQNA1GAf8ibRdg,7156
|
290
290
|
flwr/server/superlink/fleet/vce/vce_api.py,sha256=WTnUILr1OHS8LfjXQUA3FyWJYdJgdqpFAybyJUD-1Xo,13025
|
291
291
|
flwr/server/superlink/linkstate/__init__.py,sha256=v-2JyJlCB3qyhMNwMjmcNVOq4rkooqFU0LHH8Zo1jls,1064
|
292
|
-
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=
|
293
|
-
flwr/server/superlink/linkstate/linkstate.py,sha256=
|
292
|
+
flwr/server/superlink/linkstate/in_memory_linkstate.py,sha256=4ahMj7TLe-GO2ctyeZ2BBRkviGv27s6x1NS_ETRJHP8,20514
|
293
|
+
flwr/server/superlink/linkstate/linkstate.py,sha256=LWA5zRwN829GDAeSo5kmkzsMu0SkXa9qg4aG_0QN0uk,12159
|
294
294
|
flwr/server/superlink/linkstate/linkstate_factory.py,sha256=ISSMjDlwuN7swxjOeYlTNpI_kuZ8PGkMcJnf1dbhUSE,2069
|
295
|
-
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=
|
295
|
+
flwr/server/superlink/linkstate/sqlite_linkstate.py,sha256=E07w0_eCoOnZOBbdh3I3PN5k5tqt4LrEnYAuiMOF0I0,40398
|
296
296
|
flwr/server/superlink/linkstate/utils.py,sha256=EpRehwI4NeEW3oINICPWP9STK49N0aszd5s5jtle7DQ,13602
|
297
297
|
flwr/server/superlink/simulation/__init__.py,sha256=mg-oapC9dkzEfjXPQFior5lpWj4g9kwbLovptyYM_g0,718
|
298
298
|
flwr/server/superlink/simulation/simulationio_grpc.py,sha256=8aUrZZLdvprKUfLLqFID4aItus9beU6m1qLQYIPB7k0,2224
|
@@ -325,8 +325,8 @@ flwr/superexec/exec_servicer.py,sha256=X10ILT-AoGMrB3IgI2mBe9i-QcIVUAl9bucuqVOPY
|
|
325
325
|
flwr/superexec/exec_user_auth_interceptor.py,sha256=K06OU-l4LnYhTDg071hGJuOaQWEJbZsYi5qxUmmtiG0,3704
|
326
326
|
flwr/superexec/executor.py,sha256=_B55WW2TD1fBINpabSSDRenVHXYmvlfhv-k8hJKU4lQ,3115
|
327
327
|
flwr/superexec/simulation.py,sha256=WQDon15oqpMopAZnwRZoTICYCfHqtkvFSqiTQ2hLD_g,4088
|
328
|
-
flwr_nightly-1.15.0.
|
329
|
-
flwr_nightly-1.15.0.
|
330
|
-
flwr_nightly-1.15.0.
|
331
|
-
flwr_nightly-1.15.0.
|
332
|
-
flwr_nightly-1.15.0.
|
328
|
+
flwr_nightly-1.15.0.dev20250125.dist-info/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
|
329
|
+
flwr_nightly-1.15.0.dev20250125.dist-info/METADATA,sha256=6xKhBBSDBkiq4rDxICNgqjqay3PiJGuB3esHhT-i_Ig,15864
|
330
|
+
flwr_nightly-1.15.0.dev20250125.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
331
|
+
flwr_nightly-1.15.0.dev20250125.dist-info/entry_points.txt,sha256=JlNxX3qhaV18_2yj5a3kJW1ESxm31cal9iS_N_pf1Rk,538
|
332
|
+
flwr_nightly-1.15.0.dev20250125.dist-info/RECORD,,
|
{flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/LICENSE
RENAMED
File without changes
|
{flwr_nightly-1.15.0.dev20250123.dist-info → flwr_nightly-1.15.0.dev20250125.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|