From c2d869a46fffd5d00bf54f14870d012568327dec Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Thu, 6 Jun 2019 23:30:24 +0100 Subject: [PATCH 1/4] Add ZIPs 68 and 112 (OP_CHECKSEQUENCEVERIFY). Signed-off-by: Daira Hopwood --- zip-0068.rst | 315 +++++++++++++++++++++++++++++++++++++++++ zip-0112.rst | 386 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 701 insertions(+) create mode 100644 zip-0068.rst create mode 100644 zip-0112.rst diff --git a/zip-0068.rst b/zip-0068.rst new file mode 100644 index 00000000..0765c4e3 --- /dev/null +++ b/zip-0068.rst @@ -0,0 +1,315 @@ +.. + + ZIP: 68 + Title: Relative lock-time using consensus-enforced sequence numbers + Credits: Mark Friedenbach , BtcDrak , Nicolas Dorier , kinoshitajona + Category: Consensus + Status: Draft + Created: 2016-06-06 + + +Terminology +=========== + +The key words "MUST" and "MAY" in this document are to be interpreted as described in +RFC 2119. [#RFC2119]_ + +The "Median Time Past" of a block in this document refers to the median time of the prior +PoWMedianBlockSpan blocks, where the constant PoWMedianBlockSpan is defined in [#protocol]_ +section 5.3, and the median function is defined as in [#protocol]_ section 7.6.3. + + +Abstract +======== + +This ZIP introduces relative lock-time (RLT) consensus-enforced semantics of the sequence +number field, to enable a signed transaction input to remain invalid for a defined period +of time after confirmation of its corresponding outpoint. + + +Motivation +========== + +Zcash transactions have a sequence number field for each input, inherited from Bitcoin. +The original idea in Bitcoin appears to have been that a transaction in the mempool would +be replaced by using the same input with a higher sequence value. Although this was not +properly implemented, it assumes miners would prefer higher sequence numbers even if the +lower ones were more profitable to mine. However, a miner acting on profit motives alone +would break that assumption completely. The change described by this ZIP repurposes the +sequence number for new use cases without breaking existing functionality. It also leaves +room for future expansion and other use cases. + +The transaction ``nLockTime`` is used to prevent the mining of a transaction until a +certain date. ``nSequence`` will be repurposed to prevent mining of a transaction until +a certain age of the spent output in blocks or timespan. This, among other uses, allows +bi-directional payment channels as used in [#HTLCs]_ and [#zip-0112]_. + + +Specification +============= + +This specification defines the meaning of sequence numbers for transactions in blocks +after this proposal has activated. + +If bit (1 << 31) of the sequence number is set, then no consensus meaning is applied to +the sequence number and can be included in any block under all currently possible +circumstances. + +If bit (1 << 31) of the sequence number is not set, then the sequence number is +interpreted as an encoded relative lock-time. + +The sequence number encoding MUST be interpreted as follows: + +Bit (1 << 22) determines if the relative lock-time is time-based or block based: +If the bit is set, the relative lock-time specifies a timespan in units of 512 seconds +granularity. The timespan starts from the median-time-past of the output’s previous block, +and ends at the Median Time Past of the previous block. If the bit is not set, the +relative lock-time specifies a number of blocks. + +The flag (1 << 22) is the highest order bit in a 3-byte signed integer for use in +Zcash scripts as a 3-byte ``PUSHDATA`` with ``OP_CHECKSEQUENCEVERIFY`` [#zip-0112]_. + +This specification only interprets 16 bits of the sequence number as relative lock-time, +so a mask of ``0x0000FFFF`` MUST be applied to the sequence field to extract the relative +lock-time. The 16-bit specification allows for a year of relative lock-time and the +remaining bits allow for future expansion. + +:raw-html-m2r:`` + +For time based relative lock-time, 512-second granularity was chosen because Bitcoin +blocks are generated every 600 seconds. [TODO: should this be changed for Zcash?] +So when using block-based or time-based, the same amount of time can be encoded with +the available number of bits. Converting from a sequence number to seconds is performed +by multiplying by 512 = 2^9, or equivalently shifting up by 9 bits. + +When the relative lock-time is time-based, it is interpreted as a minimum block-time +constraint over the input's age. A relative time-based lock-time of zero indicates an +input which can be included in any block. More generally, a relative time-based +lock-time n can be included into any block produced 512 \* n seconds after the mining +date of the output it is spending, or any block thereafter. +The mining date of the output is equal to the Median Time Past of the previous block +which mined it. + +The block produced time is equal to the Median Time Past of its previous block. + +When the relative lock-time is block-based, it is interpreted as a minimum block-height +constraint over the input's age. A relative block-based lock-time of zero indicates an +input which can be included in any block. More generally, a relative block lock-time n +MAY be included n blocks after the mining date of the output it is spending, or any +block thereafter. + +The new rules are not applied to the ``nSequence`` field of the input of the coinbase +transaction. + + +Reference Implementation +======================== + +.. highlight::c++ + + enum { + /* Interpret sequence numbers as relative lock-time constraints. */ + LOCKTIME_VERIFY_SEQUENCE = (1 << 0), + }; + + /* Setting nSequence to this value for every input in a transaction + * disables nLockTime. */ + static const uint32_t SEQUENCE_FINAL = 0xffffffff; + + /* Below flags apply in the context of ZIP 68*/ + /* If this flag set, CTxIn::nSequence is NOT interpreted as a + * relative lock-time. */ + static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31); + + /* If CTxIn::nSequence encodes a relative lock-time and this flag + * is set, the relative lock-time has units of 512 seconds, + * otherwise it specifies blocks with a granularity of 1. */ + static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22); + + /* If CTxIn::nSequence encodes a relative lock-time, this mask is + * applied to extract that lock-time from the sequence field. */ + static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff; + + /* In order to use the same number of bits to encode roughly the + * same wall-clock duration, and because blocks are naturally + * limited to occur every 600s on average, the minimum granularity + * for time-based relative lock-time is fixed at 512 seconds. + * Converting from CTxIn::nSequence to seconds is performed by + * multiplying by 512 = 2^9, or equivalently shifting up by + * 9 bits. */ + static const int SEQUENCE_LOCKTIME_GRANULARITY = 9; + + /** + * Calculates the block height and previous block's Median Time Past at + * which the transaction will be considered final in the context of ZIP 68. + * Also removes from the vector of input heights any entries which did not + * correspond to sequence locked inputs as they do not affect the calculation. + */ + static std::pair CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector* prevHeights, const CBlockIndex& block) + { + assert(prevHeights->size() == tx.vin.size()); + + // Will be set to the equivalent height- and time-based nLockTime + // values that would be necessary to satisfy all relative lock- + // time constraints given our view of block chain history. + // The semantics of nLockTime are the last invalid height/time, so + // use -1 to have the effect of any height or time being valid. + int nMinHeight = -1; + int64_t nMinTime = -1; + + // tx.nVersion is signed integer so requires cast to unsigned otherwise + // we would be doing a signed comparison and half the range of nVersion + // wouldn't support ZIP 68. + bool fEnforceZIP68 = static_cast(tx.nVersion) >= 2 + && flags & LOCKTIME_VERIFY_SEQUENCE; + + // Do not enforce sequence numbers as a relative lock time + // unless we have been instructed to + if (!fEnforceZIP68) { + return std::make_pair(nMinHeight, nMinTime); + } + + for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { + const CTxIn& txin = tx.vin[txinIndex]; + + // Sequence numbers with the most significant bit set are not + // treated as relative lock-times, nor are they given any + // consensus-enforced meaning at this point. + if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) { + // The height of this input is not relevant for sequence locks + (*prevHeights)[txinIndex] = 0; + continue; + } + + int nCoinHeight = (*prevHeights)[txinIndex]; + + if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) { + int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast(); + // NOTE: Subtract 1 to maintain nLockTime semantics + // ZIP 68 relative lock times have the semantics of calculating + // the first block or time at which the transaction would be + // valid. When calculating the effective block time or height + // for the entire transaction, we switch to using the + // semantics of nLockTime which is the last invalid block + // time or height. Thus we subtract 1 from the calculated + // time or height. + + // Time-based relative lock-times are measured from the + // smallest allowed timestamp of the block containing the + // txout being spent, which is the Median Time Past of the + // block prior. + nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1); + } else { + nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1); + } + } + + return std::make_pair(nMinHeight, nMinTime); + } + + static bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair lockPair) + { + assert(block.pprev); + int64_t nBlockTime = block.pprev->GetMedianTimePast(); + if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime) + return false; + + return true; + } + + bool SequenceLocks(const CTransaction &tx, int flags, std::vector* prevHeights, const CBlockIndex& block) + { + return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block)); + } + + bool CheckSequenceLocks(const CTransaction &tx, int flags) + { + AssertLockHeld(cs_main); + AssertLockHeld(mempool.cs); + + CBlockIndex* tip = chainActive.Tip(); + CBlockIndex index; + index.pprev = tip; + // CheckSequenceLocks() uses chainActive.Height()+1 to evaluate + // height based locks because when SequenceLocks() is called within + // ConnectBlock(), the height of the block *being* + // evaluated is what is used. + // Thus if we want to know if a transaction can be part of the + // *next* block, we need to use one more than chainActive.Height() + index.nHeight = tip->nHeight + 1; + + // pcoinsTip contains the UTXO set for chainActive.Tip() + CCoinsViewMemPool viewMemPool(pcoinsTip, mempool); + std::vector prevheights; + prevheights.resize(tx.vin.size()); + for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { + const CTxIn& txin = tx.vin[txinIndex]; + CCoins coins; + if (!viewMemPool.GetCoins(txin.prevout.hash, coins)) { + return error("%s: Missing input", __func__); + } + if (coins.nHeight == MEMPOOL_HEIGHT) { + // Assume all mempool transaction confirm in the next block + prevheights[txinIndex] = tip->nHeight + 1; + } else { + prevheights[txinIndex] = coins.nHeight; + } + } + + std::pair lockPair = CalculateSequenceLocks(tx, flags, &prevheights, index); + return EvaluateSequenceLocks(index, lockPair); + } + + +Acknowledgments +=============== + +This ZIP is closely based on BIP 68, authored by Mark Friedenbach, BtcDrak, Nicolas Dorier, +and kinoshitajona. + +Credit goes to Gregory Maxwell for providing a succinct and clear description of the behavior of +this change, which became the basis of the BIP text. + + +Deployment +========== + +This ZIP must be deployed simultaneously with [#zip-0112]_. + + +Compatibility +============= + +The only use of sequence numbers by the zcashd reference client software is to disable checking +the ``nLockTime`` constraints in a transaction. The semantics of that application are preserved +by this ZIP. + +As can be seen from the specification section, a number of bits are undefined by this ZIP to allow for other use cases by setting bit (1 << 31) as the remaining 31 bits have no meaning under this ZIP. Additionally, bits (1 << 23) through (1 << 30) inclusive have no meaning at all when bit (1 << 31) is unset. + +Additionally, this ZIP specifies only 16 bits to actually encode relative lock-time meaning a further 6 are unused (1 << 16 through 1 << 21 inclusive). This allows the possibility to increase granularity by soft-fork, or for increasing the maximum possible relative lock-time in the future. + +The most efficient way to calculate sequence number from relative lock-time is with bit masks and shifts: + +.. hightlight::c++ + + // 0 <= nHeight < 65,535 blocks (1.25 years) + nSequence = nHeight; + nHeight = nSequence & 0x0000ffff; + + // 0 <= nTime < 33,554,431 seconds (1.06 years) + nSequence = (1 << 22) | (nTime >> 9); + nTime = (nSequence & 0x0000ffff) << 9; + + +References +========== + +Bitcoin mailing list discussion: https://www.mail-archive.com/bitcoin-development@lists.sourceforge.net/msg07864.html + +BIP9: https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki + +ZIP112: https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki + +BIP113: https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki + +Hashed Timelock Contracts (HTLCs): https://github.com/ElementsProject/lightning/raw/master/doc/deployable-lightning.pdf diff --git a/zip-0112.rst b/zip-0112.rst new file mode 100644 index 00000000..d13146a5 --- /dev/null +++ b/zip-0112.rst @@ -0,0 +1,386 @@ +.. + + ZIP: 112 + Title: CHECKSEQUENCEVERIFY + Author: Daira Hopwood + Credits: BtcDrak , Mark Friedenbach , Eric Lombrozo + Category: Consensus + Status: Draft + Created: 2019-06-06 + License: MIT + + +Terminology +=========== + +The key word "MUST" in this document is to be interpreted as described in RFC 2119. [#RFC2119]_ + + +Abstract +======== + +This ZIP describes a new opcode (``CHECKSEQUENCEVERIFY``) for the Zcash scripting system, that +in combination with ZIP 68 allows execution pathways of a script to be restricted based on the +age of the output being spent. + + +Motivation +========== + +ZIP 68 repurposes the transaction ``nSequence`` field meaning by giving sequence numbers new +consensus-enforced semantics as a relative lock-time. However, there is no way to build Zcash +scripts to make decisions based on this field. + +By making the ``nSequence`` field accessible to script, it becomes possible to construct code +pathways that only become accessible some minimum time after proof-of-publication. This enables +a wide variety of applications in phased protocols such as escrow, payment channels, or +bidirectional pegs. + + +Specification +============= + +``CHECKSEQUENCEVERIFY`` redefines the existing ``NOP3`` opcode. When executed, if any of the +following conditions are true, the script interpreter MUST terminate with an error: + +* the stack is empty; or +* the top item on the stack is less than 0; or +* the top item on the stack has the disable flag (1 << 31) unset; and any of the following hold: + + * the transaction version is less than 2; or + * the transaction input sequence number disable flag (1 << 31) is set; or + * the relative lock-time type is not the same; or + * the top stack item is greater than the transaction input sequence (when masked according to + [#zip-0068]_; + +Otherwise, script execution MUST continue as if a ``NOP`` had been executed. + +ZIP 68 prevents a non-final transaction from being selected for inclusion in a block until the +corresponding input has reached the specified age, as measured in block-height or block-time. By +comparing the argument to ``CHECKSEQUENCEVERIFY`` against the ``nSequence`` field, we indirectly +verify a desired minimum age of the the output being spent; until that relative age has been +reached any script execution pathway including the ``CHECKSEQUENCEVERIFY`` will fail to validate, +causing the transaction not to be selected for inclusion in a block. + + +Use cases +========= + +Contracts With Expiration Deadlines +----------------------------------- + +Escrow with Timeout +''''''''''''''''''' + +An escrow that times out automatically 30 days after being funded can be established in the +following way. Alice, Bob and Escrow create a 2-of-3 address with the following redeem script:: + + IF + 2 3 CHECKMULTISIG + ELSE + "30d" CHECKSEQUENCEVERIFY DROP + CHECKSIG + ENDIF + +At any time funds can be spent using signatures from any two of Alice, Bob or the Escrow. + +After 30 days Alice can sign alone. + +The clock does not start ticking until the payment to the escrow address confirms. + + +Retroactive Invalidation +------------------------ + +In many instances, we would like to create contracts that can be revoked in case of some future +event. However, given the immutable nature of the block chain, it is practically impossible to +retroactively invalidate a previous commitment that has already confirmed. The only mechanism we +really have for retroactive invalidation is block chain reorganization which, for fundamental +security reasons, is designed to be very hard and very expensive to do. + +Despite this limitation, we do have a way to provide something functionally similar to retroactive +invalidation while preserving irreversibility of past commitments using ``CHECKSEQUENCEVERIFY``. +By constructing scripts with multiple branches of execution where one or more of the branches are +delayed we provide a time window in which someone can supply an invalidation condition that allows +the output to be spent, effectively invalidating the would-be delayed branch and potentially +discouraging another party from broadcasting the transaction in the first place. If the +invalidation condition does not occur before the timeout, the delayed branch becomes spendable, +honoring the original contract. + +Some more specific applications of this idea: + +Hash Time-Locked Contracts +'''''''''''''''''''''''''' + +Hash Time-Locked Contracts (HTLCs) provide a general mechanism for off-chain contract negotiation. +An execution pathway can be made to require knowledge of a secret (a hash preimage) that can be +presented within an invalidation time window. By sharing the secret it is possible to guarantee +to the counterparty that the transaction will never be broadcast since this would allow the +counterparty to claim the output immediately while one would have to wait for the time window +to pass. If the secret has not been shared, the counterparty will be unable to use the instant +pathway and the delayed pathway must be used instead. + +Bidirectional Payment Channels +'''''''''''''''''''''''''''''' + +Scriptable relative locktime provides a predictable amount of time to respond in the event a +counterparty broadcasts a revoked transaction: Absolute locktime necessitates closing the channel +and reopening it when getting close to the timeout, whereas with relative locktime, the clock +starts ticking the moment the transaction confirms in a block. It also provides a means to know +exactly how long to wait (in number of blocks) before funds can be pulled out of the channel in +the event of a noncooperative counterparty. + +Lightning Network +''''''''''''''''' + +The lightning network protocol [#lightning]_ extends the bidirectional payment channel idea to +allow for payments to be routed over multiple bidirectional payment channel hops. + +These channels are based on an anchor transaction that requires a 2-of-2 multisig from Alice and +Bob, and a series of revocable commitment transactions that spend the anchor transaction. The +commitment transaction splits the funds from the anchor between Alice and Bob and the latest +commitment transaction may be published by either party at any time, finalising the channel. + +Ideally then, a revoked commitment transaction would never be able to be successfully spent; and the +latest commitment transaction would be able to be spent very quickly. + +To allow a commitment transaction to be effectively revoked, Alice and Bob have slightly different +versions of the latest commitment transaction. In Alice's version, any outputs in the commitment +transaction that pay Alice also include a forced delay, and an alternative branch that allows Bob +to spend the output if he knows that transaction's revocation code. In Bob's version, payments +to Bob are similarly encumbered. When Alice and Bob negotiate new balances and new commitment +transactions, they also reveal the old revocation code, thus committing to not relaying the old +transaction. + +A simple output, paying to Alice might then look like:: + + HASH160 EQUAL + IF + + ELSE + "24h" CHECKSEQUENCEVERIFY DROP + + ENDIF + CHECKSIG + +This allows Alice to publish the latest commitment transaction at any time and spend the funds +after 24 hours, but also ensures that if Alice relays a revoked transaction, that Bob has 24 hours +to claim the funds. + +With ``CHECKLOCKTIMEVERIFY``, this would look like:: + + HASH160 EQUAL + IF + + ELSE + "2015/12/15" CHECKLOCKTIMEVERIFY DROP + + ENDIF + CHECKSIG + +This form of transaction would mean that if the anchor is unspent on 2015/12/16, Alice can use this +commitment even if it has been revoked, simply by spending it immediately, giving no time for Bob +to claim it. + +This means that the channel has a deadline that cannot be pushed back without hitting the blockchain; +and also that funds may not be available until the deadline is hit. ``CHECKSEQUENCEVERIFY`` allows +you to avoid making such a tradeoff. + +Hashed Time-Lock Contracts (HTLCs) make this slightly more complicated, since in principle they may +pay either Alice or Bob, depending on whether Alice discovers a secret R, or a timeout is reached, +but the same principle applies -- the branch paying Alice in Alice's commitment transaction gets a +delay, and the entire output can be claimed by the other party if the revocation secret is known. +With ``CHECKSEQUENCEVERIFY``, a HTLC payable to Alice might look like the following in Alice's +commitment transaction:: + + HASH160 DUP EQUAL + IF + "24h" CHECKSEQUENCEVERIFY + 2DROP + + ELSE + EQUAL + NOTIF + "2015/10/20 10:33" CHECKLOCKTIMEVERIFY DROP + ENDIF + + ENDIF + CHECKSIG + +and correspondingly in Bob's commitment transaction:: + + HASH160 DUP EQUAL + SWAP EQUAL ADD + IF + + ELSE + "2015/10/20 10:33" CHECKLOCKTIMEVERIFY + "24h" CHECKSEQUENCEVERIFY + 2DROP + + ENDIF + CHECKSIG + +Note that both ``CHECKSEQUENCEVERIFY`` and ``CHECKLOCKTIMEVERIFY`` are used in the final branch +above to ensure Bob cannot spend the output until after both the timeout is complete and Alice +has had time to reveal the revocation secret. + +See also the 'Deployable Lightning' paper [#deployable-lightning]_. + + +2-Way Pegged Sidechains +----------------------- + +The 2-way pegged sidechain requires a new ``REORGPROOFVERIFY`` opcode, the semantics of which +are outside the scope of this ZIP. ``CHECKSEQUENCEVERIFY`` is used to make sure that sufficient +time has passed since the return peg was posted to publish a reorg proof:: + + IF + lockTxHeight nlocktxOut [] reorgBounty Hash160(<...>) REORGPROOFVERIFY + ELSE + withdrawLockTime CHECKSEQUENCEVERIFY DROP HASH160 p2shWithdrawDest EQUAL + ENDIF + + + +Reference Implementation +======================== + +.. highlight::c++ + + /* Below flags apply in the context of ZIP 68 */ + /* If this flag set, CTxIn::nSequence is NOT interpreted as a + * relative lock-time. */ + static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31); + + /* If CTxIn::nSequence encodes a relative lock-time and this flag + * is set, the relative lock-time has units of 512 seconds, + * otherwise it specifies blocks with a granularity of 1. */ + static const uint32_t SEQUENCE_LOCKTIME_TYPE_FLAG = (1 << 22); + + /* If CTxIn::nSequence encodes a relative lock-time, this mask is + * applied to extract that lock-time from the sequence field. */ + static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff; + + case OP_NOP3: + { + if (!(flags & SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)) { + // not enabled; treat as a NOP3 + if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) { + return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); + } + break; + } + + if (stack.size() < 1) + return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); + + // Note that elsewhere numeric opcodes are limited to + // operands in the range -2**31+1 to 2**31-1, however it is + // legal for opcodes to produce results exceeding that + // range. This limitation is implemented by CScriptNum's + // default 4-byte limit. + // + // Thus as a special case we tell CScriptNum to accept up + // to 5-byte bignums, which are good until 2**39-1, well + // beyond the 2**32-1 limit of the nSequence field itself. + const CScriptNum nSequence(stacktop(-1), fRequireMinimal, 5); + + // In the rare event that the argument may be < 0 due to + // some arithmetic being done first, you can always use + // 0 MAX CHECKSEQUENCEVERIFY. + if (nSequence < 0) + return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME); + + // To provide for future soft-fork extensibility, if the + // operand has the disabled lock-time flag set, + // CHECKSEQUENCEVERIFY behaves as a NOP. + if ((nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) != 0) + break; + + // Compare the specified sequence number with the input. + if (!checker.CheckSequence(nSequence)) + return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME); + + break; + } + + bool TransactionSignatureChecker::CheckSequence(const CScriptNum& nSequence) const + { + // Relative lock times are supported by comparing the passed + // in operand to the sequence number of the input. + const int64_t txToSequence = (int64_t)txTo->vin[nIn].nSequence; + + // Fail if the transaction's version number is not set high + // enough to trigger ZIP 68 rules. + if (static_cast(txTo->nVersion) < 2) + return false; + + // Sequence numbers with their most significant bit set are not + // consensus constrained. Testing that the transaction's sequence + // number do not have this bit set prevents using this property + // to get around a CHECKSEQUENCEVERIFY check. + if (txToSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) + return false; + + // Mask off any bits that do not have consensus-enforced meaning + // before doing the integer comparisons + const uint32_t nLockTimeMask = CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG | CTxIn::SEQUENCE_LOCKTIME_MASK; + const int64_t txToSequenceMasked = txToSequence & nLockTimeMask; + const CScriptNum nSequenceMasked = nSequence & nLockTimeMask; + + // There are two kinds of nSequence: lock-by-blockheight + // and lock-by-blocktime, distinguished by whether + // nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG. + // + // We want to compare apples to apples, so fail the script + // unless the type of nSequenceMasked being tested is the same as + // the nSequenceMasked in the transaction. + if (!( + (txToSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked < CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) || + (txToSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG && nSequenceMasked >= CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) + )) + return false; + + // Now that we know we're comparing apples-to-apples, the + // comparison is a simple numeric one. + if (nSequenceMasked > txToSequenceMasked) + return false; + + return true; + } + + +Deployment +========== + +At the time of writing it has not been decided which network upgrade (if any) will implement this +proposal. + +This ZIP must be deployed simultaneously with ZIP 68 [#zip-0068]_. + + +Acknowledgements +================ + +This ZIP is closely based on BIP 112, authored by BtcDrak. + +Mark Friedenbach invented the application of sequence numbers to achieve relative lock-time, and +wrote the reference implementation of ``CHECKSEQUENCEVERIFY`` for Bitcoin. + +The Bitcoin reference implementation and BIP 112 was based heavily on work done by Peter Todd for +the closely related BIP 65. Eric Lombrozo and Anthony Towns contributed example use cases. + + +References +========== + +.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels `_ +.. [#protocol] `Zcash Protocol Specification, Version 2019.0.1 or later [Overwinter+Sapling] `_ +.. [#bip-0065] `BIP 65: OP_CHECKLOCKTIMEVERIFY `_ +.. [#zip-0068] `ZIP 68: Relative lock-time through consensus-enforced sequence numbers `_ +.. [#deployable-lightning] `Deployable Lightning `_ +.. [#lightning] `Lightning Network paper `_ +.. [#HTLCs] `HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and revocation hashes `_ +.. [#scaling] `Scaling Bitcoin to Billions of Transactions Per Day `_ +.. [#micropayments] `Jeremy Spilman, Micropayment Channels `_ From d8b98a708b5ca58fd53ff9f5fd45dd4a8007b447 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 18 Jun 2019 20:04:23 +0100 Subject: [PATCH 2/4] Update ZIPs 68 and 112, and add ZIP 113. Signed-off-by: Daira Hopwood --- zip-0068.rst | 110 +++++++++++++++++++++++++--------------------- zip-0112.rst | 6 ++- zip-0113.rst | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 52 deletions(-) create mode 100644 zip-0113.rst diff --git a/zip-0068.rst b/zip-0068.rst index 0765c4e3..e5393051 100644 --- a/zip-0068.rst +++ b/zip-0068.rst @@ -1,8 +1,11 @@ -.. +:: ZIP: 68 Title: Relative lock-time using consensus-enforced sequence numbers - Credits: Mark Friedenbach , BtcDrak , Nicolas Dorier , kinoshitajona + Credits: Mark Friedenbach + BtcDrak + Nicolas Dorier + kinoshitajona Category: Consensus Status: Draft Created: 2016-06-06 @@ -14,9 +17,8 @@ Terminology The key words "MUST" and "MAY" in this document are to be interpreted as described in RFC 2119. [#RFC2119]_ -The "Median Time Past" of a block in this document refers to the median time of the prior -PoWMedianBlockSpan blocks, where the constant PoWMedianBlockSpan is defined in [#protocol]_ -section 5.3, and the median function is defined as in [#protocol]_ section 7.6.3. +The "Median Time Past" of a block in this document is to be interpreted as described in +[#zip-0113]_. Abstract @@ -42,7 +44,7 @@ room for future expansion and other use cases. The transaction ``nLockTime`` is used to prevent the mining of a transaction until a certain date. ``nSequence`` will be repurposed to prevent mining of a transaction until a certain age of the spent output in blocks or timespan. This, among other uses, allows -bi-directional payment channels as used in [#HTLCs]_ and [#zip-0112]_. +bi-directional payment channels as used in [#deployable-lightning]_ and [#zip-0112]_. Specification @@ -61,40 +63,43 @@ interpreted as an encoded relative lock-time. The sequence number encoding MUST be interpreted as follows: Bit (1 << 22) determines if the relative lock-time is time-based or block based: -If the bit is set, the relative lock-time specifies a timespan in units of 512 seconds -granularity. The timespan starts from the median-time-past of the output’s previous block, +If the bit is set, the relative lock-time specifies a timespan in units of 32 seconds +granularity. The timespan starts from the Median Time Past of the output’s previous block, and ends at the Median Time Past of the previous block. If the bit is not set, the relative lock-time specifies a number of blocks. +Note: the 64-second time unit differs from Bitcoin's BIP 68, which uses a 512-second +time unit. + The flag (1 << 22) is the highest order bit in a 3-byte signed integer for use in Zcash scripts as a 3-byte ``PUSHDATA`` with ``OP_CHECKSEQUENCEVERIFY`` [#zip-0112]_. -This specification only interprets 16 bits of the sequence number as relative lock-time, -so a mask of ``0x0000FFFF`` MUST be applied to the sequence field to extract the relative -lock-time. The 16-bit specification allows for a year of relative lock-time and the -remaining bits allow for future expansion. +This specification only interprets 22 bits of the sequence number as relative lock-time, +so a mask of ``0x003FFFFF`` MUST be applied to the sequence field to extract the relative +lock-time. The 22-bit specification allows for over 8.5 years of relative lock-time. -:raw-html-m2r:`` +.. image:: encoding.png + :alt:A 32-bit field with 'Disable Flag' at bit (1 << 31), 'Type Flag' at bit (1 << 22), and 'Value' in the low 22 bits. -For time based relative lock-time, 512-second granularity was chosen because Bitcoin -blocks are generated every 600 seconds. [TODO: should this be changed for Zcash?] -So when using block-based or time-based, the same amount of time can be encoded with -the available number of bits. Converting from a sequence number to seconds is performed -by multiplying by 512 = 2^9, or equivalently shifting up by 9 bits. +For time-based relative lock-time, 64-second granularity was chosen because the block +target spacing for Zcash, after activation of the Blossom network upgrade, is 75 seconds. +So when using block-based or time-based, roughly the same amount of time can be encoded +with the available number of bits. Converting from a sequence number to seconds is +performed by multiplying by 64. When the relative lock-time is time-based, it is interpreted as a minimum block-time constraint over the input's age. A relative time-based lock-time of zero indicates an input which can be included in any block. More generally, a relative time-based -lock-time n can be included into any block produced 512 \* n seconds after the mining +lock-time n can be included into any block produced 64 \* n seconds after the mining date of the output it is spending, or any block thereafter. The mining date of the output is equal to the Median Time Past of the previous block -which mined it. +that mined it. The block produced time is equal to the Median Time Past of its previous block. When the relative lock-time is block-based, it is interpreted as a minimum block-height constraint over the input's age. A relative block-based lock-time of zero indicates an -input which can be included in any block. More generally, a relative block lock-time n +input that can be included in any block. More generally, a relative block lock-time n MAY be included n blocks after the mining date of the output it is spending, or any block thereafter. @@ -116,7 +121,7 @@ Reference Implementation * disables nLockTime. */ static const uint32_t SEQUENCE_FINAL = 0xffffffff; - /* Below flags apply in the context of ZIP 68*/ + /* Below flags apply in the context of ZIP 68. */ /* If this flag set, CTxIn::nSequence is NOT interpreted as a * relative lock-time. */ static const uint32_t SEQUENCE_LOCKTIME_DISABLE_FLAG = (1 << 31); @@ -128,16 +133,16 @@ Reference Implementation /* If CTxIn::nSequence encodes a relative lock-time, this mask is * applied to extract that lock-time from the sequence field. */ - static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x0000ffff; + static const uint32_t SEQUENCE_LOCKTIME_MASK = 0x003fffff; /* In order to use the same number of bits to encode roughly the * same wall-clock duration, and because blocks are naturally - * limited to occur every 600s on average, the minimum granularity - * for time-based relative lock-time is fixed at 512 seconds. + * limited to occur every 75s on average after Blossom activation, + * the minimum granularity for time-based relative lock-time is + * fixed at 64 seconds. * Converting from CTxIn::nSequence to seconds is performed by - * multiplying by 512 = 2^9, or equivalently shifting up by - * 9 bits. */ - static const int SEQUENCE_LOCKTIME_GRANULARITY = 9; + * multiplying by 64, or equivalently shifting up by 6 bits. */ + static const int SEQUENCE_LOCKTIME_GRANULARITY = 6; /** * Calculates the block height and previous block's Median Time Past at @@ -264,17 +269,20 @@ Reference Implementation Acknowledgments =============== -This ZIP is closely based on BIP 68, authored by Mark Friedenbach, BtcDrak, Nicolas Dorier, -and kinoshitajona. +This ZIP is based on BIP 68, authored by Mark Friedenbach, BtcDrak, Nicolas Dorier, and +kinoshitajona. -Credit goes to Gregory Maxwell for providing a succinct and clear description of the behavior of -this change, which became the basis of the BIP text. +Credit goes to Gregory Maxwell for providing a succinct and clear description of the behavior +of this change, which became the basis of the BIP text. Deployment ========== -This ZIP must be deployed simultaneously with [#zip-0112]_. +At the time of writing it has not been decided which network upgrade (if any) will implement this +proposal. + +This ZIP is designed to be deployed simultaneously with [#zip-0112]_ and [#zip-0113]_. Compatibility @@ -284,32 +292,34 @@ The only use of sequence numbers by the zcashd reference client software is to d the ``nLockTime`` constraints in a transaction. The semantics of that application are preserved by this ZIP. -As can be seen from the specification section, a number of bits are undefined by this ZIP to allow for other use cases by setting bit (1 << 31) as the remaining 31 bits have no meaning under this ZIP. Additionally, bits (1 << 23) through (1 << 30) inclusive have no meaning at all when bit (1 << 31) is unset. +As can be seen from the specification section, a number of bits are undefined by this ZIP to +allow for other use cases by setting bit (1 << 31) as the remaining 31 bits have no meaning +under this ZIP. Additionally, bits (1 << 23) through (1 << 30) inclusive have no meaning at all +when bit (1 << 31) is unset. -Additionally, this ZIP specifies only 16 bits to actually encode relative lock-time meaning a further 6 are unused (1 << 16 through 1 << 21 inclusive). This allows the possibility to increase granularity by soft-fork, or for increasing the maximum possible relative lock-time in the future. +Unlike BIP 68 in Bitcoin, all of the low 22 bits are used for the value. This reflects the fact +that blocks are more frequent (75 seconds instead of 600 seconds), and so more bits are needed +to obtain approximately the same range of time. -The most efficient way to calculate sequence number from relative lock-time is with bit masks and shifts: +The most efficient way to calculate sequence number from relative lock-time is with bit masks +and shifts: .. hightlight::c++ - // 0 <= nHeight < 65,535 blocks (1.25 years) + // 0 <= nHeight <= 4194303 blocks (~10 years at post-Blossom block target spacing) nSequence = nHeight; - nHeight = nSequence & 0x0000ffff; + nHeight = nSequence & 0x003fffff; - // 0 <= nTime < 33,554,431 seconds (1.06 years) - nSequence = (1 << 22) | (nTime >> 9); - nTime = (nSequence & 0x0000ffff) << 9; + // 0 <= nTime <= 268435392 seconds (~8.5 years) + nSequence = (1 << 22) | (nTime >> 6); + nTime = (nSequence & 0x003fffff) << 6; References ========== -Bitcoin mailing list discussion: https://www.mail-archive.com/bitcoin-development@lists.sourceforge.net/msg07864.html - -BIP9: https://github.com/bitcoin/bips/blob/master/bip-0009.mediawiki - -ZIP112: https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki - -BIP113: https://github.com/bitcoin/bips/blob/master/bip-0113.mediawiki - -Hashed Timelock Contracts (HTLCs): https://github.com/ElementsProject/lightning/raw/master/doc/deployable-lightning.pdf +.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels `_ +.. [#mailing-list] `Bitcoin mailing list discussion `_ +.. [#zip-0112] `ZIP 112: CHECKSEQUENCEVERIFY `_ +.. [#zip-0113] `ZIP 113: Median Time Past as endpoint for lock-time calculations `_ +.. [#deployable-lightning] `Reaching The Ground With Lightning (draft 0.2) `_ diff --git a/zip-0112.rst b/zip-0112.rst index d13146a5..a6c130c0 100644 --- a/zip-0112.rst +++ b/zip-0112.rst @@ -1,9 +1,11 @@ -.. +:: ZIP: 112 Title: CHECKSEQUENCEVERIFY Author: Daira Hopwood - Credits: BtcDrak , Mark Friedenbach , Eric Lombrozo + Credits: BtcDrak + Mark Friedenbach + Eric Lombrozo Category: Consensus Status: Draft Created: 2019-06-06 diff --git a/zip-0113.rst b/zip-0113.rst new file mode 100644 index 00000000..d7d657a4 --- /dev/null +++ b/zip-0113.rst @@ -0,0 +1,122 @@ +:: + + ZIP: 113 + Title: Median Time Past as endpoint for lock-time calculations + Author: Daira Hopwood + Credits: Thomas Kerin + Mark Friedenbach + Gregory Maxwell + Category: Consensus + Status: Draft + Created: 2019-06-07 + License: MIT + + +Terminology +=========== + +The key words "MUST" and "MAY" in this document are to be interpreted as described in +RFC 2119. [#RFC2119]_ + + +Abstract +======== + +This ZIP is a proposal to redefine the semantics used in determining a time-locked +transaction's eligibility for inclusion in a block. The median of the last PoWMedianBlockSpan +(11) blocks is used instead of the block's timestamp, ensuring that it increases +monotonically with each block. + + +Motivation +========== + +At present, transactions are excluded from inclusion in a block if the present time or block +height is less than or equal to that specified in the locktime. Since the consensus rules +do not mandate strict ordering of block timestamps, this has the unfortunate outcome of +creating a perverse incentive for miners to lie about the time of their blocks in order to +collect more fees by including transactions that by wall clock determination have not yet +matured. + +This ZIP proposes comparing the locktime against the median of the past PoWMedianBlockSpan +blocks' timestamps, rather than the timestamp of the block including the transaction. +Existing consensus rules guarantee this value to monotonically advance, thereby removing +the capability for miners to claim more transaction fees by lying about the timestamps of +their block. + +This proposal seeks to ensure reliable behaviour in locktime calculations as required by +[#bip-0065]_ (CHECKLOCKTIMEVERIFY) and matching the behavior of [#zip-0112]_ (CHECKSEQUENCEVERIFY). +This also matches the use of Median Time Past in difficulty adjustment as specified in +section 7.6.3 of [#protocol]_. + + +Specification +============= + +Let PoWMedianBlockSpan be as defined in [#protocol]_ section 5.3, and let the median +function be as defined in [#protocol]_ section 7.6.3. + +The Median Time Past of a block is specified as the median of the timestamps of the +prior PoWMedianBlockSpan blocks, as calculated by MedianTime(height) in [#protocol]_ +section 7.6.3. + +The values for transaction locktime remain unchanged. The difference is only in the +calculation determining whether a transaction can be included. After activation of +this ZIP, lock-time constraints of a transaction MUST be checked according to the +Median Time Past of the transaction's block. + +[FIXME make this a proper specification, independent of the zcashd implementation.] + +Lock-time constraints are checked by the consensus method ``IsFinalTx()``. This method +takes the block time as one parameter. This ZIP proposes that after activation calls to +``IsFinalTx()`` within consensus code use the return value of ``GetMedianTimePast(pindexPrev)`` +instead. + +The new rule applies to all transactions, including the coinbase transaction. + + +Reference Implementation +======================== + +This will be based on `Bitcoin PR 6566 `_. + + +Acknowledgements +================ + +This ZIP is based on BIP 113, authored by Thomas Kerin and Mark Friedenbach. + +Mark Friedenbach designed and authored the reference implementation for Bitcoin. + +Gregory Maxwell came up with the original idea, in #bitcoin-wizards on +`2013-07-16 `_ and +`2013-07-17 `_. + + +Deployment +========== + +At the time of writing it has not been decided which network upgrade (if any) will implement this +proposal. + +This ZIP is designed to be deployed simultaneously with [#zip-0068]_ and [#zip-0112]_. + + +Compatibility +============= + +At the post-Blossom block target spacing of 75 seconds, transactions generated using time-based +lock-time will take approximately 7.5 minutes longer to confirm than would be expected under the +old rules. This is not known to introduce any compatibility concerns with existing protocols. +This delay is less than in Bitcoin due to the faster block target spacing in Zcash. + + +References +========== + +.. [#RFC2119] `Key words for use in RFCs to Indicate Requirement Levels `_ +.. [#protocol] `Zcash Protocol Specification, Version 2019.0.1 or later [Overwinter+Sapling+Blossom] `_ +.. [#bip-0065] `BIP 65: OP_CHECKLOCKTIMEVERIFY `_ +.. [#zip-0068] `ZIP 68: Consensus-enforced transaction replacement signaled via sequence numbers `_ +.. [#zip-0112] `ZIP 112: CHECKSEQUENCEVERIFY `_ + From ffee09963f5e2ccb83448ebd5a062369bfc27530 Mon Sep 17 00:00:00 2001 From: Daira Hopwood Date: Tue, 18 Jun 2019 20:06:03 +0100 Subject: [PATCH 3/4] Move ZIP 68 into directory and add encoding diagram. Signed-off-by: Daira Hopwood --- zip-0068/encoding.png | Bin 0 -> 6252 bytes zip-0068.rst => zip-0068/zip-0068.rst | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 zip-0068/encoding.png rename zip-0068.rst => zip-0068/zip-0068.rst (100%) diff --git a/zip-0068/encoding.png b/zip-0068/encoding.png new file mode 100644 index 0000000000000000000000000000000000000000..a244e6ba64f9254121dfe8040843146468ca0c25 GIT binary patch literal 6252 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 Date: Wed, 17 Jul 2024 02:24:32 +0000 Subject: [PATCH 4/4] Move ZIPs 68, 112, and 113 into `zips/` subdirectory --- .../assets/images/zip-0068-encoding.png | Bin {zip-0068 => zips}/zip-0068.rst | 7 +++++-- zip-0112.rst => zips/zip-0112.rst | 0 zip-0113.rst => zips/zip-0113.rst | 0 4 files changed, 5 insertions(+), 2 deletions(-) rename zip-0068/encoding.png => rendered/assets/images/zip-0068-encoding.png (100%) rename {zip-0068 => zips}/zip-0068.rst (98%) rename zip-0112.rst => zips/zip-0112.rst (100%) rename zip-0113.rst => zips/zip-0113.rst (100%) diff --git a/zip-0068/encoding.png b/rendered/assets/images/zip-0068-encoding.png similarity index 100% rename from zip-0068/encoding.png rename to rendered/assets/images/zip-0068-encoding.png diff --git a/zip-0068/zip-0068.rst b/zips/zip-0068.rst similarity index 98% rename from zip-0068/zip-0068.rst rename to zips/zip-0068.rst index e5393051..1c22879e 100644 --- a/zip-0068/zip-0068.rst +++ b/zips/zip-0068.rst @@ -78,8 +78,11 @@ This specification only interprets 22 bits of the sequence number as relative lo so a mask of ``0x003FFFFF`` MUST be applied to the sequence field to extract the relative lock-time. The 22-bit specification allows for over 8.5 years of relative lock-time. -.. image:: encoding.png - :alt:A 32-bit field with 'Disable Flag' at bit (1 << 31), 'Type Flag' at bit (1 << 22), and 'Value' in the low 22 bits. +.. figure:: ../rendered/assets/images/zip-0068-encoding.png + :align: center + :figclass: align-center + + A 32-bit field with 'Disable Flag' at bit (1 << 31), 'Type Flag' at bit (1 << 22), and 'Value' in the low 22 bits. For time-based relative lock-time, 64-second granularity was chosen because the block target spacing for Zcash, after activation of the Blossom network upgrade, is 75 seconds. diff --git a/zip-0112.rst b/zips/zip-0112.rst similarity index 100% rename from zip-0112.rst rename to zips/zip-0112.rst diff --git a/zip-0113.rst b/zips/zip-0113.rst similarity index 100% rename from zip-0113.rst rename to zips/zip-0113.rst