CHIP 2021-08 ZCEs: Zero-Confirmation Escrows

OK, I will also copy-paste my TG post with some improvements:


It should be basically trivial to construct a wallet that sends the transaction to the merchant and the double-spend transaction to other nodes with a very specific delay. As in, the transaction to the merchant will be received by nodes in 0.5s and the ZCE double spend will be received 0.5s later.

First implement a delay in software and then just use a well-connected proxy and ping other nodes.

Or you can basically sellect well-connected and badly-connected nodes and send TX1 to well connected nodes and TX-ZCE to badly connected nodes.

Seems like the result would be almost guaranteed and the first TX would be removed.

Therefore this countermeasure seems ineffective.

The counter measure for the merchant (if he doesn’t want to wait 5 seconds for a dsproof) is: Require a ZCE protected transaction.

1 Like

This is indeed an effective countermeasure, it makes sure ZCEs work as intended.

However, this makes things even worse: It will lead to non-ZCE transactions (zeroconf transactions) being abandoned by merchants who adopt ZCEs.

Essentially this countermeasure breaks the current Bitcoin Cash value proposition: Zero Confirmation Transactions. Then replaces it with a new value proposition: Zero Confirmation Escrows with forced self-escrow system.

Now it seems like ZCEs and normal ZeroConf (either with DSProofs or not) are mutually exclusive.

Unless they would wait 5 seconds after which any zero-conf tx is handled in the same way as today.

But sure, the 5 seconds might be a concern. I don’t know how long the current merchants wait with releasing products while monitoring for DSPs and how much 5 seconds is to them.

1 Like

5 seconds? This is not good enough.

Even right now in Bitcoin Cash City, Australia, almost every BCH zeroconf transaction goes through under 2 seconds, no DoubleSpendProofs used. Waiting for 5 seconds is too long comparing to instant VISA transactions (yes, I know these do not even connect to the payment server, it’s irrelevant from customer’s/merchant’s point of view)

There are lots of videos on it.

Another issue with ZCEs is that they are not really useful for customers/merchants in brick&mortar store. More like they would be useful for exchange transfers as an option, because crypto people are more understanding.

I will copy-pasta my posts from TG:


Because essentially you need more money than you pay in the wallet. Part of the money becomes frozen until transaction is confirmed.

I can tell you already people won’t like this / Will have problem with this.

(…)

I can tell you, that psychologically this will be a problem for VAST numbers of people, ESPECIALLY these who live from-paycheck-to-paycheck, which is most probably the majority.

(…)

I think that you can figure out yourself that if Joe Sixpack has $100 in his wallet, but cannot buy a $100 kitchen appliance, this will ba a huge problem, right?

(…)

this is super bad UX


Basically, common people are just not going to accept this type of transactions.

Joe Sixpack has $100 of value in his wallet. Why would Joe Sixpack want to sacrifice his $25 or $50 so that he can pay for something?

Because some people might cheat the merchant?

This is basically like accusing Joe of stealing/cheating before he even cheated (guilty by default).

Really, nobody is going to like this.

Summing up the problems after the telegram discussion:

  • Emperical tests show that after 2 seconds most of the network has a transaction. At 3 seconds this reaches the ‘nearly all nodes’ level.
    This means that not seeing a dsproof for 2 seconds is safe. 3 is super safe.
    ZCE breaks that by breaking the first-seen rule for 5 seconds.
  • ZCE is essentially replace-by-fee in a different form. Same concepts.
  • The 5 second rule is bad.
    First reason, that’s not how mempools work today.
    But the second is due to the nature of decentralization. Time is full-node local. There is no timestamp of creating / sending a transaction. Only when you first see it. So effectively it may be 6 or 7 seconds where a node accepts and forwards the double spending zce transaction. Repeating point one, zce destroys zero conf.
  • ZCE CHIP misunderstands the basic way our network works. The entire section on “long term security" is basically wrong. The understanding of what DSProofs do is wrong.
  • ZCE does not in actual fact solve any problems that are not already solved or easy-to-solve today with currently deployed tech.
  • The market is NOT asking for this. The market isn’t even pushing for double-spend proofs because there is no perceived risk of double spends on the network.

In short, full nodes should not add code to break the first-seen rule for some specific case that is eery similar to rbf.

I just got around to reading this CHIP for the first time. Yeah I am with Tom on this one – not worth doing right now.

The requirements are insanely complex on the mempool, on the customer wallet, on miners, and on merchants – all at once!

By contrast, DSProofs require 0 wallet support from clients (or nearly 0). Just the merchant has to have support, really.

Aside from that, it’s not even clear to me this would actually work any better than DSProofs. It seems to try to solve 1 class of problems but introduces a whole other large class of problems in doing so.
But even if it works as claimed – the requirements are out of this world complex. Everything from the wallets to the mempool relay policy would have to be super rock solid and have 0 bugs otherwise you’re hosed. Lots of complexity there to me means: lots of opportunities for people to implement it improperly and lots of room for exploits to exist.

