<p>mulllhausen's answer is great, but here's a shorter example that illustrates why the vin seq number can't be final or maxed.</p>

<p>Suppose I want to spend a CLTV output. I wait until the CLTV time has passed, and then create a transaction with nLockTime set to the current block time, and the sequence number set to something less than 2^32-1, say 0.</p>

<p>Now that transaction will verify because </p>

<pre><code>CLTV time &lt;= tx.nLockTime &lt;= current block time
</code></pre>

<p>We're basically using nLockTime as a proxy for the current block time to say current block time is past the CLTV time.</p>

<p>However, if I set all my seq numbers to max, I would be able to submit a transaction with an nLockTime in the future, ie, greater than current block time, thereby bypassing the CLTV time. nLockTime must be &lt;= to current block time if not all seq numbers are maxed. So by checking to make sure at least one Vin Seq number is not final, we make sure they all aren't maxed, allowing this bypass scenario.</p>

CC BY-SA 3.0
2016-03-12T18:29:06.343Z
2016-03-12T18:29:06.343Z
Scott Driscoll
<p><a href="https://bitcoin.org/en/developer-guide#locktime-and-sequence-number" rel="nofollow noreferrer">From Bitcoin.org</a>:</p>

<blockquote>
  <p>Locktime allows signers to create time-locked transactions which will only become valid in the future, giving the signers a chance to change their minds.</p>
  
  <p>...</p>
  
  <p>Previous versions of Bitcoin Core provided a feature which prevented transaction signers from using the method described above to cancel a time-locked transaction, but a necessary part of this feature was disabled to prevent denial of service attacks. A legacy of this system are four-byte sequence numbers in every input. <strong>Sequence numbers were meant to allow multiple signers to agree to update a transaction; when they finished updating the transaction</strong>, they could agree to set every input’s sequence number to the four-byte unsigned maximum (0xffffffff), allowing the transaction to be added to a block even if its time lock had not expired.</p>
  
  <p>Even today, setting all sequence numbers to 0xffffffff (the default in Bitcoin Core) can still disable the time lock, so <strong>if you want to use locktime, at least one input must have a sequence number below the maximum Since sequence numbers are not used by the network for any other purpose, setting any sequence number to zero is sufficient to enable locktime</strong>.</p>
</blockquote>

<p>So it's essentially that nLockTime is disabled if the sequence value is <code>0xffffffff</code>, but for <code>0 &lt;= sequence_value &lt; 0xffffffff</code>, nTimeLock is enabled. </p>

<p>IMO the confusion is arising because there's conflation of the functionality of <code>OP_CHECKLOCKTIMEVERIFY</code> (BIP65) and <em>nTimeLock</em>. I was <a href="https://bitcoin.stackexchange.com/questions/38444/bip65-replacing-ntimelock-entirely">similarly confused</a>, so check out <a href="https://bitcoin.org/en/developer-guide#locktime-and-sequence-number" rel="nofollow noreferrer">these Bitcoin.org definitions</a> and <a href="http://earlfox.blogspot.com/2014/06/nlocktime-may-disappoint-you.html" rel="nofollow noreferrer"><em>nTimeLock may disappoint you</em></a></p>

