From 41b4a4bd586445c415723a141788a808478e5868 Mon Sep 17 00:00:00 2001 From: Ludovic Lars Date: Tue, 25 Feb 2020 22:46:50 +0000 Subject: [PATCH 01/24] Added the remaining arithmetic and crypto opcodes - Added the remaining arithmetic and cryptography opcodes. - With Schnorr multisig support added in November 2019, OP_CHECKMULTISIG description may be too long. It coud be nice if it was moved somewhere else. - Added OP_REVERSEBYTES to the list of uncategorized opcodes. --- protocol/blockchain/script.md | 87 ++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/protocol/blockchain/script.md b/protocol/blockchain/script.md index 033a7a6..89ab568 100644 --- a/protocol/blockchain/script.md +++ b/protocol/blockchain/script.md @@ -124,21 +124,51 @@ Op codes marked with **(do not use)** are disallowed and will make a transaction ### Arithmetic -|Word |Value |Hex |Input |Output | Description | -|-----------|-------|----|--------------|--------|------------------------------------------------------------------| -|OP_DIV |150 |0x96|a b |out |*a* is divided by *b* | -|OP_MOD |151 |0x97|a b |out |return the remainder after *a* is divided by *b* | +|Word |Value |Hex |Input |Output | Description | +|---------------------|-------|----|--------------|-----------------|------------------------------------------------------| +|OP_1ADD | 139 |0x8b|in |out | 1 is added to the input. | +|OP_1SUB | 140 |0x8c|in |out | 1 is subtracted from the input. | +|OP_2MUL | 141 |0x8d|in |out | The input is multiplied by 2. **DISABLED** | +|OP_2DIV | 142 |0x8e|in |out | The input is divided by 2. **DISABLED** | +|OP_NEGATE | 143 |0x8f|in |out | The sign of the input is flipped. | +|OP_ABS | 144 |0x90|in |out | The input is made positive. | +|OP_NOT | 145 |0x91|in |true / false | If the input is 0 or 1, it is flipped. Otherwise the output will be 0. | +|OP_0NOTEQUAL | 146 |0x92|in |true / false | Returns 0 if the input is 0. 1 otherwise. | +|OP_ADD | 147 |0x93|a b |out | *a* is added to *b*. | +|OP_SUB | 148 |0x94|a b |out | *b* is subtracted from *a*. | +|OP_MUL | 149 |0x95|a b |out | *a* is multiplied by *b*. **DISABLED** | +|OP_DIV | 150 |0x96|a b |out | *a* is divided by *b*. | +|OP_MOD | 151 |0x97|a b |out | Returns the remainder after *a* is divided by *b*. | +|OP_LSHIFT | 152 |0x98|a b |out | Shifts *a* left *b* bits, preserving sign. **DISABLED** | +|OP_RSHIFT | 153 |0x99|a b |out | Shifts *a* right *b* bits, preserving sign. **DISABLED** | +|OP_BOOLAND | 154 |0x9a|a b |true / false | If both *a* and *b* are not 0, the output is 1. Otherwise 0. | +|OP_BOOLOR | 155 |0x9b|a b |true / false | If *a* or *b* is not 0, the output is 1. Otherwise 0.| +|OP_NUMEQUAL | 156 |0x9c|a b |true / false | Returns 1 if the numbers are equal, 0 otherwise. | +|OP_NUMEQUALVERIFY | 157 |0x9d|a b |Nothing / *fail* | Same as OP_NUMEQUAL, but runs OP_VERIFY afterward. | +|OP_NUMNOTEQUAL | 158 |0x9e|a b |true / false | Returns 1 if the numbers are not equal, 0 otherwise. | +|OP_LESSTHAN | 159 |0x9f|a b |true / false | Returns 1 if *a* is less than *b*, 0 otherwise. | +|OP_GREATERTHAN | 160 |0xa0|a b |true / false | Returns 1 if *a* is greater than *b*, 0 otherwise. | +|OP_LESSTHANOREQUAL | 161 |0xa1|a b |true / false | Returns 1 if *a* is less than or equal to *b*, 0 otherwise. | +|OP_GREATERTHANOREQUAL| 162 |0xa2|a b |true / false | Returns 1 if *a* is greater than or equal to *b*, 0 otherwise. | +|OP_MIN | 163 |0xa3|a b |out | Returns the smaller of a and b. | +|OP_MAX | 164 |0xa4|a b |out | Returns the larger of a and b. | +|OP_WITHIN | 165 |0xa5|x min max |true / false | Returns 1 if *x* is within the specified range (left-inclusive), 0 otherwise. | ### Cryptography -|Word |Value |Hex |Input |Output | Description | -|-----------------------|------|------|----------------|--------|------------------------------------------------------------------| -| OP_RIPEMD160 | | 0xa6 | in | hash | Hashes input with RIPEMD-160. -| OP_SHA1 | | 0xa7 | in | hash | Hashes input with SHA-1. -| OP_SHA256 | | 0xa8 | in | hash | Hashes input with SHA-256. -| OP_HASH160 | | 0xa9 | in | hash | Hashes input with SHA-256 and then with RIPEMD-160. -| OP_HASH256 | | 0xaa | in | hash | Hashes input twice with SHA-256. -| OP_CHECKDATASIG | 186 | 0xba | sig msg pubkey | true / false | Check if signature is valid for message and a public key. [See spec](/protocol/forks/op_checkdatasig) | +|Word |Value | Hex |Input |Output | Description | +|------------------------|------|------|----------------|---------|--------------------------------------------------------| +| OP_RIPEMD160 | 166 | 0xa6 | in | hash | Hashes input with RIPEMD-160. | +| OP_SHA1 | 167 | 0xa7 | in | hash | Hashes input with SHA-1. | +| OP_SHA256 | 168 | 0xa8 | in | hash | Hashes input with SHA-256. | +| OP_HASH160 | 169 | 0xa9 | in | hash | Hashes input with SHA-256 and then with RIPEMD-160. | +| OP_HASH256 | 170 | 0xaa | in | hash | Hashes input twice with SHA-256. | +| OP_CODESEPARATOR | 171 | 0xab | Nothing | Nothing | All of the signature checking words will only match signatures to the data after the most recently-executed OP_CODESEPARATOR. | +| OP_CHECKSIG | 172 | 0xac | sig pubkey | true / false | The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise. | +| OP_CHECKSIGVERIFY | 173 | 0xad | sig pubkey | Nothing / *fail* | Same as OP_CHECKSIG, but OP_VERIFY is executed afterward. | +| OP_CHECKMULTISIG | 174 | 0xae | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | true / false | **For an ECDSA multisig scheme** (*dummy* = 0): Compares the first signature against each public key until it finds an ECDSA match. Starting with the subsequent public key, it compares the second signature against each remaining public key until it finds an ECDSA match. The process is repeated until all signatures have been checked or not enough public keys remain to produce a successful result. All signatures need to match a public key. Because public keys are not checked again if they fail any signature comparison, signatures must be placed in the scriptSig using the same order as their corresponding public keys were placed in the scriptPubKey or redeemScript. If all signatures are valid, 1 is returned, 0 otherwise. The *dummy* element is removed from the stack. **For a Schnorr multisig scheme** (*dummy* > 0): [see spec](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-11-15-schnorrmultisig.md) (TODO) | +| OP_CHECKMULTISIGVERIFY | 175 | 0xaf | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | Nothing / *fail* | Same as OP_CHECKMULTISIG, but OP_VERIFY is executed afterward. | +| OP_CHECKDATASIG | 186 | 0xba | sig msg pubkey | true / false | Check if signature is valid for message and a public key. [See spec](/protocol/forks/op_checkdatasig) | | OP_CHECKDATASIGVERIFY | 187 | 0xbb | sig msg pubkey | nothing / *fail* | Same as OP_CHECKDATASIG, but runs OP_VERIFY afterward. | ### Locktime @@ -167,37 +197,8 @@ Please help improve this article by catigorizing and describing the following up | 0x66 | OP_VERNOTIF **(do not use)** | | 0x89 | OP_RESERVED1 **(do not use)** | | 0x8A | OP_RESERVED2 **(do not use)** | -| 0x8B | OP_1ADD | -| 0x8C | OP_1SUB | -| 0x8D | OP_2MUL | -| 0x8E | OP_2DIV | -| 0x8F | OP_NEGATE | -| 0x90 | OP_ABS | -| 0x91 | OP_NOT | -| 0x92 | OP_0NOTEQUAL | -| 0x93 | OP_ADD | -| 0x94 | OP_SUB | -| 0x95 | OP_MUL | -| 0x98 | OP_LSHIFT | -| 0x99 | OP_RSHIFT | -| 0x9A | OP_BOOLAND | -| 0x9B | OP_BOOLOR | -| 0x9C | OP_NUMEQUAL | -| 0x9D | OP_NUMEQUALVERIFY | -| 0x9E | OP_NUMNOTEQUAL | -| 0x9F | OP_LESSTHAN | -| 0xA0 | OP_GREATERTHAN | -| 0xA1 | OP_LESSTHANOREQUAL | -| 0xA2 | OP_GREATERTHANOREQUAL | -| 0xA3 | OP_MIN | -| 0xA4 | OP_MAX | -| 0xA5 | OP_WITHIN | -| 0xAB | OP_CODESEPARATOR | -| 0xAC | OP_CHECKSIG | -| 0xAD | OP_CHECKSIGVERIFY | -| 0xAE | OP_CHECKMULTISIG | -| 0xAF | OP_CHECKMULTISIGVERIFY | -| 0xBC - 0xFF | Unused **(disabled)** | +| 0xBC | OP_REVERSEBYTES **(disabled)** | +| 0xBD - 0xFF | Unused **(disabled)** | ### Node-Specific Behavior From 8ecdbb731d2dc4cbfa72087dd58ac6654a53c67e Mon Sep 17 00:00:00 2001 From: lugaxker Date: Mon, 2 Mar 2020 11:42:05 +0100 Subject: [PATCH 02/24] Create the Multisignature section, and describe how OP_CHECKMULTISIG and OP_CHECKMULTISIGVERIFY opcodes work. --- home.md | 2 +- .../blockchain/cryptography/multisignature.md | 84 +++++++++++++++++++ 2 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 protocol/blockchain/cryptography/multisignature.md diff --git a/home.md b/home.md index 76c377f..0a47a46 100644 --- a/home.md +++ b/home.md @@ -28,7 +28,7 @@ Pay To Public Key (P2PK) — Pay To Public Key Hash (P2PKH) — Pay To Script Hash (P2SH) — Base 58 encoding (legacy) — Cashaddr encoding ### Cryptography -Secp256k1 — Public Key — Private Key — ECDSA signatures — Schnorr signatures — N-of-M multisig signatures +Secp256k1 — Public Key — Private Key — ECDSA signatures — Schnorr signatures — [Multisignature (M-of-N multisig)](/protocol/cryptography/multisignature) ### Network upgrades [Bip-16](/protocol/forks/bip-0016) — [Bip-34](/protocol/forks/bip-0034) — [Bip-37](/protocol/forks/bip-0037) — [Bip-64](/protocol/forks/bip-0064) — [Bip-65](/protocol/forks/bip-0065) — [Bip-66](/protocol/forks/bip-0066) — [Bip-68](/protocol/forks/bip-0068) — [Bip-112](/protocol/forks/bip-0112) — [Bip-113](/protocol/forks/bip-0113) — [Bip-157](/protocol/forks/bip-0157) — [Bip-158](/protocol/forks/bip-0158) — [Bip-159](/protocol/forks/bip-0159) — BCH-UAHF (BUIP-55) — [HF-20171113](/protocol/forks/hf-20171113) — HF-20180515 — HF-20181115 — HF-20190515 — HF-20191115 diff --git a/protocol/blockchain/cryptography/multisignature.md b/protocol/blockchain/cryptography/multisignature.md new file mode 100644 index 0000000..c96bab3 --- /dev/null +++ b/protocol/blockchain/cryptography/multisignature.md @@ -0,0 +1,84 @@ +# Multisignature + +Multisignature (often called "multisig") refers to requiring multiple keys to spend funds in a Bitcoin Cash transaction, rather than a single signature from one key. It has a number of applications and allows users to divide up responsibility for possession of coins. + +Multisignature scripts set a condition where N public keys are recorded in the script and at least M of those must provide signatures to unlock the funds. This is also known as *M-of-N multisignature scheme*, where N is the total number of keys and M is the threshold of signatures required for validation. The signatures used can either be ECDSA signatures or Schnorr signatures. + +## Public multisignature: OP_CHECKMULTISIG(VERIFY) + +Multisig schemes can be built with the opcodes `OP_CHECKMULTISIG` and `OP_CHECKMULTISIGVERIFY`, two opcodes of the Bitcoin Cash [scripting language](/protocol/blockchain/script). `OP_CHECKMULTISIGVERIFY` has the same implementation as `OP_CHECKMULTISIG`, except OP_VERIFY is executed afterward. + +The opcode `OP_CHECKMULTISIG` can be included in all sorts of scripts. The minimal [locking script](https://reference.cash/protocol/blockchain/transaction/locking-script) using `OP_CHECKMULTISIG` is: + +``` +M ... N CHECKMULTISIG +``` + +This script creates a P2MS (raw multisig) output. It can also be used as a *redeem script* for a P2SH output. + +The [unlocking script](/protocol/blockchain/transaction/unlocking-script) corresponding to the previous locking script is: + +``` + ... +``` + +Upon script execution, this will act like: + +``` + ... M ... N CHECKMULTISIG +``` + +Due to a historical bug (the original implementation of `OP_CHECKMULTISIG` consumed `M+N+3` items on the stack instead of `M+N+2`), an extra unusued value called the `dummy` element was included in the script. This was usually done via `OP_0`. Since the [HF-2019115](/protocol/forks/hf-20191115) Bitcoin Cash upgrade, this element has been repurposed as a trigerring and execution mechanism. + +In particular, the value of the `dummy` element determines whether ECDSA or Schnorr signatures have to be used. If `dummy` is `0` (i.e., an empty byte array), then all signatures must be produced by ECDSA. If `dummy` is not `0`, then all signatures must be produced by the Schnorr algorithm and the `dummy` element is interpreted as a bitfield called `checkbits`. + +Upon `OP_CHECKMULTISIG` execution, the ECDSA mode (`dummy = 0`) is: + +* The first signature is checked against each public key until a match is found. +* Starting with the subsequent public key, the second signature is checked against each remaining public key until a match is found. +* The process is repeated until all signatures have been checked or not enough public keys remain to produce a successful result. +* All signatures need to match a public key, otherwise `false` is returned. + +The Schnorr mode (`dummy = checkbits > 0`) operates similarly, but only checks signatures as requested, according to the `checkbits` field: + +* If the least significant bit of `checkbits` is set, then the first signature is checked against the first public key. +* If it is not but if the second least significant bit is set, then the first signature is checked against the second public key. +* Once the first signature has been checked against a matching public key, `checkbits` is bit-shifted to the right (`checkbits := checkbits >> 1`). +* The process is repeated until all signatures have been checked or not enough public keys remain to produce a successful result. +* All signatures need to match a public key, otherwise `false` is returned. +* If the final `checkbits` value is non-zero, then `false` is returned. + +Because public keys are not checked again if they fail any signature comparison (in both cases), signatures must be placed in the unlocking script using the same order as their corresponding public keys were placed in the locking script (P2MS) or redeem script (P2SH). + +Note that the `checkbits` element is encoded as a byte array of length `floor((N + 7)/8)` (the shortest byte array that can hold N bits) and must have exactly M bits set to ensure that all signatures are checked against public keys. + +To know more about the Schnorr mode, see the [official specification](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-11-15-schnorrmultisig.md). + +### Example + +The most commonly used scheme is the 2-of-3 multisig scheme: + +``` +2 3 CHECKMULTISIG +``` + +where 2 out of 3 participants (Alice, Bob and Carol) can sign a transaction from the shared account. + +Let's say Alice and Carol want to spend funds. If they want to use ECDSA, they have to sign the transaction with this algorithm and build the following script: + +``` +0 +``` + +If they want to use Schnorr, they have to sign the transaction with this algorithm and build the following script: + +``` +5 +``` + +The value of the `dummy` element is 5, whose binary representation is `0b101`. This ensures that Alice's signature (`sigA`) is checked against her public key (`pubkeyA`), that Carol's signature (`sigC`) is not checked against Bob's public key (`pubkeyB`) but against her public key (`pubkeyC`). + +## Private multisignature + +Multisig schemes can also be implemented in P2PKH outputs, using Schnorr agregation property. + From 4dd9f319b74477a4be49b1ea29de62cfc6b01528 Mon Sep 17 00:00:00 2001 From: lugaxker Date: Mon, 2 Mar 2020 11:43:36 +0100 Subject: [PATCH 03/24] Remove the detailed description of OP_CHECKMULTISIG and add a link to the Multisignature section. --- protocol/blockchain/script.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/blockchain/script.md b/protocol/blockchain/script.md index 89ab568..8b605dc 100644 --- a/protocol/blockchain/script.md +++ b/protocol/blockchain/script.md @@ -166,7 +166,7 @@ Op codes marked with **(do not use)** are disallowed and will make a transaction | OP_CODESEPARATOR | 171 | 0xab | Nothing | Nothing | All of the signature checking words will only match signatures to the data after the most recently-executed OP_CODESEPARATOR. | | OP_CHECKSIG | 172 | 0xac | sig pubkey | true / false | The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise. | | OP_CHECKSIGVERIFY | 173 | 0xad | sig pubkey | Nothing / *fail* | Same as OP_CHECKSIG, but OP_VERIFY is executed afterward. | -| OP_CHECKMULTISIG | 174 | 0xae | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | true / false | **For an ECDSA multisig scheme** (*dummy* = 0): Compares the first signature against each public key until it finds an ECDSA match. Starting with the subsequent public key, it compares the second signature against each remaining public key until it finds an ECDSA match. The process is repeated until all signatures have been checked or not enough public keys remain to produce a successful result. All signatures need to match a public key. Because public keys are not checked again if they fail any signature comparison, signatures must be placed in the scriptSig using the same order as their corresponding public keys were placed in the scriptPubKey or redeemScript. If all signatures are valid, 1 is returned, 0 otherwise. The *dummy* element is removed from the stack. **For a Schnorr multisig scheme** (*dummy* > 0): [see spec](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-11-15-schnorrmultisig.md) (TODO) | +| OP_CHECKMULTISIG | 174 | 0xae | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | true / false | Signatures are checked against public keys. Signatures must be placed in the unlocking script using the same order as their corresponding public keys were placed in the locking script or redeem script. If all signatures are valid, 1 is returned, 0 otherwise. All elements are removed from the stack. For more information on the execution of this opcode, see [Multisignature](/protocol/blockchain/cryptography/multisignature). | | OP_CHECKMULTISIGVERIFY | 175 | 0xaf | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | Nothing / *fail* | Same as OP_CHECKMULTISIG, but OP_VERIFY is executed afterward. | | OP_CHECKDATASIG | 186 | 0xba | sig msg pubkey | true / false | Check if signature is valid for message and a public key. [See spec](/protocol/forks/op_checkdatasig) | | OP_CHECKDATASIGVERIFY | 187 | 0xbb | sig msg pubkey | nothing / *fail* | Same as OP_CHECKDATASIG, but runs OP_VERIFY afterward. | From e025b29e5ee2e08c5973620c4c3bfeb6dd1934ea Mon Sep 17 00:00:00 2001 From: dagurval Date: Tue, 3 Mar 2020 14:18:33 +0100 Subject: [PATCH 04/24] Update home.md Fix URL --- home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/home.md b/home.md index 0a47a46..00e64ed 100644 --- a/home.md +++ b/home.md @@ -28,7 +28,7 @@ Pay To Public Key (P2PK) — Pay To Public Key Hash (P2PKH) — Pay To Script Hash (P2SH) — Base 58 encoding (legacy) — Cashaddr encoding ### Cryptography -Secp256k1 — Public Key — Private Key — ECDSA signatures — Schnorr signatures — [Multisignature (M-of-N multisig)](/protocol/cryptography/multisignature) +Secp256k1 — Public Key — Private Key — ECDSA signatures — Schnorr signatures — [Multisignature (M-of-N multisig)](/protocol/blockchain/cryptography/multisignature.md) ### Network upgrades [Bip-16](/protocol/forks/bip-0016) — [Bip-34](/protocol/forks/bip-0034) — [Bip-37](/protocol/forks/bip-0037) — [Bip-64](/protocol/forks/bip-0064) — [Bip-65](/protocol/forks/bip-0065) — [Bip-66](/protocol/forks/bip-0066) — [Bip-68](/protocol/forks/bip-0068) — [Bip-112](/protocol/forks/bip-0112) — [Bip-113](/protocol/forks/bip-0113) — [Bip-157](/protocol/forks/bip-0157) — [Bip-158](/protocol/forks/bip-0158) — [Bip-159](/protocol/forks/bip-0159) — BCH-UAHF (BUIP-55) — [HF-20171113](/protocol/forks/hf-20171113) — HF-20180515 — HF-20181115 — HF-20190515 — HF-20191115 From eb358ea9e9fe5590ee4b8879aa8b59340f9951e0 Mon Sep 17 00:00:00 2001 From: dagurval Date: Tue, 3 Mar 2020 14:20:19 +0100 Subject: [PATCH 05/24] Update multisignature.md Nits from #19 --- protocol/blockchain/cryptography/multisignature.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/blockchain/cryptography/multisignature.md b/protocol/blockchain/cryptography/multisignature.md index c96bab3..0533a9d 100644 --- a/protocol/blockchain/cryptography/multisignature.md +++ b/protocol/blockchain/cryptography/multisignature.md @@ -8,7 +8,7 @@ Multisignature scripts set a condition where N public keys are recorded in the s Multisig schemes can be built with the opcodes `OP_CHECKMULTISIG` and `OP_CHECKMULTISIGVERIFY`, two opcodes of the Bitcoin Cash [scripting language](/protocol/blockchain/script). `OP_CHECKMULTISIGVERIFY` has the same implementation as `OP_CHECKMULTISIG`, except OP_VERIFY is executed afterward. -The opcode `OP_CHECKMULTISIG` can be included in all sorts of scripts. The minimal [locking script](https://reference.cash/protocol/blockchain/transaction/locking-script) using `OP_CHECKMULTISIG` is: +The opcode `OP_CHECKMULTISIG` can be included in all sorts of scripts. The minimal [locking script](/protocol/blockchain/transaction/locking-script.md) using `OP_CHECKMULTISIG` is: ``` M ... N CHECKMULTISIG @@ -52,7 +52,7 @@ Because public keys are not checked again if they fail any signature comparison Note that the `checkbits` element is encoded as a byte array of length `floor((N + 7)/8)` (the shortest byte array that can hold N bits) and must have exactly M bits set to ensure that all signatures are checked against public keys. -To know more about the Schnorr mode, see the [official specification](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-11-15-schnorrmultisig.md). +To know more about the Schnorr mode, see the [specification](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/2019-11-15-schnorrmultisig.md). ### Example From 0267139ddc4a2d68e99aefeaea8c3ec3915dfbc6 Mon Sep 17 00:00:00 2001 From: Tobias Date: Wed, 11 Mar 2020 01:45:50 +0100 Subject: [PATCH 06/24] =?UTF-8?q?Updated=20OP=5FCODESEPARATOR=20and=20OP?= =?UTF-8?q?=5FCHECKSIG=20to=20BCH=E2=80=98s=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OP_CODESEPARATOR and OP_CHECKSIG‘s descriptions were based on pre-BCH rules and have been updated to the current BCH rules --- protocol/blockchain/script.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/blockchain/script.md b/protocol/blockchain/script.md index 8b605dc..56396ba 100644 --- a/protocol/blockchain/script.md +++ b/protocol/blockchain/script.md @@ -163,8 +163,8 @@ Op codes marked with **(do not use)** are disallowed and will make a transaction | OP_SHA256 | 168 | 0xa8 | in | hash | Hashes input with SHA-256. | | OP_HASH160 | 169 | 0xa9 | in | hash | Hashes input with SHA-256 and then with RIPEMD-160. | | OP_HASH256 | 170 | 0xaa | in | hash | Hashes input twice with SHA-256. | -| OP_CODESEPARATOR | 171 | 0xab | Nothing | Nothing | All of the signature checking words will only match signatures to the data after the most recently-executed OP_CODESEPARATOR. | -| OP_CHECKSIG | 172 | 0xac | sig pubkey | true / false | The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise. | +| OP_CODESEPARATOR | 171 | 0xab | Nothing | Nothing | Makes `OP_CHECK(MULTI)SIG(VERIFY)` set `scriptCode` to everything after the most recently-executed OP_CODESEPARATOR when computing the sighash. | +| OP_CHECKSIG | 172 | 0xac | sig pubkey | true / false | The last byte (=sighash type) of the signature is removed. The sighash for this input is calculated based on the sighash type. The truncated signature used by OP_CHECKSIG must be a valid ECDSA or Schnorr signature for this hash and public key. If it is valid, 1 is returned, if it is empty, 0 is returned, otherwise the operation fails. | | OP_CHECKSIGVERIFY | 173 | 0xad | sig pubkey | Nothing / *fail* | Same as OP_CHECKSIG, but OP_VERIFY is executed afterward. | | OP_CHECKMULTISIG | 174 | 0xae | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | true / false | Signatures are checked against public keys. Signatures must be placed in the unlocking script using the same order as their corresponding public keys were placed in the locking script or redeem script. If all signatures are valid, 1 is returned, 0 otherwise. All elements are removed from the stack. For more information on the execution of this opcode, see [Multisignature](/protocol/blockchain/cryptography/multisignature). | | OP_CHECKMULTISIGVERIFY | 175 | 0xaf | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | Nothing / *fail* | Same as OP_CHECKMULTISIG, but OP_VERIFY is executed afterward. | From a358b3ca1d3ebbcbc78478e75031fa1dc60b6278 Mon Sep 17 00:00:00 2001 From: dagurval Date: Wed, 11 Mar 2020 10:41:36 +0100 Subject: [PATCH 07/24] =?UTF-8?q?[nit]=C2=A0Reword=20OP=5FCODESEPARATOR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As per discussion: https://github.com/BitcoinUnlimited/BitcoinCashSpecification/pull/20#discussion_r390840926 --- protocol/blockchain/script.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/blockchain/script.md b/protocol/blockchain/script.md index 56396ba..3fcfab0 100644 --- a/protocol/blockchain/script.md +++ b/protocol/blockchain/script.md @@ -163,7 +163,7 @@ Op codes marked with **(do not use)** are disallowed and will make a transaction | OP_SHA256 | 168 | 0xa8 | in | hash | Hashes input with SHA-256. | | OP_HASH160 | 169 | 0xa9 | in | hash | Hashes input with SHA-256 and then with RIPEMD-160. | | OP_HASH256 | 170 | 0xaa | in | hash | Hashes input twice with SHA-256. | -| OP_CODESEPARATOR | 171 | 0xab | Nothing | Nothing | Makes `OP_CHECK(MULTI)SIG(VERIFY)` set `scriptCode` to everything after the most recently-executed OP_CODESEPARATOR when computing the sighash. | +| OP_CODESEPARATOR | 171 | 0xab | Nothing | Nothing | Makes `OP_CHECK(MULTI)SIG(VERIFY)` use the subset of the script of everything after the most recently-executed OP_CODESEPARATOR when computing the sighash. | | OP_CHECKSIG | 172 | 0xac | sig pubkey | true / false | The last byte (=sighash type) of the signature is removed. The sighash for this input is calculated based on the sighash type. The truncated signature used by OP_CHECKSIG must be a valid ECDSA or Schnorr signature for this hash and public key. If it is valid, 1 is returned, if it is empty, 0 is returned, otherwise the operation fails. | | OP_CHECKSIGVERIFY | 173 | 0xad | sig pubkey | Nothing / *fail* | Same as OP_CHECKSIG, but OP_VERIFY is executed afterward. | | OP_CHECKMULTISIG | 174 | 0xae | dummy sig1 sig2 ... <# of sigs> pub1 pub2 ... <# of pubkeys> | true / false | Signatures are checked against public keys. Signatures must be placed in the unlocking script using the same order as their corresponding public keys were placed in the locking script or redeem script. If all signatures are valid, 1 is returned, 0 otherwise. All elements are removed from the stack. For more information on the execution of this opcode, see [Multisignature](/protocol/blockchain/cryptography/multisignature). | From 6f3ec7356e1160a7512c68ca2d0c4ae3260f8b84 Mon Sep 17 00:00:00 2001 From: lugaxker Date: Thu, 12 Mar 2020 00:35:35 +0100 Subject: [PATCH 08/24] Create the Base58Check encoding section. --- protocol/blockchain/encoding/base58check.md | 176 ++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 protocol/blockchain/encoding/base58check.md diff --git a/protocol/blockchain/encoding/base58check.md b/protocol/blockchain/encoding/base58check.md new file mode 100644 index 0000000..37c1be8 --- /dev/null +++ b/protocol/blockchain/encoding/base58check.md @@ -0,0 +1,176 @@ +# Base58check encoding + +In Bitcoin Cash, an encoding used for keys and addresses is **Base58Check**. This is a Base58 encoding format that unambiguously encodes the type of data in the first few characters (the *version*) and includes an error detection code in the last few characters (the *checksum*). Its goal is to make it easier to copy and to share information, by using a QR code for instance. + +To encode a Bitcoin Cash address, it is however recommended to use the CashAddr encoding instead, because it prevents confusion with Bitcoin-BTC addresses. + +## Base58 + +Base58's goal is to avoid copy error and enable doublecliking selection. That is why it uses all the alphanumeric symbols excluding `0`, `O`, `I` and `l`, these last characters being hard to ditinguish from one another in some fonts. + +Base58 alphabet: + +``` +123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz +``` + +Base58 symbol chart: + +| Value | Character | Value | Character | Value | Character | Value | Character | +| ----- | --------- | ------| --------- | ------| --------- | ------| --------- | +| 0 | 1 | 15 | G | 30 | X | 45 | n | +| 1 | 2 | 16 | H | 31 | Y | 46 | o | +| 2 | 3 | 17 | J | 32 | Z | 47 | p | +| 3 | 4 | 18 | K | 33 | a | 48 | q | +| 4 | 5 | 19 | L | 34 | b | 49 | r | +| 5 | 6 | 20 | M | 35 | c | 50 | s | +| 6 | 7 | 21 | N | 36 | d | 51 | t | +| 7 | 8 | 22 | P | 37 | e | 52 | u | +| 8 | 9 | 23 | Q | 38 | f | 53 | v | +| 9 | A | 24 | R | 39 | g | 54 | w | +| 10 | B | 25 | S | 40 | h | 55 | x | +| 11 | C | 26 | T | 41 | i | 56 | y | +| 12 | D | 27 | U | 42 | j | 57 | z | +| 13 | E | 28 | V | 43 | k | +| 14 | F | 29 | W | 44 | m | + + +## Version bytes + +In the Base58Check encoding, the version byte indicates the type of the data encoded. The mainnet version bytes are: + +| Type | Hex value | Decimal value | Base58 prefix | +| ---------------------------- | ---------- | --------------| ------------- | +| P2PKH address | 0x00 | 0 | 1 | +| P2SH address | 0x05 | 5 | 3 | +| Private key (WIF) | 0x80 | 128 | 5 | +| Private key (WIF-compressed) | 0x80 | 128 | K or L | +| Extended private key | 0x0488ade4 | 76066276 | xpub | +| Extended public key | 0x0488b21e | 76067358 | xprv | + +The testnet version bytes are: + +| Type | Hex value | Decimal value | Base58 prefix | +| ------------------------------------ | ---------- | --------------| ------------- | +| Testnet P2PKH address | 0x6f | 111 | m or n | +| Testnet P2SH address | 0xc4 | 196 | 2 | +| Testnet private key (WIF) | 0xef | 239 | 9 | +| Testnet private key (WIF-compressed) | 0xef | 239 | c | +| Testnet extended private key | 0x043587cf | 70617039 | tpub | +| Testnet extended public key | 0x04358394 | 70615956 | tprv | + +## Encoding + +Base58Check is used to encode a `payload` and a `version` byte. It is done by following the steps described below. + +1. Take the `version` byte and the `payload` bytes, and concatenate them together (bytewise): + + ``` + version || payload + ``` + +2. Compute the `checksum` by taking the first four bytes of the double SHA256 hash function of this concatenation. + + ``` + checksum = SHA256( SHA256( version || payload ) )[:4] + ``` + +3. Concatenate all three of them together: + + ``` + version || payload || checksum + ``` + +4. Encode the result with Base58. Note that each leading zero bytes are encoded with the character `1` which is added to the string. + + ``` + Base58( version || payload || checksum ) + ``` + +## Encoding a private key (Wallet Import Format) + +Private keys in Bitcoin Cash are usually encoded with Base58Check. This is known as *Wallet Import Format* (WIF). + +Steps to encode a private key: + +1. Take a private key, i.e., a number between 0 and the order of the generator point (G) of secp256k1. Let's consider the following private key (32-byte array): + + ``` + 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd + ``` + +2. Take the `version` byte corresponding to it (`0x80` for mainnet, `0xef` for testnet), and concatenate them together: + + ``` + 801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd + ``` + +3. Compute the checksum by performing the double SHA256 on it, and by taking the first four bytes of this hash: + + ``` + SHA256( SHA256( 801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd ) ) = **c47e83ff**afda3ba4396e1bc6a648515e5fc9aa95910af6a4429537b87fb7b474 + ``` + +4. Concatenate the result from step 2 and the checksum together: + + ``` + 801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aeddc47e83ff + ``` + +5. Encode it with Base58. The result is the Wallet Import Format, or WIF, of the private key. If it is a mainnet (uncompressed) private key, it will always start with a `5`. + + ``` + 5J3mBbAH58CpQ3Y5RNJpUKPE62SQ5tfcvU2JpbnkeyhfsYB1Jcn + ``` + +If you want to derive a compressed public key from this private key, which is usually done in every modern wallets, simply add the prefix `0x01` to the private key bytes: + +``` +1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd01 +``` + +and follow the steps (2-5) described above, to get the encoded private key: + +``` +KxFC1jmwwCoACiCAWZ3eXa96mBM6tb3TYzGmf6YwgdGWZgawvrtJ +``` + +It is known as the WIF-compressed format. Even if the private key is not compressed, the wallet will take this encoding into account and will derive a compressed public key from it. Note that WIF-compressed private keys always start with a `K` or a `L`. + +## Encoding a Bitcoin Cash address + +Addresses in Bitcoin Cash can sometimes be encoded with Base58Check. These encoded addresses are called *legacy address*. Even if this format is still supported by various wallets, it is strongly recommended to use CashAddr encoding instead. + +Steps to encode a legacy address: + +1. Take an address payload, i.e., the hash of a public key (P2PKH) or a redeem script (P2SH) which is a 20-byte array: + + ``` + 211b74ca4686f81efda5641767fc84ef16dafe0b + ``` + +2. Take the corresponding `version` byte (`0x00` for mainnet P2PKH, `0x05` for mainnet P2SH, `0x6f` for testnet P2PKH, `0xc4` for testnet P2SH), and concatenate them together. In our case, this is a mainnet P2PKH address: + + ``` + 00211b74ca4686f81efda5641767fc84ef16dafe0b + ``` + +3. Compute the checksum by performing the double SHA256 on it, and by taking the first four bytes of this hash: + + ``` + SHA256( SHA256( 00211b74ca4686f81efda5641767fc84ef16dafe0b ) ) = **388c8d1d**3f70ec351abf400fadf7756418e6b3835c01fe78206b39ec1ab8a37a + ``` + +4. Concatenate the result from step 2 and the checksum together: + + ``` + 00211b74ca4686f81efda5641767fc84ef16dafe0b388c8d1d + ``` + +5. Encode it with Base58. Note that each leading zero byte must be encoded with the prefix `1` which is appended to the beginning of the string. Thus, if it is a mainnet P2PKH legacy address (`0x00` version byte), it will always start with a `1`. + + ``` + 1424C2F4bC9JidNjjTUZCbUxv6Sa1Mt62x + ``` + +**Important notice.** Please do not use this encoding for P2SH address. It can (and should) be deactivated by wallets in order to prevent to send funds to P2SH-embedded SegWit addresses, which are not supported by the Bitcoin Cash protocol. From 2725d00cf0e4bc9b1496abe584534ceb2c45c003 Mon Sep 17 00:00:00 2001 From: lugaxker Date: Thu, 12 Mar 2020 00:39:08 +0100 Subject: [PATCH 09/24] Add a link to the Base58Check section. --- home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/home.md b/home.md index 00e64ed..de273f8 100644 --- a/home.md +++ b/home.md @@ -25,7 +25,7 @@ [Proof of Work](/protocol/blockchain/proof-of-work) — [Difficulty Adjustment Algorithm](/protocol/blockchain/proof-of-work/difficulty-adjustment-algorithm) — [Mining](/protocol/blockchain/proof-of-work/mining) — Stratum Protocol — Mining Pools ### Addresses -Pay To Public Key (P2PK) — Pay To Public Key Hash (P2PKH) — Pay To Script Hash (P2SH) — Base 58 encoding (legacy) — Cashaddr encoding +Pay To Public Key (P2PK) — Pay To Public Key Hash (P2PKH) — Pay To Script Hash (P2SH) — [Base58Check encoding (legacy)](/protocol/blockchain/encoding/base58check) — Cashaddr encoding ### Cryptography Secp256k1 — Public Key — Private Key — ECDSA signatures — Schnorr signatures — [Multisignature (M-of-N multisig)](/protocol/blockchain/cryptography/multisignature.md) From 399c71fa685368dcf0d889d3ae3feaf1cc69b4b0 Mon Sep 17 00:00:00 2001 From: lugaxker Date: Fri, 27 Mar 2020 21:52:14 +0100 Subject: [PATCH 10/24] Create the CashAddr encoding section. --- protocol/blockchain/encoding/cashaddr.md | 201 +++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 protocol/blockchain/encoding/cashaddr.md diff --git a/protocol/blockchain/encoding/cashaddr.md b/protocol/blockchain/encoding/cashaddr.md new file mode 100644 index 0000000..52bcfb5 --- /dev/null +++ b/protocol/blockchain/encoding/cashaddr.md @@ -0,0 +1,201 @@ +# CashAddr encoding + +CashAddr encoding is an address format used in Bitcoin Cash. This is a Base32 encoding format that prevents confusion with [Base58Check](/protocol/blockchain/encoding/base58check) legacy address encoding also used by Bitcoin-BTC. The goal of the encoding is to make it easier to copy and to share information, by using a QR code for instance. + +A Cash Address consists of: + +- A **prefix** which is human-readable. +- A **separator** (`:`). +- A Base32 **payload** which contains a version byte and the data (or hash). +- A Base32 **checksum**. + +This format reuses the work done for Bech32 (see [BIP173](https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki)) and is similar in some aspects, but improves on others. See the [original specification](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md) for more details. + +## Prefix + +The prefix is a human-readable part of the address which indicates the network on which the addess is valid. It can only contain ASCII characters. The 3 prefixes used in Bitcoin Cash are: + +| Network | Prefix | +| ------- | ------------- | +| Mainnet | `bitcoincash` | +| Testnet | `bchtest` | +| Regtest | `bchreg` | + +The prefix is always followed by the separator `:`. + +When presented to users, the prefix and the separator may be omitted as it is part of the checksum computation. + +## Base32 + +CashAddr uses Base32 to encode information. The symbols used in CashAddr Base32 are the lowercase alphanumeric characters excluding `1`, `b`, `i`, and `o`. + +Base32 alphabet: + +``` +qpzry9x8gf2tvdw0s3jn54khce6mua7l +``` + +Base32 symbol chart: + +| Value | Character | Value | Character | +| ----- | --------- | ------| --------- | +| 0 | q | 16 | s | +| 1 | p | 17 | 3 | +| 2 | z | 18 | j | +| 3 | r | 19 | n | +| 4 | y | 20 | 5 | +| 5 | 9 | 21 | 4 | +| 6 | x | 22 | k | +| 7 | 8 | 23 | h | +| 8 | g | 24 | c | +| 9 | f | 25 | e | +| 10 | 2 | 26 | 6 | +| 11 | t | 27 | m | +| 12 | v | 28 | u | +| 13 | d | 29 | a | +| 14 | w | 30 | 7 | +| 15 | 0 | 31 | l | + +## Version bytes + +The version byte is divided into 3 parts: + +- The most significant bit is reserved and must be `0`. + +- The 4 next bits indicate the type of address: `0b000` for P2PKH, and `0b001` for P2SH. + +- The last 3 bits indicate the size of the data. This ensures that it is possible to check that the length of the address is correct. The size options are: + + | Size bits | Data size (bytes) | + | --------- | ----------------- | + | 0b000 | 20 | + | 0b001 | 24 | + | 0b010 | 28 | + | 0b011 | 32 | + | 0b100 | 40 | + | 0b101 | 48 | + | 0b110 | 56 | + | 0b111 | 64 | + +For a legacy 20-byte (160-bit) hash, the follwoing version bytes are currently allowed: + +| Type | Type bits | Version byte | Address prefix | +| ------------- | ---------- | -------------| -------------- | +| P2PKH address | 0b0000 | 0 | q | +| P2SH address | 0b0001 | 5 | p | + +Note that further types will be added as new features are added. + +## Checksum + +The checksum is a 40 bits [BCH code](https://en.wikipedia.org/wiki/BCH_code) defined over the finite field GF(2^5). It ensures the detection of up to 6 errors in the address and 8 in a row. Combined with the length check, this provides very strong guarantee against errors. + +The checksum is computed by the following `polymod` function (written in Python): + +```python +def polymod(values): + c = 1 + for d in values: + c0 = c >> 35 + c = ((c & 0x07ffffffff) << 5) ^ d + if (c0 & 0x01): + c ^= 0x98f2bc8e61 + if (c0 & 0x02): + c ^= 0x79b76d99e2 + if (c0 & 0x04): + c ^= 0xf33e5fb3c4 + if (c0 & 0x08): + c ^= 0xae2eabe2a8 + if (c0 & 0x10): + c ^= 0x1e4f43e470 + return c ^ 1 +``` + +where `&` is the bitwise AND operator, `^` is the bitwise XOR operator, and `>>` is the bitwise right shift. + + +## Encoding a Bitcoin Cash address + +To encode an address with CashAddr, follow the steps described below: + +1. Take the address data, which is usually the hash of a public key (P2PKH) or a redeem script (P2SH), and compute the corresponding version byte. + +2. Concatenate the version byte and the data bytes together (bytewise): + + ``` + payload = version || data + ``` + +3. Divide the payload into chunks of 5 bits. The payload is padded to the right with zero bits to complete any unfinished chunk at the end. + +4. Compute the checksum by applying `polymod` to the following values: + + a. The lower 5 bits of each character of the prefix. For letters, this corresponds to their position in the alphabet. + + b. A zero for the separator (5 zero bits). + + c. The payload. + + d. Eight zeros as a template for the checksum. + +5. Encode each chunk of the payload and each chunk of the checksum with Base32. + + +## Example + +The steps to encode a P2PKH address which is valid on the Bitcoin Cash main network are: + +1. Take the address data, i.e., the 20-byte hash of the public key: + + ``` + 211b74ca4686f81efda5641767fc84ef16dafe0b + ``` + +2. Concatenate the version byte (here `0x00`) and the data bytes together to get the payload: + + ``` + 00211b74ca4686f81efda5641767fc84ef16dafe0b + ``` +2. Divide the payload into chunks of 5 bits. In this example, the payload is 168-bit long; therefore, it is padded to the right with **2** zero bits to complete the last chunk. The resulting chunks are: + + ``` + [ 0, 0, 16, 17, 22, 29, 6, 10, 8, 26, 3, 15, 16, 7, 23, 29, 20, 21, 18, 1, 14, 25, 31, 28, 16, 19, 23, 17, 13, 22, 23, 30, 1, 12 ] + ``` + +3. Compute the checksum by applying `polymod` to the concatenation of: + + a. The lower 5 bits of each character of the prefix `bitcoincash`: + + ``` + [ 2, 9, 20, 3, 15, 9, 14, 3, 1, 19, 8 ] + ``` + + b. A zero for the separator: + + ``` + [ 0 ] + ``` + + c. The payload chunks: + + ``` + [ 0, 0, 16, 17, 22, 29, 6, 10, 8, 26, 3, 15, 16, 7, 23, 29, 20, 21, 18, 1, 14, 25, 31, 28, 16, 19, 23, 17, 13, 22, 23, 30, 1, 12 ] + ``` + + d. The template of the checksum: + + ``` + [ 0, 0, 0, 0, 0, 0, 0, 0 ] + ``` + + The checksum is: + + ``` + [ 28, 10, 17, 3, 2, 3, 3, 28 ] + ``` + +4. Encoded with Base32, the payload and the checksum are, respectively, `qqs3kax2g6r0s8ha54jpwelusnh3dkh7pv` and `u23rzrru`. The resulting addres is: + + ``` + bitcoincash:qqs3kax2g6r0s8ha54jpwelusnh3dkh7pvu23rzrru + ``` From ab05beac067c755c7d65b4cfc43d030349717c61 Mon Sep 17 00:00:00 2001 From: lugaxker Date: Fri, 27 Mar 2020 21:55:48 +0100 Subject: [PATCH 11/24] Remove some layout details. --- protocol/blockchain/encoding/base58check.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/protocol/blockchain/encoding/base58check.md b/protocol/blockchain/encoding/base58check.md index 37c1be8..03d2675 100644 --- a/protocol/blockchain/encoding/base58check.md +++ b/protocol/blockchain/encoding/base58check.md @@ -61,15 +61,15 @@ The testnet version bytes are: ## Encoding -Base58Check is used to encode a `payload` and a `version` byte. It is done by following the steps described below. +Base58Check is used to encode a **payload** and a **version** byte. It is done by following the steps described below. -1. Take the `version` byte and the `payload` bytes, and concatenate them together (bytewise): +1. Take the version byte and the payload bytes, and concatenate them together (bytewise): ``` version || payload ``` -2. Compute the `checksum` by taking the first four bytes of the double SHA256 hash function of this concatenation. +2. Compute the checksum by taking the first four bytes of the double SHA256 hash function of this concatenation. ``` checksum = SHA256( SHA256( version || payload ) )[:4] @@ -99,7 +99,7 @@ Steps to encode a private key: 1e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd ``` -2. Take the `version` byte corresponding to it (`0x80` for mainnet, `0xef` for testnet), and concatenate them together: +2. Take the version byte corresponding to it (`0x80` for mainnet, `0xef` for testnet), and concatenate them together: ``` 801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd @@ -108,7 +108,7 @@ Steps to encode a private key: 3. Compute the checksum by performing the double SHA256 on it, and by taking the first four bytes of this hash: ``` - SHA256( SHA256( 801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd ) ) = **c47e83ff**afda3ba4396e1bc6a648515e5fc9aa95910af6a4429537b87fb7b474 + SHA256( SHA256( 801e99423a4ed27608a15a2616a2b0e9e52ced330ac530edcc32c8ffc6a526aedd ) ) = c47e83ffafda3ba4396e1bc6a648515e5fc9aa95910af6a4429537b87fb7b474 ``` 4. Concatenate the result from step 2 and the checksum together: @@ -158,7 +158,7 @@ Steps to encode a legacy address: 3. Compute the checksum by performing the double SHA256 on it, and by taking the first four bytes of this hash: ``` - SHA256( SHA256( 00211b74ca4686f81efda5641767fc84ef16dafe0b ) ) = **388c8d1d**3f70ec351abf400fadf7756418e6b3835c01fe78206b39ec1ab8a37a + SHA256( SHA256( 00211b74ca4686f81efda5641767fc84ef16dafe0b ) ) = 388c8d1d3f70ec351abf400fadf7756418e6b3835c01fe78206b39ec1ab8a37a ``` 4. Concatenate the result from step 2 and the checksum together: From 6be31639cc45b83ab78da185de64e244e0daad34 Mon Sep 17 00:00:00 2001 From: lugaxker Date: Fri, 27 Mar 2020 21:57:41 +0100 Subject: [PATCH 12/24] Add a link to the CashAddr encoding section. --- home.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/home.md b/home.md index de273f8..1cf586e 100644 --- a/home.md +++ b/home.md @@ -25,7 +25,7 @@ [Proof of Work](/protocol/blockchain/proof-of-work) — [Difficulty Adjustment Algorithm](/protocol/blockchain/proof-of-work/difficulty-adjustment-algorithm) — [Mining](/protocol/blockchain/proof-of-work/mining) — Stratum Protocol — Mining Pools ### Addresses -Pay To Public Key (P2PK) — Pay To Public Key Hash (P2PKH) — Pay To Script Hash (P2SH) — [Base58Check encoding (legacy)](/protocol/blockchain/encoding/base58check) — Cashaddr encoding +Pay To Public Key (P2PK) — Pay To Public Key Hash (P2PKH) — Pay To Script Hash (P2SH) — [Base58Check encoding (legacy)](/protocol/blockchain/encoding/base58check) — [Cashaddr encoding](/protocol/blockchain/encoding/cashaddr) ### Cryptography Secp256k1 — Public Key — Private Key — ECDSA signatures — Schnorr signatures — [Multisignature (M-of-N multisig)](/protocol/blockchain/cryptography/multisignature.md) From e9b2e3fd1fd90dff9d32c88a7db9fd77614e00d6 Mon Sep 17 00:00:00 2001 From: Ludovic Lars Date: Mon, 6 Apr 2020 22:15:44 +0200 Subject: [PATCH 13/24] Add simpleledger prefix and uppercase option Add simpleledger prefix and uppercase option for CashAddr, correct 1 typo --- protocol/blockchain/encoding/cashaddr.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/protocol/blockchain/encoding/cashaddr.md b/protocol/blockchain/encoding/cashaddr.md index 52bcfb5..a1ae538 100644 --- a/protocol/blockchain/encoding/cashaddr.md +++ b/protocol/blockchain/encoding/cashaddr.md @@ -13,7 +13,9 @@ This format reuses the work done for Bech32 (see [BIP173](https://github.com/bit ## Prefix -The prefix is a human-readable part of the address which indicates the network on which the addess is valid. It can only contain ASCII characters. The 3 prefixes used in Bitcoin Cash are: +The prefix is a human-readable part of the address which indicates the network on which the addess is valid, or the metaprotocol used. It can only contain ASCII characters. + +There are 3 prefixes used in Bitcoin Cash to indicate the network: | Network | Prefix | | ------- | ------------- | @@ -21,13 +23,15 @@ The prefix is a human-readable part of the address which indicates the network o | Testnet | `bchtest` | | Regtest | `bchreg` | +The prefix can also indicate for which metaprotocol the addres must be used. For instance, Simple Ledger Protocol (SLP) addresses are required to begin with `simpleledger` in order to avoid sending SLP tokens to a non-SLP wallet. + The prefix is always followed by the separator `:`. When presented to users, the prefix and the separator may be omitted as it is part of the checksum computation. ## Base32 -CashAddr uses Base32 to encode information. The symbols used in CashAddr Base32 are the lowercase alphanumeric characters excluding `1`, `b`, `i`, and `o`. +CashAddr uses Base32 to encode information. The symbols used in CashAddr Base32 are the lowercase alphanumeric characters excluding `1`, `b`, `i`, and `o`. Uppercase characters are also valid to enable efficient QR code encoding ([see spec](https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md#uppercaselowercase)). However, any mixture of lowercase and uppercase characters must be rejected. Base32 alphabet: @@ -194,7 +198,7 @@ The steps to encode a P2PKH address which is valid on the Bitcoin Cash main netw [ 28, 10, 17, 3, 2, 3, 3, 28 ] ``` -4. Encoded with Base32, the payload and the checksum are, respectively, `qqs3kax2g6r0s8ha54jpwelusnh3dkh7pv` and `u23rzrru`. The resulting addres is: +4. Encoded with Base32, the payload and the checksum are, respectively, `qqs3kax2g6r0s8ha54jpwelusnh3dkh7pv` and `u23rzrru`. The resulting address is: ``` bitcoincash:qqs3kax2g6r0s8ha54jpwelusnh3dkh7pvu23rzrru From 5813756cad877f76a9393fa7a03de59933b3f3b1 Mon Sep 17 00:00:00 2001 From: Greg-Griffith Date: Wed, 8 Apr 2020 17:38:15 -0700 Subject: [PATCH 14/24] add xversionkeys.md for central db for prefix/suffix info. add page refs --- protocol/p2p/xupdate.md | 6 +++--- protocol/p2p/xversion.md | 21 +++++---------------- protocol/p2p/xversionkeys.md | 24 ++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 19 deletions(-) create mode 100644 protocol/p2p/xversionkeys.md diff --git a/protocol/p2p/xupdate.md b/protocol/p2p/xupdate.md index 2b60ec7..b28659c 100644 --- a/protocol/p2p/xupdate.md +++ b/protocol/p2p/xupdate.md @@ -1,6 +1,6 @@
{ "title":"XUPDATE", -"related":["/protocol","/protocol/p2p/xversion"] +"related":["/protocol","/protocol/p2p/xversion" ,"/protocol/p2p/xversionkeys"] }
*Notifies peers about an XVERSION configuration value update* @@ -10,9 +10,9 @@ This message notifies a peer about changes to protocol parameters. It follows t See the [XVERSION](/protocol/p2p/xversion.md) message for detailed information about each parameter. | compact int | compact int | variable bytes |... | compact int | 32 bytes | -|----------|---------|----------|---|---------|----------| +|----------|---------|----------|---|---------|----------| |[vector](/protocol/p2p/vector) size N of| key 1 | [vector](/protocol/p2p/vector) of bytes | | key N | [vector](/protocol/p2p/vector) of bytes ### Support -Supported by: **Bitcoin Unlimited** \ No newline at end of file +Supported by: **Bitcoin Unlimited** diff --git a/protocol/p2p/xversion.md b/protocol/p2p/xversion.md index eff0b5d..f008d17 100644 --- a/protocol/p2p/xversion.md +++ b/protocol/p2p/xversion.md @@ -1,6 +1,6 @@
{ "title":"XVERSION", -"related":["/protocol","/protocol/p2p/xupdate"] +"related":["/protocol","/protocol/p2p/xupdate","/protocol/p2p/xversionkeys"] }
*Notifies peers about a protocol configuration value* @@ -8,7 +8,7 @@ This message notifies a peer about extended protocol parameters. This message MAY be sent during connection initialization. If sent, it MUST be sent immediately subsequent to the receipt of the [VERACK](/protocol/p2p/verack.md) message, and before other non-initialization messages are sent. | compact int | compact int | variable bytes |... | compact int | variable bytes | -|----------|---------|----------|---|---------|----------| +|----------|---------|----------|---|---------|----------| |[vector](/protocol/p2p/vector) size N of| key 1 | value 1 [vector](/protocol/p2p/vector) of bytes | | key N | value N [vector](/protocol/p2p/vector) of bytes The *value* is a vector of bytes. These bytes can be an object that is itself serialized, but **MUST** exist within the vector "envelope" so that implementations that do not recognize a field can skip it. The serialization format of the bytes inside the "envelope" is defined by the creator of the key, however, Bitcoin P2P network serialization is recommended since it is also used to encode/decode all the messages of this protocol. @@ -19,20 +19,9 @@ See [XVERSION specification](https://github.com/BitcoinUnlimited/BitcoinUnlimite XVERSION field identifiers are 32 bits and split into a 16 bit prefix and 16 bit suffix. Each development group is assigned a prefix so that new identifiers do not accidentally conflict. Once a field identifier is created by group A, it should be used by other software both to receive that information from A and to present that information to other software. Therefore, group A **MUST NOT** change the syntax or semantics of a field once defined. To change a field, create a new identifier and deprecate (by no longer using the original identifier). -#### Prefix Assignments -| Group | Value | -|-------------------|-------| -| Bitcoin ABC | 0 | -| Bitcoin Unlimited | 2 | - - -#### Field Assignments - -See [xversionkeys.dat](https://github.com/BitcoinUnlimited/BitcoinUnlimited/blob/bucash1.7.0.0/src/xversionkeys.dat) for the most up-to-date field definitions defined by the BitcoinUnlimited full node. -Note that: -* *u64c* refers to a [compact int](/protocol/p2p/compact__int.md) serialization of an unsigned 64-bit value. -* *Changeable* fields MAY be changed during the course of a connection via the [XUPDATE](/protocol/p2p/xupdate) message. +#### Prefix and Suffix Assignments +See [xversionkeys](/protocol/p2p/xversionkeys.md) for a full list of assigned prefixes and field definitions. ### Support -Supported by: **Bitcoin Unlimited** \ No newline at end of file +Supported by: **Bitcoin Unlimited** diff --git a/protocol/p2p/xversionkeys.md b/protocol/p2p/xversionkeys.md new file mode 100644 index 0000000..7b8376c --- /dev/null +++ b/protocol/p2p/xversionkeys.md @@ -0,0 +1,24 @@ +
{ +"title":"XVERSIONKEYS", +"related":["/protocol","/protocol/p2p/xversion","/protocol/p2p/xupdate"] +}
+ + +### Prefix Assignments +| Group | Value | +|-------------------------|-------| +| Reserved for versioning | 0 | +| Bitcoin Cash Node | 1 | +| Bitcoin Unlimited | 2 | + + +#### Field Assignments + +See [xversionkeys.dat](https://github.com/BitcoinUnlimited/BitcoinUnlimited/blob/bucash1.7.0.0/src/xversionkeys.dat) for the most up-to-date field definitions defined by the BitcoinUnlimited full node. +Note that: +* *u64c* refers to a [compact int](/protocol/p2p/compact__int.md) serialization of an unsigned 64-bit value. +* *Changeable* fields MAY be changed during the course of a connection via the [XUPDATE](/protocol/p2p/xupdate) message. + +### Support + +Supported by: **Bitcoin Unlimited** From c61ce632085e01271ef25d8ef41881fd3956e6fe Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Tue, 9 Jun 2020 11:46:28 -0400 Subject: [PATCH 15/24] merge a few changes from the verde repo --- protocol/blockchain/block.md | 10 +++++++++- protocol/blockchain/transaction-validation.md | 18 +++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/protocol/blockchain/block.md b/protocol/blockchain/block.md index e2c0509..9754410 100644 --- a/protocol/blockchain/block.md +++ b/protocol/blockchain/block.md @@ -31,4 +31,12 @@ The block reward started at 5,000,000,000 satoshis (50 BCH) and decreases by hal Transaction fees are often required by the network for transactions to be relayed across the network. Satoshis provided as inputs to a transaction, but not consumed by its outputs, are collected by the coinbase transaction as implicit inputs. -The coinbase message is provided in the inputs unlocking script. The unlocking script is required to begin with a push of the block height which can then be followed why whatever data is desired. The block height encoded as a variable-length, little-endian integer. The [OP_DATA_X](/protocol/blockchain/script/op-codes/op-data-x) operation is used to push the necessary number of bytes to encode the length. This requirement was added with version 2 blocks as a part of [BIP-34](/protocol/forks/bip-0034). \ No newline at end of file +The coinbase message is provided in the inputs unlocking script. +The unlocking script is required to begin with a push of the block height which can then be followed why whatever data is desired. +The block height encoded as a variable-length, little-endian integer. +The [OP_DATA_X](/protocol/blockchain/script/op-codes/op-data-x) operation is used to push the necessary number of bytes to encode the length. +This requirement was added with version 2 blocks as a part of [BIP-34](/protocol/forks/bip-0034). + +Each coinbase transaction may only have one transaction input. + +Each coinbase transaction's unlocking script must be less than or equal to 100 bytes. diff --git a/protocol/blockchain/transaction-validation.md b/protocol/blockchain/transaction-validation.md index a0de586..e58fd1e 100644 --- a/protocol/blockchain/transaction-validation.md +++ b/protocol/blockchain/transaction-validation.md @@ -8,4 +8,20 @@ Transaction validation can be broken down into three major categories: - [Block-Level Validation Rules](/protocol/blockchain/transaction-validation/block-level-validation-rules) which determine whether transactions are valid in a given blockchain context (i.e. in a given block with a given history) - [Network-Level Validation Rules](/protocol/blockchain/transaction-validation/network-level-validation-rules) which determine whether transactions are relayed from node to node -The three of these are closely intertwined but often result in different behavior when they are violated. For details, see the linked pages for definitions of each. \ No newline at end of file +The three of these are closely intertwined but often result in different behavior when they are violated. For details, see the linked pages for definitions of each. + +## Miscellaneous Validation Rules + +Bitcoin also has some miscellaneous rules for validation, which include exceptions or oddities. +The following are miscellaneous rules. + +### Genesis Block Coinbase + +The genesis block's coinbase may not be spent. +Furthermore, this coinbase's output is not considered an unspent transaction output. + +### Extra Coinbase Validation Rules + +Coinbases may only have one transaction input. + +All coinbase unlocking script must be less than or equal to 100 bytes in size. From e091aa5dce26985059670199c306a9841c0139bf Mon Sep 17 00:00:00 2001 From: qr8ruwyx0u7fqeyu5n49t2paw0ghhp8xsgmffesqzs Date: Tue, 9 Jun 2020 16:10:13 +0000 Subject: [PATCH 16/24] wiki commit From 7055275bbbf5991875954b3bb38cdde1f98c7b7f Mon Sep 17 00:00:00 2001 From: qr8ruwyx0u7fqeyu5n49t2paw0ghhp8xsgmffesqzs Date: Tue, 9 Jun 2020 17:03:54 +0000 Subject: [PATCH 17/24] wiki commit --- protocol/network/messages.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/network/messages.md b/protocol/network/messages.md index fe0f4ed..493f991 100644 --- a/protocol/network/messages.md +++ b/protocol/network/messages.md @@ -39,9 +39,9 @@ The `net magic` is designed to be unlikely to occur in normal data--the characte The `command string` is a fixed-length 12 byte ASCII string. Commands may not be longer than 12 bytes. -Commands that are shorter than 12-bytes are right-padded with null bytes (`0x00`). +Commands that are shorter than 12 bytes are right-padded with null bytes (`0x00`). The command string is used to determine the type of message being transmitted. -Messages with an unrecognized `command string` are ignored. +Messages with an unrecognized `command string` are ignored by most implementations but may result in a ban by implementations that diverge from the Satoshi-client defacto standard. The following messages are considered standard by all node implementations. From 6880c0e9d6f08336cd72404e278b06c301e4a55e Mon Sep 17 00:00:00 2001 From: qr8ruwyx0u7fqeyu5n49t2paw0ghhp8xsgmffesqzs Date: Tue, 9 Jun 2020 17:17:37 +0000 Subject: [PATCH 18/24] wiki commit --- protocol/network/messages.md | 48 +++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/protocol/network/messages.md b/protocol/network/messages.md index 493f991..6e89e9d 100644 --- a/protocol/network/messages.md +++ b/protocol/network/messages.md @@ -46,42 +46,44 @@ Messages with an unrecognized `command string` are ignored by most implementatio The following messages are considered standard by all node implementations. #### Announcements -| Command String | Name | -| -- | -- | -| filteradd | | -| filterclear | | -| filterload | | -| inv | | +| Command String | Synopsis | Supported Implementations +| -- | -- | -- | +| [filteradd](/protocol/p2p/filteradd) | *Adds a single item into an installed filter* | all +| [filterclear](/protocol/p2p/filterclear) | *Removes an installed filter* | all +| [filterload](/protocol/p2p/filterload) | *Inserts a transaction and merkle block filter into the peer* | all +| [inv](/protocol/p2p/inv) | *Notifies peers about the existence of some information (generally a block or transaction)* | all + | [xupdate](/protocol/p2p/xupdate) | *Communicates a change in peer capabilities* | BCHUnlimited #### Requests -| Command String | Name | -| -- | -- | +| Command String | Synopsis | Supported Implementations +| -- | -- | -- | | feefilter | | | getaddr | | -| getblocks | | -| getdata | | -| getheaders | | -| ping | [Ping](/protocol/network/messages/ping) | +| [getblocks](/protocol/p2p/getblocks) | *Requests block hash identifiers* | all | +| [getdata](/protocol/p2p/getdata) | *Requests information from a peer* | all | +| [getheaders](/protocol/p2p/getheaders) | *Requests block headers from a peer* | all | +| ping | [Ping](/protocol/network/messages/ping) | all | | sendheaders | | -| version | [Handshake: Version](/protocol/network/messages/version) | +| [version](/protocol/network/messages/version) | *Describes peer capabilities* | all +| [xversion](/protocol/p2p/xversion) | *Describes peer capabilities in an extensible manner* | BCHUnlimited #### Responses -| Command String | Name | -| -- | -- | -| addr | | +| Command String | Synopsis | Supported Implementations +| -- | -- | -- | +| [addr](/protocol/p2p/addr) | *Provides a peer with the addresses of other peers* | all | block | | -| headers | | +| [headers](/protocol/p2p/headers) | *Provides a set of block headers (unsolicited or GETHEADERS response)* | all | | notfound | | -| merkleblock | | -| pong | [Pong](/protocol/network/messages/pong) | -| reject | | -| tx | | -| verack | [Handshake: Acknowledge Version](/protocol/network/messages/verack) | +| [merkleblock](protocol/p2p/merkleblock) | *Provides a provable subset of a block's transactions, as filtered by FILTERADD* | all | +| [Pong](/protocol/network/messages/pong) | *Reply to a ping message* | all | +| [reject](/protocol/p2p/reject) | *Response by well-behaved clients if a message cannot be handled* | all +| [TX](/protocol/p2p/tx) | *Provide a transaction* | all +| [verack](/protocol/network/messages/verack) | *Respond to an [xversion](/protocol/p2p/xversion) message* | all The following messages are well known, but not implemented by all node implementations. -| Command String | Name | Supported Implementations | +| Command String | Synopsis | Supported Implementations | -- | -- | -- | | get_xblocktx | | | | get_xthin | | | From 178338b2682830a255c5883c3185c7d1d186eba2 Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Wed, 1 Jul 2020 19:29:16 +0000 Subject: [PATCH 19/24] wiki commit From 25f6a50fb78e15167cacf323489c3e7ecd754f4b Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Wed, 1 Jul 2020 19:29:22 +0000 Subject: [PATCH 20/24] wiki commit From 8fc427b867394bd607e1bacecb31e3ef51cd9c9d Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Wed, 1 Jul 2020 19:29:26 +0000 Subject: [PATCH 21/24] wiki commit From ac347d9016b750ea02f7299b14c7f22e4a653f39 Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Wed, 1 Jul 2020 19:31:50 +0000 Subject: [PATCH 22/24] wiki commit From 92d9212ce94824dff3ca949ca201e5537bdf23ce Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Wed, 1 Jul 2020 19:31:53 +0000 Subject: [PATCH 23/24] wiki commit From 00e7136b3193a99c3092119c1ce8f768c67f9c57 Mon Sep 17 00:00:00 2001 From: Andrew Stone Date: Wed, 1 Jul 2020 19:42:06 +0000 Subject: [PATCH 24/24] wiki commit