I figured I'd start a new thread for this despite that there are a few similar threads already, as I wanted discussion of this exact design all in one place. I will incorporate feedback and put it onto the wiki in the coming week. These ideas are of course not really mine, they have come out of lots of different discussions and debates. But I want to try blending them in a different way, with more technical detail.
"Bitcoin passports" are related to
fidelity bonds discussed elsewhere in this forum, but I think it's a slightly better sounding name (if a little misleading).
Services that can be abused (wikis, forums, webmail etc) need a blacklistable identity for each user so bad behaviour can be punished through exclusion. If no such blacklistable identity exists then account termination is pointless because the abuser will just immediately sign up again. This is why Tor tends to have a read-only view of the internet. Mesh networks like cjdns will have the same problem. Small sites tend to use IP address but this is weak; more advanced operations like the Google abuse team use phone verification and other techniques.
For anonymous users to take part, a cost on establishing an identity must be imposed. We can do this by requiring users to present a proof that they gave away some coins to miner fees. The proof is standalone and can be checked by anyone who has a copy of the block headers. The hash of that proof becomes the pseudonym, it can be checked against Spamhaus style DNS blacklists to discover past behaviour that has been associated with that nym and optionally blocked.
To create one, you take X coins and spent them to miner fees over the course of Y consecutive blocks. The outputs of the transactions are set to OP_FALSE so nodes can be taught to prune them. Each transaction and its merkle branch are included into a data structure, called the passport:
message BitcoinPassport {
// A name that sites can refer to the user as - for convenience only, it is
// not checked anywhere and can be of any form. Websites must sanitize
// it for XSS before rendering as there may be arbitrary UTF-8 data in it.
required string textual_name = 1;
repeated Sacrifice sacrifices = 2;
// Some optional data that can help simplify signup for websites ....
optional string email = 3; // etc
}
message Sacrifice {
// The raw transaction as included into the block chain, the merkle branch
// proving its inclusion and the co-ordinates of the block.
required bytes tx = 1;
required bytes merkle_branch = 2;
required bytes included_in_block = 3;
required int inclusion_height = 4; // Some implementations may benefit from this.
}
If a service or application wishes to verify a passport, it asks the operating system to open a URL of the form:
bitcoinpassport+https://accounts.google.com/VerifyAnonymousAccount?value=0.01&challenge=f3626fca2ce9ffd23e0abd859faeff5384b63834&state=dNaBzuXCE7a7UGSO+deEbX/8XDNESGSD/lQ9vmO9/NU=
An application, call it the Passport Manager, handles this URI and then signs the given challenge using each public key in each sacrifice transaction (in order). The challenge is randomly generated by the server. The signatures are then bundled up together with the state and the passport itself:
message IdentityProof {
// An series of embedded messages containing passports. This is not an embedded type to ensure
// reliable hashing of the contents without any confusion caused by protocol upgrades in future.
// There can be more than one so you can present multiple passports to reach the required size
// of sacrifice, in case your first one isn't large enough.
repeated bytes passport = 1;
// A list of signatures, one for each input in each sacrifice, in order.
repeated bytes signatures = 2;
// This is simply a copy of the state parameter in the URI.
optional string state = 3;
}
The state parameter is arbitrary data looped through the client from the server. It allows for a stateless server implementation that does not need a database to track what challenge corresponds to what server action is currently suspended pending verification. For instance, the server could encrypt any state it requires into this field. It is useful for operations that use global load balancing.
Upon receiving an IdentityProof, the server parses the passport field into a BitcoinPassport message, verifies the signatures (the passport is presented by its owner), verifies that the sacrifice transactions link back to the given block headers based on the servers copy of those headers, and then verifies that the number and value of the sacrifices is sufficient. The transactions should appear more or less in consecutive blocks the chain, though there should be a bit of leeway allowed.
If the proof is validated, the server can then check against its own blacklists of abusers or look up the hash in a remote database. If no problems are found, the nym (proof hash) can be stored in the newly created account. If later the account turns out to be abusive, it can be blacklisted. The state variable can be decrypted and whatever data needs to be adjusted then can be. The server replies to the app with an HTTP redirect and the app then opens the redirect URI, which takes the user back to the browser. The redirect URI may complete registration with a welcome message, or alternatively explain to the user why their nym is not accepted.
Passports can be created using the Passport Manager app. It is a standalone program that maintains its own Bitcoin wallet. You send money to it, click the "Make passport" button and then go to bed. It ensures there are outputs of the right quantity and value before starting, and then sends transactions such that they get into consecutive blocks. This may take an hour or two, but once complete the passport can be written to a .passport file which contains the public data and of course, the private keys used to sign for them.
Design choices(1) Why miner fees instead of a charity?There are several problems with the idea of donating to charity:
- Charities are not politically neutral as miners are. For instance, if you wanted to donate to charities that operate in Iran that might be an issue. Nobody will be able to agree on one set of charities that makes everyone happy - even "no brainers" like open source foundations would be a turnoff to non-technical people who may wish to use the system.
- Charities massively prefer to have real relationships with donators who commit to the long term (or can be convinced to do so). Anonymous, unpredictable revenue flows can make their accounting much harder because they don't know when money might arrive, so it can't be relied upon. A charity that received money this way then didn't use it would lose a lot of goodwill through no real fault of their own.
- Some charities do not want to or cannot accept anonymous donations at all.
- Everyone would have to agree on the list of charities to use ahead of time, so there would be no connection between how well a charity does and how much it received in sacrifice fees. A charity may operate effectively for a few years and then become corrupt or incompetent, but upgrading everyones software to use a new list would be difficult.
Miners are politically neutral, anonymous, indistinguishable, the money is almost guaranteed to quickly re-circulate into the economy via exchanges and it helps support network security.
(2) Why require multiple sacrifices in consecutive blocks?This is to avoid people mining their own sacrifice. It's very hard to mine 6 consecutive blocks but relatively easy to get transactions into them. A gap of 1 block or so would be acceptable, you don't need to hit every single block to have very high confidence.
(3) What are good values for the size of the sacrifice and the number of blocks?Abuse is cheap. Let's imagine we deploy this for Gmail. The cost of Gmail accounts on the black market is roughly $100-$150 per thousand accounts. This is what it costs professional spammers to overcome phone verification and successfully avoid bulk termination.
Thus a single account costs about 10 to 15 cents. Assume a price of $20 per coin, that means 10 cents is 0.005 coins. If we say you need to spend 0.005 coins to fees in the space of 6 blocks, then this means 0.001 coins per sacrifice with an allowable gap of 1 block in 6 total. That sounds quite reasonable to me. Because you know when the sacrifice was made, calculating the value of it in the currency of your choice is straightforward despite floating exchange rates.
(4) Why a new URI scheme?For a website to ask an app for data, there are only a few possibilities. Magic HTTP headers, JavaScript APIs etc all require browser extensions to implement, which is hard or impossible to do on mobile/tablet browsers. URI registration is simple, universally supported and does not impose any browser requirements.
Don't bother with blacklists. Just use micropayments to charge uses a fee.