From 2f5dc867488f702ee68f6519a9838768ca64a15a Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Sun, 11 Mar 2018 13:11:07 +0000 Subject: [PATCH] Address my comments on ZIP 202. Signed-off-by: Daira Hopwood --- zip-0202.rst | 138 +++++++++++++++++++++++++-------------------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/zip-0202.rst b/zip-0202.rst index fcae262f..8b763d97 100644 --- a/zip-0202.rst +++ b/zip-0202.rst @@ -10,9 +10,9 @@ Terminology =========== -The key words "MUST", "MUST NOT", "SHOULD", and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ +The key words "MUST", "MUST NOT", and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ -The terms "branch" and "network upgrade" in this document are to be interpreted as described in ZIP 200. [#zip-0200]_ +The terms "branch", "network upgrade", and "consensus rule change" in this document are to be interpreted as described in ZIP 200. [#zip-0200]_ The term "Overwinter" in this document is to be interpreted as described in ZIP 201. [#zip-0201]_ @@ -26,20 +26,20 @@ Motivation Zcash launched with support for upstream Bitcoin version 1 transactions and defined a new version 2 transaction format which added fields required for shielded transactions. -======== ================== =========================== ========== -Version Field Description Type -======== ================== =========================== ========== ->= 1 version positive value int32 ->= 1 tx_in_count variable length integer compactSize ->= 1 tx_in list of inputs vector ->= 1 tx_out_count variable length integer compactSize ->= 1 tx_out list of outputs vector ->= 1 lock_time block height or timestamp uint32 ->= 2 nJoinSplit variable length integer compactSize ->= 2 vJoinSplit list of joinsplits vector ->= 2 joinSplitPubKey joinsplit_sig public key 32 bytes ->= 2 joinSplitSig signature 64 bytes -======== ================== =========================== ========== +======== ====================== =========================== =============== +Version Field Description Type +======== ====================== =========================== =============== +>= 1 ``version`` positive value ``int32`` +>= 1 ``tx_in_count`` variable-length integer ``compactSize`` +>= 1 ``tx_in`` list of inputs ``vector`` +>= 1 ``tx_out_count`` variable-length integer ``compactSize`` +>= 1 ``tx_out`` list of outputs ``vector`` +>= 1 ``lock_time`` block height or timestamp ``uint32`` +>= 2 ``nJoinSplit`` variable-length integer ``compactSize`` +>= 2 ``vJoinSplit`` list of joinsplits ``vector`` +>= 2 ``joinSplitPubKey`` joinsplit_sig public key 32 bytes +>= 2 ``joinSplitSig`` signature 64 bytes +======== ====================== =========================== =============== A new transaction format is required to: @@ -61,33 +61,33 @@ A new version 3 transaction format will be introduced for Overwinter. The version 3 format differs from the version 2 format in the following ways: -* header (first four bytes, little endian encoded) +* header (first four bytes, little-endian encoded) - * fOverwintered flag : bit 31, must be set - * nVersion : bits 30-0, positive integer -* nVersionGroupId -* nExpiryHeight + * ``fOverwintered`` flag : bit 31, must be set + * ``nVersion`` : bits 30-0, positive integer +* ``nVersionGroupId`` +* ``nExpiryHeight`` -======== ================== =========================== ========= -Version Field Description Type -======== ================== =========================== ========= ->= 3 header contains: uint32 +======== ====================== =========================== =============== +Version Field Description Type +======== ====================== =========================== =============== +>= 3 header contains: ``uint32`` - - fOverwintered flag - (bit 31, always set) - - nVersion (bits 30-0) ->= 3 nVersionGroupId version group id (not zero) uint32 ->= 1 tx_in_count variable length integer compactSize ->= 1 tx_in list of inputs vector ->= 1 tx_out_count variable length integer compactSize ->= 1 tx_out list of outputs vector ->= 1 lock_time block height or timestamp uint32 ->= 3 expiryHeight block height uint32 ->= 2 nJoinSplit variable length integer compactSize ->= 2 vJoinSplit list of joinsplits vector ->= 2 joinSplitPubKey joinsplit_sig public key 32 bytes ->= 2 joinSplitS ig signature 64 bytes -======== ================== =========================== ========= + - ``fOverwintered`` flag + (bit 31, always set) + - ``nVersion`` (bits 30-0) +>= 3 ``nVersionGroupId`` version group id (not zero) ``uint32`` +>= 1 ``tx_in_count`` variable-length integer ``compactSize`` +>= 1 ``tx_in`` list of inputs ``vector`` +>= 1 ``tx_out_count`` variable-length integer ``compactSize`` +>= 1 ``tx_out`` list of outputs ``vector`` +>= 1 ``lock_time`` block height or timestamp ``uint32`` +>= 3 ``expiryHeight`` block height ``uint32`` +>= 2 ``nJoinSplit`` variable-length integer ``compactSize`` +>= 2 ``vJoinSplit`` list of joinsplits ``vector`` +>= 2 ``joinSplitPubKey`` joinsplit_sig public key 32 bytes +>= 2 ``joinSplitSig`` signature 64 bytes +======== ====================== =========================== =============== Header Field @@ -97,45 +97,45 @@ The first four bytes of pre-Overwinter and Overwinter transactions are little-en Version 1 transaction (txid 5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061 https://zcash.blockexplorer.com/tx/5c6ba844e1ca1c8083cd53e29971bd82f1f9eea1f86c1763a22dd4ca183ae061) -* begins with little-endian byte sequence [0x01, 0x00, 0x00, 0x00] -* deserialized as 32-bit signed integer with decimal value of 1 +* begins with little-endian byte sequence [0x01, 0x00, 0x00, 0x00]; +* deserialized as 32-bit signed integer with decimal value of 1. Version 2 transaction (txid 4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b https://zcash.blockexplorer.com/tx/4435bf8064e74f01262cb1725fd9b53e600fa285950163fd961bed3a64260d8b) -* begins with little-endian byte sequence [0x02, 0x00, 0x00, 0x00] -* deserialized as 32-bit signed integer with decimal value of 2 +* begins with little-endian byte sequence [0x02, 0x00, 0x00, 0x00]; +* deserialized as 32-bit signed integer with decimal value of 2. Transaction parsers for versions of Zcash prior to Overwinter, and for most other Bitcoin forks, require the transaction version number to be positive. With the version 3 transaction format, the first four bytes of a serialized transaction, the 32-bit header, are made up of two fields as shown in the table above: -* 1 bit Overwinter flag, must be set -* 31 bit unsigned int for the Version +* 1-bit ``fOverwintered`` flag, must be set; +* 31-bit unsigned int for the version. -Pre-Overwinter parsers will deserialize these four bytes as a 32-bit signed integer. With two's complement integers, the most significant bit indicates whether an integer is positive or negative. With the Overwinter flag set, the transaction version will be negative, resulting in pre-Overwinter parsers rejecting the transaction as invalid. This provides transaction replay protection between per-Overwinter and Overwinter software. +Pre-Overwinter parsers will deserialize these four bytes as a 32-bit signed integer. With two's complement integers, the most significant bit indicates whether an integer is positive or negative. With the Overwinter flag set, the transaction version will be negative, resulting in pre-Overwinter parsers rejecting the transaction as invalid. This provides transaction replay protection between pre-Overwinter and Overwinter software. Consider the following example of a serialized version 3 transaction. Pre-Overwinter parser: -* data begins with little-endian byte sequence: [0x03, 0x00, 0x00, 0x80] -* deserialized as 32-bit signed integer +* data begins with little-endian byte sequence: [0x03, 0x00, 0x00, 0x80]; +* deserialized as 32-bit signed integer. - * with hexadecimal value of 0x80000003 (most significant bit is set) - * decimal value of -2147483645 + * with hexadecimal value of 0x80000003 (most significant bit is set); + * decimal value of -2147483645. Legacy parsers will expect the version to be a positive value, such as 1 or 2, and will thus reject the Overwinter transaction as invalid. Overwinter parser: -- data begins with little-endian byte sequence: [0x03, 0x00, 0x00, 0x80] +- data begins with little-endian byte sequence: [0x03, 0x00, 0x00, 0x80]; - deserialized as 32-bit unsigned integer - - with binary value of 0b10000000000000000000000000000011 -- the 32-bits are decomposed into two fields + - with binary value of 0b10000000000000000000000000000011; +- the 32-bits are decomposed into two fields: - - overwinter flag (bit 31) as a boolean, expected to be set - - version (bits 30 - bit 0) as an unsigned integer, expected to have a decimal value of 3 + - ``fOverwintered`` flag (bit 31) as a boolean, expected to be set; + - version (bits 30 - bit 0) as an unsigned integer, expected to have a decimal value of 3. Overwinter parsers will accept the transaction as valid as the most significant bit of the header has been set. By masking off (unsetting) the most significant bit, the parser can retrieve the transaction version number:: @@ -144,15 +144,15 @@ Overwinter parsers will accept the transaction as valid as the most significant Version Group Id ---------------- -The version group id is a non-zero, random and unique identifier, of type uint32_t, assigned to a transaction format version, or a group of soft-forking transaction format versions. The version group id helps nodes disambiguate between branches using the same version number. +The version group id is a non-zero, random and unique identifier, of type ``uint32``, assigned to a transaction format version, or a group of soft-forking transaction format versions. The version group id helps nodes disambiguate between branches using the same version number. That is, it prevents a client on one branch of the network from attempting to parse transactions intended for another branch, in the situation where the transactions share the same format version number but are actually specified differently. For example, Zcash and a clone of Zcash might both define their own custom v3 transaction formats, but each will have its own unique version group id, so that they can reject v3 transactions with unknown version group ids. -The combination of transaction version and version group id, `nVersion || nVersionGroupId`, uniquely defines the transaction format, thus enabling parsers to reject transactions from outside the client's chain which cannot be parsed. +The combination of transaction version and version group id, ``nVersion || nVersionGroupId``, uniquely defines the transaction format, thus enabling parsers to reject transactions from outside the client's chain which cannot be parsed. By convention, it is expected that when introducing a new transaction version requiring a network upgrade, a new unique version group id will be assigned to that transaction version. -However, if new transaction versions are soft-fork compatible with older transaction versions, the same version group id can be re-used. +However, if a new transaction version can be correctly parsed according to the format of a preceding version (that is, it only restricts the format, or defines fields that were previously reserved and which old parsers can safely ignore), then the same version group id MAY be re-used. Expiry Height ------------- @@ -164,15 +164,15 @@ Transaction Validation A valid Overwinter transaction intended for Zcash MUST have: -- version number 3 -- version group id 0x03C48270 [#versiongroupid]_ -- fOverwintered flag set +- version number 3; and +- version group id 0x03C48270 [#versiongroupid]_; and +- ``fOverwintered`` flag set. -Overwinter transaction parsers should reject transactions for violating consensus rules if: +Overwinter validators MUST reject transactions for violating consensus rules if: -- the fOverwintered flag is not set -- the version group id is unknown -- the version number is unknown +- the ``fOverwintered`` flag is not set; or +- the version group id is unknown; or +- the version number is unknown. Implementation ============== @@ -192,7 +192,7 @@ Tests can continue to check for the existence of forwards-compatible transaction } } -When (de)serializing v3 transactions, the version group id should also be checked in case the transaction is intended for a branch which has a different format for its version 3 transaction:: +When (de)serializing v3 transactions, the version group id must also be checked in case the transaction is intended for a branch which has a different format for its version 3 transaction:: if (tx.nVersion == 3 && tx.nVersionGroupId == OVERWINTER_VERSION_GROUP_ID) { auto expiryHeight = tx.nExpiryHeight; @@ -231,12 +231,12 @@ Ultimately, a client can determine if a transaction is truly intended for the cl Deployment ========== -This proposal will be deployed with the Overwinter network upgrade. +This proposal will be deployed with the Overwinter network upgrade. The activation block height proposal is in [#zip-0201]_. Backwards compatibility ======================= -This proposal intentionally creates what is known as a "bilateral hard fork" between pre-Overwinter software and Overwinter-compatible software. Use of this new transaction format requires that all network participants upgrade their software to a compatible version within the upgrade window. Pre-Overwinter software will treat Overwinter transactions as invalid. +This proposal intentionally creates what is known as a "bilateral consensus rule change" [#zip-0200]_ between pre-Overwinter software and Overwinter-compatible software. Use of this new transaction format requires that all network participants upgrade their software to a compatible version within the upgrade window. Pre-Overwinter software will treat Overwinter transactions as invalid. Once Overwinter has activated, Overwinter-compatible software will reject version 1 and version 2 transactions, and will only accept transactions based upon supported transaction version numbers and recognized version group ids.