You've already forked specification
DSProof Specific Clarification
Improved the verbiage and reduced ambiguities, particularly endianness, within the Double Spend Proof specification.
This commit is contained in:
@@ -52,10 +52,25 @@ Combining these, there are 6 valid signature hash types in Bitcoin Cash. Only t
|
|||||||
|
|
||||||
## Bitcoin Cash Signatures
|
## Bitcoin Cash Signatures
|
||||||
|
|
||||||
In Bitcoin Cash, transaction signatures use the transaction digest algorithm described in [BIP143](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki), in order to minimize redundant data hashing in verification and to cover the input value by the signature.
|
In Bitcoin Cash, transaction signatures use the transaction digest algorithm described in a modification of [BIP143](/protocol/forks/replay-protected-sighash), in order to minimize redundant data hashing in verification and to cover the input value by the signature.
|
||||||
|
|
||||||
### Preimage Format
|
### Preimage Format
|
||||||
|
|
||||||
|
At a high level, the preimage format for a signature within a single input is a serialization of the following transaction components, **many of which are hashed, modified, or substituted** depending on the context:
|
||||||
|
|
||||||
|
1. Transaction version
|
||||||
|
2. Previous transaction outputs identifiers
|
||||||
|
3. Transaction input sequence numbers
|
||||||
|
4. The identifier of the output being spent
|
||||||
|
5. The locking script of the output being spent
|
||||||
|
6. The value of the output being spent
|
||||||
|
7. The sequence number of the transaction input
|
||||||
|
8. The created transaction outputs
|
||||||
|
9. Transaction locktime
|
||||||
|
10. The signature hash type
|
||||||
|
|
||||||
|
The following table specifies, in detail, the preimage format for a signature within a single input:
|
||||||
|
|
||||||
| Field | Length | Format | Description |
|
| Field | Length | Format | Description |
|
||||||
|--|--|--|--|
|
|--|--|--|--|
|
||||||
| transaction version | 4 bytes | unsigned integer<sup>[(LE)](/protocol/misc/endian/little)</sup> | The value of transaction's version field. |
|
| transaction version | 4 bytes | unsigned integer<sup>[(LE)](/protocol/misc/endian/little)</sup> | The value of transaction's version field. |
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
This document describes proposed requirements and design for a reusable signing mechanism ensuring replay protection in the event of a chain split.
|
This document describes proposed requirements and design for a reusable signing mechanism ensuring replay protection in the event of a chain split.
|
||||||
It provides a way for users to create transactions which are invalid on forks lacking support for the mechanism and a fork-specific ID.
|
It provides a way for users to create transactions which are invalid on forks lacking support for the mechanism and a fork-specific ID.
|
||||||
|
|
||||||
The proposed digest algorithm is adapted from BIP143[1][1] as it minimizes redundant data hashing in verification, covers the input value by the signature and is already implemented in a wide variety of applications[2][2].
|
The proposed digest algorithm is adapted from BIP143<sup>[1][1]</sup> as it minimizes redundant data hashing in verification, covers the input value by the signature and is already implemented in a wide variety of applications<sup>[2][2]</sup>.
|
||||||
|
|
||||||
The proposed digest algorithm is used when the `SIGHASH_FORKID` bit is set in the signature's sighash type.
|
The proposed digest algorithm is used when the `SIGHASH_FORKID` bit is set in the signature's sighash type.
|
||||||
The verification of signatures which do not set this bit is not affected.
|
The verification of signatures which do not set this bit is not affected.
|
||||||
@@ -53,7 +53,7 @@ The proposed digest algorithm computes the double SHA256 of the serialization of
|
|||||||
9. nLocktime of the transaction (4-byte little endian)
|
9. nLocktime of the transaction (4-byte little endian)
|
||||||
10. sighash type of the signature (4-byte little endian)
|
10. sighash type of the signature (4-byte little endian)
|
||||||
|
|
||||||
Items 1, 4, 7 and 9 have the same meaning as in the original algorithm[3][3].
|
Items 1, 4, 7 and 9 have the same meaning as in the original algorithm<sup>[3][3]</sup>.
|
||||||
|
|
||||||
#### hashPrevouts
|
#### hashPrevouts
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ The 8-byte value of the amount of Bitcoin this input contains.
|
|||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
1. In the original algorithm[3][OP_CHECKSIG], a `uint256` of `0x0000......0001` is committed if the input index for a `SINGLE` signature is greater than or equal to the number of outputs.
|
1. In the original algorithm<sup>[3][3]</sup>, a `uint256` of `0x0000......0001` is committed if the input index for a `SINGLE` signature is greater than or equal to the number of outputs.
|
||||||
In this BIP a `0x0000......0000` is committed, without changing the semantics.
|
In this BIP a `0x0000......0000` is committed, without changing the semantics.
|
||||||
|
|
||||||
#### sighash type
|
#### sighash type
|
||||||
@@ -205,16 +205,20 @@ Gating code:
|
|||||||
|
|
||||||
## Note
|
## Note
|
||||||
|
|
||||||
In the UAHF, a `fork id` of 0 is used (see [4][4] REQ-6-2 NOTE 4), i.e.
|
In the UAHF, a `fork id` of 0 is used (see UAHF<sup>[4][4]</sup> REQ-6-2 NOTE 4), i.e.
|
||||||
the GetForkID() function returns zero.
|
the GetForkID() function returns zero.
|
||||||
In that case the code can be simplified to omit the function.
|
In that case the code can be simplified to omit the function.
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
[1]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
|
[1]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
|
||||||
|
\[1]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki
|
||||||
|
|
||||||
[2]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#Motivation
|
[2]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#Motivation
|
||||||
|
\[2]: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki#Motivation
|
||||||
|
|
||||||
[3]: https://en.bitcoin.it/wiki/OP_CHECKSIG
|
[3]: https://en.bitcoin.it/wiki/OP_CHECKSIG
|
||||||
|
\[3]: https://en.bitcoin.it/wiki/OP_CHECKSIG
|
||||||
|
|
||||||
[4]: https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/uahf-technical-spec.md
|
[4]: https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/uahf-technical-spec.md
|
||||||
|
\[4]: https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/uahf-technical-spec.md
|
||||||
|
|||||||
@@ -1,103 +1,100 @@
|
|||||||
# Announcement: Double Spend Proof ("dsproof-beta")
|
# Announcement: Double Spend Proof ("dsproof-beta")
|
||||||
|
|
||||||
This message is meant to inform participants of attempts of double
|
This message is meant to inform participants of attempts of double spending an unconfirmed transaction by providing cryptographic provable evidence that one UTXO entry was spent twice by the owner(s) of the funds.
|
||||||
spending an unconfirmed transaction by providing cryptographic provable
|
|
||||||
evidence that one UTXO entry was spent twice by the owner(s) of the funds.
|
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
A double spend attack can be used, for instance, to redirect payments meant for a specific
|
A double spend attack can be used, for instance, to redirect payments meant for a specific merchant to a different target and thus defraud the merchant we want to pay to.
|
||||||
merchant to a different target and thus defraud the merchant we want to pay to. The basic
|
The basic concept of a double spend is that (at least) one unspent output is spent twice in different transactions which forces miners to pick one of them to mine.
|
||||||
concept of a double spend is that (at least) one unspent output is spent
|
|
||||||
twice in different transactions which forces miners to pick one of them to mine.
|
|
||||||
|
|
||||||
At its most basic we can detect this by finding two signed inputs both
|
At its most basic we can detect this by finding two signed inputs both spending the same output.
|
||||||
spending the same output. In the case of pay-to-public-key-hash (P2PKH)
|
In the case of pay-to-public-key-hash (P2PKH) this means two signatures signing the same public key.
|
||||||
this means two signatures signing the same public key.
|
|
||||||
|
|
||||||
Cryptographic signatures in Bitcoin Cash follow the 'fork-id' algorithm described
|
Cryptographic signatures in Bitcoin Cash follow the "fork-id" algorithm described [here](/protocol/forks/replay-protected-sighash).
|
||||||
[here](/protocol/forks/replay-protected-sighash),
|
Since a hash of the transaction is signed, the protocol sends only the intermediate components used to build the preimage for the hash, while still allowing receivers to validate both signatures of the same public key, and therefore proving that a double spend has taken place.
|
||||||
which explains a change made to the Satoshi designed algorithm, a change after which the containing transaction itself is not signed, but a unique hash of that
|
|
||||||
transaction is being signed. This gives us the opportunity to send only
|
|
||||||
the intermediate hashes instead of the whole transaction while allowing
|
|
||||||
receivers to still validate both signatures of the same public
|
|
||||||
key. And therefore prove that a double spend has taken place.
|
|
||||||
|
|
||||||
## Network specification
|
## Network specification
|
||||||
|
|
||||||
A node that finds itself in possession of a correct double-spend-proof
|
A node that finds itself in possession of a correct double-spend-proof
|
||||||
shall notify its peers using the INV message, using a 'type' field with
|
shall notify its peers using the [inventory](/protocol/network/messages/inv) message, using a "type" field with the value **`0x94A0`**.
|
||||||
number **0x94a0**. This will be changed to another number as this spec
|
This inventory type value will be changed to another number once double-spend proofs move out of beta and is finalized.
|
||||||
is finalized.
|
|
||||||
|
|
||||||
The hash-ID for the double-spend-proof is a double sha256 over the entire
|
The hash-ID for the double-spend-proof is a double sha256 over the entire serialized content of the proof, as defined next.
|
||||||
serialized content of the proof, as defined next.
|
|
||||||
|
|
||||||
In response to an INV any peer can issue a `getdata` message which will
|
In response to an inventory message, any peer can issue a [getdata](/protocol/network/messages/getdata) message which will cause a reply with the following message.
|
||||||
cause a reply with the following message. The name of the message (until
|
This type of message is **`dsproof-beta`** but will be changed to another identifier once double-spend proofs move out of beta and is finalized.
|
||||||
this spec is finalized) is **`dsproof-beta`**.
|
|
||||||
|
|
||||||
|
| Field | Length | Format | Description |
|
||||||
| Field Size | Description | Data Type | Comments |
|
|
||||||
| -----------|:-----------:| ----------:|---------:|
|
| -----------|:-----------:| ----------:|---------:|
|
||||||
| 32 | TxInPrevHash | sha256 | The txid being spent |
|
| previous [transaction output](/protocol/blockchain/transaction#transaction-output)'s transaction hash | 32 | sha256<sup>[(LE)](/protocol/misc/endian/little)</sup> | The **transaction hash** of the output being spent |
|
||||||
| 4 | TxInPrevIndex | int | The output being spent |
|
| previous [transaction output](/protocol/blockchain/transaction#transaction-output)'s index | 4 | unsigned integer<sup>[(LE)](/protocol/misc/endian/little)</sup> | The **index** of the transaction output being spent |
|
||||||
| | FirstSpender | spender | the first sorted spender |
|
| first spender | variable | spender<sup>[(BE)](/protocol/misc/endian/big)</sup> | The preimage data structure needed to validate a transaction's signature. |
|
||||||
| | DoubleSpender | spender | the second spender |
|
| second spender | variable | spender<sup>[(BE)](/protocol/misc/endian/big)</sup> | The preimage data structure needed to validate a transaction's signature. |
|
||||||
|
|
||||||
A double-spend-proof essentially describes two inputs, both spending the
|
A double-spend-proof describes two inputs, both spending the same output.
|
||||||
same output. As such the prev-hash and prev-index point to the output and
|
As such the previous transaction output's hash and previous transaction output's index point to the output and the spenders each describe inputs.
|
||||||
the spenders each describe inputs.
|
|
||||||
|
|
||||||
The details required to validate one input are provided in the spender field;
|
### Spender Format
|
||||||
|
|
||||||
| Field Size | Description | Data Type | Comments |
|
The `spender` format is as follows.
|
||||||
|
Each field in the (below) table's `description` column loosely corresponds to the name of the preimage component used when generating transaction signatures per the [transaction signing algorithm](/protocol/blockchain/transaction/transaction-signing).
|
||||||
|
|
||||||
|
| Field | Length | Format | [Signature Preimage](/protocol/blockchain/transaction/transaction-signing#preimage-format) Component | Description |
|
||||||
| -----------|:-----------:| ----------:|---------:|
|
| -----------|:-----------:| ----------:|---------:|
|
||||||
| 4 | tx-version | unsigned int | Copy of the transactions version field |
|
| tx version | 4 | unsigned integer <sup>[(LE)](/protocol/misc/endian/little)</sup> | #1 | Copy of the transactions version field |
|
||||||
| 4 | sequence | unsigned int | Copy of the sequence field of the input |
|
| sequence | 4 | unsigned integer <sup>[(LE)](/protocol/misc/endian/little)</sup> | #7 | Copy of the sequence field of the input |
|
||||||
| 4 | locktime | unsigned int | Copy of the transactions locktime field |
|
| locktime | 4 | unsigned integer <sup>[(LE)](/protocol/misc/endian/little)</sup> | #9 | Copy of the transactions locktime field |
|
||||||
| 32 | hash-prevoutputs | sha256 | Transaction hash of prevoutputs |
|
| hash prevoutputs | 32 | sha256 <sup>[(BE)](/protocol/misc/endian/big)</sup> | #2 | Transaction hash of prevoutputs |
|
||||||
| 32 | hash-sequence | sha256 | Transaction hash of sequences |
|
| hash sequence | 32 | sha256 <sup>[(BE)](/protocol/misc/endian/big)</sup> | #3 | Transaction hash of sequences |
|
||||||
| 32 | hash-outputs | sha256 | Transaction hash of outputs |
|
| hash outputs | 32 | sha256 <sup>[(BE)](/protocol/misc/endian/big)</sup> | #8 | Transaction hash of outputs |
|
||||||
| 1-9 | list-size | var-int | Number of items in the push-data list |
|
| push-data count | variable | [variable length integer](/protocol/formats/variable-length-integer) | | Number of push-data objects within in the push-data list |
|
||||||
| | push-data | byte-array | Raw byte-array of a push-data. For instance a signature |
|
| push-data | variable | bytes <sup>[(BE)](/protocol/misc/endian/big)</sup> | #10 | List of push-data objects |
|
||||||
|
|
||||||
|
### Push Data Format
|
||||||
|
|
||||||
|
The `push data` format is as follows.
|
||||||
|
Each item is a value pushed by the [unlocking script](/protocol/blockchain/transaction/unlocking-script).
|
||||||
|
|
||||||
|
| Field | Length | Format | Description |
|
||||||
|
| -----------|:-----------:| ----------:|---------:|
|
||||||
|
| byte count | variable | [variable length integer](/protocol/formats/variable-length-integer) | The number of bytes in this push-data object |
|
||||||
|
| bytes | variable | bytes <sup>[(BE)](/protocol/misc/endian/big)</sup> | The resulting bytes pushed by an [unlocking script](/protocol/blockchain/transaction/unlocking-script)'s push [operation](/protocol/blockchain/script#operation-codes-opcodes) (ex. signature data). |
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
|
|
||||||
It is required that nodes validate the proof before using it or forward it to other
|
It is required that nodes validate the proof before using it or forwarding it to other
|
||||||
nodes. Please check against the matching transaction in your mempool for
|
nodes.
|
||||||
addresses so you can limit sending the proof only to interested nodes that
|
Double spend proofs only apply to transactions within the [memory pool](/protocol/blockchain/memory-pool).
|
||||||
have registered a bloom filter.
|
Validated double spend proofs should be advertised (via [inventory message](/protocol/network/messages/inv)) to all connected peers.
|
||||||
|
If a peer has a bloom filter set, nodes should only relay double spend proofs that the [bloom filter](/protocol/spv/bloom-filter).
|
||||||
|
|
||||||
Validation includes a short list of requirements;
|
Validation includes a short list of requirements;
|
||||||
|
|
||||||
1. The DSP message is well-formed and contains all fields. It is allowed (by
|
1. The message is well-formed and contains all fields.
|
||||||
nature of Bitcoin Cash) for some hashes to be all-zeros.
|
It is allowed for some hashes to be all-zeros.
|
||||||
2. The two spenders are different, specifically the signature (push data)
|
2. The two `spenders` must be are different.
|
||||||
has to be different.
|
3. The first & double `spender`s are sorted via the following algorithm:
|
||||||
3. The first & double spenders are sorted with two hashes as keys.
|
|
||||||
Compare on the hash-outputs, and if those are equal, then compare on
|
3a. sort via the `hash-outputs` field of the `spender`.
|
||||||
hash-prevoutputs.
|
|
||||||
The sorting order is in numerically ascending order of the hash,
|
3b. if `hash-outputs` are equal, then compare on `hash-prevoutputs`.
|
||||||
interpreted as 256-bit little endian integers.
|
|
||||||
4. The double spent output is still available in the UTXO database,
|
The sorting order is in numerically ascending order of the hash, interpreted as 256-bit [little endian](/protocol/misc/endian/little) integers.
|
||||||
implying no spending transaction has been mined.
|
|
||||||
|
4. The double spent output is still available in the UTXO database, implying no spending transaction has been mined.
|
||||||
|
|
||||||
5. No other valid proof is known.
|
5. No other valid proof is known.
|
||||||
|
|
||||||
Further validation can be done by essentially validating the signature that
|
Further validation can be done by validating the signature that
|
||||||
was copied from the inputs of both transactions against the output a node
|
was copied from the inputs of both transactions against the (soon to be spent) previous transaction output.
|
||||||
should have in either its memory pool or its UTXO database.
|
|
||||||
|
|
||||||
To validate a spender of the proof, a node requires to have;
|
To validate a spender of the proof, a node is required to have;
|
||||||
|
|
||||||
* The output being spent (mempool or UTXO)
|
* The output being spent (mempool or UTXO)
|
||||||
* One of the transactions trying to spend the output.
|
* One of the transactions trying to spend the output.
|
||||||
* The double-spend-proof.
|
* The double-spend-proof.
|
||||||
|
|
||||||
As the forkid
|
As the forkid [specification](/protocol/blockchain/transaction/transaction-signing#preimage-format) details, the digest algorithm hashes 10 items in order to receive a sha256 hash, which is then signed.
|
||||||
[specification](/protocol/forks/replay-protected-sighash)
|
|
||||||
details, the digest algorithm hashes 10 items in order to receive a sha256
|
|
||||||
hash, which is then signed.
|
|
||||||
|
|
||||||
These 10 items are;
|
These 10 items are;
|
||||||
|
|
||||||
@@ -112,22 +109,17 @@ These 10 items are;
|
|||||||
9. nLocktime of the transaction (4-byte little endian)
|
9. nLocktime of the transaction (4-byte little endian)
|
||||||
10. sighash type of the signature (4-byte little endian)
|
10. sighash type of the signature (4-byte little endian)
|
||||||
|
|
||||||
In the double spend message we include items: 1, 2, 3, 4, 7, 8, 9 and 10.
|
The double spend message includes items: 1, 2, 3, 4, 7, 8, 9 and 10.
|
||||||
|
|
||||||
From the output we are trying to spend you can further obtain items: 5 & 6
|
Items 5 & 6 can be obtained from the output being spent.
|
||||||
|
|
||||||
The full transaction also spending the same output which you found in your
|
The transaction that first spent the output within the node's [memory pool](/protocol/blockchain/memory-pool), can be used to get the public key required to validate that the signature within the `push-data` field of the double spend proof is correct.
|
||||||
mempool, can be used to get the public key which you can use to validate
|
|
||||||
that the signature is actually correct.
|
|
||||||
|
|
||||||
When all rules are followed, the proof is valid.
|
When all rules are followed, the proof is valid.
|
||||||
|
|
||||||
## Limitation and risks
|
## Limitation and risks
|
||||||
|
|
||||||
Not all types and all combinations of transactions are supported. Wallets
|
Not all types and all combinations of transactions are supported.
|
||||||
and point-of-sale applications are suggested to give a rating of how secure
|
Wallets and point-of-sale applications are suggested to give a rating of how secure an unconfirmed transaction is based on various factors.
|
||||||
an unconfirmed transaction is based on various factors.
|
|
||||||
|
|
||||||
Transactions that spend all, confirmed, P2PKH outputs with all inputs
|
Transactions that spend all, confirmed, P2PKH outputs with all inputs signed `SIGHASH_ALL` without `ANYONECANPAY`, are double-spend-proof's "protected transactions".
|
||||||
signed SIGHASH\_ALL without ANYONECANPAY, are double-spend-proof's
|
|
||||||
"protected transactions".
|
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ The type of the object that is available.
|
|||||||
|
|
||||||
| Type | Value|
|
| Type | Value|
|
||||||
|------|------|
|
|------|------|
|
||||||
| 1 | Transaction |
|
| 0x0001 | Transaction |
|
||||||
| 2 | Block |
|
| 0x0002 | Block |
|
||||||
| 3 | Filtered Block (partial block with merkle proof)
|
| 0x0003 | Filtered Block (partial block with merkle proof)
|
||||||
| 4 | Compact block
|
| 0x0004 | Compact block
|
||||||
| 5 | Xthin block (Bitcoin Unlimited)
|
| 0x0005 | Xthin block (Bitcoin Unlimited)
|
||||||
| 6 | Graphene Block (Bitcoin Unlimited)
|
| 0x0006 | Graphene Block (Bitcoin Unlimited)
|
||||||
| 0x94a0 | [DSProof](/protocol/network/messages/dsproof-beta) |
|
| 0x94A0 | [Double Spend Proof](/protocol/network/messages/dsproof-beta) |
|
||||||
|
|
||||||
Implementations: [C++](https://github.com/BitcoinUnlimited/BitcoinUnlimited/blob/eb264e627e231f7219e60eef41b4e37cc52d6d9d/src/protocol.h#L477)
|
Implementations: [C++](https://github.com/BitcoinUnlimited/BitcoinUnlimited/blob/eb264e627e231f7219e60eef41b4e37cc52d6d9d/src/protocol.h#L477)
|
||||||
|
|||||||
Reference in New Issue
Block a user