Bitcoin full node and query server

Mar 24, 2025

View in context in the libbitcoin Slack #general mirror.

A
Antoine Poinsot20:15
Does libbitcoin enforce transactions' locktime since genesis or since block 31,000?
11 replies · Antoine Poinsot, evoskuil · last Mar 25, 2025
evoskuil21:03
Right, there's no block height condition.
evoskuil22:16
Absolute height locktime ("finality") was implemented in Satoshi's first release ("First commit" in GitHub/bitcoin dated 29 AUG 2009).
class CTransaction
{
public:
...
    int nLockTime;
...    
    bool IsFinal() const
    {
        if (nLockTime == 0 || nLockTime < nBestHeight)
            return true;
        foreach(const CTxIn& txin, vin)
            if (!txin.IsFinal())
                return false;
        return true;
    }
...
};

class CTxIn
{
public:
...
    bool IsFinal() const
    {
        return (nSequence == UINT_MAX);
    }
...
};
This was modified to include absolute timestamp locktime in a commit on 18 OCT 2009 and subsequently released as v0.2.0 on 13 DEC 2009. It also included a change of nLockTime type to unsigned.
class CTransaction
{
public:
...
    unsigned int nLockTime;
...
    bool IsFinal(int64 nBlockTime=0) const
    {
        // Time based nLockTime implemented in 0.1.6,
        // do not use time based until most 0.1.5 nodes have upgraded.
        if (nBlockTime == 0)
            nBlockTime = GetAdjustedTime();
        if (nLockTime == 0)
            return true;
        if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime))
            return true;
        foreach(const CTxIn& txin, vin)
            if (!txin.IsFinal())
                return false;
        return true;
    }
...
};
Block 31,000 was mined on 22 DEC 2009. This is nine days after the tag applied to v0.2.0, and between the tags of v0.2.5 and v0.2.6. So it seems you are referring to enforcement of time-based absolute locktime (block time, as MTP didn't arrive until BIP113) around this approximate block height. Libbitcoin doesn't implement activation for various forks during this period, as they were just released without activation and themselves applied to all blocks. We do have plans to do so at some point, and have stubbed in several, for historical/educational purposes. To my knowledge bitcoind has also never applied these forks conditionally. So absolute block locktime was always active, it was forked in v0.2.0 to include time, and that was immediately applied to all blocks. At the time time the integer was also forked from signed to unsigned comparisons (and a validation failure introduced to support it).
// To help v0.1.5 clients who would see it as negative number. please delete this later.
if (nLockTime > INT_MAX)
    return error("AcceptTransaction() : not accepting nLockTime beyond 2038");
evoskuil22:20
Of course Satoshi could not have made these changes because he has no idea what a signed integer is.
A
Antoine Poinsot13:39
So absolute block locktime was always active, it was forked in v0.2.0 to include time
No it was not. 🙂 The block locktime was not enforced by consensus in the first release. It was only enforced when creating a block, not when validating it. In other words this was mining policy, not consensus. The enforcement by consensus was made at the same time the field was repurposed to also optionally consider time, in commit cc0b4c3b62367a2aebe5fc1f4d0ed4b97e9c2ac9 . This change was a soft fork which activated on block 31,000. Had it been enforced by consensus before, the change to include time would have been a hard fork.
A
Antoine Poinsot15:38
Turns out Satoshi even later shifted the soft fork height to a later one in commit b075bbf9862df41cdf5265026ba787b7d0fecb07. Technically a hard fork, but at this time all new releases were hard forks due to OP_VER anyways.
A
Antoine Poinsot15:42
and that was immediately applied to all blocks.
Bitcoin Core started validating it from the genesis block in commit cb420a1dfc23d3c11c5281ed8f7ae003c2f61594 (February 2010). Before that it was only applied from block 36,001, starting with commit b075bbf9862df41cdf5265026ba787b7d0fecb07. Before that it was only applied from block 31,001.
evoskuil16:10
Thanks for the additional info. I hadn’t looked into it before. Libbitcoin started in 2011 so we were well past the point that it had been retroactively applied to all blocks, so I wasn’t aware of the prior variations. As I mentioned, I have tasks to implement various lost forks (all of our forks are conditionally applied via config). Though digging through the code to isolate them can be a challenge. Just setting the limit at v0.2.0 is a lot.
evoskuil16:11
What precipitated the question?
A
Antoine Poinsot16:13
A
Antoine Poinsot16:14
And in my BIP i write that all implementations i'm aware of enforce this since genesis, so i wanted to check first.
👍🏻 1