DSProofs seem like a great solution in that they are simple, are here today, and are available right now for merchants to use even if customers or miners don’t even “know” about their existence.

If you are really an interested merchant, you can find out with great confidence that no double-spends exist (provided your node is proparly randomizing its peers)… for a particular purchase.

I vote we maximize the emphasis that merchants start to use DSProofs … and they implement those properly.

And I vote we don’t do ZCE until and unless we find that DSProofs don’t do enough and we need to do something as elaborate as ZCE… which I think is insanely complex for what it is.

1 Like

I’m afraid that the forum format isn’t very useful for continuing research on this topic; the discussion has gone in circles many times now.

I’ve posted a ZCE thread that I’ll keep updated here:

https://x.com/bitjson/status/1864045897023164701

I don’t have anything new to say, so I’ll avoid adding to the noise by responding further unless people have specific questions (just @ me and I’ll try to respond).

I’ll reply here again when I get around to updating the ZCE CHIP to the treeless construction. Again, hoping to get back to this myself in 2025, it’s not waiting on consensus, only development work.

4 Likes

As this topic here is thus practically dead, it is fun and probably useful to go over the escrow history and what it ACTUALLY is.

So, back in 2018 we enabled this new opcode op checkdatasig. A couple of months later there was a workshop in Italy (online) where, among others, escrows were proposed as a way to increase the certainty of instant transactions.

Besides the escrow based solution several other solutions were proposed and compared at that workshop. Check the presentations for details.

Based on excellent empirical research presented there, based on good discussions on the pluses and minuses of the various ideas we came to the conclusion that double spend proofs were by far the best solution to increase security of instant transactions.
Nobody has yet presented any evidence that disagrees with that conclusion we reached back in 2018.

The basic conclusion is that in order to have the best security around instant transactions we need the ‘first seen’ rule, as built into full nodes since Satoshi, to remain untouched. They are our firewall. This is our most important defense against double spend attempts.

The only proposal that leaves the first seen rule completely untouched is the double-spend-proof, and as a result of the workshop the dsproof proposal has since been adopted by all full nodes and by various interested parties who wanted their protection. It is live on mainnet. It is supported by middleware. It is used by things like vending machines.

Back to escrows to improve instant transactions:
so, the legendary developer awemany invented the idea based on the then new opcode. But it had the flawed requirement that when a stealing transaction gets seen by miners first, they are not aware of the escrowed one and thus won’t be able to take the money. The obvious solution is to do a replace-by-[something] in the mempool. Very similar to replace-by-fee. Which we know from BTC is a terrible idea. See calin above who repeats this common knowledge. The saboteur on that side is the one that pushed it the hardest. That should tell us something.

We have not seen any rationale that didn’t instantly get refuted why dsproof is actually not serving the people. Or why it would fail in the future. Various reasons have been given, none of them made sense.

The basic innovations on a better or more interesting script compared to the awemany 2018 proposal are all about moving chairs on the deck of the Titanic. None of them cover the basic issue that a miner will only ever see one of the two transactions due to the basic protection of the first seen rule. This is our firewall, it would be insane to break it! And so this is like the chairs on the deck of the Titanic. No changes in the script will remove the underlying iceberg where the miners not getting both transactions which is required to make the scheme work.

So, even if we innovate to version 20 of the unlocking script, this is irrelevant if it is not seen by miners together with the stealing transaction. And they won’t, as long as we don’t punch a hole in the first-seen rule. And we really don’t want to affect that as that is our core protection.

I’m happy we can close this topic as to most the point was clear already in 2018. So this was a huge waste of time. I hope we never see this topic opened again like it actually is a solution to anything.

2 Likes

So during a heated discussion I thought out a way to (hopefully, possibly) save the concept of ZCE from destruction.

Assuming this scheme works and could be (somehow) implemented, ZCEs could work without changing the relay rules to de-prioritize normal 0-conf transactions, thus nuking them.


Basic concept:

  • To use ZCE, user’s wallet has to create a “ZCE-only UXTO”, basically a pile of coins that can be only spent using a ZCE transaction
  • User’s wallets would simply allow users to pick in which “bag” they want to hold the money. “ZCE bag” or “Zeroconf bag”
  • Basically, we need to create a pile of coins that can only be spendable/movable via a ZCE transaction.
  • So users that use ZCEs more often, like when funding exchanges, would have more in their “ZCE bag”, while users using zeroconf daily (like paying for coffee and shopping) would have more coins in their “Zeroconf bag”.
  • I am guessing that, to ensure no shenanigans, moving the money between the bags would require at least 1 real hard mining confirmation, otherwise we could run into some kind of multi-level unspent chain shenanigans
  • I am not sure if this would require a consensus change or could be just done simply using OpCodes/Scriping magic.

This idea is only a stud. I (obviously) cannot make the full design myself, it would require help from OpCode technicians like Jonas, BitcoinCashAutist, Jimtendo and obviously Jason.


Diagrams

Here is how ZCE works now:


Here is how ZCE would work after the implementation:


Here are the scenarios that need to be (somehow) effectively disabled, in order for the scheme to work:

zce_impossible_scenarios


Hopefully this can be done. If not, then well - at least I tried (real hard)


EDIT:

Legend:

legend

So what do you guys think? Is this doable or did I make some mistake / wrong assumption here?

@bitjson @jimtendo @Jonas

More details is needed to be able to understand this.

How would those coins be able to escape this covenant?

This requires a policy or consensus change since a transaction in itself can not be valid/invalid based on the confirmation status of its parents.

I don’t understand the diagram. If TX2 is the double-spend the input can not be “OUTPUT 1” from TX1, it should be the same input as TX1.

1 Like

Thanks for your reply, your input is valuable.

If I understand correctly, you mean to “move the coins back from ZCE bag into normal bag”?

Well, indeed the scheme is incomplete, I did not include this scenario. I did not think through the “escape” part yet, will probably need more time.

But so far, I think the basic way to “escape” (go back) would be via creating a ZCE transaction with 0% reclaim ratio that leads back to normal P2KPH realm.

Hm, yes indeed, this is very probably accurate. I also did not include this in the scheme (yet).

But what about if we make PoS software review the chain of transactions back to the last confirmed TX, check whether the money were not moved without confirmation and accept the transaction or not basing on that? This way there would be no consensus change needed.

Also Jason in his spec also requires 11 confirmations in UXTO selection phase. I assume this should be also checked on the receiving side, otherwise an attacker could craft his own ZCEs that do not fulfill the criteria:

Wallet UTXO Selection

Wallets creating ZCE-secured transactions must implement the following UTXO selection criteria:

    All selected UTXOs must use P2PKH contracts.
    Each selected UTXOs must use a unique public key1 which:
        has never previously produced a signature (e.g. made past transactions, including in other cryptocurrency networks), and
        will not produce another signature until the created ZCE-secured transaction has received 11 confirmations2.
    All selected UTXOs must be either:
        confirmed (included in a block), or

TX2 is the normal reclaim transaction done by the payer, not the double spend. There are no double spends in the diagram.

Maybe I should have made it more clear in the diagram, my apologies.

I will produce an improved diagram with descriptions.

Just so we’re completely clear: The diagrams do not contain any kind of double spending transaction.

They only show “top up” TX (that fills the ZCE bag), payment TX, escrow reclaim TX and (possible) miner reclaim TX.

EDIT:

Fixed missing TX

FYI, I made the diagram basing on Jason’s spec, completely and exclusively.

Did not use any other sources.

Here is the legend from above:

legend

EDIT:

Wording improvements.

The second one would be impossible to stop. It’s a p2pkh spend with one p2pkh output and one p2sh output. Impossible to know that it’s a ZCE reclaim.

This would make your scheme vulnerable to this attack:

  • Pay a merchant $50 with a normal p2pkh and two p2pkh outputs, get the goods or service.
  • 2 minutes later create a double spend with the same input but $40 to yourself and $10 in a p2sh. We can’t stop this transaction shape in consensus.
  • Create a ZCE reclaim of the p2sh output to yourself.
  • Give[*] the double-spend+reclaim to a miner.
  • The miner will take the $10 for himself and confirm the double-spend.
  • You got the goods, payed $10 to a miner and the merchant got nothing.

[*] The part where a miner can be given a transaction via a side-channel for greater profits is what ZCE is supposed to protect against. So claiming that “it’s not possible due to first-seen!” misses the point.

If an “evil pool” that accepts and mines such transactions has 5% of the total hash power the success rate of this attack is 5% and if it fails you just payed a merchant the correct price for the goods. There is no downside to it, unless you have some personal relation to the merchant or not doing this attack anonymous.

Edit:
Just realized that this is just a plain and normal miner bribe attack but with extra steps. I will hold on any comments until there is more details about the “ZCE bag”.

2 Likes

Good thinking. I believe I understand.

So what about creating a dumb opcode called (for example) OP_IS_ZCE that does not do anything specific in particular except maintaining the separation?

This opcode would be required to spend from ZCE Bag and forbidden in any other context.

Of course, this would affect consensus so I understand it could be controversial, but the idea is simple enough and should not create any weak points or vulnerabilities.

Does this sound viable / make sense?

Basically, a special opcode would function as a simple marker that uniquely identifies ZCE transactions so that they can be immediately identified and differentiated from any other contract (P2SH).