Webcash is an investigation into what kind of practical system you get if you eliminate the requirement for censorship resistance from a blockchain-based payment network. Webcash is a system that I have been spending a lot of time on recently, both personally and professionally, and it occupies a relatively unexplored but important niche of the cryptocurrency ecosystem. I’ve written this document as a way of explaining why I find Webcash interesting, and introducing the project to a larger audience of technically-minded people.
When I was at Blockstream I spent a lot of time interacting with potential customers. Blockchain was hot and everyone wanted one, even if they didn’t really understand what it was. The question “do you even need a blockchain?” became a meme, because in so many cases the answer was a resounding “NO!”
Blockchains provide censorship resistance as their core value proposition, and in many ways their designs are at odds with scalability; one might even say they are crippled to achieve the property of censorship resistance. Blockchains do not scale. Blockchains require always-on internet connections with non-trivial bandwidth and local resource use. Blockchains provide no avenue for recovery from theft or fraud. But the one thing a blockchain does for which literally no other payment network comes close is censorship resistance. So long as you have an internet connection, you cannot be stopped from accessing and using the bitcoin network.
Is this censorship resistance something most businesses or consumers need, most of the time? Not really. Do you need censorship resistance when buying groceries from the farmer’s market? Not typically. Do you need censorship resistance when trading playable assets in your favorite video game or the metaverse? No. Do you need censorship resistance when doing inventory and supply chain tracking? Not usually. Do you need censorship resistance when donating funds to the Ukrainian army? …ah yeah you might for that, depending on the jurisdiction in which you live. So don’t get me wrong, there’s an important role for bitcoin and friends. But so many times in meetings with potential customers I had to wonder “why don’t you just use PostgreSQL? Or Riak? Does this really need a blockchain?” There are flowcharts like the one above to answer the question “Do I need a blockchain?” And unless you have very specific requirements, then the answer is always “No: use a database instead.”
But what does that mean, to use a database instead of a blockchain? Are there off-the-shelf solutions you can install to get a payment or token network setup using a centralized server and database? Well yes, there are in fact some open-source software projects. GNU Taler is a privacy-focused payment server, and Open-Transactions is an under-appreciated account management software focused on providing an implementation of Chaum’s e-cash model. But although you can use these systems to spin up your own payment network or e-bank for your token, these projects aren’t showcased in an existing production network you can just connect to and use from day one, with customers already up and running, as is the case with bitcoin or ethereum.
Part of the reason for this is regulatory. If you provide a service that has accounts and facilitates the transfer of value from one individual to another, you are probably a money-transmitter under the law and must work to get an expensive license in every jurisdiction in which your customers reside. If your tokens are convertible to national currency, then you must interface with the legacy financial system, might be considered a bank by the relevant authorities, and therefore need to apply for a banking license. Either license is way, way, waaay outside the capabilities of all but the largest and most dedicated businesses to obtain and maintain.
So rather than simply using a database, as would be better suited to their application requirements, many innovation labs end up using public blockchains to implement their experimental products for which they don’t actually need a blockchain, because it is easier to setup and permission-less. But does this have to be? Could we not design a centralized payment network which anyone can use without (we hope!) having to obtain expensive financial licenses?
It turns out that we can.1
What's actually required to make a digital currency?
Imagine an unspent transaction-output ledger like bitcoin’s UTXO set, which I assume readers of this blog are familiar with, but stripped down to its bare essentials. Every output has some amount of currency, let’s call it webcash, stored as an integer, and a secret value known only to its owner. As we require secret values to be one-time-use only, the hash of the secret serves as a unique identifier for the output. The database ledger on the server is a key-value datastore mapping these hash strings to a simple field encoding the value of the output (an integer) and whether it is spent (a boolean).
API: /replace
The holder of some webcash can replace the secret protecting it with the replace API call. This HTTP endpoint receives a POST verb with a JSON object containing the inputs and outputs of a replace operation. The inputs and outputs are arrays of webcash secrets, and in the case of the outputs their associated value.
For the inputs, the server checks that each input exists (looking it up by the hash of its secret value), that it is not already spent, and retrieves its value from the ledger.
For the outputs, the server checks that each output does not yet exist, calculates its hash from the provided secret before throwing the secret away (secrets are never stored on the server!), then checks the sum of all outputs equals the sum of all inputs.
If the checks pass, the server atomically marks all inputs as spent, creates unspent ledger entries for the outputs, and returns a success code to the caller.
That’s all that it takes to define a high-performance payment network with direct payments and a server to provide transaction ordering and double-spend protection. We’re done!
The End.
Just kidding, there’s more to explain and a few more API calls to cover. But that really was the entire server-side support for webcash payments. Webcash is a thesis on simplicity and minimalism.
But let’s go over how a payment works in detail. SpongeBob wants to pay Patrick 10 webcash. He first looks in his digital purse and discovers that he has a 5 webcash output and a 8 webcash output. So SpongeBob sends a POST to the server replace API endpoint with the following data:
{
“inputs”: [
“e5:secret:9046e611bcab8311213cb91a0df0cc481acb20fa”,
“e8:secret:a49036a960726e07b3d660c14a3c197d6c6ec29c”
],
“outputs”: [
“e10:secret:23ddda4810068cc44360dffd31b6c5a9ad13fb9e”,
“e3:secret:2744ccd10c7533bd736ad890f9dd5cab2adb27b0”
]
}
This combines SpongeBob’s two outputs to create a single 10 webcash output, with the 3 webcash left over as change. The hexadecimal values are the secret values which protect the webcash; the hash of these secrets must match a hash value stored in the ledger. Now SpongeBob uses whatever mechanism at his disposal to transmit to Patrick the webcash claim code: “e10:secret:23ddda4810068cc44360dffd31b6c5a9ad13fb9e”. This action, the transmission of a secret from one user to another, constitutes payment.
Patrick is no dummy though, and he wants to make sure SpongeBob doesn’t use the secret in another replace operation. So he goes to the server right away with his own replacement:
{
“inputs”: [
“e10:secret:23ddda4810068cc44360dffd31b6c5a9ad13fb9e”
],
“outputs”: [
“e10:secret:56eb7ed22475975b2b78b4f6632bee3445d7487a”
]
}
Now Patrick is in sole possession of the secret data needed to spend his 10 webcash. If SpongeBob did try to spend the claim code he gave Patrick at a later point in time, the server will reject the replace call as attempting to spend an already-spent output.
But how does webcash come into being in the first place? Where does the first baby webcash output come from? Webcash uses a simplified variant of bitcoin’s initial issuance mechanism: honoring the newly generated webcash contained valid proof-of-work solutions.
API: /target
The target input takes no parameters and returns the current reward amount and proof-of-work difficulty setting, which is an integer value based on the last reported difficulty and how far ahead or behind the issuance is compared to a preset schedule.
API: /mining_report
Takes a base64-encoded JSON string containing a list of generated webcash. If the SHA-256 hash of the base64-encoded string has a number of leading zeros equal to or greater than the current difficulty, and if neither the mining report nor the included webcash secrets have ever been seen before, then the proof-of-work solution is accepted as valid and the webcash are entered into the database.
That’s it for webcash issuance. There is one more API which is not strictly necessary but is an important part of how wallets are implemented:
API: /health_check
Takes a list of public hash values (the SHA-256 hash of a secret), and for each one returns a field indicating whether the secret has been seen before, and if so whether it is spent and its value. The health_check API is used for wallet repair or recovery from a backup.
I Am Not A Lawyer And This Is Definitely Not Legal Advice
In the remainder of this article I discuss the inferred design rationale for Webcash, with a particular focus on legal and regulatory compliance. I discuss whether and how Webcash might meet with approval given the pattern of previous regulator statements and actions in this space. However I am not a lawyer or an attorney. More importantly, I am not your lawyer. Nothing in this article is legal advice. If you desire legal advice, consult a competent, licensed lawyer in your area.
Whew.
Engineering requirements
Most of the engineering requirements which drive Webcash’s design come from a desire of the server operator to skillfully navigate potential legal and regulatory issues. In order to avoid excessive interaction with regulators, a payment network ought to have at least the following properties:
Payments are done directly between users, without the server acting as an intermediary.
The server does not track user account balances or require user accounts with authentication.
The server is not custodian to any user assets, tokens, or cryptocurrency.
The server does not issue an asset, token, or cryptocurrency.
The server is capable of carrying out lawful requests from enforcement agencies.
In addition, although not strictly necessary, there is one other design criteria which greatly affected the Webcash architectural design:
The protocol should be simple and performant!
Let’s take these requirements in turn.
Direct payments only
It could be argued that any intermediaries for a payment act as money transmitters, a role which carries stringent financial surveillance responsibilities in order to prevent money-laundering or payment to sanctioned individuals or regimes. In order to avoid burdening the server operator and unrelated users of the network with the costs of being a money transmitter, all payments must be done by users directly from the sender to the recipient without involvement of the server operator.
How can a payment network somehow process a transaction without the operators of the network facilitating that transaction? Well to prime your intuition, observe that bitcoin transactions can be done without actually communicating with the bitcoin network, and without layer-2 protocols like lightning. To give bitcoin to someone, simply hand them the private key for an output that contains exactly the right amount of bitcoin! Done. Far from being an obscure technicality, this is actually how bitcoin transfers occur in the trade of physicals like Casascius coins. The private key for the bitcoin is contained inside the tamper-evident holographic sticker on the coin, which physically changes hands.
For this transfer to be secure, the recipient needs assurance that the sender no longer has access to the private key for the coins being transferred, or else the sender may fraudulently double-spend the coins. In the case of Casascius physical coins the tamper-evident features (and trust in Casascius) serve as this protection. In the case of Webcash the server acts as a transaction-orderer and witness against double-spends.
No user accounts
If the server tracks and maintains user account balances then it might be said that the server operator is providing financial services akin to a bank or custodian, and fall under the purview of various regulatory regimes. To avoid the possibility, the protocol must be designed to avoid the notion of an “account” or any balance that persists longer than the duration of a single transaction.
Once again, bitcoin provides an illustrative example of how to meet this requirement. Unlike traditional finance applications, or ethereum, bitcoin eschews the notion of accounts entirely in favor of the unspent transaction-output model. In this model the ledger keeps track of coins in buckets called “transaction outputs” which can be spent at most once. A user’s wallet consists of the outputs for which it has spending authority, and transfers involve consuming one or more outputs entirely and splitting their value across multiple transaction outputs—typically one to the recipient and one back to the sender as change. Bitcoin users still have a notion of an “account balance,” but only as a user-interface fabrication at the level of wallet software. Neither the bitcoin network nor the user’s own validation node keeps track of the user’s account balances directly.
No custodianship
The server or payment network as a whole cannot be custodian to user funds. Unfortunately this pretty much rules out all known ways of integrating with the existing financial system to create an asset that is 1:1 pegged with a national currency like the dollar, or use of an existing cryptocurrency like bitcoin or ethereum. Both stablecoins and sidechain pegs involve holding the aggregate balance of users in custodianship. The payment network must therefore provide its own exchange-floated, non-collateralized asset for payments.
Not a security
The server or payment network as a whole ought not to have issuing authority over assets, tokens, or cryptocurrency which might be interpreted to be securities by the SEC or corresponding regulatory bodies in other jurisdictions. What guidance we do have from regulatory bodies states pretty clearly that only bitcoin and bitcoin-like issuances which are fully proof-of-work mined without a crowdsale seem to be exempt from securities registration. Thus emulating as closely as possible bitcoin’s decentralized, proof-of-work mined issuance mechanism is the only surefire way to avoid securities registration issues.
Supporting lawful requests from enforcement agencies
This is admittedly a more controversial requirement among cryptocurrency enthusiasts, and it isn’t a driving design force so much as a pragmatic recognition of the reality of the industry and its governing bodies.
Personally I feel that certain categories of privacy-enhancing features ought to be compatible with the needs of regulators. Confidential transactions, for example, enables masking amounts from public view, while allowing users to selectively disclose blinding factors on a per-transaction basis, or sharing the root blinding key for the entire wallet while still keeping user funds secure. Similarly CoinJoin permits obfuscating the transaction graph from public view, while still allowing tracing outputs by selectively sharing the BIP32 xpub for the wallet. Both approaches permit keeping the relevant data private, while allowing opt-in sharing with selected parties, as required.
Unfortunately it appears that regulators find opt-in sharing to be insufficient at this time. Grin, which implements a form of confidential transactions, has been delisted from many exchanges. Likewise, many users who send funds to CoinJoin wallets have had their accounts banned. Zcash and Monero, which support similar privacy features, have also been de-listed. Tornado Cash, which provides similar privacy-enhancing services for the ethereum ecosystem has been sanctioned by the U.S. government and its lead developer arrested by dutch authorities. At the same time, regulators and law enforcement agencies seem to have no major problem with less privacy-focused cryptocurrencies like bitcoin which do nothing to prevent the tracing of flows of money.
A blockchain developer seems to be presented with a conundrum: either support privacy enhancing features and be blocked from accessing the financial system and possible growth vectors, as well as face prison time, or leave your user’s information bare and exposed for everyone to see. However, a server-oriented architecture is not forced to make this choice! As we saw above, Webcash does not employ available cryptography to hide transaction amounts or the payment graph from the server operator, but at the same time only the server operator is able to see this information. He may share access with appropriate agencies when lawfully compelled to do so, but unlike the case with a blockchain, that information is not sitting in public for everyone to see. Thus the level of privacy offered is no worse than bitcoin, in regards to the server operator and law enforcement agencies, and in practice quite a bit better against many other potential snoops. And, critically, it has a lower likelihood of being shut down by financial regulators compared with stronger privacy protections.
Simplicity
The original Python server implementation consists of 666 lines of Python code. I have written a more performant, production-grade server in C++ using a rather verbose asynchronous event handling web server framework in 1,500 lines of code. A Rust version of the server, still being written, clocks in at roughly 1,000 lines of code. In all three cases, the actual code that deals with handling a replace operation is quite simple, adding up to only a few tens of lines. The rest of the code mostly deals with database connections, event handlers, asynchronous state management, and request serialization/deserialization—the sort of boilerplate common to all web applications.
Performance
Validating a bitcoin transaction requires checking at least one elliptic curve digital signature per input. Validating a Webcash replace operation requires at least one SHA256 hash to be performed per input. A typical server-grade CPU can perform thousands of ECDSA or Schnorr validations per second, but millions of SHA256 hashes in the same time period. Thus bitcoin validation is can limited by signature validation speed, but validating secrets in Webcash poses no special difficulty.
The primary bottleneck for replacement throuput is database access. Each replacement operation requires confirming the existence of the inputs, confirming the non-existence of the outputs, then performing update and insert operations to mark the inputs as spent and create the outputs, all performed as an ACID-compliant database transaction. The C++ Webcash server implementation is able to achieve 6,500 transactions per second on my 12th generation Framework laptop with an Intel Core i7-1260P using PostgreSQL as the database backend. This is more than triple the peak number of payments typically handled by VisaNet on a daily basis. Nevertheless, it is justifiably believed that switching database backends (FoundationDB looks promising) and upgrading server hardware could result in 100,000 - 1,000,000 replacements per second.
Webcash is ridiculously fast. On a regular, run-of-the-mill laptop, a container running the Webcash server is able to handle more full transactions per second than any public blockchain. With high quality hardware, a good network connection, and decently good database software, Webcash is able to outcompete even the most used payment networks of the legacy financial system.
Conclusion
Blockchains are slow, expensive, complex beasts requiring teams of competent engineers and security professionals to create products on top of. Webcash, as a treatise on simplicity, eschews all of complexity in favor of a simple HTTP server endpoint, and a simple direct peer-to-peer payment model. Without a doubt, some applications really do need decentralization, and that is only achievable on a blockchain. For everything else, there’s Webcash.
Going forward I’m going to be splitting my time working on both Tradecraft/Freicoin, my preferred blockchain solution, and Webcash. If you found yourself interested by any of the above discussion, then I encourage you to take a look as well. Working on Webcash feels like the early days of bitcoin: full of promise and unrestrained delight at the ability to do new things without legacy cruft.
Well, maybe. Until someone does the work required to get a non-action letter from the relevant regulatory agencies we won’t know for certain. The best we can do is design a system which we think might meet with approval given the pattern of previous regulator statements and actions in this space. Seek your own legal counsel before proceeding. I am not a lawyer and nothing in this article is meant as legal advice!