Skip to content

Commit

Permalink
Add multisig, command name change
Browse files Browse the repository at this point in the history
  • Loading branch information
imaginaryusername authored Apr 11, 2019
1 parent 7632178 commit 34b344f
Showing 1 changed file with 37 additions and 18 deletions.
55 changes: 37 additions & 18 deletions dsproof/dsproof.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

@im_uname
WIP
Last revised: 20190327
Last revised: 20190411

Author: @im_uname, adapted from Chris Pacia's Double Spend Alert (https://github.com/cpacia/spec/blob/master/double-spend-alerts.md)

Expand All @@ -12,19 +12,19 @@ This document describes a new Bitcoin Cash network message that is generated whe

## Design requirements

A transaction that has its inputs all being from P2PKH outputs, follow prevailing standardness rules and signed with SIGHASH_ALL without the ANYONECANPAY flag is hereby referred as "protected transactions".
A transaction that has its inputs all being from P2PKH or P2SH-multisig outputs, follow prevailing standardness rules and has all signatures signed with SIGHASH_ALL without the ANYONECANPAY flag is hereby referred as "protected transactions".


1. The proof message, by itself, must be sufficient to prove the offending output(s) being signed for different transactions.
2. The proof message, by itself, must not be sufficient to reconstruct the offending transactions in whole unless additional information is relayed.
3. Generating and relaying proof must not create additional bandwidth and processing requirement for nodes above O(n) where n is existing transaction traffic in the worst case.
4. Node wallets and SPV wallets should be able to conclude from the absence of a DS proof over a tolerated time t before next block, that a protected transaction has been relayed to all mempools of the "honest" public network following rules no more stringent than prevailing relay rules, and no alternative was able to supercede the transaction in question in terms of first-seen.
5. (Optional): For a DAG (or chain) of unconfirmed protected transactions all lacking DS proofs over time t, we also get the same certainty as in #4. (subject to chain-length limits)
5. (Optional, subject to BIP62 implementation): For a DAG (or chain) of unconfirmed protected transactions all lacking DS proofs over time t, we also get the same certainty as in #4. This will require full deployment of BIP62 third-party malleability fixes. (subject to chain-length limits)

## Specification


The `dblspndproof` command generates the following, with two different transactions spending the same outpoint as input:
The `dsproof` command generates the following, with two different transactions spending the same outpoint as input:

| Field Size | Description | Data Type | Comments |
| -----------|:-----------:| ----------:|---------:|
Expand All @@ -37,14 +37,32 @@ If the two transaction share more than one outpoint, then a corresponding number

| Field Size | Description | Data Type | Comments |
| -----------|:-----------:| ----------:|---------:|
| 1 | version | uint8 | version byte |
| 1 | version | uint8 | version byte; 1 for p2pkh |
| ? | tx_dig1 | tx_dig | Transaction digest of the one transaction before final double SHA256 hash, corresponding to the doublespent outpoint|
| ? | tx_dig2 | tx_dig | Transaction digest of a different transaction before final double SHA256 hash, corresponding to the doublespent outpoint|
| ? | sig1 | char | signature of the double-SHA256 of tx_dig1, extracted from tx1 |
| ? | sig2 | char | signature of the double-SHA256 of tx_dig2, extracted from tx2 |

A second type that addresses p2sh-multisignature transactions is structured as follows:

| Field Size | Description | Data Type | Comments |
| -----------|:-----------:| ----------:|---------:|
| 1 | version | uint8 | version byte; 2 for p2sh-multisig |
| 1 | pk_seq1 | uint8 | "sequence" number that points to which pubkey in checkmultisig the first signature pertains to |
| 1 | pk_seq2 | uint8 | "sequence" number that points to which pubkey in checkmultisig the second signature pertains to. May be identical to pk_seq1. |
| ? | tx_dig1 | tx_dig | Transaction digest of the one transaction before final double SHA256 hash, corresponding to the doublespent outpoint|
| ? | tx_dig2 | tx_dig | Transaction digest of a different transaction before final double SHA256 hash, corresponding to the doublespent outpoint|
| ? | sig1 | char | signature of the double-SHA256 of tx_dig1, extracted from tx1 |
| ? | sig2 | char | signature of the double-SHA256 of tx_dig2, extracted from tx2 |

For tx_dig, refer to https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/replay-protected-sighash.md.

A message type 'dsproof_req' is structured as follows:

| Field Size | Description | Data Type | Comments |
| -----------|:-----------:| ----------:|---------:|
| 36 | outpoint | outpoint | The outpoint that was double spent |

A new inventory type is added:

| Value | Name |
Expand All @@ -55,26 +73,24 @@ The inventory vector hash shall be set to the hash of the serialized outpoint wh

## Message Generation and Relaying

