I Built Financial Systems, Then I Questioned Them: My Journey into Bitcoin and Privacy

I Built Financial Systems, Then I Questioned Them: My Journey into Bitcoin and Privacy

There's a moment, when you've worked long enough in traditional finance, when something quietly stops making sense. For me, it wasn't dramatic. There was no single breaking point, just a growing discomfort. I spent over five years as a software engineer building systems for banks and fintech platforms, systems that moved money efficiently, reliably, and at scale. On paper, everything worked: the transactions were fast, the APIs were clean, the UIs were intuitive, the infrastructure was solid. But underneath all that engineering elegance was a trade-off we rarely questioned: privacy. Every transaction required identity checks. Every movement of value left a trail. Every user had to reveal more of themselves than felt necessary just to participate, and as an engineer, I wasn't just observing this, I was helping build it. That realization crystallized for me one evening after a ride-hailing trip in Nigeria. At the point of payment, I received the driver's account number, and paying into it triggered an automatic name lookup and the driver's full name appeared on my screen. In turn, once he confirmed receipt, mine appeared on his. He now knew my name, and because he'd just dropped me at my door, he knew where I lived too. Neither of us had asked for that information. The payment rail handed it over as a side effect of doing something as ordinary as paying for a ride. I wasn't comfortable with that, and I started wondering how far you could push a payment system before privacy stopped being an afterthought and became a design requirement. Bitcoin offered part of an answer, with wallet addresses instead of identity-linked accounts. Cashu, as I'd later learn, pushes that idea considerably further using blinded signatures. We'll get to exactly how that works. I'd followed the Bitcoin space loosely since the 2017 bull run, and again through 2020–2021, but back then it lived in my head as a price chart and a headline cycle not as software that needed contributors. In 2023, a friend who was actively contributing to open-source work at the time introduced me to it as a technology rather than an asset. That was my first real exposure to the engineering side of things. I didn't go all-in, not because I couldn't follow the material, but because I didn't commit to it. I hadn't yet understood that in this space, the development ecosystem matters as much as the asset ecosystem. It isn't something you half-learn. It demands depth, and I wasn't ready to give it that yet. By January 2025, I got another opportunity: a structured, contribution-focused engineering program. This time I treated it like a reset, not a browse. The program stripped things down to their foundations: Transaction construction Script and validation rules Lightning Network fundamentals Protocol design trade-offs It wasn’t about memorising concepts, it was about understanding systems deeply enough to build on them and at the same time, life didn’t pause for any of this. I was balancing a full-time 9–5 job, the intensity of the program and the expectation to contribute meaningfully to the open source ecosystem. It didn’t get easier because two months in, my laptop crashed under the weight of everything I was running (nodes, tooling, multiple environments). It sounds small, but at that moment, it felt symbolic, this wasn’t casual anymore, things started to click and it felt like a brave new world had been opened up to me. At the same time, I wasn't sure I was ready to move from learning to contributing, but the program gave me something as valuable as the curriculum: a mentor who kept meeting with me weekly long after the formal program ended, working through open-source projects I might contribute to. We first tried a project called Polar, but it didn't click. Around that time, I read an article my friend had written about Ecash for commerce, focused on a protocol called Cashu, which he called a "gift card for Bitcoin." That framing did something the price charts never had: it made the underlying tooling feel personal. You can read the full piece here.Cashu is a Chaumian Ecash protocol that enables fast, Bitcoin-backed transactions while preserving user privacy through blinded tokens. This is a system with privacy built into the protocol itself, not bolted on or an afterthought, for me, it wasn’t just interesting, it was obvious this is protocol I was going to fall in love with as it was the inverse of everything I'd spent years building. Instead of applications that strip users of the ability to protect their identity, here was a protocol whose entire purpose was protecting it.All the problems I had seen in building banking and fintech applications especially around privacy, this protocol approached from a completely different angle where the mint which we can see in this instance as the “bank”, doesn’t know which tokens belong to which user, transactions don’t expose identity and value can move without surveillance, it aligned almost perfectly with the discomfort I had carried from my previous work and it was time for me to get started with this amazing piece of art. How the Protocol Works Every payment system needs some way to stop the same unit of value from being spent twice. Banks solve this by keeping a ledger with your name on it. Bitcoin solves it with a public, shared ledger anyone can audit. This protocol solves it differently: the mint keeps track of which secrets have already been spent, without ever needing to know who spent them. Here's the mechanism, step by step, using the same notation the protocol's own specification uses. Step 1: Your wallet picks a secret Before you ever talk to the mint, your wallet generates a random secret, call it x. Nobody else has this, not yet, not even the mint. x = random_secret() Y = hash_to_curve(x) hash_to_curve deterministically maps that secret onto a point on the secp256k1 curve, the same curve used for keys and signatures elsewhere in this ecosystem. Y is now a point that only your wallet knows how to derive from x. Step 2: Blind it before the mint ever sees it If your wallet just sent Y to the mint and asked for a signature, the mint would know exactly which point it signed, and could later recognize that same point when you tried to spend it. So instead, your wallet blinds it first: r = random_blinding_factor() B_ = Y + r·G G is the curve's standard generator point, and r is a random scalar your wallet picks and never shares with anyone. B_ is the blinded message, this is what actually gets sent to the mint. Mathematically, it's indistinguishable from a random point on the curve. The mint has no way to recover Y or x from it. Step 3: The mint signs what it can't read The mint holds a private key k for this token denomination (it uses a different keypair per amount: one key for a 1-sat token, another for a 2-sat token, and so on), with a corresponding public key K = k·G. It signs the blinded point: C_ = k·B_ That's the entire signing operation. The mint has just certified a value it structurally cannot connect to any secret. Step 4: Unblind it, locally, alone Your wallet gets C_ back and removes the blinding factor r , which is the same factor the mint never saw: C = C_ - r·K Since K = k·G, this works out to: C_ - r·K = k·(Y + r·G) - r·(k·G) = k·Y + rk·G - rk·G = k·Y So C = k·Y. Your wallet now holds the pair (x, C) , a valid signature from the mint on your secret x, produced without the mint ever seeing x or the blinded point that led to it. Step 5 — Spend it When you later pay someone (or redeem it with the mint), you hand over (x, C) in the clear. The mint checks it like this: Y' = hash_to_curve(x) accept if k·Y' == C reject if x is already in spent_secrets If the math checks out and x hasn't been seen before, the mint accepts the token and adds x to its spent-secrets set, this protocol's equivalent of a nullifier set. If someone tries to reuse the same x, the mint rejects it instantly. Here's the part that actually matters for privacy: the mint has now seen this secret twice, once as a blinded point B_ during minting, once as a plain secret x during spending and it has no mathematical way to connect the two. Doing so would require knowing r, and r never left your wallet. It wasn't encrypted and hidden from the mint, it simply was never sent to the mint at all. Go back to the ride-hailing driver from the start of this piece. If that payment rail had used this protocol instead of a bank account, the mint backing my wallet would have gone through exactly this dance the moment I acquired the tokens. When I paid the driver, his side would only ever see (x, C), a signature that checks out mathematically, with no path back to which blinding request produced it, because the one number that could make that link was never something the mint held in the first place. It's worth being precise about what this does and doesn't protect against. A mint can still see the total value it has issued and redeemed at any given time, and it can refuse service to anyone at the point of minting. What it can't do is build a transaction graph connecting your deposits to your spends, the way a bank or a blockchain explorer can. The privacy here isn't a policy the mint promises to follow, it's a property of the arithmetic. There's nothing for the mint to leak, accidentally or otherwise, because it never had the link to begin with. Forging Your Path In Open Source Many people in my cohort leaned into Rust or C or C++, I mean I’ve been a Typescript engineer my entire career, if I was to make an impact in this space I had to do something I’m comfortable with so I doubled down on what I already knew and started contributing to a protocol I already believed in and was itching to help out. At first, it was about understanding how token creation and destruction works, how mints validate these tokens, how edge cases are handled etc, and as I understood better I went deeper into the protocol itself and then I began to work on the Python implementation of the protocol, not because a program required it, but because the work I now cared about did. For me this wasn’t just curiosity anymore, it was commitment towards moving the protocol forward. If you're an engineer considering something similar, here's roughly the path I'd repeat: Pick one implementation, in a language you already know. Don't try to absorb an entire multi-language ecosystem at once, that's how people quit in week two. Start with narrow, verifiable contributions. Tests, documentation, small edge-case fixes. These build both your understanding and the maintainers' trust in you faster than a large first PR ever will. Read the protocol spec directly, not just the code. In this case, that means the NUT specifications. Code tells you how something works; the spec tells you why it was designed that way, which matters when you eventually want to propose changes. Ask to review PRs before anyone asks you to. You learn more from contested, debated code than from code you wrote alone. Budget for your tooling to break. Running multiple nodes and environments on a personal machine will eventually punish you for it. Mine did, literally, when my laptop gave out mid-program. To close this out I’ll say, I still spend most of my working hours in TypeScript, the same language I used to build the fintech systems that started all of this. What's different is what the code is optimizing for. A banking API is built to know as much about you as regulation and business logic allow. An Ecash mint is built to know as little as the protocol allows, while still refusing to let anyone spend the same token twice. Those are genuinely different design goals, and once you've spent time inside both, it's hard to keep treating identity-by-default as a neutral engineering choice rather than a trade-off someone made on your behalf.That's really what this piece has been about, not a conversion story, but a design comparison. One system needed my name to let a driver get paid. The other doesn't need to and never will!

Original Source

Read the full article at Hackernoon →

KhanList aggregates and links to publicly available news content. We do not host full articles from third-party sources. Always verify important information with original sources.