Merge pull request #240 from daira/op-csv

Add ZIPs 68, 112, and 113 (OP_CHECKSEQUENCEVERIFY)
This commit is contained in:
Jack Grigg 2024-07-17 15:55:08 +01:00 committed by GitHub
commit 94f654c2ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 838 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

328
zips/zip-0068.rst Normal file
View File

@ -0,0 +1,328 @@
::
ZIP: 68
Title: Relative lock-time using consensus-enforced sequence numbers
Credits: Mark Friedenbach <mark@friedenbach.org>
BtcDrak <btcdrak@gmail.com>
Nicolas Dorier <nicolas.dorier@gmail.com>
kinoshitajona <kinoshitajona@gmail.com>
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 outputs 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<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* 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<uint32_t>(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<int, int64_t> 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<int>* 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<int> 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<int, int64_t> 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 <https://tools.ietf.org/html/rfc2119>`_
.. [#mailing-list] `Bitcoin mailing list discussion <https://www.mail-archive.com/bitcoin-development@lists.sourceforge.net/msg07864.html>`_
.. [#zip-0112] `ZIP 112: CHECKSEQUENCEVERIFY <https://github.com/daira/zips/blob/op-csv/zip-0112.rst>`_
.. [#zip-0113] `ZIP 113: Median Time Past as endpoint for lock-time calculations <https://github.com/daira/zips/blob/op-csv/zip-0113.rst>`_
.. [#deployable-lightning] `Reaching The Ground With Lightning (draft 0.2) <https://github.com/ElementsProject/lightning/raw/master/doc/deployable-lightning.pdf>`_

388
zips/zip-0112.rst Normal file
View File

@ -0,0 +1,388 @@
::
ZIP: 112
Title: CHECKSEQUENCEVERIFY
Author: Daira Hopwood <daira@electriccoin.co>
Credits: BtcDrak <btcdrak@gmail.com>
Mark Friedenbach <mark@friedenbach.org>
Eric Lombrozo <elombrozo@gmail.com>
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 <Alice's pubkey> <Bob's pubkey> <Escrow's pubkey> 3 CHECKMULTISIG
ELSE
"30d" CHECKSEQUENCEVERIFY DROP
<Alice's pubkey> 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 <revokehash> EQUAL
IF
<Bob's pubkey>
ELSE
"24h" CHECKSEQUENCEVERIFY DROP
<Alice's pubkey>
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 <revokehash> EQUAL
IF
<Bob's pubkey>
ELSE
"2015/12/15" CHECKLOCKTIMEVERIFY DROP
<Alice's pubkey>
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 <R-HASH> EQUAL
IF
"24h" CHECKSEQUENCEVERIFY
2DROP
<Alice's pubkey>
ELSE
<Commit-Revocation-Hash> EQUAL
NOTIF
"2015/10/20 10:33" CHECKLOCKTIMEVERIFY DROP
ENDIF
<Bob's pubkey>
ENDIF
CHECKSIG
and correspondingly in Bob's commitment transaction::
HASH160 DUP <R-HASH> EQUAL
SWAP <Commit-Revocation-Hash> EQUAL ADD
IF
<Alice's pubkey>
ELSE
"2015/10/20 10:33" CHECKLOCKTIMEVERIFY
"24h" CHECKSEQUENCEVERIFY
2DROP
<Bob's pubkey>
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 <lockTxHash> nlocktxOut [<workAmount>] reorgBounty Hash160(<...>) <genesisHash> 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<uint32_t>(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 <https://tools.ietf.org/html/rfc2119>`_
.. [#protocol] `Zcash Protocol Specification, Version 2019.0.1 or later [Overwinter+Sapling] <https://github.com/zcash/zips/blob/master/protocol/protocol.pdf>`_
.. [#bip-0065] `BIP 65: OP_CHECKLOCKTIMEVERIFY <https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>`_
.. [#zip-0068] `ZIP 68: Relative lock-time through consensus-enforced sequence numbers <https://github.com/zcash/zips/blob/op-csv/zip-0068.rst>`_
.. [#deployable-lightning] `Deployable Lightning <https://github.com/ElementsProject/lightning/blob/master/doc/deployable-lightning.pdf>`_
.. [#lightning] `Lightning Network paper <http://lightning.network/lightning-network-paper.pdf>`_
.. [#HTLCs] `HTLCs using OP_CHECKSEQUENCEVERIFY/OP_LOCKTIMEVERIFY and revocation hashes <http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-July/000021.html>`_
.. [#scaling] `Scaling Bitcoin to Billions of Transactions Per Day <http://diyhpl.us/diyhpluswiki/transcripts/sf-bitcoin-meetup/2015-02-23-scaling-bitcoin-to-billions-of-transactions-per-day/>`_
.. [#micropayments] `Jeremy Spilman, Micropayment Channels <https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2013-April/002433.html>`_

122
zips/zip-0113.rst Normal file
View File

@ -0,0 +1,122 @@
::
ZIP: 113
Title: Median Time Past as endpoint for lock-time calculations
Author: Daira Hopwood <daira@electriccoin.co>
Credits: Thomas Kerin <me@thomaskerin.io>
Mark Friedenbach <mark@friedenbach.org>
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 <https://github.com/bitcoin/bitcoin/pull/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 <https://download.wpsoftware.net/bitcoin/wizards/2013/07/13-07-16.log>`_ and
`2013-07-17 <https://download.wpsoftware.net/bitcoin/wizards/2013/07/13-07-17.log>`_.
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 <https://tools.ietf.org/html/rfc2119>`_
.. [#protocol] `Zcash Protocol Specification, Version 2019.0.1 or later [Overwinter+Sapling+Blossom] <https://github.com/zcash/zips/blob/master/protocol/blossom.pdf>`_
.. [#bip-0065] `BIP 65: OP_CHECKLOCKTIMEVERIFY <https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki>`_
.. [#zip-0068] `ZIP 68: Consensus-enforced transaction replacement signaled via sequence numbers <https://github.com/daira/zips/blob/op-csv/zip-0068.rst>`_
.. [#zip-0112] `ZIP 112: CHECKSEQUENCEVERIFY <https://github.com/daira/zips/blob/op-csv/zip-0112.rst>`_