CHIP 2021-08 ZCEs: Zero-Confirmation Escrows

I agree with everything except:

Nah, it wouldn’t.

He was talking about having a modified SPV client that actually sends 2 transactions when making a payment:

  • TX A: The fake TX, broadcasted to his own pool only, his pool does not share this TX with the rest of the network
  • TX B: The “legit” TX - broadcasted to everyone else

There is no way for any kind of DSP to catch this scheme, because the fake transaction is completely invisible to the network.

When you have 1% pool, there is 1 in 100 chance the fake TX A will get confirmed by the network first, while being completely invisible to the network otherwise.

@bitcoincashautist

EDIT:

Also, the probability of success maybe less than 1% actually, because there is still some risk of a reorg.

As I said, extremely complicated, very low profit to risk ratio. No wonder nobody did it since 2015.

1 Like

Yup. It will be invisible until the block is mined. With only DSPs, nothing anyone can do about it, they could be constructed only after seeing the 1-conf TX and it’d tell you what you already know - a double-spend transaction got mined instead of the one you have seen.
However, with ZCEs, the DSP could be used to try and take the cheater’s money even after a 1-conf - there would be incentive to reorg the 1-conf block that has offending TX-es in them and replace them with donations to miners, giving them some extra BCH on top of the block reward and both the cheater and the miner who helped him would be losing money.

(DSP+ZCE)-assisted reorg consensus?

We may be onto something here…

That assumes that the full nodes behind the pool (the one you don’t own, nor run) are somehow not going to send an INV for your stealing transaction. Why would they magically know this one should be kept secret?

How can your special SPV server even connect to them? No pool has their full nodes connectable on the general Internet. Because that would be stupid.

You’d need to start a full miner outfit to do this. Which gets me to this great joke about the guy that found a foolproof way to steal from banks which included working for them for 30 years and get a good paycheck from said bank :grinning:

This scheme is indeed convoluted, extremely complicated, risky, low profit-to-risk ratio and insanely difficult to do properly.

But still doable.

Which is @bitcoincashautist’s point.

Nobody ever did it and it is possible that nobody ever will, because there are thousands easier ways to steal crypto/goods paid with crypto from other people, which is my point.

2 Likes

Hi all, thanks for all the discussion.

I think this earlier comment summarizes my goal in working on ZCEs:

There’s also an existing forum topic for this conversation that I hadn’t seen before:

Could we move further discussion on whether or not BCH zero-conf is already “feature complete” there? It would be helpful to focus this forum topic more on technical discussion of ZCEs.


Treeless ZCE

I’ll have to stay focused on CashTokens for several more months, but I don’t want to keep sitting on some ZCE development I’m excited about.

The original ZCE contract design used a merkle tree to enforce not double spending any input P2PKH keys, but in June I realized there’s another construction with better tradeoffs: we entirely drop the need for pre-computation (including the merkle tree), significantly simplifying transaction creation, validation, and size in the common case, at the cost of limiting the number of ZCE transaction inputs to 3 (given the current 520 byte push limit).

With this change, the common case saves 15 bytes (mostly by dropping the ZCE root hash), and creating/verifying a ZCE output no longer requires meaningful computation – it’s basically just a P2PKH output with some extra, static bytes (adding only 22 bytes to the whole transaction vs. no-ZCE transactions!). The implementation is also far easier for wallets, merchants, nodes, and the claiming miner. As a side effect of the simpler implementation, chains of ZCE-secured transactions are also immediately supported (they were hypothetically possible before, but e.g. @escrowtim’s BCHN patch didn’t yet include support).

The contract is here.

The primary downside to this change is the 3 input limit vs. practically unlimited in ZCEv1 (due to the 520-byte push limit constraining the Miner Claim code path). But in practice, I don’t think it’s an actual limitation: if wallets use CashFusion properly, they should always be able to create transactions using 1 or 2 fresh UTXOs, and most coin management and selection algorithms have been optimized to do this since 2013. To corroborate, even before the scaling issues in ~2015, average input count was 2. So if anything, this limit might actually encourage healthier use of CashFusion for UTXO consolidation in wallets.

It may be a while still before I get around to revising the ZCE CHIP (we also need to review some cases where the beta DSP specs miss transactions), but I’d love to take feedback and questions here!

3 Likes

