secure-fl 26.8.85__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 (62) hide show
  1. secure_fl/__init__.py +452 -0
  2. secure_fl/__main__.py +11 -0
  3. secure_fl/benchmarks/__init__.py +42 -0
  4. secure_fl/benchmarks/attacks.py +444 -0
  5. secure_fl/benchmarks/defaults.py +15 -0
  6. secure_fl/benchmarks/execution.py +573 -0
  7. secure_fl/benchmarks/pipeline.py +104 -0
  8. secure_fl/benchmarks/reporting.py +185 -0
  9. secure_fl/cli/__init__.py +70 -0
  10. secure_fl/cli/__main__.py +6 -0
  11. secure_fl/cli/handlers.py +240 -0
  12. secure_fl/cli/main.py +253 -0
  13. secure_fl/cli/setup.py +143 -0
  14. secure_fl/cli/zkp_check.py +93 -0
  15. secure_fl/core/__init__.py +137 -0
  16. secure_fl/core/_version.py +44 -0
  17. secure_fl/core/config.py +366 -0
  18. secure_fl/core/exceptions.py +509 -0
  19. secure_fl/core/types.py +634 -0
  20. secure_fl/data/__init__.py +23 -0
  21. secure_fl/data/benchmark_data.py +300 -0
  22. secure_fl/federation/__init__.py +33 -0
  23. secure_fl/federation/aggregation.py +466 -0
  24. secure_fl/federation/client.py +638 -0
  25. secure_fl/federation/client_runtime.py +113 -0
  26. secure_fl/federation/client_utils.py +138 -0
  27. secure_fl/federation/server.py +470 -0
  28. secure_fl/federation/server_runtime.py +103 -0
  29. secure_fl/federation/stability_monitor.py +484 -0
  30. secure_fl/models/__init__.py +85 -0
  31. secure_fl/models/factory.py +55 -0
  32. secure_fl/models/mnist_cnn.py +30 -0
  33. secure_fl/models/simple.py +94 -0
  34. secure_fl/proofs/__init__.py +0 -0
  35. secure_fl/proofs/client/__init__.py +0 -0
  36. secure_fl/proofs/client/delta_bound.circom +56 -0
  37. secure_fl/proofs/client_circuits/__init__.py +0 -0
  38. secure_fl/proofs/client_circuits/delta_bound.py +36 -0
  39. secure_fl/proofs/server/aggregation.circom +55 -0
  40. secure_fl/proofs/server/pot12_final.ptau +0 -0
  41. secure_fl/proofs/server/pot13_final.ptau +0 -0
  42. secure_fl/proofs/server/test.txt +3 -0
  43. secure_fl/py.typed +0 -0
  44. secure_fl/utils/__init__.py +59 -0
  45. secure_fl/utils/helpers.py +286 -0
  46. secure_fl/utils/logging_config.py +433 -0
  47. secure_fl/zkp/__init__.py +39 -0
  48. secure_fl/zkp/base.py +33 -0
  49. secure_fl/zkp/client_proof_manager.py +504 -0
  50. secure_fl/zkp/client_setup.py +205 -0
  51. secure_fl/zkp/client_snark_io.py +164 -0
  52. secure_fl/zkp/proof_manager.py +11 -0
  53. secure_fl/zkp/proof_schema.py +69 -0
  54. secure_fl/zkp/quantization.py +703 -0
  55. secure_fl/zkp/server_proof_manager.py +627 -0
  56. secure_fl/zkp/server_setup.py +127 -0
  57. secure_fl/zkp/server_snark_io.py +142 -0
  58. secure_fl-26.8.85.dist-info/METADATA +344 -0
  59. secure_fl-26.8.85.dist-info/RECORD +62 -0
  60. secure_fl-26.8.85.dist-info/WHEEL +4 -0
  61. secure_fl-26.8.85.dist-info/entry_points.txt +5 -0
  62. secure_fl-26.8.85.dist-info/licenses/LICENSE +21 -0
