Bitcoin is one of the most pivotal breakthroughs in the entire digital age in terms of transferring value between one person and another. It does not require intermediaries. It is secured by a decentralized quorum of miners and validated by every participant on the network who chooses to in order to guarantee the validity of individual payments. The architecture of the system is designed to allow anyone from anywhere on the planet to receive money from anyone else regardless of where they are. Crowdfunding, charity, funding anything you want becomes instantly possible without needing anyone’s permission, without dealing with any gatekeepers, without any red tape. It’s a brilliant idea in theory, but in reality, it suffers from one massive shortcoming: privacy.
As a push based payment system (no one is allowed to “pull” payments from you, you have to explicitly authorize them yourself and “push” them to other people), Bitcoin requires the sender to have the information necessary to define the destination for money they send. This requires the recipient communicating to the sender their Bitcoin address in one way or another. In the case of trying to raise money from the general public, this has massive consequences in terms of privacy or needing to maintain a constant interactive presence online. Anyone is totally capable of simply posting a single Bitcoin address somewhere online, and from that point, anyone who wishes to send money to that person can simply do so, but there is no privacy in raising money in this way. Simply take that address and look it up on the blockchain, and you cannot only see how much money that person has been sent, but you can see the footprint on the blockchain of everyone who has sent them money. Both the person attempting to raise funds and everyone who has donated to them have no privacy whatsoever; everything is completely open and correlated for the whole world to see.
The only alternative to address reuse in the form of posting a single static address publicly requires running a server that remains online constantly so that people can request a new unused address every time someone new wants to donate money. While it might not seem like a problem to have something online all the time in the digital age, it does come at a cost and complexity, especially if someone is trying to run it themselves at home on their own hardware. And what about people who only have a mobile device? It is almost impossible these days, with current operating system features, to optimize battery use to keep something running in the background all day, and even if you can, it’s going to drain the battery.
Enter BIP47 by Justus Ranvier. The purpose of this proposal is to enable a way for someone to be able to post enough information publicly to be able to receive funds from anyone who chooses to, without that public information being enough to (1) track how much money the person who posted it has received and (2) revealing to the pubic any information about who has sent funds to the person requesting them. The core idea is taking that publicly posted information (or payment code) and, from there, combine their own payment code to generate a new set of addresses the receiver can construct the private keys for. This new set of addresses is specific to the relationship between a single sender and the receiver, each time a new sender utilizes this protocol to send money to a receiver, it will generate a new set of addresses unique to the two of them.
At a high level, the general flow follows as such: The person who wants to receive money generates a new extended public key from their HD wallet in a new derivation path and publishes this publicly. This new public key functions as their “payment code.” From here, someone wanting to send them money will take this new payment code, and they have all the information necessary in order to generate new addresses to send money. The problem is though, the sender needs to communicate their own payment code information to the receiver, otherwise they will be unable to generate the private key needed to actually spend the funds sent to them. This requires a special “notification transaction.”
Say Alice wants to transact with Bob using payment codes. Alice selects a UTXO to send to Bob’s notification address, from here she takes the private key associated with this UTXO and the public key associated with Bob’s notification address. She multiplies them together to create a secret blinding key. With this, she can encrypt her payment code and encode them in an OP_RETURN output. This means that Bob, taking the private key to his notification address and the public key of Alice’s spent input, is the only person who can decrypt and read this information. This works because multiplying Alice’s private key with Bob’s public key produces the same value as multiplying Bob’s private key with Alice’s public key.
Alice and Bob can now derive a new set of addresses that only the two of them are aware of, and Alice can now send any amount of transactions to Bob using a new address each time without any external observer being aware of the linkage between them. There is a second variation where, instead of sending an output to Bob’s notification transaction, Alice creates a change output to herself using a 1-of-2 multisig where one key is her change address, and the second is Bob’s payment code identifier. A third variation uses a 1-of-3 multisig output to encode the necessary information in lieu of OP_RETURN. Other than that, things function the same.
The one shortcoming of BIP47 is the need to utilize blockspace to send a special transaction notifying a recipient they are going to be receiving money before actually spending it. This winds up being very inefficient for use cases where someone is only trying to send a single payment. There is also the risk of actively damaging privacy if the UTXO used for the notification transaction is connected to the UTXOs used to make payments to someone’s BIP47 addresses. Care must be taken to ensure isolation between these two things to not create correlations that could be tracked on chain and associate ownership of UTXOs resulting from different payments.
Silent payments are Ruben Somsen’s latest idea. It effectively solves the same problem as BIP47 without needing a notification transaction with the trade-off of needing to scan more transactions to detect payments made to the recipient. The idea is abstractly pretty much the same: You publish a piece of public information, and from that, a sender is able to construct a new address that only the recipient will be able to reconstruct. The difference is in the implementation details.
The receiver posts a “silent” public key in some accessible location, and then the sender takes this and tweaks this public key using the private key of an input they are going to spend to make a payment to the receiver. This is done by multiplying the private key of the sender with the silent public key of the receiver and then adding that silent public key again. This results in a new address, which the receiver can recover by multiplying their private key with the sender input’s public key, and adding their silent public key. It’s that simple.
The big downside here is that support for light clients is very difficult, as the receiver has to scan every transaction in each block and compute the combinations of inputs tweaked to their key to see if it matches an output in a transaction. For a full node user, this isn’t an unbearable increase in validation costs, but for light wallets without their own full node this becomes very expensive. This could be optimized even further by simply scanning the UTXO set. Jonas Nick from Blockstream ran a benchmark test on an Intel i7, and he found it took about three-and-a-half hours to scan the entire set and run the computations to check for addresses. This did not include the time it takes to look up the transaction that created each UTXO to find the input public keys necessary to run that computation. That has not yet been benchmarked or tested, so the cost and time remain an open question.
A further optimization that could be made is using every input in the sending transaction’s public key as part of the tweak, which would bring down the cost of scanning to see if you have received money by not requiring you to scan each individual input in a transaction and run the computation individually. This would raise the complexity of doing it with CoinJoin transactions though, as it would require every other participant to actively participate in the key tweaking. It would also leak to them the output you are paying to in the naive implementation. However, it would prevent the recipient from learning what input was used to pay them, and by cryptographically blinding the information shared with other participants in the CoinJoin, it would prevent them from learning which output is the silent payment, thus mitigating all privacy concerns.
It is also possible to add together a scanning and spending key in the derivation process so that the receiver can have one key online that is all that is needed to detect incoming payments, while keeping the key necessary to spend coins they’ve received offline and in cold storage. This would change the derivation to multiplying the sender’s input private key with the scanning key and then adding the key necessary for spending. This would allow for more security in receiving payments, leaving only your privacy at risk if the receiver’s device was compromised.
A last major thing to consider is the potential for address reuse on the sender’s side. In the base implementation, if a sender has multiple UTXOs with the same public key, reusing those to send to the same person with a silent payment would result in the same silent address and constitute address reuse. This could be prevented by including the TXID and input index of the transaction input used in the scheme, which could be precomputed before being sent to light clients to not create an additional computational burden for them.
Overall the idea is a substantial improvement over BIP47 in every way, except the higher validation costs for the receiver to scan for funds they have been sent. It retains the deterministic recovery property, achieves unlinkability between different payments sent to the receiver, and removes the need for a notification transaction to take place before payments are made. Once again, Somsen has come up with a very solid idea for a protocol that could be implemented to improve the usefulness of Bitcoin.
This is a guest post by Shinobi. Opinions expressed are entirely their own and do not necessarily reflect those of BTC Inc or Bitcoin Magazine.