This project combines federated machine learning (using Flower) with on-chain model deployment via the Filecoin Ethereum Virtual Machine (FEVM). It trains a CNN on CIFAR-10 across 16 simulated clients using federated averaging, exports the model to ONNX, and provides Solidity smart contracts for model service and Filecoin storage deal management.
FML_with_FEVM_Workshop/
├── fml_fevm/ # Python package (FL + model)
│ ├── model.py # CNN architecture (Net)
│ ├── data.py # CIFAR-10 loading & partitioning
│ ├── utils.py # Training, testing, parameter helpers
│ ├── export.py # ONNX export & bytecode conversion
│ ├── optimization.py # Pruning, quantization, profiling
│ └── federated/ # Flower-based FL components
│ ├── client.py # FlowerClient implementation
│ ├── compressed_client.py # Client with gradient compression
│ ├── compression.py # Sparse gradient utilities
│ ├── strategy.py # FedAvg + optimized strategy configs
│ ├── simulation.py # FL simulation runner
│ ├── byzantine.py # Byzantine-robust median aggregation
│ ├── profiling.py # Communication profiling & analysis
│ └── tuning.py # Local epoch tuning utilities
├── FML_Model/
│ ├── FML_with_FEVM_Workshop.ipynb # Original workshop notebook
│ └── optimization_benchmark.ipynb # Optimization benchmark notebook
├── contracts/
│ ├── basic-solidity-examples/
│ │ └── ModelService.sol # On-chain model service proxy
│ ├── filecoin-api-examples/
│ │ ├── DealRewarder.sol # Storage deal bounty contract
│ │ └── FilecoinMarketConsumer.sol # Market data consumer
│ └── basic-deal-client/
│ └── DealClient.sol # Filecoin storage deal client
├── deploy/ # Hardhat deployment scripts
├── tasks/ # Hardhat task scripts
├── docs/ # Project documentation
├── tests/ # Test suites
│ ├── python/ # pytest: model, data, optimization, compression, export, profiling, tuning, byzantine
│ └── solidity/ # Hardhat: ModelService, DealRewarder, DealClient
├── model.onnx # Exported ONNX model
├── model_onnx_bytecode.txt # Model bytecode for on-chain reference
├── requirements.txt # Python dependencies
├── pyproject.toml # Python build configuration
├── package.json # Node.js dependencies
└── hardhat.config.js # Hardhat configuration
The workshop notebook is available at FML_Model/FML_with_FEVM_Workshop.ipynb. For GPU access and pre-installed dependencies, upload it to Google Colab or run it in a local environment with the required packages installed.
The fml_fevm package provides the same functionality as the notebook in a modular, importable format:
pip install -r requirements.txtfrom fml_fevm.model import Net
from fml_fevm.data import load_datasets
from fml_fevm.utils import train, test, DEVICE
from fml_fevm.federated import run_simulation
from fml_fevm.export import export_to_onnx, onnx_to_bytecode, save_bytecode
# Train centrally
trainloaders, valloaders, testloader = load_datasets()
net = Net().to(DEVICE)
train(net, trainloaders[0], epochs=5, verbose=True)
loss, accuracy = test(net, testloader)
# Or run federated simulation
history = run_simulation(num_clients=16, num_rounds=5)
# Export to ONNX and generate bytecode
onnx_path = export_to_onnx(net)
bytecode = onnx_to_bytecode(onnx_path)
save_bytecode(bytecode)- Architecture: Small CNN (~62K parameters) — 2 conv layers + 3 fully connected layers
- Dataset: CIFAR-10 (10-class image classification)
- FL Setup: 16 simulated clients, FedAvg strategy, 5 training rounds
- Export: ONNX format with bytecode conversion for on-chain reference
The optimization_benchmark.ipynb notebook (in FML_Model/) benchmarks the full optimization pipeline. The fml_fevm.optimization module and fml_fevm.federated.compression module provide:
- Model pruning — L1 unstructured pruning on fc layers (fc1 50%, fc2 30%), targeting the 77% of parameters in fc1
- Dynamic quantization — INT8 quantization on all linear layers for smaller model size and faster inference
- Gradient compression — Top-k sparsification of gradient deltas, transmitting only the most significant updates per FL round
- Compressed FL client —
CompressedFlowerClientcombines sparse gradients with multiple local epochs, reducing both per-round bandwidth and total rounds needed
from fml_fevm.optimization import apply_pruning, make_pruning_permanent, apply_dynamic_quantization
from fml_fevm.federated.compressed_client import compressed_client_fn, set_compressed_config
# Prune and quantize a trained model
apply_pruning(net, fc1_amount=0.5, fc2_amount=0.3)
make_pruning_permanent(net)
quantized = apply_dynamic_quantization(net)
# Run FL with gradient compression
set_compressed_config(trainloaders, valloaders, keep_ratio=0.3, local_epochs=3)The fml_fevm.federated package includes communication-optimized FL with tunable hyperparameters:
- Optimized strategy —
create_optimized_strategy()samples 10 of 16 clients per round (37.5% fewer communications) - Optimized simulation —
run_optimized_simulation()combines compressed clients, tuned sampling, and fewer rounds - Communication profiling —
profiling.pycalculates baseline vs compressed byte counts and reduction percentages - Local epoch tuning —
tuning.pyestimates rounds needed and communication savings for different configurations
from fml_fevm.federated import run_optimized_simulation, create_optimized_strategy
from fml_fevm.federated.tuning import recommended_config, communication_savings
# Get recommended FL hyperparameters
config = recommended_config() # local_epochs=3, keep_ratio=0.3, fraction_fit=0.625
# Run optimized FL (3 rounds instead of 5, compressed gradients, partial participation)
history = run_optimized_simulation(num_rounds=3, keep_ratio=0.3, local_epochs=3)The byzantine.py module implements coordinate-wise median aggregation to defend against model poisoning attacks:
- Median aggregation — Filters out extreme/poisoned gradient updates from malicious clients
- Tolerance — Resists up to floor(n/2) - 1 Byzantine clients (7 of 16)
- Poisoning simulation —
simulate_poisoning_attack()for testing defense effectiveness
from fml_fevm.federated.byzantine import create_byzantine_strategy, simulate_poisoning_attack
# Create a Byzantine-robust strategy
robust_strategy = create_byzantine_strategy(max_malicious_fraction=0.5)git clone https://github.com/TechieTeee/FML_with_FEVM_Workshop.git
cd FML_with_FEVM_Workshop
yarn installYou can get a private key from a wallet provider such as Metamask.
export PRIVATE_KEY='abcdef'Or create a .env file (already in .gitignore). Never commit your private key.
yarn hardhat get-addressThis shows your Ethereum-style address and Filecoin f4 address.
Go to the Hyperspace testnet faucet and paste your Ethereum address.
yarn hardhat deployThis compiles and deploys all contracts to the Hyperspace testnet:
- ModelService — On-chain model service proxy with owner access control and event logging (
ModelUpdated,PredictionRequested). After deployment, callsetModel(address)to link a model contract. - FilecoinMarketConsumer — Queries and stores Filecoin storage deal data via the MarketAPI, with owner access control.
- DealRewarder — Creates bounties for storing specific data on Filecoin, with event logging (
CIDAdded,BountyClaimed,DataAuthorized) and hardened access control. - DealClient — Creates Filecoin storage deals from Solidity with reentrancy protection, emitting events for Boost storage providers.
Use Hardhat tasks in the tasks/ folder:
yarn hardhat get-balance --contract 'DEPLOYED_ADDRESS' --account 'YOUR_ADDRESS'The project uses the Filecoin.sol library by Zondax to interact with Filecoin storage deals on-chain. Example:
yarn hardhat store-all --contract "DEPLOYED_MARKET_CONSUMER_ADDRESS" --dealid "707"Files must be converted to .car format before storage. Use the FVM Data Depot for automatic conversion and metadata generation.
- DealClient: Creates storage deals via Solidity. See the deal-making starter kit for details.
- DealRewarder: Incentivizes data storage with bounties. See the original Foundry project for details.
Run on the local Hardhat network (no private key or testnet needed):
PRIVATE_KEY="0x0000000000000000000000000000000000000000000000000000000000000001" npx hardhat test tests/solidity/ModelService_test.js --network hardhat
PRIVATE_KEY="0x0000000000000000000000000000000000000000000000000000000000000001" npx hardhat test tests/solidity/DealRewarder_test.js --network hardhat
PRIVATE_KEY="0x0000000000000000000000000000000000000000000000000000000000000001" npx hardhat test tests/solidity/DealClient_test.js --network hardhatModelService (10 tests): Ownership, setModel access control, zero address rejection, predict-without-model revert, ModelUpdated event emission, ownership transfer prevention.
DealRewarder (8 tests): Ownership, addCID access control, authorizeData internal verification, fund deposits, CIDAdded event, security (call_actor_id internal, authorizeData internal).
DealClient (4 tests): Ownership, access control on makeDealProposal, initial deal count, reentrancy guard validation.
Requires PyTorch and dependencies (pip install -r requirements.txt):
pytest tests/python/test_model (8 tests): Output shape, batch sizes, param count, fc1 dominance, deterministic output, parameter get/set roundtrip.
test_data (9 tests): Partition count, no overlap across clients, train/val split ratio, image shape, label range, seed reproducibility.
test_optimization (10 tests): Profiling accuracy, pruning sparsity, quantization output validity, prune+quantize pipeline, inference benchmark.
test_compression (17 tests): Threshold sparsification, top-k keeps largest values, delta roundtrip, transmission size estimation, keep_ratio validation edge cases.
test_export (5 tests): ONNX file creation, ONNX validity, PyTorch-ONNX output match, bytecode hex format, bytecode-to-file-size match.
test_profiling (12 tests): Communication profile metrics, compression byte reduction, local epoch round reduction, FL config participation, report formatting, edge cases (zero epochs, zero rounds).
test_tuning (15 tests): Round estimation with local epochs, communication savings calculations, reduction percentages, recommended config validation, edge cases (zero epochs, zero clients).
test_byzantine (13 tests): Median aggregation (odd/even/single clients), poisoning attack rejection, majority-poisoned failure, strategy creation, parameter aggregation, empty input guard.
test_strategy (4 tests): Weighted average normal case, empty metrics, single client, equal weights.
MIT
