Published: 2018-12-15

BIP113(Median Time Past)

1 BIP地址

BIP113

BIP: 113
Layer: Consensus (soft fork)
Title: Median time-past as endpoint for lock-time calculations
Author: Thomas Kerin <me@thomaskerin.io>
        Mark Friedenbach <mark@friedenbach.org>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/bitcoin/bips/wiki/Comments:BIP-0113
Status: Final
Type: Standards Track
Created: 2015-08-10
License: PD

2 原因和目的

BIP113定义了Block的Median time-past(MTP):该Block之前的11个Block的timestamp的中位值。

BIP113重新定义了有时间锁定(time-locked)的交易(Transactions)被是否能被包含到一个区块(Block)条件。

Transaction 的 lock_time 字段 定义了该交易可被包含到Block的限制(到一定时间或者block的到一定的高度后才可以被包含到block)。 这里到达一定的时间由block的timestamp决定,这会造成一个问题,因为目前的共识机制并没有强制限制block的timestamp的顺序,所以为了获得更多的挖矿奖励,miner会倾向将timestamp往后设定来包含更多的transactions,而这些transacts本不应该被包含。

所以这个BIP提出了用该block的前11个block的timestamp的中值来做该block的lock-time。该时间可以简称MTP(median time past)。

现有的共识机制保证了MTP是单调增的,也消除了由miner来有意设置block的timestamp对有时间锁定(time-locked)的行为的影响。

这个提案努力保证了BIP65 (CHECKLOCKTIMEVERIFY)所要求的locktime计算的可靠性,并且和 BIP68 (sequence numbers)以及 BIP112 (CHECKSEQUENCEVERIFY)向关联。

该提案只对Transaction的locktime并无改变,只影响Transaction是否应该被包含到Block中。

3 实现

btcd的实现 这里的node是Block的上一个Block, medianTimeBlocks是常量11,该方法从Block的上一个Block开始,向前找11个Block的timestamp

注意最后求中位值的一个小bug(也是共识的一部分了),只影响初始几个块。

// https://github.com/btcsuite/btcd/blob/7d2daa5bfef28c5e282571bc06416516936115ee/blockchain/blockindex.go#L185

// CalcPastMedianTime calculates the median time of the previous few blocks
// prior to, and including, the block node.
//
// This function is safe for concurrent access.
func (node *blockNode) CalcPastMedianTime() time.Time {
    // Create a slice of the previous few block timestamps used to calculate
    // the median per the number defined by the constant medianTimeBlocks.
    timestamps := make([]int64, medianTimeBlocks)
    numNodes := 0
    iterNode := node
    for i := 0; i < medianTimeBlocks && iterNode != nil; i++ {
            timestamps[i] = iterNode.timestamp
            numNodes++

            iterNode = iterNode.parent
    }

    // Prune the slice to the actual number of available timestamps which
    // will be fewer than desired near the beginning of the block chain
    // and sort them.
    timestamps = timestamps[:numNodes]
    sort.Sort(timeSorter(timestamps))

    // NOTE: The consensus rules incorrectly calculate the median for even
    // numbers of blocks.  A true median averages the middle two elements
    // for a set with an even number of elements in it.   Since the constant
    // for the previous number of blocks to be used is odd, this is only an
    // issue for a few blocks near the beginning of the chain.  I suspect
    // this is an optimization even though the result is slightly wrong for
    // a few of the first blocks since after the first few blocks, there
    // will always be an odd number of blocks in the set per the constant.
    //
    // This code follows suit to ensure the same rules are used, however, be
    // aware that should the medianTimeBlocks constant ever be changed to an
    // even number, this code will be wrong.
    medianTimestamp := timestamps[numNodes/2]
    return time.Unix(medianTimestamp, 0)

4 兼容性

通常来讲,用MTP来做时间锁定判断的交易会比用block.timestamp的晚大约1个小时的时间生效(因为前11个Block的中位值约为之前第6个的时间,每个block大约10分钟,6*10=60min)。 引入MTP对目前的协议并未可知的影响。

5 部署

用BIP9提案的"versionbits"第0位部署。

需要BIP68(nSequence),112(CheckSequenceVerify)同时部署。

6 END

Author: Nisen

Email: imnisen@163.com