BIP113(Median Time Past)
1 BIP地址
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)同时部署。