Excited to announce that I’ve implemented Zero-Confirmation Escrows for BCHN in the following merge request:
Improvements to the ZCE Specification
While implementing this MR (and after discussing with @bitjson and @marty), it became clear that the implementation would be simpler (and more secure) with one change to the spec, which I have incorporated into the MR:
Make the ZCE locking script standard (rather than wrapping it in
P2SH). That way, nodes can determine whether a transaction is ZCE-secured simply by inspecting it (without needing to wait for the subsequent
escrowReclaimTx to reveal the redeem script).
This MR also features a more optimized version of the ZCE locking script (courtesy of @bitjson) that saves a few bytes of data and no longer requires the altstack.
A special thanks to @TierNolan, who identified a potential DoS issue involving the replacement of long chains of unconfirmed transactions.
This MR addresses that issue by ensuring that a ZCE-secured transaction may only replace a double-spend (and its descendants) if doing so is economically rational (i.e. the value of the escrow on the ZCE-secured transaction exceeds the cumulative value of the miner fees on the transactions it replaces).
Any peers that repeatedly send ZCE-secured transactions without adequate escrow to warrant replacement get banned.
In my testing, I found that removing an unconfirmed chain of transactions from the mempool is ~30x faster than adding it:
* The data in the above table was collected by running the
chain_of_double_spends_replaced_by_zce unit test in my MR and varying the length of the unconfirmed transaction chain.
Additionally, after setting up a local network of 3 interconnected BCHN regtest nodes, I discovered that nodes are able to propagate chained transactions over p2p at a maximum rate of ~30 tx/s. And since an attacker has only 5 seconds to build his chain of conflicting unconfirmed transactions, the maximum number of chained conflicting transactions that can be propagated network-wide in under 5 seconds is ~150, implying a worst-case replacement time of ~2.5ms per the table above.
Therefore, the low computational cost of replacement, combined with the DoS mitigation code above, should provide adequate DoS protection.
Proposed Testing and Activation Timeline
Because deploying ZCE requires a standardness change, it is critical that all participants in the BCH ecosystem (especially miners and merchants) activate ZCE standardness at the same time to ensure that non-ZCE zero-confirmation transactions remain secure. Therefore, the May 2023 upgrade would be an ideal time to activate ZCE on mainnet and would give us almost a full year to fully vet ZCE on testnet to ensure there are no unforseen issues.
Thank you to everyone who made Double-Spend Proofs a reality, especially @tom, @freetrader, @cculianu, and @im_uname. This MR would not have been possible without DSPs, which enabled ZCE to be implemented in less than 600 lines of code (excluding tests). And thank you to @bitjson and @marty who authored the ZCE CHIP and answered questions and made improvements to the spec as I was implementing this MR, as well as Awemany who pioneered the original Zero-Conf Forfeits mechanism on which ZCE is based.
Would love to get feedback on this implementation!