Ah, I should add that we save at least 10 bytes by assuming that an attacker cannot produce a private key for any string of 33 bytes in the produced ZCE transaction, as I believe it requires ~2^128 operations (via birthday attack) to find the 256 bit collision (e.g. a 35-byte,P2SH32 locking bytecode where some 33-byte slice also happens to be the public key to a private key known by the attacker). If that’s correct, the attack requires the same amount of work as finding a private key for someone else’s address, i.e. impossible. (Assuming wallets don’t naively include e.g. an attacker-provided OP_RETURN with a public key in their ZCE transactions – the CHIP will need a few wallet guidelines around ZCE transaction creation).

I’d appreciate if anyone with more crypto expertise could verify this security assumption. We could design the contract to not rely on it, but if it’s a reasonable assumption, the savings are meaningful.

1 Like

@ShadowOfHarbringer would you mind moving these posts over to that thread?

I moved the relevant section of my post there too:

I’d appreciate if we could keep this thread more focused on the technical implementation of ZCEs. That thread already has a lot of relevant discussion on whether or not zero-conf development is “feature complete”, and ZCEs are just one technical solution to the types of issues being discussed there.

Can I do it automatically somehow, or should I just copy-paste the text?

Some super admin might have a way to move, but I can’t find it. Can you just copy paste to there and delete here?

1 Like

I can and I will then.

Done.

2 Likes

Is this proposal still under discussion/consideration?

Yes, Treeless ZCEs work today and are also a useful construction for improving finality in more complex applications (e.g. DEXs).

The next step here is all wallet development work – we need end-user wallets that are sufficiently-advanced enough to work with these types of contracts.

Once we have user-facing applications ready to use ZCEs, the rollout doesn’t need to be coordinated in a network upgrade, miners that want to maximize revenue can just patch their own software at any time. (And once tooling is ready, I’ll clean up the CHIP as a reference for implementers.)

I’m working on that wallet development in Libauth – most recent status update here, and other developers are also independently working on similar projects.

3 Likes

In the recent Reddit AMA it was asked how the VM Limits CHIP would impact ZCE’s, here’s Jason’s response:

[The VM Limits CHIP] makes ZCEs more practical for mobile wallets, where the existing limits made implementation a bit harder (the 3 input limit of the most efficient “treeless” scheme).

While 3 inputs seems like it should be sufficient – given most transactions use only 1 or 2 inputs – I think in practice it creates edge cases that slow down user facing product development, and there’s a chicken and egg problem in getting node implementations to deeply review the idea and implement some claiming and transaction relay code.

Though, note that BitPay had public pull requests for bitcore and BitPay wallet with a full ZCE implementation in 2021. The CHIP was paused exclusively by concerns from a few stakeholders about the 5 second period of fast ZCE relay. I plan to get back to it eventually, or others are welcome to push the proposal forward without waiting for me. It’s waiting primarily for node implementations to give users/miners an option to turn on.

1 Like

As this has gotten some unexpected push, which I don’t really understand, here is the current state of the union.

  • ZCEs are in essence allowing a 3rd party triple spending a transaction that was double spend by the user.
  • ZCEs thus require the first-seen rule to be (partially) broken in order to ensure a “correct” double spend can take place to punish an “incorrect” attempt of double spend. Today it would block both indiscriminently.
  • Double spends today are insanely hard to do. You need specialized software, you need very good connectivity and an ideal setup with a merchant and your merchant should not listen to double spend proofs.
    Even then you’re not going to get a very good result. Most double spend attempts will fail for various reasons.

I don’t really understand the reason why people want to have ZCEs, there is no actual problem we have today that would be fixed by them. It sounds geeky and fun, devs love to dev, but it would be better to not actually require breaking even a little the actual rule that protects the network today.

Remember, a ZCE is an actual double spend. It tries to front-run the transaction being paid to the merchant with one that sends the money elsewhere. Likely a miner.

