nLockTime
field is ignored
when all nSequence
fields are final, so this change aims to clarify this
behavior and cross reference relevant details of OP_CHECKLOCKTIMEVERIFY
.
nLockTime
field is ignored
when all nSequence
fields are final, so this change aims to clarify this
behavior and cross reference relevant details of OP_CHECKLOCKTIMEVERIFY
.
1352- // finalized by setting nSequence to maxint. The
1353+ // Finally the nLockTime feature can be disabled in IsFinalTx()
1354+ // and thus CHECKLOCKTIMEVERIFY bypassed if every txin has
1355+ // been finalized by setting nSequence to maxint. The
1356 // transaction would be allowed into the blockchain, making
1357 // the opcode ineffective.
I expanded a bit on your suggestion in c4a022d4
p.s. sorry for accidentally clicking resolve
ACK 5546ed6
Thanks for documenting this foresight of OP_CLTV design.
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
No conflicts as of last run.
19@@ -20,6 +20,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
20 return true;
21 if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
22 return true;
23+
24+ // Even if tx.nLockTime isn't satisfied by nBlockHeight/nBlockTime, a
25+ // transaction is still considered final if all nSequence values are final,
0xffffffff
. Perhaps this wording of final is clear to everyone else (in which case ignore).
1433@@ -1434,16 +1434,22 @@ bool GenericTransactionSignatureChecker<T>::CheckLockTime(const CScriptNum& nLoc
1434 if (nLockTime > (int64_t)txTo->nLockTime)
1435 return false;
1436
1437- // Finally the nLockTime feature can be disabled and thus
1438- // CHECKLOCKTIMEVERIFY bypassed if every txin has been
1439- // finalized by setting nSequence to maxint. The
1440+ // Finally the nLockTime feature can be disabled in IsFinalTx()
I’m not a huge fan of having function names in the comments, because the code might change over time. eg. theoretically there could be another calling path that also disables, right?
in this case I don’t think its a big deal esp bc its consensus code that seems quite unlikely to change
FWIW the rationale for adding it was specifically to cross reference these the two locations in the code, as they are more easily understood together.
I can definitely see why this is not worth the risk of stale comments, but [edit to add: assuming it’s desired] couldn’t think of a simpler way.
Maybe just mentioning CHECKLOCKTIMEVERIFY
and SEQUENCE_FINAL
is a good compromise, there are few false positives, and those are even less likely to change.
FWIW the rationale for adding it was specifically to cross reference these the two locations in the code, as they are more easily understood together.
fair enough. makes sense in this case
ACK ae93eb3379604a5ee83242f420bb5431fa238b9e
one comment, but not worth holding up the PR. its been open for a while and overall this documentation helps clarify some unexpected logic, so def an improvement in my eyes.
ACK abc8f3bae2cd9a65e170528d77973307050c5b47.
Hoping this PR can get merged soon!
abc8f3b
1451+ // This additional constraint enables a kind of lightweight
1452+ // covenant: by using OP_CHECKLOCKTIMEVERIFY an output may
1453+ // be unspendable until a specific nBlockHeight/nBlockTime
1454+ // committed in the scriptPubKey, as opposed to a spending
1455+ // transaction's nLockTime only being constrained by
1456+ // signature verification.
I think the Bitcoin Core source code (or interpreter source code) is the wrong place to document what is possible with each opcode. Better places to document this is the BIPs repo (or stackexchange, the mailing list, your private blog or website, …).
In fact the BIP already mentions several use cases. See https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki#Motivation . Should the other use-cases be copy-pasted here as well? If a new use-case is found, should it be copied here, too? How much review/maintenance time is this going to consume?
Also, you mention the word covenant
, which isn’t defined in our source code, nor the BIP text. I think this section adds more confusion for anyone reading the BIP and then this section.
Fine to remove it. IIRC, I did advise you this comment because I was surprised to see nowhere this relation between nLocktime enforcement and finality of inputs documented. At least not in BOLT3, where timeout transactions nSequence are carefully set to non-final.
Overall I agree with @MarcoFalke. Though I would say some mechanism usage towards specific Bitcoin applications are already documented in the codebase. For e.g the carve-out rule in the mempool : https://github.com/bitcoin/bitcoin/blob/683dda2a70e7a210996fa34be23bd0c563971ba9/src/validation.cpp#L801
19@@ -20,6 +20,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
20 return true;
21 if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
22 return true;
23+
24+ // Even if tx.nLockTime isn't satisfied by nBlockHeight/nBlockTime, a
25+ // transaction is still considered final if all nSequence == SEQUENCE_FINAL
It's somewhat surprising that a transaction's nLockTime field is ignored
when all nSequence fields are final, so this change aims to clarify this
behavior and cross reference relevant details of OP_CHECKLOCKTIMEVERIFY.