OrangeCheck for Builders: A Bitcoin Proof of Skin in the Game You Can Verify Without Us
A short, technical introduction to OrangeCheck for the Bitcoin builder community. It is an open protocol, not a required service: sign a canonical message with a Bitcoin address you control, and anyone can recompute two numbers from public chain data, how many satoshis you have bonded and how long they have stayed unspent. The hosted verifier and badges are conveniences you can self-host or ignore. The piece covers what the primitive solves today and what it could solve, and it is honest about where it does not help.
Table of Contents
Every API meets the same attacker eventually
Run a forum, a public API, a marketplace, or any service that lets strangers register for free, and you will meet the same problem within a week of launch. One actor can become ten thousand. Fake signups, scripted posts, review manipulation, vote stuffing, free-tier abuse: all of it is the same underlying failure, which is that creating an account is cheap and you have no way to tell a thousand throwaway keys from a thousand people. The standard fix is to make accounts expensive. You demand an email, then a phone number, then a captcha, then in the worst case a government document or a face. The mechanism works, and the cost lands almost entirely on the honest user, who hands over a permanent, linkable, resellable record of who they are in exchange for the right to participate. You then store that record, become responsible for it, and leak it in the next breach.
OrangeCheck is a small attempt to price that same scarcity in something other than the user's identity. It is a Bitcoin-native proof of skin in the game, and the thing I most want a builder to understand before anything else is that it is not a service you are required to trust. It is an open protocol with a reference implementation. The hosted pieces exist to save you work, and you can throw all of them away and still get the full guarantee, because every claim it produces is verifiable from public data with arithmetic you run yourself. The demo is at ochk.io, the canonical spec and conformance vectors live in oc-attest-protocol, the SDKs, middleware, React bindings, and CLI are in oc-packages, and the unified docs are in oc-docs.
The primitive is a signature and two numbers anyone can recompute
The core of OrangeCheck is one move. A user signs a canonical, human-readable message with a Bitcoin address they control. The message is fixed in shape: a small number of defined lines, defined line endings, a required trailing newline, and a short list of optional extension fields that live inside the signed text rather than alongside it, so nothing can be smuggled in around the signature. Modern wallets sign it with BIP-322, which works for any script type; older tooling can fall back to legacy signmessage on a P2PKH address. No transaction is broadcast. No fee is paid. No coin moves. The signature proves control of a key, and that is the entire enrollment.
From that signature and the address, a verifier reads the public chain and computes two numbers. Bond is how many satoshis sit unspent at that address. Streak is how long they have sat there. Those two values feed a small scoring function that carries a version number, so the score can change without breaking old proofs. That is the whole primitive. The unit it trades in is satoshis multiplied by days, and the reason that unit is useful is the reason a fresh keypair is not: generating a keypair is free and unlimited, while leaving a coin untouched for a month has a real, externally measurable cost in foregone liquidity, and the age of an unspent output is public. Holding a hundred thousand satoshis idle for thirty days costs a real participant almost nothing and costs an attacker who needs ten thousand identities the same stake ten thousand times over. Spending the coins to recycle them into a new identity resets the streak and destroys the proof. You cannot fake time without actually surrendering the time.
This is proof of stake in the original and literal sense, where the stake is denominated in the one asset whose holding cost is real and is not issued by the party measuring it. It is not a claim about who someone is. It is a claim that a key controls some value and has held it, which is exactly the thing an authentication system usually needs and exactly the thing an email was always a clumsy proxy for.
Nothing in the path is something you have to trust
The property that matters most for adoption is that OrangeCheck removes itself from the trust path. The signature is verifiable locally with no server involved. The two numbers are recomputable from any block explorer, from a light client, or from your own full node. There is no account system, no custody, no database of users that you or I have to keep, and no central authority telling you what a proof means. If you do not like the default scoring function, you run your own; the protocol does not care, because the score is just a function over the bond and the streak, and you can pick the function that fits your risk model.
There is a hosted verifier you can send a message, signature, and address to and get back a clean result with the bond, the streak, and a labeled score version. There are badge embeds for profiles and pages. Use them if they save you time. None of them are load-bearing. You can self-host the verifier, run it against your own node, or reimplement it from the spec in an afternoon, and the proof a user gave you remains valid the entire time, because its validity was never a function of my infrastructure being up. This is the deliberate opposite of the usual reputation product, which is a leaderboard you rent until the platform changes the rules or bans you. A proof you can verify yourself is one nobody can revoke by turning off a server.
What it solves today
The immediate use is making abuse controls less punishing without building an identity dossier. If you run an API, you can let any key in and rate-limit anonymous callers hard, then lift the ceiling for keys that carry a minimum bond, and lift it further for keys whose bond has stayed unspent for thirty days. If you run a forum or a feed, you can keep registration open to everyone and gate only the expensive actions, write access, posting links, listing high-value items, behind a minimum score. A spammer who spins up a thousand keys hits the same anonymous floor as everyone else, and buying their way past it means actually bonding stake on each key, which is the cost you wanted them to bear in the first place. The trust tier updates from on-chain truth with no support ticket and no manual review. If a user spends their bond tomorrow, their tier decays on the next check. The honesty is built into the fact that the signal is expensive to fake and cheap to read.
What you are adding is one input that is hard to forge, not a replacement for your existing logic. OrangeCheck deliberately fails the substitution test that the rest of the family is built on: if a generic keypair would do the job identically, the feature does not belong, because then Bitcoin is decoration. Here a generic keypair will not do, because the entire signal is the publicly verifiable age and cost of a held coin, which a keypair does not have. That is the line that keeps the primitive worth using rather than reinventing a credential system on ordinary keys.
What it could solve
The larger surface is reputation that travels without anyone tracking you, and that is where the family goes beyond a single badge. The consumer front door, me.ochk.io, lets a person onboard to a site by signing a message, hand over no personal data, and receive a scoped, unlinkable pseudonym per site rather than one global identifier that every site can correlate. On top of that it inverts the onboarding economics: an integrating site funds activity from a prepaid balance and the user is paid satoshis for the legitimate activity they generate, so the cost of deterring fakes moves off the user's identity and onto a fungible asset the site controls. Reputation built across many sites can then be exposed as an aggregate, a single integer like total activity or count of distinct sites, that proves a pseudonym has history without revealing where that history was made. Reputation and tracking, which the advertising internet has always sold as one inseparable bundle, come apart, because the linkage becomes a value the user holds and chooses to disclose rather than a record a platform compiles behind their back.
I am careful not to oversell any of this as solved. These are the directions the primitive opens, not promises about underwriting or about replacing how anyone signs in. The point of keeping the core small and verifiable is that the interesting systems are the ones you compose on top of it with your own context, not the ones I bake into the protocol.
Where it does not help, stated plainly
A fair introduction names the gaps, and for a builder deciding whether to integrate, the gaps are the part that matters. A Bitcoin address is pseudonymous, not anonymous. The moment a user reveals the same address to two parties, those parties can link them and can run the public chain history of that address to infer balances, timing, and counterparties. The protection against lazy correlation is fresh, per-role addresses and disciplined non-reuse, which works only to the degree users actually practice it, and users famously do not. OrangeCheck gives you a signal, not an identity, so it tells you a key has stake and time and tells you nothing about the human behind it; pair it with your own application logic rather than treating it as a verdict. The custody invariant across the family is that it never holds user funds, with one named exception on the me.ochk.io email path, where satoshis are held as ecash in a Fedimint federation until the user graduates to their own keys, and that graduation flow is still being finished. The cryptography underneath is secure against classical computers, not against a future quantum one. None of these are hidden in the design, and a primitive whose failure modes are this legible is easier to reason about than one that promises more than it can prove.
One more input that is hard to fake
OrangeCheck is not trying to be your trust model, your login system, or a company that sells you reputation as a service. It is a tiny receipt of stake and time that anyone can check locally, an optional convenience layer for the people who would rather not run the verifier themselves, and an open spec for the people who would. If a proof of skin in the game would make your abuse controls less punishing on honest users and more expensive for attackers, it is worth an afternoon to wire in, and if it would not, you have lost nothing by reading this far. Try the demo, read the spec, file an issue where it breaks, and if you trust nothing else about it, verify the signature and recompute the numbers yourself. That last sentence is the entire design goal. The proof was never supposed to depend on me.