CC BY-SA 3.0
2015-09-30T14:40:56.240Z
some more good discussion on the topic - https://bitcointalk.org/index.php?topic=766893.0
mulllhausen
CC BY-SA 3.0
2015-10-01T13:35:36.297Z
I'm still confused - mainly by the comment where it says "and thus CHECKLOCKTIMEVERIFY bypassed". If the sequence number is maxxed out but there is a script with CHECKLOCKTIMEVERIFY in it, then this will NOT be bypassed - the script will fail!
mulllhausen
CC BY-SA 3.0
2015-10-01T13:42:57.733Z
@mulllhausen I'm not versed in C++, so can you clarify what `if (txTo->vin[nIn].isFinal());` means? txTo is the spending transaction, and vin[nIn] is just an array of UTXOs, right? What does `->` mean? Re `if the sequence number is maxxed out but there is a script with CHECKLOCKTIMEVERIFY in it, then this will NOT be bypassed - the script will fail!`... Hmm, yes, I see your point. I wonder what bypassing means? It may just mean the scripting drops OP_CLTV if the sequence is less than 0xffffffff?
Wizard Of Ozzie
CC BY-SA 3.0
2015-10-01T14:31:00.247Z
`isFinal()` [is a method in transaction.h](https://github.com/bitcoin/bitcoin/blob/24ce77d775f48034ef0c42fa21017d145c790921/src/primitives/transaction.h#L81). its basically a check for `sequence num == 0xffffffff` for this txin. when this condition is met then a script containing `OP_CHECKLOCKTIMEVERIFY` fails with [`set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);`](https://github.com/bitcoin/bitcoin/blob/24ce77d775f48034ef0c42fa21017d145c790921/src/script/interpreter.cpp#L377)
mulllhausen
CC BY-SA 3.0
2015-09-30T04:48:47.203Z
2015-09-30T04:48:47.203Z
2017-04-13T12:47:33.283Z
Wizard Of Ozzie
<p>the purpose of <code>OP_CHECKLOCKTIMEVERIFY</code> is kind of the opposite to the purpose of <code>tx.nLockTime</code>. <code>tx.nLockTime</code> prevents transactions with future dates from entering the blockchain, whereas <code>OP_CHECKLOCKTIMEVERIFY</code> enables someone to freeze funds so that they can only be spent <em>after</em> a given timestamp or block height.</p>
<h2><code>tx.nLockTime</code></h2>
<p><code>tx.nLockTime</code> is validated by function <code>IsFinalTx()</code> <a href="https://github.com/bitcoin/bitcoin/blob/4899a04c24b927166048a74999992d216a543c23/src/main.cpp#L641-L651" rel="nofollow noreferrer">in <code>src/main.cpp</code></a>:</p>
<pre class="lang-cpp prettyprint-override"><code>bool IsFinalTx(const CTransaction &amp;tx, int nBlockHeight, int64_t nBlockTime)
{
    if (tx.nLockTime == 0)
        return true;
    if ((int64_t)tx.nLockTime &lt; ((int64_t)tx.nLockTime &lt; LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
        return true;
    BOOST_FOREACH(const CTxIn&amp; txin, tx.vin)
        if (!txin.IsFinal())
            return false;
    return true;
}
</code></pre>
<p>where <code>txin.IsFinal()</code> is <a href="https://github.com/bitcoin/bitcoin/blob/24ce77d775f48034ef0c42fa21017d145c790921/src/primitives/transaction.h#L81-L84" rel="nofollow noreferrer">in <code>src/primitives/transaction.h</code></a>:</p>
<pre class="lang-cpp prettyprint-override"><code>bool IsFinal() const
{
    return (nSequence == std::numeric_limits&lt;uint32_t&gt;::max());
}
</code></pre>
<p>If the tx locktime is below the threshold then it is treated as a block height and if it is above the threshold then it is treated as a timestamp. Either way, the transaction locktime value must be smaller than the relevant constraint. If it is larger then miners must wait before including the transaction in a block.</p>
<p>The only way to bypass this transaction locktime constraint is to disable the transaction locktime completely by setting all txin sequence numbers to maxint. When this is done then miners will include the transaction straight away, even if the locktime has not yet been reached.</p>
<p>The idea with the transaction locktime is that before the transaction is locked (ie before the block height or timestamp catch up with tx locktime), someone can make amendments to the transaction. Each time they make a change then they must increment the sequence number to let miners know which amendment comes after another.</p>
<p>One use case for this might be a digital <em>will</em>. If you wanted to pass your money on to someone else specifically in the event of your death then you could create a transaction with a locktime of one year from now and then give it to a few friends. In the event of your death they can broadcast this transaction on the network <em>after</em> one year and the funds will be sent accordingly. Broadcasting the transaction before this time period of one year would not enable them to receive funds, since miners will ignore the transaction until the time period becomes valid (and obviously the friends cannot alter the functionality of this transaction since it is signed by your private key which you never disclose).</p>
<p>If you don't die then you can spend the funds to a different address of your own choosing by broadcasting a different transaction on the network. Your friends will then not be able to use the original transaction you gave them since this would be a doublespend, which the miners do not allow. For the transaction which you broadcast to cancel the <em>will</em> you would alter the locktime to make it sooner, and increment the sequence number. Alternatively you could set the locktime to 0 or set the sequence number to maxint to spend straight away.</p>
<h2><code>OP_CHECKLOCKTIMEVERIFY</code></h2>
<p><code>OP_CHECKLOCKTIMEVERIFY</code> has a very different use. It is validated in function <code>EvalScript()</code> <a href="https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L340-L380" rel="nofollow noreferrer">in <code>src/script/interpreter.cpp</code></a>:</p>
<pre class="lang-cpp prettyprint-override"><code>            case OP_CHECKLOCKTIMEVERIFY:
            {
                if (!(flags &amp; SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
                   // not enabled; treat as a NOP2
                   if (flags &amp; SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) {
                        return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS);
                    }
                    break;
                }

                if (stack.size() &lt; 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.
                //
                // If we kept to that limit we'd have a year 2038 problem,
                // even though the nLockTime field in transactions
                // themselves is uint32 which only becomes meaningless
                // after the year 2106.
                //
                // 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 nLockTime field itself.
                const CScriptNum nLockTime(stacktop(-1), fRequireMinimal, 5);

                // In the rare event that the argument may be &lt; 0 due to
                // some arithmetic being done first, you can always use
                // 0 MAX CHECKLOCKTIMEVERIFY.
                if (nLockTime &lt; 0)
                return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);

                // Actually compare the specified lock time with the transaction.
               if (!checker.CheckLockTime(nLockTime))
                    return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);

                break;
            }
</code></pre>
<p>which relies on function <code>CheckLockTime()</code> <a href="https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1129-L1163" rel="nofollow noreferrer">in the same file</a>:</p>
<pre class="lang-cpp prettyprint-override"><code>bool TransactionSignatureChecker::CheckLockTime(const CScriptNum&amp; nLockTime) const
{
    // There are two kinds of nLockTime: lock-by-blockheight
    // and lock-by-blocktime, distinguished by whether
    // nLockTime &lt; LOCKTIME_THRESHOLD.
    //
    // We want to compare apples to apples, so fail the script
    // unless the type of nLockTime being tested is the same as
    // the nLockTime in the transaction.
    if (!(
       (txTo-&gt;nLockTime &lt;  LOCKTIME_THRESHOLD &amp;&amp; nLockTime &lt; LOCKTIME_THRESHOLD) ||
       (txTo-&gt;nLockTime &gt;= LOCKTIME_THRESHOLD &amp;&amp; nLockTime &gt;= LOCKTIME_THRESHOLD)
    ))
        return false;

    // Now that we know we're comparing apples-to-apples, the
    // comparison is a simple numeric one.
    if (nLockTime &gt; (int64_t)txTo-&gt;nLockTime)
        return false;
 
    // Finally the nLockTime feature can be disabled and thus
    // CHECKLOCKTIMEVERIFY bypassed if every txin has been
    // finalized by setting nSequence to maxint. The
    // transaction would be allowed into the blockchain, making
    // the opcode ineffective.
    //
    // Testing if this vin is not final is sufficient to
    // prevent this condition. Alternatively we could test all
    // inputs, but testing just this input minimizes the data
    // required to prove correct CHECKLOCKTIMEVERIFY execution.
    if (txTo-&gt;vin[nIn].IsFinal())
        return false;

    return true;
}
</code></pre>
<p>Here the transaction locktime is compared to a value on the stack. To validate successfully, both must be the same side of the theshold (ie both must be interpreted as a block height, or both as a timestamp), and the script will only validate if the stack value is lower than the tx locktime. Or to put it another way, the script will only validate if the transaction locktime has passed the stack value.</p>
<p>Whereas <code>IsFinalTx()</code> prevents transactions with locktimes in the future from being included into the blockchain in the present, <code>OP_CHECKLOCKTIMEVERIFY</code> freezes funds in the blockchain so that they can only be spent after a specified time in the future.</p>
<p>Note that the stack value used for comparison is most useful when placed in the scriptPubKey. The locktime used for comparison against the stack value is that of the signing transaction. This forces the spender to wait for the block or timestamp in order to spend the funds.</p>
<p>As previously discussed, <code>IsFinalTx()</code> <strong>does</strong> allow transactions with locktimes above the current block height or timestamp to be mined - providing the sequence number is maxxed out, thus disabling the tx locktime. Submitting such a transaction with a maxxed out sequence number would be a sneaky way for the recipient to spend the funds earlier than the time specified by the sender in the txout script. So, to prevent the <code>OP_CHECKLOCKTIMEVERIFY</code> criteria from being bypassed, the script validation must fail when the tx locktime is disabled by the sequence number.</p>

CC BY-SA 3.0
2016-03-12T16:21:17.160Z
I've been searching for an example using OP_CLTV, and I think I found one here: https://api.blockcypher.com/v1/btc/main/txs/7b8846797d9c43c7c89543dda13ad5f8742f0068c56c0fa884692a62fe81a79c?limit=50&includeHex=true 

However, the nLockTime for that transaction is 0, and seq is max. I was expecting the source code to compare the value pushed to stack before OP_CHECKLOCKTIMEVERIFY to compare against the current block time and not tx.nLockTime
Scott Driscoll
CC BY-SA 4.0
2015-10-07T13:46:28.003Z
2024-01-04T21:06:01.777Z
2024-01-04T21:06:01.777Z
mulllhausen
<p>In the code for <code>OP_CHECKLOCKTIMEVERIFY</code> i noticed that if the txin sequence number is maxxed out then the script will fail to validate. I'm wondering what the point of this is? Why would anybody ever submit a transaction that will fail to verify to the network?</p>

<p>Here is the relevant section of <a href="https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1149-L1160" rel="noreferrer">code</a>:</p>

<pre><code>// Finally the nLockTime feature can be disabled and thus
// CHECKLOCKTIMEVERIFY bypassed if every txin has been
// finalized by setting nSequence to maxint. The
// transaction would be allowed into the blockchain, making
// the opcode ineffective.
//
// Testing if this vin is not final is sufficient to
// prevent this condition. Alternatively we could test all
// inputs, but testing just this input minimizes the data
// required to prove correct CHECKLOCKTIMEVERIFY execution.
if (txTo-&gt;vin[nIn].IsFinal())
    return false;
</code></pre>

<p>I'm also confused about the comments in the code for this. They say that every sequence number has to be maxxed out to get the script to fail to validate, but it looks to me like this is not true - it looks like only one sequence number needs to be maxxed out and then the whole transaction (all txins) will fail. And I assume this would mean that the transaction will therefore not be included in the blockchain? But that runs counter to the code comments. It would make sense if there were a <code>!</code> on the if condition.</p>

CC BY-SA 3.0
2015-10-01T14:34:50.010Z
this explanation made more sense to me: ["A transaction is final when the sequences are no longer incrementable **or** the locktime is in the past. A transaction that is not final will not be accepted for relay."](https://bitcointalk.org/index.php?topic=23501.msg4504671#msg4504671)
mulllhausen
<script><locktime><opcodes><checklocktimeverify>
Why is OP_CHECKLOCKTIMEVERIFY disabled by maximum sequence number?
mulllhausen
# Why is OP_CHECKLOCKTIMEVERIFY disabled by maximum sequence number?

(Asked by: username_0 on 2015-09-30)

In the code for `OP_CHECKLOCKTIMEVERIFY` i noticed that if the txin sequence number is maxxed out then the script will fail to validate. I'm wondering what the point of this is? Why would anybody ever submit a transaction that will fail to verify to the network?

Here is the relevant section of [code](https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1149-L1160):

```
// Finally the nLockTime feature can be disabled and thus
// CHECKLOCKTIMEVERIFY bypassed if every txin has been
// finalized by setting nSequence to maxint. The
// transaction would be allowed into the blockchain, making
// the opcode ineffective.
//
// Testing if this vin is not final is sufficient to
// prevent this condition. Alternatively we could test all
// inputs, but testing just this input minimizes the data
// required to prove correct CHECKLOCKTIMEVERIFY execution.
if (txTo->vin[nIn].IsFinal())
    return false;

```

I'm also confused about the comments in the code for this. They say that every sequence number has to be maxxed out to get the script to fail to validate, but it looks to me like this is not true - it looks like only one sequence number needs to be maxxed out and then the whole transaction (all txins) will fail. And I assume this would mean that the transaction will therefore not be included in the blockchain? But that runs counter to the code comments. It would make sense if there were a `!` on the if condition.

**Tags:** script, locktime, opcodes, checklocktimeverify

> **Comments:**
> **username_0**: this explanation made more sense to me: ["A transaction is final when the sequences are no longer incrementable **or** the locktime is in the past. A transaction that is not final will not be accepted for relay."](https://bitcointalk.org/index.php?topic=23501.msg4504671#msg4504671)  

---

## 3 answers

### Answer by username_0 on 2015-10-07. Score: 9 | Accepted answer

the purpose of `OP_CHECKLOCKTIMEVERIFY` is kind of the opposite to the purpose of `tx.nLockTime`. `tx.nLockTime` prevents transactions with future dates from entering the blockchain, whereas `OP_CHECKLOCKTIMEVERIFY` enables someone to freeze funds so that they can only be spent *after* a given timestamp or block height.

## `tx.nLockTime`

`tx.nLockTime` is validated by function `IsFinalTx()` [in `src/main.cpp`](https://github.com/bitcoin/bitcoin/blob/4899a04c24b927166048a74999992d216a543c23/src/main.cpp#L641-L651):

```cpp
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
    if (tx.nLockTime == 0)
        return true;
    if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
        return true;
    BOOST_FOREACH(const CTxIn& txin, tx.vin)
        if (!txin.IsFinal())
            return false;
    return true;
}

```

where `txin.IsFinal()` is [in `src/primitives/transaction.h`](https://github.com/bitcoin/bitcoin/blob/24ce77d775f48034ef0c42fa21017d145c790921/src/primitives/transaction.h#L81-L84):

```cpp
bool IsFinal() const
{
    return (nSequence == std::numeric_limits<uint32_t>::max());
}

```

If the tx locktime is below the threshold then it is treated as a block height and if it is above the threshold then it is treated as a timestamp. Either way, the transaction locktime value must be smaller than the relevant constraint. If it is larger then miners must wait before including the transaction in a block.

The only way to bypass this transaction locktime constraint is to disable the transaction locktime completely by setting all txin sequence numbers to maxint. When this is done then miners will include the transaction straight away, even if the locktime has not yet been reached.

The idea with the transaction locktime is that before the transaction is locked (ie before the block height or timestamp catch up with tx locktime), someone can make amendments to the transaction. Each time they make a change then they must increment the sequence number to let miners know which amendment comes after another.

One use case for this might be a digital *will*. If you wanted to pass your money on to someone else specifically in the event of your death then you could create a transaction with a locktime of one year from now and then give it to a few friends. In the event of your death they can broadcast this transaction on the network *after* one year and the funds will be sent accordingly. Broadcasting the transaction before this time period of one year would not enable them to receive funds, since miners will ignore the transaction until the time period becomes valid (and obviously the friends cannot alter the functionality of this transaction since it is signed by your private key which you never disclose).

If you don't die then you can spend the funds to a different address of your own choosing by broadcasting a different transaction on the network. Your friends will then not be able to use the original transaction you gave them since this would be a doublespend, which the miners do not allow. For the transaction which you broadcast to cancel the *will* you would alter the locktime to make it sooner, and increment the sequence number. Alternatively you could set the locktime to 0 or set the sequence number to maxint to spend straight away.

## `OP_CHECKLOCKTIMEVERIFY`

`OP_CHECKLOCKTIMEVERIFY` has a very different use. It is validated in function `EvalScript()` [in `src/script/interpreter.cpp`](https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L340-L380):

```cpp
            case OP_CHECKLOCKTIMEVERIFY:
            {
                if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY)) {
                   // not enabled; treat as a NOP2
                   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.
                //
                // If we kept to that limit we'd have a year 2038 problem,
                // even though the nLockTime field in transactions
                // themselves is uint32 which only becomes meaningless
                // after the year 2106.
                //
                // 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 nLockTime field itself.
                const CScriptNum nLockTime(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 CHECKLOCKTIMEVERIFY.
                if (nLockTime < 0)
                return set_error(serror, SCRIPT_ERR_NEGATIVE_LOCKTIME);

                // Actually compare the specified lock time with the transaction.
               if (!checker.CheckLockTime(nLockTime))
                    return set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);

                break;
            }

```

which relies on function `CheckLockTime()` [in the same file](https://github.com/bitcoin/bitcoin/blob/master/src/script/interpreter.cpp#L1129-L1163):

```cpp
bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) const
{
    // There are two kinds of nLockTime: lock-by-blockheight
    // and lock-by-blocktime, distinguished by whether
    // nLockTime < LOCKTIME_THRESHOLD.
    //
    // We want to compare apples to apples, so fail the script
    // unless the type of nLockTime being tested is the same as
    // the nLockTime in the transaction.
    if (!(
       (txTo->nLockTime <  LOCKTIME_THRESHOLD && nLockTime < LOCKTIME_THRESHOLD) ||
       (txTo->nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
    ))
        return false;

    // Now that we know we're comparing apples-to-apples, the
    // comparison is a simple numeric one.
    if (nLockTime > (int64_t)txTo->nLockTime)
        return false;
 
    // Finally the nLockTime feature can be disabled and thus
    // CHECKLOCKTIMEVERIFY bypassed if every txin has been
    // finalized by setting nSequence to maxint. The
    // transaction would be allowed into the blockchain, making
    // the opcode ineffective.
    //
    // Testing if this vin is not final is sufficient to
    // prevent this condition. Alternatively we could test all
    // inputs, but testing just this input minimizes the data
    // required to prove correct CHECKLOCKTIMEVERIFY execution.
    if (txTo->vin[nIn].IsFinal())
        return false;

    return true;
}

```

Here the transaction locktime is compared to a value on the stack. To validate successfully, both must be the same side of the theshold (ie both must be interpreted as a block height, or both as a timestamp), and the script will only validate if the stack value is lower than the tx locktime. Or to put it another way, the script will only validate if the transaction locktime has passed the stack value.

Whereas `IsFinalTx()` prevents transactions with locktimes in the future from being included into the blockchain in the present, `OP_CHECKLOCKTIMEVERIFY` freezes funds in the blockchain so that they can only be spent after a specified time in the future.

Note that the stack value used for comparison is most useful when placed in the scriptPubKey. The locktime used for comparison against the stack value is that of the signing transaction. This forces the spender to wait for the block or timestamp in order to spend the funds.

As previously discussed, `IsFinalTx()` **does** allow transactions with locktimes above the current block height or timestamp to be mined - providing the sequence number is maxxed out, thus disabling the tx locktime. Submitting such a transaction with a maxxed out sequence number would be a sneaky way for the recipient to spend the funds earlier than the time specified by the sender in the txout script. So, to prevent the `OP_CHECKLOCKTIMEVERIFY` criteria from being bypassed, the script validation must fail when the tx locktime is disabled by the sequence number.

> **Comments:**
> **username_1**: I've been searching for an example using OP_CLTV, and I think I found one here: https://api.blockcypher.com/v1/btc/main/txs/7b8846797d9c43c7c89543dda13ad5f8742f0068c56c0fa884692a62fe81a79c?limit=50&includeHex=true   However, the nLockTime for that transaction is 0, and seq is max. I was expecting the source code to compare the value pushed to stack before OP_CHECKLOCKTIMEVERIFY to compare against the current block time and not tx.nLockTime  

---

### Answer by username_1 on 2016-03-12. Score: 3

username_0's answer is great, but here's a shorter example that illustrates why the vin seq number can't be final or maxed.

Suppose I want to spend a CLTV output. I wait until the CLTV time has passed, and then create a transaction with nLockTime set to the current block time, and the sequence number set to something less than 2^32-1, say 0.

Now that transaction will verify because

```
CLTV time <= tx.nLockTime <= current block time

```

We're basically using nLockTime as a proxy for the current block time to say current block time is past the CLTV time.

However, if I set all my seq numbers to max, I would be able to submit a transaction with an nLockTime in the future, ie, greater than current block time, thereby bypassing the CLTV time. nLockTime must be <= to current block time if not all seq numbers are maxed. So by checking to make sure at least one Vin Seq number is not final, we make sure they all aren't maxed, allowing this bypass scenario.


---

### Answer by username_2 on 2015-09-30. Score: 2

[From Bitcoin.org](https://bitcoin.org/en/developer-guide#locktime-and-sequence-number):

> Locktime allows signers to create time-locked transactions which will only become valid in the future, giving the signers a chance to change their minds.
>
> ...
>
> Previous versions of Bitcoin Core provided a feature which prevented transaction signers from using the method described above to cancel a time-locked transaction, but a necessary part of this feature was disabled to prevent denial of service attacks. A legacy of this system are four-byte sequence numbers in every input. **Sequence numbers were meant to allow multiple signers to agree to update a transaction; when they finished updating the transaction**, they could agree to set every input’s sequence number to the four-byte unsigned maximum (0xffffffff), allowing the transaction to be added to a block even if its time lock had not expired.
>
> Even today, setting all sequence numbers to 0xffffffff (the default in Bitcoin Core) can still disable the time lock, so **if you want to use locktime, at least one input must have a sequence number below the maximum Since sequence numbers are not used by the network for any other purpose, setting any sequence number to zero is sufficient to enable locktime**.

So it's essentially that nLockTime is disabled if the sequence value is `0xffffffff`, but for `0 <= sequence_value < 0xffffffff`, nTimeLock is enabled.

IMO the confusion is arising because there's conflation of the functionality of `OP_CHECKLOCKTIMEVERIFY` (BIP65) and *nTimeLock*. I was [similarly confused](https://bitcoin.stackexchange.com/questions/38444/bip65-replacing-ntimelock-entirely), so check out [these Bitcoin.org definitions](https://bitcoin.org/en/developer-guide#locktime-and-sequence-number) and [*nTimeLock may disappoint you*](http://earlfox.blogspot.com/2014/06/nlocktime-may-disappoint-you.html)

> **Comments:**
> **username_0**: some more good discussion on the topic - https://bitcointalk.org/index.php?topic=766893.0  
> **username_0**: I'm still confused - mainly by the comment where it says "and thus CHECKLOCKTIMEVERIFY bypassed". If the sequence number is maxxed out but there is a script with CHECKLOCKTIMEVERIFY in it, then this will NOT be bypassed - the script will fail!  
> **username_2**: @username_0 I'm not versed in C++, so can you clarify what `if (txTo->vin[nIn].isFinal());` means? txTo is the spending transaction, and vin[nIn] is just an array of UTXOs, right? What does `->` mean? Re `if the sequence number is maxxed out but there is a script with CHECKLOCKTIMEVERIFY in it, then this will NOT be bypassed - the script will fail!`... Hmm, yes, I see your point. I wonder what bypassing means? It may just mean the scripting drops OP_CLTV if the sequence is less than 0xffffffff?  
> **username_0**: `isFinal()` [is a method in transaction.h](https://github.com/bitcoin/bitcoin/blob/24ce77d775f48034ef0c42fa21017d145c790921/src/primitives/transaction.h#L81). its basically a check for `sequence num == 0xffffffff` for this txin. when this condition is met then a script containing `OP_CHECKLOCKTIMEVERIFY` fails with [`set_error(serror, SCRIPT_ERR_UNSATISFIED_LOCKTIME);`](https://github.com/bitcoin/bitcoin/blob/24ce77d775f48034ef0c42fa21017d145c790921/src/script/interpreter.cpp#L377)  

---

