Please note, this is an unproven idea and a request for comments. Please avoid premature claims until at least a few experts confirm that this is indeed possible and secure. There is only one way to make something secure - to spread the algorithm as wide as possible and have experts poke the holes in it.

Discussion is here or in the comments below.



Feedback overview will be updated here as it happens, positive or negative. (!) Negative feedback from BigBlocksIfTrue, presenting an interesting vector of attack.



Positive feedback from Karol Trzeszczkowski (who is definitely an expert in my opinion): "This is absolutely going to work, don't worry about that" Positive feedback from btcfork: "Don't see a reason this couldn't work, and am quite excited by the idea." Positive feedback from bit-architect: "Beautiful! Very well done" (with caveats) Steve Shadders from Bitcoin SV points out that it would be possible to create a scheme with similar characteristics on Bitcoin SV next February (but you'd need to safekeep something like a paper wallet) .

Interesting, how sometimes people trying to troll you suddenly make you realize something even bigger about the thing you support (namely: Bitcoin Cash).

Today, I've read this on Reddit:

When at first I read this, I thought the guy was talking about Bitcoin (BTC)'s "Replace-by-Fee", but a cursory glance at his history showed he supports Bitcoin SV and dislikes BTC. Why would he be talking about "recoverability", if SV is no better in this regard than Bitcoin Cash, is beyond my understanding.

Having "recoverable" coins is pretty important (that means that if you lose your private key, you can still recover the access to them), while at the same time you should have the ability to spend your coins daily. (Ok, this point doesn't ring a bell with Bitcoin BTC supporters, I understand)

It seems that these both points are possible on Bitcoin Cash today.

Actually, it can be even be used to safely recover stolen phone's wallet (from the example) if the thief haven't spent the money yet.

A "contract" in Bitcoin Cash allows you to define who can spend the coins. You basically always send the money to a "locking" mechanism and whoever can unlock it - gets to spend the money.

A regular wallet in Bitcoin Cash

Your regular Bitcoin Cash address is a locking mechanism that says "whoever signs a message with the private key that matches in some complex way the number I have written here gets to spend this particular coin" (it's a bit more complex, read our other article for more details if you are interested in details about the contracts).

I sign the transaction and I can spend the coins now

A regular way to buy a coffee and send the change back: you sign a transaction with the private key - that allows you to spend the money

You actually have a whole programming language in Bitcoins (all of them) that allows pretty complex interaction: Bitcoin Script (again, see previous article for more details).

You also have something like 2-of-3 multi-signature in Bitcoin Script, which was long thought of as the solution to recoverability. Hopefully, that changes today.

Multi-signature means that you can give 3 different private keys (very big numbers) to friends or institutions you trust and if you need to spend your coins - you can contact two of them and ask them to sign a transaction for you. Alas, it's not convenient and not secure. Let me explain.

You (actually, your wallet) can construct a special contract address and send your money to it, which has two unlocking functions "regularSpend" and "recover".

If you call the first one ("RegularSpend") - it is the usual spending: private key, address, change address, business as usual:

I'm signing a transaction

Buying my morning coffee with BCH and sending the change back

Or, alternatively, you can send the change to a new address, constructed in the same way - it's all the same, just a bit more secure.

Let's say you've lost your private key and can't sign a transaction. Typically, that means you're out of luck and lost your coins forever.

The second function could be a "recovery" multi-signature unlocking mechanism, where multiple trusted parties (Mom, bank, lawyer) can recover your money and then send any amount anywhere.

So, for 2-of-3 multi-signature that can look like this:

"Mom", "Bank" and "Lawyer" all have different private keys specially for this case

See the problems? Safekeeping, collusion, sending anywhere... Not to mention the usability nightmare to actually do the signing.

This is definitely possible on Bitcoin Cash and probably on BTC and BSV, so we're not any better in this regard.

Now, you can spend your funds daily using the first function, all your change goes the the new contract addresses, which also contain the recovery function.

Downsides:

you need to have 2-3 trusted third parties ;

they must manage the keys for you;

they need to be very technically advanced to sign a transaction on your behalf;

if they aren't reliable and lose 2 keys - you're out of luck;

some of them can collude and send your money anywhere.

When I was writing the previous article about the contracts - the first and the easiest contract that I've explained was very simple. You can supply a "word" that would unlock your funds. So, like you say "read.cash" and you can spend the coins.

Seriously, this address: ppfuzf5f52ypwm0jrnnfqtwafrtfx0zgcshtux8zk3 has $5 in it as of this writing. These $5 are there courtesy of btcfork's chaintip. Reward for the technically advanced or for fast learner!

To take it you need to just say read.cash in Bitcoin Script and that's it, you don't need my private key. Up for grabs!

You can even see one spending transaction here (I made it for the demonstration purposes):

The transaction was unlocked by the phrase 'read.cash', the second part is not important here, what's important is that it doesn't require my private key.

Can we modify our recovery idea using this new knowledge?

Can you spot the security problem here?

It's almost cool - now you can do your regular spending and you can use an additional way to recover your funds, kind of like a "password", to recover your money if you have lost your private key.

It has a security problem, obviously.

Even though nobody knows what unlocks this address ppfuzf5f52ypwm0jrnnfqtwafrtfx0zgcshtux8zk3, still if someone can guess that it is "read.cash" - they can send your money anywhere! And it's cheap to guess - you can probably brute-force it in a few minutes to few days.

Sidenote: If you're wondering what "ppfuz.." address does even have to do with the script - it's actually an encoded hash of the locking script. When you lock the money - you don't reveal what the "locking" script is, just its hash. Again, previous article covers it in details.

Here's the kicker. Bitcoin Cash has a great operation CHECKDATASIG (here's the story), which checks if the signature of the raw data matches some public key.

Bitcoin (BTC) didn't implement it and is against it. Can't use it there.

Bitcoin SV split away just to avoid adding this operation. Can't use it there.

For many of us it was a non-issue, which added some nice things to Bitcoin Cash.

What's important, CHECKDATASIG enables us to do something interesting (among other things) - it enables us to limit "where" the money goes.

Can you feel it coming? The power of the recoverable wallets exclusively on Bitcoin Cash?

We can now restrict "where" the money would go if somebody uses the secret word. That means we can do things like this:

Or this:

Obviously, even if somebody guesses that your recovery word is "mom" - they'll only be able to send the money to your Mom's wallet. They won't be able to send the money anywhere.

This is not possible to do without CHECKDATASIG operation, therefore it's possible exclusively on Bitcoin Cash. (Unlike Bitcoin BTC and Bitcoin SV)

Ok, let's talk about limitations and problems.

There is a small problem though - when you spend the money - you reveal what was in the contract. That, in turn, reveals your "recovery" words.

So, your first coffee would reveal the recovery word.

We can avoid it by doing what we do to store the passwords - by storing a salted hash of the password, which cannot be easily decrypted, instead of storing the plain-text password.

We don't do something like this:

verify password == "mom"

but rather

verify hash("abc#431!$" + password) == "871293fe891a298....3e289" # where, "871293fe891a298....3e289" is the result of hash("abc#431!$mom") # and "abc#431!$" is a random string called "salt"

Even though it doesn't even make sense to spend the time guessing your recovery word, since all it can do is send the money to your another trusted account (a minor inconvenience at best).

The salt can be probably stored in an OP_RETURN output, since it's needed for the recovery, at least for the first spending.

If the contract was already spent once - the salt can be recovered from the previous spending transaction, probably enabling the application of this to SLP tokens, which require at least 1 OP_RETURN. (I defer to experts on whether this is really possible)

If this idea really works that would mean that now when you create a wallet you can, for example add someones address as a "recovery" address with an associated "recovery" word, or you can buy another cheap phone, install a mobile wallet, use its address as a "recovery" address and just forget about the phone until recovery is needed. You can probably even have some institution's address, like a bank, in the worst case.

Lost private key? Just type in your recovery word phone and your last address (more on "how to recover the last address" in the next section) and your wallet will send your money to your phone, from where you can move them to your "recoverable" wallet again.

Even better you can have multiple recovery words and means. And you can change them as often as you want.

Be aware though that contract spending is a bit more expensive, than regular spending, so instead of typical $0.001 transaction fee, you'd pay something like $0.002 or maybe $0.003 each time you spend the money, because of the transaction size.

And you can use your wallet for your daily spending just as your regular Bitcoin Cash wallet - it will just send your change back to the contract or to a new contract using a nonce.

I defer to experts on whether any "replay" attacks are possible here with reusing the old contract. If they are possible - then the new contract should be used each time with a random nonce, not a problem.

Ok, there's one more problem to solve.

Even if you can recover the funds - you still need to remember where the funds are, like this address: ppfuzf5f52ypwm0jrnnfqtwafrtfx0zgcshtux8zk3 and if the address changes after each spending - that means there will be a new address each time.

The good part: the address itself is not a secret. The wallet can publish it as widely as possible or store in on third-party servers in the open or use brute-force approach from any last-known address or transaction.

One way to do it is to use one last known "root" address - from there we can find all the UTXOs that stem from that transaction and try to brute-force them using the provided recovery word.

Brute-force from last-known address

In the worst case the owner can even attempt to brute-force spending all UTXOs (unspent transaction outputs) in existence using the recovery password, which is slow, but feasible. There aren't that many.

We can also filter some UTXOs out that doesn't match some user-provided information about when their last spending was done. Like if the user last used the wallet 2-3 days ago - try only UTXOs around that time.

No last known address, but we still can filter something out before the brute-force. Time is of course "fuzzy" in Bitcoin, so wallet should try additional UTXOs reasonably outside of the range later.

The constantly happening brute-force means though, that the "recovery" word should still be at least a bit harder than "mom" to avoid accidental recoveries (which again is more of a nuisance, rather than a security problem).

Maybe the wallet can add something like the birthdate and wallet provider name (anything easily recallable by user later) to the recovery word of the user to avoid "accidental" recoveries. We're only trying to prevent accidents, there is no point for hackers to try to actively be stealing your funds, since in the end, they can only send it to trusted wallet.

We can use Satoshi-style hash(hash(...)) comparison to avoid disclosing personal information:

verify hash("abc#431!$" + "3298470923874") == "871293fe891a298....3e289" # where "3298470923874" is hash(birthday + provider + password) # and, "871293fe891a298....3e289" is the result # of hash(salt + hash(birthday + provider + password))

Again, I ask for everybody to wait for experts to weigh in on whether this is something great or it's a spectacular failure, but even if it is - hopefully at least that was an enjoyable read. It's also possible that I've invented something that was already widely known.

Anyway... Let's keep the innovation on Bitcoin Cash going!

By the way, read.cash uses Bitcoin Cash exclusively to upvote the authors (though you can deposit and withdraw other cryptocurrencies to your non-custodial browser-only wallet). You don't even need an account to upvote the articles.

Join us if you are an author (you don't even need to understand Bitcoin Cash to earn it!) and especially if you are a software developer that might benefit from having your own sponsorship program promoted by our affiliates. More about us.