Which leads to the not very technical observations:

  • A merchant honestly doesn’t want the escrowed money. Where would they put that? Especially since the original party has a clear claim to want it back.
    A merchant doesn’t care about all of this. They just want to get paid the money they asked for. And BCH delivers that much better than visa or btc.
  • There seems to be a theory that miners in future would turn evil and start doing replace-by-fee.
    Apart from the fact that this hasn’t happened in 15 years, neither have the assisted-double-spend services.
    Apart from that, the miners don’t actually have the ability to do that.
    This was a consious decision in the design of the double spend proof, for instance, we don’t propegate the second transaction. A double spend is ONLY seen by the peers that the user send it to and they reject it and do not forward it.
    Miners never see the higher-fee transaction, as such they can’t be tempted to implement replace-by-fee.
  • A customer may be asked to spend $50 plus lock up $50 for at most a couple of hours. But the customer may very honestly not have that money in their wallet. A huge percentage of the population lives paycheck to paycheck!
    This requirement of locking up money in order to allow people to use zero conf is completely at odds with the markets wishes.
  • Double Spend Proofs exist. Their purpose is simple and effective.
    Protect the 99.99% of the normal every day transactions. It can do that with some engineering in middleware or in all wallets. Make the ones that do funky things (using custom wallets designed to do funky things, really) stand out as a sore thumb.
    And make the transaction finality show to the end-user after some 3 to 5 seconds.
    That is possible today with the tech that is running on the network today. Why ZCEs?

Edit, adding more points. Can’t call it a state of the union and then trying to be terse :wink:

  • The concept of confiscating the person’s money has always been possible using double spend proofs. It was silent, but the graph here explains it: The Double Spend flowchart
  • The idea that seems to go around about double spend proos not being complete is misunderstanding their purpose.
    In essence people are saying that since p2sh isn’t covering them, they need fixing. I disagree.
    The basic concept of dsproofs are to make normal daily payments smoother. In normal daily payments people use p2pkh. People have wallets that in almost all cases will spend confirmed coins.
    It would make sense to go back a couple of transactions in the chain, but honestly the moment you get to a situation that seems artificial you don’t have to bother. You can just tell the customer to wait for a confirmation. Because those situations don’t actually happen in normal shopping. Normal wallets can avoid them very easily.
    So you have two states. Either a payment is not protected and this means the customer did weird stuff. Make them wait and bear the consequences of said weird stuff.
    The second state is it is eligable for double spend protection and you know that after a couple of seconds you can give the product to the customer because the transaction is settled.
  • Exchanges. Yeah, it needs attention since so many people seem to care an exceptional amount about sending coins there. Mind you, those people are selling their BitcoinCash, why would we need enabling them? Anywho…
    Catering to exchanges is equivalent to you trying to change yourself in order for that movie star to notice you. Sorry, that’s just not going to happen. The reason they are not noticing you has practically nothing to do with the technicals of BitcoinCash. Has nothing to do with anything we can actually change.
    If you want exchanges to be more friendly to Bitcoin Cash: get a wider userbase. Make products that actual normal people want to use.

You must misunderstand the escrow. The merchant never holds that money, it’s just an additional output in the paying transaction that pays money to a p2sh address. The payer can (and should!) spend those money immediately, which actually only solidifies that the merchant gets the money for the goods in his output. The only other entitiy that can spend the p2sh contract is someone (i.e. a miner) that has two signatures for a pubkey used as input (i.e. a double spend) and take the money himself. Either way the merchant gets his money.

AFAIK that’s not true, if the double-spend succeeds then the merchant doesn’t get the money, but the buyer still loses the same amount of money (the escrow) as if he paid for the goods, money which the miner gets when he sweeps the escrow.

I like to think of ZCEs as userspace microPoS: you put up your own stake to secure your own TXs, a stake that can be slashed if anyone can prove you even tried to cheat, you get punished even if it did not succeed, but it still has a chance of succeeding.

Than there must have been significant updates to the mechanics of ZCE still not written in the CHIP:

If a payer attempts to invalidate a ZCE-secured transaction by double-spending any of its inputs, a miner can claim the ZCE using information available in either the double-spending transaction itself or a Double Spend Proof (DSP). To claim the ZCE, the miner must confirm the ZCE-secured transaction, ensuring the payee also receives the expected funds1.

1 Like

Then I must have misunderstood something as well :sweat_smile:

Can you elaborate on this? How precisely does this triple-spending happen?

The reason and usage is simple. Instant secure transfers to exchanges at the cost of only being able to transfer a % (like 50%-75%) to the exchange.

I agree that it is not actually usable to merchants.

The UX of having $100 in wallet while actually being able to only spend $50 or $75 at best would be terrible.

Common people are never going to like this when shopping. It’s just not happening.