Inspiration
I am passionate about C programming and embedded systems. I love the intersection of hardware and software - the idea that code can directly control physical devices.
That passion sparked a question: what if a merchant's payment terminal was not a smartphone app but an actual embedded device? Something running on an ESP32 with an OLED display, an NFC reader, and a keypad. A real physical point-of-sale terminal built from scratch in C.
Since the hardware was not available, I built a digital twin first - a software simulator using SDL2 that behaves exactly like the physical device would. Same state machine, same network layer, same display logic. The digital twin lets me develop and test the full payment flow now, with a clear path to deploying the same C codebase directly onto ESP32 hardware later.
When I discovered Midnight Network on the hackathon track, the privacy angle clicked immediately. A physical merchant terminal in a Lagos market handling confidential payments - no one on the blockchain should know how much a small business made today. Midnight's zero-knowledge proofs made that possible without any compromise on verifiability.
That is how ChainEngineers was born: a C programmer's answer to financial privacy for embedded point-of-sale systems.
What it does
ChainEngineers is a point-of-sale payment terminal for small merchants.
The merchant enters an amount in Nigerian Naira on a physical terminal. The system converts it to DUST (Midnight's spendable token), generates a QR code, and waits for the customer to pay. When payment is confirmed on-chain, the terminal shows a confirmation screen with the transaction hash.
The key difference from any other crypto POS system: the payment amount, merchant identity, and customer details never touch the public ledger. Only a cryptographic commitment is stored on-chain. A zero-knowledge proof mathematically guarantees the payment was correct without revealing what was paid or to whom.
The chain sees: "a valid payment happened." The chain never sees: "N5000 was paid to Ade's Electronics on Lagos Island."
How I built it
The project has three layers:
C Terminal (SDL2) The merchant-facing interface is built entirely in C with SDL2 for rendering. It handles amount input, QR code display using the Nayuki qrcodegen library, payment status polling, transaction history, and balance display. It talks to the backend over raw TCP sockets with no external dependencies.
Node.js Backend An Express server handles all communication between the C terminal and the Midnight Network. It manages payment sessions, converts Naira to DUST, generates midnight: URI scheme QR codes, and monitors the Midnight Indexer via GraphQL for payment confirmations.
A dedicated MonitorService uses an EventEmitter pattern to watch multiple pending payments simultaneously with exponential backoff on network failures.
A CommitmentService manages the ZK commitment lifecycle: creating commitments before QR codes are shown, verifying proofs when payments confirm, and archiving finalized records to prevent replay attacks.
Compact Smart Contract payment.compact defines three circuits on the Midnight blockchain:
submit_payment(): called when a QR is generated. Computes commitment = hash(amount + merchant_id + salt) and stores it on-chain with status PENDING.
confirm_payment(): called by the customer's Lace wallet after scanning. Recomputes the commitment from private witnesses and asserts it matches. Transitions status to CONFIRMED.
expire_payment(): called by the backend after TTL elapses. Marks the payment EXPIRED with no private witnesses needed.
The amount and merchant identity are private witnesses that never leave the proof server. The chain only ever sees the commitment hash.
Challenges I ran into
Migrating from Solana to Midnight required rethinking the entire data model. Solana uses base58 public keys and lamports. Midnight uses Bech32m addresses, DUST tokens, and a GraphQL Indexer instead of direct RPC calls.
Every field name across the C codebase had to be updated: tx_signature to tx_hash, amount_sol to amount_dust, balance_sol to balance_dust. Buffer sizes had to be increased for longer Midnight addresses and transaction hashes.
The Compact compiler is not available as a standard npm package - it ships inside the Midnight devkit. Without Docker available locally, I designed the backend with a full demo mode that simulates the complete payment flow without a live contract, so the terminal UI could be developed and tested independently.
Understanding the ZK commitment design took significant research. The key insight was that the commitment scheme did not need to be complex for an MVP. hash(amount + merchant_id + salt) stored on-chain with the private values as witnesses gives real confidentiality with manageable implementation complexity.
Accomplishments that I'm proud of
Building a working privacy-preserving POS terminal in 48 hours as a solo participant while learning a completely new blockchain from scratch.
Designing a digital twin in C and SDL2 that faithfully simulates how the terminal will behave on real ESP32 hardware. The same state machine, network layer, and display logic will run on physical hardware with minimal changes.
The architecture is genuinely extensible: one deployed contract handles unlimited payment sessions, merchant addresses are passed per payment supporting multi-terminal deployment, and the passive monitor watches for incoming payments even when the terminal is idle.
The C terminal compiles and runs on Windows with a single gcc command and zero external dependencies beyond the SDL2 DLLs.
What I learned
Midnight's Compact language makes ZK proofs accessible in a way no other platform currently does. Writing a circuit feels like writing normal TypeScript-adjacent code. The compiler handles the ZK math entirely.
The privacy narrative matters as much as the technical implementation. The strongest argument for Midnight is not "we use ZK proofs" but "a competitor cannot watch your blockchain address and know you made N200,000 today." Real privacy for real people.
What's next for ChainEngineers
- Deploy payment.compact to Midnight preprod testnet
- Integrate Midnight Wallet SDK for real ZK proof generation
- Port the C terminal to ESP32 hardware with OLED display and NFC reader
- Add NGN/DUST live exchange rate feed
- Add multi-merchant routing via merchant_id
- Add thermal printer receipt output via GPIO
Built With
- c
- compact
- express.js
- graphql
- midnight
- network
- node.js
- proofs
- sdl2
- winsock2
- zero-knowledge
Log in or sign up for Devpost to join the conversation.