Skip to content

Double Spend Proofs - BCHN Implementation Notes

This document serves a two-fold purpose:

  1. To give information to users of the BCHN software about expected behavior of the DSProof feature which is not fully addressed in the current draft specification maintained upstream

  2. To provide additional notes about interpretation of the upstream specification in instances where more clarity is deemed useful - for anyone trying to understand or implement the upstream specification.

Note about upstream DSProof specification

A copy of the most recent upstream specification should be found at

It is currently in Draft, and some review discussion can be found below it.

This draft specification has been merged into the common BCH specification repository maintained by Software Verde, and has since started to appear on the downstream sites such as

We cannot currently include this specification in the documentation set here because its license is CC-BY-SA and it would need to be dual-licensed under MIT license to be included with the BCHN client.

DSProof implementation behavior in BCHN

As the DSProof specification is still in Draft, we are providing here some additional notes on the BCHN implementation of this feature.

  1. The DSProof functionality is enabled by default, this means DS proofs are created and relayed. Both creation and relay can be disabled by setting doublespendproof=0 in the configuration or passing -doublespendproof=0 or -disabledoublespendproof on the command line.

  2. DSProofs are issued even for double spent transactions whose direct ancestors are not confirmed. This includes transactions whose ancestry includes unspent P2SH inputs, or unspent transactions signed with ANYONECANPAY hash type.

  3. If a transaction that is double spent is in the mempool (or UTXO set) and has descendants in the mempool, a DSProof is currently only issued for the double spent transaction itself. There is no notification or query mechanism yet to inform that the descendants have now been put at risk too due to the double spend.

  4. The GUI wallet does not display any notice yet when a transaction pending to be confirmed is double spent.

  5. There is a parameter for debug logging of DSProof functionality. It can be enabled by by adding dsproof to the debug flags.

  6. Orphans:

  7. DS proofs are stored as either orphans or non-orphans
  8. Orphans are proofs we have received for which the conflicting transaction (or UTXO) has not yet been seen, therefore the proof cannot be validated yet when it is seen.
  9. There is a maximum number of orphans (default 65535) but in practice an extra 25% is allowed for performance reasons. The high water mark is 1.25 * max = 81918, if exceeded, the oldest orphans are removed until the subsystem is below the high water mark again.
  10. There is an orphan expiry time which defaults to 90 seconds.
  11. A periodic cleanup thread runs every 60 seconds, to reap expired orphans.
  12. Orphans can become non-orphans when the necessary information to validate them, is received.
  13. Non-orphan proofs are not subject to automatic expiry.
  14. Misbehaving peers that supplied orphan proofs which turn out to be fake (after a valid proof is received that shows the orphan was fake) will get punished (misbehaviour score increased by 10 points).

Notes on the upstream specification(s)

  1. The sizes of the FirstSpender and DoubleSpender fields are variable.

  2. The value of the first list-size field in the spender record (the Number-of-pushdata's) is currently fixed to 1, and thus its encoding only occupies a single byte.

  3. The specification license (CC-BY-SA) is stricter than MIT, preventing its direct inclusion together with the BCHN documentation.

  4. The document linked in the References can also be found within BCHN upgrade documents at