ChainGuardFL: checking the data behind a federated model
In federated learning the server never sees what clients train on. This project screens every client's images for AI-generated fakes and duplicates before training starts, and records each decision in a ledger anyone can verify.
Average test accuracy (%) over 8 backbones. Centralized figures come from an earlier benchmark on the same dataset.
Read the full case study
The problem
FedAvg assumes every image a client holds is real. Two things break that. A client's data can contain AI-generated artwork, by accident or on purpose. And the same painting can arrive through several clients at different sizes or formats, which quietly gives it extra weight. Afterwards, nobody but the server operator can check what was accepted or rejected.
How it works
- Fake filter. A DaViT-Base real versus fake classifier scores each training image once, before round 1. Anything scoring above 0.5 is dropped.
- Duplicate registry. Each image is converted to RGB, resized to 256 by 256 and hashed with SHA-256. The same artwork gives the same hash in any file format, so copies from other clients are rejected.
- Training. 10 clients with uneven class splits (Dirichlet 0.5), 50 rounds of standard FedAvg on the verified data.
- Ledger. Every verdict, update hash and global model hash goes into a SHA-256 chain, so editing an old record breaks every later one.
It adds a step in front of FedAvg and leaves the aggregation rule alone, so the checking cost is paid once instead of every round.
Results for each backbone (test accuracy, %)
| Backbone | Clean | Fakes mixed | Filtered | Recovered |
|---|---|---|---|---|
| Inception-ResNet-V2 | 54.40 | 47.16 | 50.88 | +3.72 |
| ResNet-101 | 56.36 | 53.23 | 54.03 | +0.80 |
| ViT-B/16 | 62.82 | 55.77 | 56.56 | +0.79 |
| MaxViT-tiny | 59.69 | 55.19 | 56.56 | +1.37 |
| MViTv2-tiny | 65.17 | 59.30 | 61.64 | +2.34 |
| FocalNet-tiny | 65.95 | 55.58 | 58.32 | +2.74 |
| DaViT-base | 66.54 | 56.67 | 58.71 | +2.04 |
| RepViT-m3 | 63.99 | 57.84 | 61.27 | +3.43 |
| Average | 61.86 | 55.09 | 57.25 | +2.15 |
The ordering fakes mixed, then filtered, then clean, then centralized held for every backbone. A model's centralized rank did not predict its federated rank: RepViT-m3 was fourth centrally and second after filtering.
How good is the filter?
On 7,575 training images it caught 1,965 of 2,407 fakes (81.6% recall) with 70.0% precision, and wrongly removed 843 real images.
Limitations
- The filter runs once, so a weakness against a new image generator affects the whole run.
- The ledger is a hash chain inside one process. It shows tampering but has no multi-node consensus.
- Only pixel-identical copies are caught, not two photos of the same painting.
- It checks data, not weight updates, so a poisoned update would pass.
- Everything was tested at a single heterogeneity setting.
The audit ledger
Every integrity decision is written to a SHA-256 hash chain, so the whole training run can be checked afterwards. The chain is implemented in Python with hashlib and runs inside the training process. It is not Ethereum, Hyperledger or any public network, and the report says so openly: it proves that records were changed, but it has no independent validator nodes.
Each block stores its index, its payload, and the hash of the block before it. The block hash is SHA-256(index + payload + previous hash). Change any old record and every block after it stops matching.
The records above are illustrative. The hashing is real and runs in your browser.
What gets recorded
- Filter verdicts: client, image pixel hash, DaViT score, kept or removed.
- Duplicate registry: each registration, and each rejection with the original owner and timestamp.
- Training: a hash of every client's weight update, and a hash of each global model.
- Final certificate: written once all 50 rounds are done.
Where it connects to the pipeline
The ledger is written to at both stages. Before round 1, the filter and the registry log every verdict. Then in each round, every client update is hashed and logged before it reaches the server, and the new global model is hashed and logged after FedAvg. A live dashboard shows the latest block hash, the block count and whether the chain is valid.
