diff --git a/rendered/assets/images/zip-0068-encoding.png b/rendered/assets/images/zip-0068-encoding.png new file mode 100644 index 00000000..a244e6ba Binary files /dev/null and b/rendered/assets/images/zip-0068-encoding.png differ diff --git a/zips/zip-0068.rst b/zips/zip-0068.rst new file mode 100644 index 00000000..1c22879e --- /dev/null +++ b/zips/zip-0068.rst @@ -0,0 +1,328 @@ +:: + + 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 is to be interpreted as described in +[#zip-0113]_. + + +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 [#deployable-lightning]_ 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 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 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. + +.. 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. +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 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 +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 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. + +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 = 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 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 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 + * 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 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 +========== + +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 +============= + +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. + +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: + +.. hightlight::c++ + + // 0 <= nHeight <= 4194303 blocks (~10 years at post-Blossom block target spacing) + nSequence = nHeight; + nHeight = nSequence & 0x003fffff; + + // 0 <= nTime <= 268435392 seconds (~8.5 years) + nSequence = (1 << 22) | (nTime >> 6); + nTime = (nSequence & 0x003fffff) << 6; + + +References +========== + +.. [#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/zips/zip-0112.rst b/zips/zip-0112.rst new file mode 100644 index 00000000..a6c130c0 --- /dev/null +++ b/zips/zip-0112.rst @@ -0,0 +1,388 @@ +:: + + 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 `_ diff --git a/zips/zip-0113.rst b/zips/zip-0113.rst new file mode 100644 index 00000000..d7d657a4 --- /dev/null +++ b/zips/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 `_ +