The proof must be only generated when at least two different valid transactions spending at least one identical output, at least one of them being a protected transaction, are detected; it must not be forged otherwise. Note that two transactions are considered different if they contain different signatures, even if their transaction digests are exactly the same.
The proof must be only generated when at least two different valid transactions spending at least one identical output, at least one of them being a protected transaction, are detected; it must not be forged otherwise. Note that two transactions are considered different if they contain different signatures, even if their transaction digests are exactly the same. In the case of multisignature, any pubkey signing a different transaction spending the same outpoint as a protected transaction is sufficient proof.

When a node detects two transactions that spends the same outpoint, AND at least one of the transactions is a protected transaction, it should check to see if it has a double spend proof to that outpoint in inventory.
If not it should construct a `dblspndproof` message for the outpoint and announce to its peers via `inv` packets.
If not it should construct a `dsproof` message for the outpoint and announce to its peers via `inv` packets.

When receiving an `inv` packet for a double spend proof a node should:

1. Check if the outpoint is spent by any transaction in mempool. If not, record the outpoint and corresponding peer in an index.
2. Check to see if there is a double spend proof corresponding to the same outpoint in inventory.
3. If not, download, validate, store and announce the dblspndproof.
4. If a transaction that matches a recorded outpoint is relayed to the node, request dbspendproof from previous recorded peer.

TODO: request message format
3. If not, download, validate, store and announce the dsproof.
4. If a transaction that matches a recorded outpoint is relayed to the node, request dsproof from previous recorded peer with a "dsproof_req" message.

The validation of the double spend proof fails if:

* The double spent `outpoint` is not in `tx_dig1` or `tx_dig2` of the proof.
* The signature for any of the transaction digests is invalid.

If validation is successful the node should announce and relay the `dblspndproof` message to its peers.
If validation is successful the node should announce and relay the `dsproof` message to its peers.

A proof of a given outpoint shall also be retrievable by requesting the corresponding mempool transaction spending the same outpoint. This will be useful for servicing SPV clients (see below).

Expand All @@ -96,15 +112,18 @@ TODO: How big can the set of DSproofs be for a mempool that's almost entirely ma

A merchant node which utilizes double spend proofs should follow the following general procedure, when receiving a transaction that pays them whether through network or direct connection (e.g. BIP70):

1. Broadcast the transaction if it has not been broadcast already, in the case of direct connection.
2. Evaluate the transaction that pays them. If it does not fit any of the following criteria, do not rely on doublespend proof, and instead either wait for confirmation or apply more stringent risk management:
1. Evaluate the transaction that pays them. If the transaction does not pay sufficient fee or is otherwise unfit as defined by the merchant independent of the criteria below, apply remedial action either by rejecting transaction of custom negotiations with the customer - fast transaction becomes irrelevant.

The transaction must contain all P2PKH inputs.
The transaction must either be spending only from confirmed UTXOs, or all of its ancestors in mempool must also be all-P2PKH-only transactions.
All of the inputs in the relevant transaction, and its mempool ancestor chain, must be signed SIGHASH_ALL without ANYONECANPAY.
2. If the transaction does not fit any of the following criteria, do not rely on doublespend proof, and instead either wait for confirmation or apply more stringent risk management:

The transaction must contain all P2PKH or multisig-P2SH inputs.
The transaction must either be spending only from confirmed UTXOs, or all of its ancestors in mempool must also be all-P2PKH/P2SH-multisig-only transactions (Optional, requires BIP62).
All of the inputs in the relevant transaction, and its mempool ancestor chain (Optional, requires BIP62), must be signed SIGHASH_ALL without ANYONECANPAY.

3. After affirming that the transaction fits the critera for applying double spend proofs, the merchant then waits T seconds, T being a variable adjusted to risk tolerance, for a proof to arrive. If a double spend proof corresponding to the paying transaction or any of its ancestors arrive, the merchant shall either decline the payment, or wait for confirmation. If no proof arrives within T seconds, the merchant hands out goods or services.

Note that in the case of an unconfirm chain, if BIP62 fixes are not implemented in full, transactions can be malleated by third parties to invalidate descendents without triggering doublespend proof - and any attempt at making proof against this will be vulnerable to false positive attacks. Double spend proof against unconfirmed proofs should therefore only be activated after implementation of the full set of BIP62 fixes (https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki).

TODO: Simulate merchant risk in both single-tx and unconfirmed chain.

## Limitations
Expand All @@ -115,4 +134,4 @@ As of current version of this spec, nodes that are more stringent in relay crite

TODO: Explanation for specs, attack scenarios

Thanks to Tom Zander, Mark Lundeberg, Peter Rizun, Andrew Stone, Dagur, Greg Griffith for feedback and initial reworks. Thanks to Tom Harding for providing the inspiration and initial framework in tackling different doublespend types.
Thanks to Tom Zander, Mark Lundeberg, Peter Rizun, Andrew Stone, Dagur, Greg Griffith for feedback and initial reworks; Jonathan Silverblood and Chris Pacia for additional comments; thanks to Tom Harding for providing the inspiration and initial framework in tackling different doublespend types.

0 comments on commit 34b344f

Please sign in to comment.