Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chaining: child payments must commit to parent public keys #14

Closed
bitjson opened this issue Aug 26, 2021 · 1 comment
Closed

Chaining: child payments must commit to parent public keys #14

bitjson opened this issue Aug 26, 2021 · 1 comment

Comments

@bitjson
Copy link
Owner

bitjson commented Aug 26, 2021

@msalcala11 noticed that we prematurely removed an important security requirement for chained ZCE payments before publication: requiring child ZCE payments to commit to all public keys contained in parent ZCE outputs.

The attack: thief buys five $100 items back to back via a chain of unconfirmed ZCE-secured transactions (each with a $100 ZCE). He then double-spends the first transaction by creating a ZCE-secured double-spend with $101 escrow. Thief gets $500 worth of goods for $101.

While this could often be prevented by merchants waiting for the 5 second lock-in period (after which honest network participants will refuse to accept ZCE replacements), this scenario is still not incentive-secure against fraud-as-a-service miners: the thief can directly pay cooperating miner(s) $101 to replace the first transaction, and cooperating miners gain a competitive advantage over honest miners. (A protocol bug, since the goal of this specification is to offer complete, incentive-based security.)

The solution is simple but requires slightly more complex logic: the ZCE root hash of chained ZCE-secured transactions must include all public keys included by any unconfirmed, parent ZCE-secured transactions. Now the above example is incentive secure: with each new transaction, the "bounty" increases for miners to claim the ZCEs of the honest chain of transactions. Using only a double spend proof for an input of the first transaction, all 5 ZCEs can be claimed, ensuring the 5 ZCE-secured transactions will be confirmed. (And now the attacker(s) lose $500 for a possible gain of $500, even with a colluding fraud-as-a-service miner.)

Note, because the creator(s) of previous ZCE-secured transactions may be different entities, we should also make a strategy recommendation for wallets: wallets should not overly rely on parent ZCE-secured transactions to not double spend. E.g. Alice sends Bob $10 with $10 ZCE. Bob pays Charlie $20 with $20 ZCE, including the $10 from Alice as an input. If Alice double-spends, Alice loses her $10 ZCE, but Bob also loses a $20 ZCE.

A reasonable strategy here is for wallets to never include an unconfirmed, ZCE-secured input (which they didn't create) which has a smaller ZCE than is required by the current transaction (i.e. ensure the previous sender always has an equal or larger ZCE to lose). So for example, if Alice gives $10 to Bob (with a $10 ZCE), Bob's wallet can reasonably buy a $10 item (with a $10 ZCE) without concern that an attempted parent double-spend will leave Bob at a net loss.

I'll send a PR with those two changes.

@bitjson
Copy link
Owner Author

bitjson commented Aug 26, 2021

Ah, just realized the "strategy recommendation" is just rephrasing the existing requirement 😅

  1. All selected UTXOs must be either:
    1. confirmed (included in a block), or
    2. an output of a previous ZCE-secured transaction in which the ZCE output met the minimum escrow requirement of the current transaction.

A UTXO from a smaller-ZCE parent transaction wouldn't be accepted by the merchant anyway, so previous transactions must necessarily have more at stake than the current transaction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant