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)同时部署。