secure_fl/__init__.py ADDED
@@ -0,0 +1,452 @@
1
+ """
2
+ Secure FL: Dual-Verifiable Federated Learning with Zero-Knowledge Proofs
3
+
4
+ A dual-verifiable framework for federated learning using zero-knowledge proofs to ensure
5
+ training integrity and aggregation correctness.
6
+
7
+ Main components:
8
+ - Core: Types, exceptions, configuration, and version information
9
+ - Federation: FL clients, servers, and aggregation algorithms
10
+ - ZKP: Zero-knowledge proof managers and quantization
11
+ - Models: Pre-built neural network architectures
12
+ - Utils: Logging, parameter handling, and helper utilities
13
+ - CLI: Command-line interface for interaction
14
+
15
+ Example usage:
16
+ # Server setup
17
+ from secure_fl import create_server_strategy, SecureFlowerServer
18
+
19
+ strategy = create_server_strategy(
20
+ model_fn=lambda: MyModel(),
21
+ enable_zkp=True,
22
+ proof_rigor="high"
23
+ )
24
+ server = SecureFlowerServer(strategy=strategy)
25
+ server.start(num_rounds=10)
26
+
27
+ # Client setup
28
+ from secure_fl import create_client, start_client
29
+
30
+ client = create_client(
31
+ client_id="client_1",
32
+ model_fn=lambda: MyModel(),
33
+ train_data=train_dataset,
34
+ enable_zkp=True
35
+ )
36
+ start_client(client, "localhost:8080")
37
+ """
38
+
39
+ from typing import Any
40
+
41
+ # Version information
42
+ from .core import DEFAULT_CLIENT_CONFIG
43
+ from .core import DEFAULT_SERVER_CONFIG
44
+ from .core import DEFAULT_ZKP_CONFIG
45
+ from .core import AggregationError
46
+ from .core import AggregationResult
47
+ from .core import BaseAggregator
48
+ from .core import BaseProofManager
49
+ from .core import CircuitCompilationError
50
+ from .core import ClientConfig
51
+ from .core import ClientError
52
+ from .core import ClientID # Types
53
+ from .core import ComponentStatus
54
+ from .core import ConfigManager
55
+ from .core import ConfigurationError
56
+ from .core import DataError
57
+ from .core import Metrics
58
+ from .core import ModelError
59
+ from .core import ModelFunction
60
+ from .core import ModelParameters
61
+ from .core import NetworkError
62
+ from .core import ProofData
63
+ from .core import ProofError
64
+ from .core import ProofGenerationError
65
+ from .core import ProofID
66
+ from .core import ProofMetrics
67
+ from .core import ProofResult
68
+ from .core import ProofRigor
69
+ from .core import ProofVerificationError
70
+ from .core import QuantizationBits
71
+ from .core import QuantizationError
72
+ from .core import RoundID
73
+
74
+ # Core components
75
+ from .core import SecureFlConfig # Configuration
76
+ from .core import SecureFlError # Exceptions
77
+ from .core import ServerConfig
78
+ from .core import ServerError
79
+ from .core import SystemMetrics
80
+ from .core import TrainingMetrics
81
+ from .core import TrainingPhase
82
+ from .core import TrainingResult
83
+ from .core import ValidationError
84
+ from .core import ValidationResult
85
+ from .core import ZKPConfig
86
+ from .core import __version__
87
+ from .core import create_example_config
88
+ from .core import ensure_model_parameters
89
+ from .core import get_client_config
90
+ from .core import get_default_config
91
+ from .core import get_server_config
92
+ from .core import get_zkp_config
93
+ from .core import handle_error
94
+ from .core import is_valid_client_id # Utilities
95
+ from .core import is_valid_proof_rigor
96
+ from .core import is_valid_round_id
97
+ from .core import load_config
98
+ from .core import safe_execute
99
+ from .core import save_config
100
+ from .core import validate_client_id
101
+ from .core import validate_positive_int
102
+ from .core import validate_proof_rigor
103
+ from .core import validate_range
104
+ from .core import wrap_error
105
+ from .federation import FedJSCMAggregator
106
+ from .federation import SecureFlowerClient
107
+
108
+ # Federation components
109
+ from .federation import SecureFlowerServer
110
+ from .federation import SecureFlowerStrategy
111
+ from .federation import StabilityMetrics
112
+ from .federation import StabilityMonitor
113
+ from .federation import create_client
114
+ from .federation import create_server_strategy
115
+ from .federation import start_client
116
+ from .models import MNISTCNN
117
+ from .models import ResNet18Model
118
+
119
+ # Models
120
+ from .models import SimpleModel
121
+ from .models import model_fn
122
+ from .utils import AuditLogger
123
+ from .utils import PerformanceLogger
124
+ from .utils import SecureFlLogger
125
+ from .utils import aggregate_weighted_average
126
+ from .utils import compute_hash
127
+ from .utils import compute_parameter_diff
128
+ from .utils import compute_parameter_norm
129
+ from .utils import deserialize_parameters
130
+ from .utils import get_client_logger
131
+ from .utils import get_logger
132
+ from .utils import get_parameter_stats
133
+ from .utils import get_proof_logger
134
+ from .utils import get_server_logger
135
+ from .utils import ndarrays_to_parameters
136
+ from .utils import ndarrays_to_torch
137
+
138
+ # Utility functions
139
+ from .utils import parameters_to_ndarrays # Parameter utilities
140
+ from .utils import serialize_parameters
141
+ from .utils import setup_development_logging
142
+ from .utils import setup_logging # Logging utilities
143
+ from .utils import setup_production_logging
144
+ from .utils import setup_testing_logging
145
+ from .utils import torch_to_ndarrays
146
+ from .utils import validate_parameters
147
+
148
+ # ZKP components
149
+ from .zkp import ClientProofManager
150
+ from .zkp import FixedPointQuantizer
151
+ from .zkp import GradientAwareQuantizer
152
+ from .zkp import QuantizationConfig
153
+ from .zkp import QuantizationScheme
154
+ from .zkp import ScaleMethod
155
+ from .zkp import ServerProofManager
156
+ from .zkp import compute_quantization_error
157
+ from .zkp import dequantize_parameters
158
+ from .zkp import get_circuit_friendly_config
159
+ from .zkp import get_high_precision_config
160
+ from .zkp import get_int8_config
161
+ from .zkp import quantize_parameters
162
+
163
+ # Package metadata
164
+ __author__ = "Krishant Timilsina, Bindu Paudel"
165
+ __email__ = "krishtimil@gmail.com, binduupaudel565@gmail.com"
166
+ __title__ = "secure-fl"
167
+ __description__ = (
168
+ "Dual-Verifiable Framework for Federated Learning using Zero-Knowledge Proofs"
169
+ )
170
+ __url__ = "https://github.com/krishantt/secure-fl"
171
+ __license__ = "MIT"
172
+ __copyright__ = "Copyright (c) 2024 Krishant Timilsina, Bindu Paudel"
173
+
174
+ # Export main classes and functions
175
+ __all__ = [
176
+ # Version information
177
+ "__version__",
178
+ # Package metadata
179
+ "__author__",
180
+ "__email__",
181
+ "__title__",
182
+ "__description__",
183
+ "__url__",
184
+ "__license__",
185
+ "__copyright__",
186
+ # Configuration
187
+ "SecureFlConfig",
188
+ "ConfigManager",
189
+ "get_default_config",
190
+ "load_config",
191
+ "save_config",
192
+ "get_server_config",
193
+ "get_client_config",
194
+ "get_zkp_config",
195
+ "create_example_config",
196
+ # Types
197
+ "ClientID",
198
+ "RoundID",
199
+ "ProofID",
200
+ "ModelFunction",
201
+ "ModelParameters",
202
+ "ProofData",
203
+ "Metrics",
204
+ "ProofRigor",
205
+ "QuantizationBits",
206
+ "TrainingPhase",
207
+ "ComponentStatus",
208
+ "ClientConfig",
209
+ "ServerConfig",
210
+ "ZKPConfig",
211
+ "TrainingMetrics",
212
+ "ProofMetrics",
213
+ "SystemMetrics",
214
+ "TrainingResult",
215
+ "ProofResult",
216
+ "AggregationResult",
217
+ "ValidationResult",
218
+ "BaseProofManager",
219
+ "BaseAggregator",
220
+ "DEFAULT_CLIENT_CONFIG",
221
+ "DEFAULT_SERVER_CONFIG",
222
+ "DEFAULT_ZKP_CONFIG",
223
+ "is_valid_client_id",
224
+ "is_valid_round_id",
225
+ "is_valid_proof_rigor",
226
+ "ensure_model_parameters",
227
+ # Main FL components
228
+ "SecureFlowerServer",
229
+ "SecureFlowerStrategy",
230
+ "SecureFlowerClient",
231
+ "create_server_strategy",
232
+ "create_client",
233
+ "start_client",
234
+ # Aggregation
235
+ "FedJSCMAggregator",
236
+ # ZKP components
237
+ "ClientProofManager",
238
+ "ServerProofManager",
239
+ # Stability monitoring
240
+ "StabilityMonitor",
241
+ "StabilityMetrics",
242
+ # Quantization
243
+ "FixedPointQuantizer",
244
+ "GradientAwareQuantizer",
245
+ "QuantizationConfig",
246
+ "ScaleMethod",
247
+ "QuantizationScheme",
248
+ "quantize_parameters",
249
+ "dequantize_parameters",
250
+ "compute_quantization_error",
251
+ "get_int8_config",
252
+ "get_circuit_friendly_config",
253
+ "get_high_precision_config",
254
+ # Utilities
255
+ "parameters_to_ndarrays",
256
+ "ndarrays_to_parameters",
257
+ "torch_to_ndarrays",
258
+ "ndarrays_to_torch",
259
+ "compute_parameter_norm",
260
+ "compute_parameter_diff",
261
+ "compute_hash",
262
+ "serialize_parameters",
263
+ "deserialize_parameters",
264
+ "aggregate_weighted_average",
265
+ "validate_parameters",
266
+ "get_parameter_stats",
267
+ # Logging
268
+ "setup_logging",
269
+ "setup_development_logging",
270
+ "setup_production_logging",
271
+ "setup_testing_logging",
272
+ "get_logger",
273
+ "SecureFlLogger",
274
+ "PerformanceLogger",
275
+ "AuditLogger",
276
+ "get_client_logger",
277
+ "get_server_logger",
278
+ "get_proof_logger",
279
+ # Exceptions
280
+ "SecureFlError",
281
+ "ConfigurationError",
282
+ "ClientError",
283
+ "ServerError",
284
+ "ProofError",
285
+ "CircuitCompilationError",
286
+ "ProofGenerationError",
287
+ "ProofVerificationError",
288
+ "AggregationError",
289
+ "QuantizationError",
290
+ "DataError",
291
+ "NetworkError",
292
+ "ValidationError",
293
+ "ModelError",
294
+ "handle_error",
295
+ "wrap_error",
296
+ "safe_execute",
297
+ "validate_positive_int",
298
+ "validate_range",
299
+ "validate_client_id",
300
+ "validate_proof_rigor",
301
+ # Models
302
+ "SimpleModel",
303
+ "MNISTCNN",
304
+ "ResNet18Model",
305
+ "model_fn",
306
+ ]
307
+
308
+
309
+ def get_default_config_dict() -> dict[str, Any]:
310
+ """Get default configuration as dictionary (for backward compatibility)."""
311
+ return get_default_config().to_dict()
312
+
313
+
314
+ def _command_available(command: list[str], timeout: int = 5) -> bool:
315
+ import subprocess
316
+
317
+ try:
318
+ result = subprocess.run(command, capture_output=True, timeout=timeout)
319
+ return result.returncode == 0
320
+ except (subprocess.SubprocessError, OSError, FileNotFoundError):
321
+ return False
322
+
323
+
324
+ def _get_component_status() -> dict[str, bool]:
325
+ components = {
326
+ "Flower": False,
327
+ "PyTorch": False,
328
+ "Circom": _command_available(["circom", "--version"]),
329
+ "SnarkJS": _command_available(["snarkjs", "help"]),
330
+ }
331
+
332
+ try:
333
+ import torch # noqa: F401
334
+
335
+ components["PyTorch"] = True
336
+ except ImportError:
337
+ pass
338
+
339
+ try:
340
+ import flwr # noqa: F401
341
+
342
+ components["Flower"] = True
343
+ except ImportError:
344
+ pass
345
+
346
+ return components
347
+
348
+
349
+ def print_system_info() -> None:
350
+ """Print system information and component status."""
351
+ print(f"Secure FL v{__version__}")
352
+ print(f"Description: {__description__}")
353
+ print(f"Authors: {__author__}")
354
+ print()
355
+
356
+ components = _get_component_status()
357
+
358
+ print("Component Status:")
359
+ for component, available in components.items():
360
+ status = "✓ Available" if available else "✗ Not Found"
361
+ print(f" {component}: {status}")
362
+
363
+ print()
364
+ print("Note: Cairo, Circom, and SnarkJS are required for full ZKP functionality")
365
+ print("Install them separately for complete proof generation capabilities")
366
+
367
+
368
+ def create_secure_fl_setup(
369
+ model_fn: Any,
370
+ train_datasets: Any,
371
+ val_datasets: Any = None,
372
+ config: Any = None,
373
+ ) -> Any:
374
+ """
375
+ Create a complete secure FL setup with server and multiple clients.
376
+
377
+ Args:
378
+ model_fn: Function that returns a PyTorch model
379
+ train_datasets: List of training datasets for each client
380
+ val_datasets: Optional list of validation datasets
381
+ config: Optional configuration dictionary or SecureFlConfig instance
382
+
383
+ Returns:
384
+ Tuple of (server, clients) ready for training
385
+ """
386
+ if config is None:
387
+ config = get_default_config()
388
+
389
+ # Create server strategy
390
+ if isinstance(config, SecureFlConfig):
391
+ server_config = config.server
392
+ else:
393
+ # Legacy dict format
394
+ server_config = ServerConfig(**config.get("server", {}))
395
+
396
+ strategy = create_server_strategy(
397
+ model_fn=model_fn,
398
+ momentum=server_config.momentum,
399
+ learning_rate=server_config.learning_rate,
400
+ enable_zkp=server_config.enable_zkp,
401
+ proof_rigor=(
402
+ server_config.proof_rigor.value
403
+ if isinstance(server_config.proof_rigor, ProofRigor)
404
+ else server_config.proof_rigor
405
+ ),
406
+ )
407
+
408
+ # Create server
409
+ if isinstance(config, SecureFlConfig):
410
+ server = SecureFlowerServer(
411
+ strategy=strategy, num_rounds=config.server.num_rounds
412
+ )
413
+ else:
414
+ # Legacy dict format
415
+ server = SecureFlowerServer(strategy=strategy, **config.get("server", {}))
416
+
417
+ # Create clients
418
+ clients = []
419
+ for i, train_data in enumerate(train_datasets):
420
+ val_data = val_datasets[i] if val_datasets else None
421
+
422
+ if isinstance(config, SecureFlConfig):
423
+ client_config = config.client
424
+ client = create_client(
425
+ client_id=f"client_{i}",
426
+ model_fn=model_fn,
427
+ train_data=train_data,
428
+ val_data=val_data,
429
+ enable_zkp=client_config.enable_zkp,
430
+ proof_rigor=(
431
+ client_config.proof_rigor.value
432
+ if isinstance(client_config.proof_rigor, ProofRigor)
433
+ else client_config.proof_rigor
434
+ ),
435
+ quantization_bits=(
436
+ client_config.quantization_bits.value
437
+ if isinstance(client_config.quantization_bits, QuantizationBits)
438
+ else client_config.quantization_bits
439
+ ),
440
+ )
441
+ else:
442
+ # Legacy dict format
443
+ client = create_client(
444
+ client_id=f"client_{i}",
445
+ model_fn=model_fn,
446
+ train_data=train_data,
447
+ val_data=val_data,
448
+ **config.get("zkp", {}),
449
+ )
450
+ clients.append(client)
451
+
452
+ return server, clients
secure_fl/__main__.py ADDED
@@ -0,0 +1,11 @@
1
+ """
2
+ Main entry point for Secure FL CLI
3
+
4
+ This allows the package to be executed as a module:
5
+ python -m secure_fl <command>
6
+ """
7
+
8
+ from .cli import main
9
+
10
+ if __name__ == "__main__":
11
+ main()
@@ -0,0 +1,42 @@
1
+ """Benchmark orchestration helpers for experiment entrypoints."""
2
+
3
+ from secure_fl.data.benchmark_data import SUPPORTED_DATASETS
4
+ from secure_fl.data.benchmark_data import kfold_split_indices
5
+ from secure_fl.data.benchmark_data import load_dataset
6
+ from secure_fl.data.benchmark_data import normalize_datasets
7
+ from secure_fl.data.benchmark_data import partition_dataset
8
+ from secure_fl.data.benchmark_data import subsample_dataset
9
+ from secure_fl.models.factory import model_fn
10
+
11
+ from .attacks import ATTACK_SCALE
12
+ from .attacks import MAX_NORM
13
+ from .attacks import GradientPoisonClient
14
+ from .attacks import run_attack_fold
15
+ from .defaults import PAPER_DEFAULT_ROUNDS
16
+ from .defaults import resolve_num_rounds
17
+ from .execution import run_training_rounds
18
+ from .pipeline import run_single
19
+ from .reporting import build_tradeoff_report
20
+ from .reporting import summarize_folds
21
+ from .reporting import summarize_repeats
22
+
23
+ __all__ = [
24
+ "PAPER_DEFAULT_ROUNDS",
25
+ "resolve_num_rounds",
26
+ "SUPPORTED_DATASETS",
27
+ "normalize_datasets",
28
+ "load_dataset",
29
+ "partition_dataset",
30
+ "subsample_dataset",
31
+ "kfold_split_indices",
32
+ "model_fn",
33
+ "run_single",
34
+ "run_attack_fold",
35
+ "run_training_rounds",
36
+ "summarize_folds",
37
+ "summarize_repeats",
38
+ "build_tradeoff_report",
39
+ "GradientPoisonClient",
40
+ "MAX_NORM",
41
+ "ATTACK_SCALE",
42
+ ]