Bachelor’s thesis 2026 Grade 10/10
Designing Trust Across Seven Organisations
A permissioned dApp for verifiable agricultural subsidy workflows
- Department
- Informatics and Telematics, Harokopio University of Athens
- Supervisor
- Anargyros Tsadimas
Overview
Most public-service software digitises a form. This project asked a harder question:
Can the decision behind a subsidy become independently verifiable, without giving one organisation complete control of the workflow or custody of the citizen’s signing key?
For my B.Sc. thesis I designed and built the application layer of a research platform for agricultural subsidies on Hyperledger Fabric. Seven participants share one workflow. Policy rules run as deterministic smart contracts, sensitive records reach only the organisations that need them, and farmers sign their own transactions from a browser wallet.
It is a fully implemented research prototype. It is not an official OPEKEPE service, not an official implementation of the EU Common Agricultural Policy and not a production government service: the institutional registries are simulated, and no real funds move.
The thesis was written in two parts. I built the application layer described on this page; Anastasia Zerva led the Hyperledger Fabric infrastructure, its orchestration and the network evaluation.
At a glance
- Type
- B.Sc. thesis
- Applied research
- Full-stack distributed system
- My role
- Application architect, blockchain and full-stack engineer, wallet developer, researcher
- Scope I led
- Chaincodes and smart contracts, application services, external-system connectors, seven role-specific portals, the farmer wallet, end-to-end workflows and application-level testing
- Collaboration
- Two-part thesis with Anastasia Zerva, who led the Fabric infrastructure, orchestration and network evaluation
- Technologies
- Hyperledger Fabric, Go, React, TypeScript, Web Crypto API, Keycloak, PostgreSQL, CouchDB, IPFS/Kubo, Docker Compose, Playwright, Vitest
The challenge
Agricultural subsidy administration is not one transaction between a citizen and an application. It is a long-running process across several authorities, with private records, changing policy rules, eligibility checks, approvals and payment instructions.
Nobody rewrites history alone
No single organisation should be able to silently rewrite the history of a case. The parties need a shared record, while their legal responsibilities stay distinct.
The farmer authorises
A farmer should authorise their own application. A server signing on their behalf is convenient, but it weakens non-repudiation and turns the service provider into a key custodian.
Verification without exposure
Shared verification must not mean shared visibility. Tax, land and banking records cannot reach every participant just because they work on the same process.
Policy without a release
Rates, thresholds, eligibility windows and penalty scales change. Hard-coding them would tie every regulatory change to a new deployment.
The goal was not to put the process on a blockchain. It was to decide precisely which facts belong on a shared ledger, which must stay private, who may move a case forward, and what evidence should remain after every decision.
The design response
Institutions keep control of their systems. The consortium shares only the proofs, decisions and state required to complete the process.
The platform separates three planes. The systems each institution already owns, such as its tax, land, reserve and banking registries, form the external plane. The connector plane is the only layer allowed to talk both to an institution’s registry and to its Fabric peer. The consortium plane holds the shared ledger and the smart contracts.
External registries
Simulated in the prototype
- OPEKEPEFarmer and parcel registry
- AADETax registry
- RegionLand registry
- MinistryNational reserve
- BankCore banking
- EU ObserverNo registry
Organisation connectors
One Go service per organisation
- OPEKEPE
- AADE
- Region
- Ministry
- Bank
- EU Observer
Fabric consortium
Shared ledger and smart contracts
subsidychannel
Three chaincodes, five private data collections
Static architecture checks enforce the boundary: connectors cannot import a database driver, and external registries cannot depend on Fabric.
A consortium should integrate sovereign systems, not quietly absorb them into a new central database.
Seven organisations, one channel
Seven organisations take part in one channel, subsidychannel. Six of them run their own infrastructure, and their staff sign in through Keycloak. Farmers run nothing: each holds an X.509 identity under FarmersMSP and signs in a browser wallet.
Three chaincodes keep their world state in separate namespaces. Five private data collections narrow who can read sensitive values, and OPEKEPE is a member of every one of them.
Farmer’s browser
Self-custody X.509, no Keycloak
FarmerFarmersMSP
Applies and signsNo peer, no orderer
Organisations
Staff sign in through Keycloak SSO
OPEKEPEOpekepeMSP
Payment authorityOrchestrator, consenter
AADEAADEMSP
Tax verification
RegionRegionalMSP
Parcel validation
MinistryMinistryMSP
National allocationCo-approves high-value cases
BankBankMSP
Payment executionNo consenter
EU ObserverEUObserverMSP
Read-only auditNo consenter, cannot endorse or submit
subsidychannel
One permissioned ledger
Chaincodes on the channel
policy-chaincode1 contract
World state
entitlement-chaincode7 contracts
World state
- entitlement-opekepe-aade-collectionMembers: OPEKEPE, AADE
- entitlement-opekepe-regional-collectionMembers: OPEKEPE, Region
subsidy-chaincode7 contracts
World state
- opekepe-aade-collectionMembers: OPEKEPE, AADE
- opekepe-regional-collectionMembers: OPEKEPE, Region
- opekepe-bank-collectionMembers: OPEKEPE, Bank
Each chaincode keeps its world state and its private data collections in its own namespace.
- Staff sign in through Keycloak
- Self-held key, signed in the browser
- Trust boundary: the farmer’s device
Policy became data, not code
I split the on-chain domain into three chaincodes with separate responsibilities.
- policy-chaincode
- Stores the active policy version, payment schemes, rates, thresholds and penalty parameters as ledger data.
- entitlement-chaincode
- Manages the request, verification, allocation and issuance of subsidy entitlements.
- subsidy-chaincode
- Manages the annual application, from submission and eligibility checks through approval and the payment order.
The ledger runs a test policy, CAP-2026-v1, inspired by the Common Agricultural Policy and explicitly not legislation. A new policy period becomes a new version in the ledger, not a set of hidden constants in a code release.
Across the three chaincodes, fifteen contracts implement state transitions, access rules, deadlines, duplicate-claim prevention and subsidy calculations.
A transition goes through only when
- the current state of the case allows it
- the caller’s MSP is authorised for it
- its deadline or time window holds
- it does not duplicate an existing claim
- every amount follows from a deterministic calculation
Timestamps come from the Fabric transaction context, never from a local clock, so every endorsing peer computes the same result.
The farmer signs, not the platform
The most distinctive part of the project is a Chrome-compatible wallet extension for citizen self-custody.
Each farmer has a real X.509 identity under a dedicated FarmersMSP. The wallet generates an ECDSA P-256 key pair in the browser, encrypts the private key at rest with AES-256-GCM under a PBKDF2-derived key, and offers an encrypted backup that the farmer controls. The private key is never sent to the portal or the backend.
The wallet
- Identity
- X.509 under FarmersMSP
- Key pair
- ECDSA P-256, generated in the browser
- At rest
- AES-256-GCM, key derived with PBKDF2
- Backup
- Encrypted, kept by the farmer
- Leaves the wallet
- Signatures, never the private key
The backend may transport a transaction. The backend cannot authorise it on the farmer’s behalf.
A browser cannot act as a native Fabric Gateway client, so I designed an offline-signing protocol. The wallet does not sign a byte array because a server sent it: it decodes the bytes and checks what they would authorise first.
Nine steps in two rounds. Round 1, the proposal: the backend prepares an unsigned proposal, and the wallet decodes it, verifies it and signs it before the backend sends it for endorsement. Round 2, the transaction: the backend returns the transaction bytes, and the wallet verifies and signs the envelope before the backend submits it to ordering. The portal only relays bytes between wallet and backend.
- WalletHolds the key
- PortalRelays bytes, holds no key
- BackendPrepares and transports
- FabricEndorses and orders
Round 1 / proposal
- 1
Backend
Prepare the proposal
Unsigned, built from the farmer’s public identity
- 2
Wallet
Decode the protobuf
The actual proposal payload
- 3
Wallet Verify
Check what it authorises
Channel, chaincode function, MSP, certificate, farmer ID
- 4
Wallet Sign
Sign the proposal
ECDSA P-256, low-S, DER-encoded
- 5
Backend
Send for endorsement
The signed proposal goes to the peers
Endorsing peers
Round 2 / transaction
- 6
Backend
Return the transaction
Transaction bytes built from the endorsements
- 7
Wallet Verify
Verify the envelope
Decoded and checked before a second signature
- 8
Wallet Sign
Sign the transaction
Same key, same low-S DER form
- 9
Backend
Submit to ordering
Only now does the transaction reach the orderer
Ordering service
- Verify
- Sign
- Relayed by the portal
- Trust boundary: the private key stays in the wallet
Protected reads
The same identity protects reads. Each step closes a specific gap:
One-time challenge
A short-lived session starts from a single-use nonce.
Domain-separated signature
The wallet signs a message that cannot double as a signature on anything else.
Certificate chain
The backend validates it against the FarmersMSP CA.
Farmer ID from the certificate
Never from a query parameter, which closes an enumeration path against citizen records.
Privacy, designed field by field
One shared channel gives every participant the same process history, while five private data collections keep sensitive values with the organisations that need them. Tax and land data are shared only with the relevant authority and OPEKEPE. The bank resolves the IBAN inside its own registry; the IBAN never enters the ledger.
Large or erasable documents take another path. A young farmer’s diploma is stored in a private two-node IPFS/Kubo swarm operated by separate organisations, and only its content identifier (CID) is committed to the workflow. That keeps an integrity reference without placing the PDF in immutable ledger state.
A person still reviews the document: a hash proves that the content has not changed, not that it belongs to the applicant.
Immutability is useful for decisions and evidence. It is often the wrong property for personal documents.
Where the data lives
Workflow state and decisions
Stored inThe channel ledger
Every organisation’s peer keeps the same history of states and decisions. The EU Observer can read it, but cannot endorse or submit. Farmers have no peer and read their own case through signed requests.
- Farmer
- Own case, signed read
- OPEKEPE
- Ledger copy
- AADE
- Ledger copy
- Region
- Ledger copy
- Ministry
- Ledger copy
- Bank
- Ledger copy
- EU Observer
- Read-only copy
Tax and land facts
Stored inPrivate data collections
Tax facts are shared only between OPEKEPE and AADE, land facts only between OPEKEPE and the Region. The other peers see a hash of each private value, which is how Fabric records private data on the shared ledger.
- Farmer
- Not stored
- OPEKEPE
- Tax and land
- AADE
- Tax
- Region
- Land
- Ministry
- Hash only
- Bank
- Hash only
- EU Observer
- Hash only
Bank account (IBAN)
Stored inThe bank’s own registry
OPEKEPE issues the payment order. The bank resolves the farmer’s IBAN in its own system, so the IBAN never enters the ledger.
- Farmer
- Not stored
- OPEKEPE
- Not stored
- AADE
- Not stored
- Region
- Not stored
- Ministry
- Not stored
- Bank
- Own registry
- EU Observer
- Not stored
Young farmer’s diploma
Stored inA private two-node IPFS swarm
The PDF stays off the ledger, on two IPFS/Kubo nodes run by separate organisations. Only its CID is committed to the workflow, and a person still reviews the document.
- Farmer
- Not stored
- OPEKEPE
- Swarm node
- AADE
- CID only
- Region
- CID only
- Ministry
- Swarm node
- Bank
- CID only
- EU Observer
- CID only
- Holds the value
- Hash or CID only
- Nothing stored
One workflow, seven perspectives
The system includes seven role-specific React portals and a browser wallet. Each portal is a controlled window onto the same state machine, not a separate dashboard.
The backends react to chaincode events instead of relying on a central workflow engine. When a case reaches the relevant state, each organisation checks it against its own registry and records a signed result.
Farmers
Portal and wallet
Enrol, review entitlements, prepare applications and sign transactions.
OPEKEPE
Manages campaigns, registrations, escalations and final decisions.
AADE
Verifies tax-related conditions.
Regional authorities
Validate parcels and declared land.
Ministry
Decides on the National Reserve and co-approves high-value cases.
Bank
Processes payment orders without disclosing banking data to the consortium.
EU Observer
Read-only
Receives an audit view of the ledger. It cannot endorse or submit state changes.
Engineering for the failure that still looks successful
In a payment system, the most dangerous defect is not always a crash. It is a workflow that completes normally with the wrong amount.
That shaped the verification strategy. Tests assert exact monetary outcomes, authorised callers, legal state transitions, privacy boundaries and end-to-end ledger state, not only HTTP status codes.
What the repository contains
- Chaincodes
- 3
- Smart contracts
- 15
- Private data collections
- 5
- Channel
- 1
- Institution-specific connectors
- 6
- Simulated sovereign registries
- 5
- Portals, plus a browser wallet
- 7
How it is tested
- Top-level chaincode test functions
- 157
- Frontend unit-test declarations
- More than 300
Unit, integration, end-to-end, security and conformance suites. Private data isolation is checked live, from the peers of different organisations.
Signing was not the bottleneck
I benchmarked the self-custody signing path with a real proposal captured from the running system, timing decoding, verification, signing and DER encoding together.
The cryptographic work was effectively imperceptible. Network endorsement and consensus, not client-side signing, dominated the wait. These are measurements on two machines, not a projection to other devices or loads.
Median time for the signing path
- 2022 hardware
- about 0.075 ms
- 2011 desktop
- about 0.21 ms
Deployment
The platform also ran beyond a laptop: the consortium was deployed on six physical machines connected over WireGuard, with a cloud node serving the citizen-facing edge. That deployment belongs to Anastasia Zerva’s infrastructure half of the joint thesis; the application workflows described here ran on top of it.
Where the guarantees end
Simulated registries, no real funds
The institutional registries are simulated, and the prototype cannot move real money.
A test policy, not law
CAP-2026-v1 is representative. It is not an authoritative codification of EU law.
Self-custody with real farmers is untested
The signing flow was validated technically. Its usability with real farmers remains a future study.
Erasure is reduced, not solved
Keeping documents off-chain reduces the tension between an immutable ledger and the right to erasure, but some identifying fields still remain on-chain.
Contracts only know their inputs
A rule cannot be enforced if the domain model does not contain the fact it depends on. Smart-contract code cannot responsibly invent missing data.
These constraints are not footnotes. They define where the system’s guarantees end.
What I learned
The strongest result was not that a blockchain can record subsidy decisions. A conventional database can record them too.
The meaningful result was that authority can be distributed without making responsibility ambiguous.
The project became an exercise in a broader kind of engineering: designing not only what a system does, but who is allowed to know, decide, sign and prove each part of it.
Who may know
Tax and land facts reach only the relevant authority and OPEKEPE. Banking data stays at the bank.
Who may decide
OPEKEPE remains the payment authority, the tax agency answers for tax facts, and every transition checks the caller’s MSP.
Who may sign
The farmer holds the key that authorises the application. The platform carries the transaction but cannot sign it.
What can be proven
The ledger keeps a shared sequence of signed decisions that no participant can rewrite alone. A hash proves a document is unchanged, not whose it is.
Outcome
The thesis produced a working, measurable answer to its central question. A citizen can sign their own public-service transaction. Changing policy can be represented as governed, versioned data. Several institutions can coordinate on one ledger without exposing every underlying record. And verification can focus on whether decisions are correct, not only on whether the software is available.
Back to selected work