比特币源码阅读(0.16)(十四)

BIP9Deployment

BIP9允许部署多个向后兼容的软分叉,通过旷工在一个目标周期内投票,如果达到激活阈值nRuleChangeActivationThreshold,就能成功的启用该升级。在实现方面,通过重定义区块头信息中的version字段,将version字段解释为bit vector,每一个bit可以用来跟踪一个独立的部署,在满足激活条件之后,该部署将会生效,同时该bit可以被其他部署使用。

开始时间和过期时间主要为了在检查BIP9部署状态时,提供状态判断的依据和临界值。比如如果区块的中位数时间超过了过期时间nTimeTimeout,则判断该BIP9部署已经失败。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* Struct for each individual consensus rule change using BIP9.
*/
struct BIP9Deployment {
/** Bit position to select the particular bit in nVersion. */
int bit;
/** Start MedianTime for version bits miner confirmation. Can be a date in the past */
int64_t nStartTime;
/** Timeout/expiry MedianTime for the deployment attempt. */
int64_t nTimeout;

/** Constant for nTimeout very far in the future. */
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();

/** Special value for nStartTime indicating that the deployment is always active.
* This is useful for testing, as it means tests don't need to deal with the activation
* process (which takes at least 3 BIP9 intervals). Only tests that specifically test the
* behaviour during activation cannot use this. */
static constexpr int64_t ALWAYS_ACTIVE = -1;
};

consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008

// Deployment of BIP68, BIP112, and BIP113.
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017

// Deployment of SegWit (BIP141, BIP143, and BIP147)
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016.
consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.

DEPLOYMENT_SEGWIT

隔离见证,英文全文为Segregated Witness,缩写Segwit。就是把脚本签名(scriptSig)信息从基本结构 (base block) 里拿出来,放在一个新的数据结构当中。做验证工作的节点和矿工也会验证这个新的数据结构里的脚本签名,以确保交易是有效的。

首先,这种解决方案采用的是一种软分叉,而不是硬分叉来解决扩容问题。

更通俗一点,软分叉需要的代码变化不会对Bitcoin Core客户端的底层协议造成影响,而硬分叉虽然可以在短期内完成部署,但是却会冒着整个比特币协议无法正确执行的风险。对比下来,这就意味着隔离见证是一种稍微缓慢的区块大小解决方案。

另外,软分叉只需要大多数比特币网络用户升级客户端,而硬分叉则需要所有人在最短的时间内进行升级更新。

隔离见证还不只是如此,它允许比特币的签名字段与比特币的转移过程分离。事实上,交易签名会被放入一个Merkle树内,因此,交易的大小看起来会变小,因此比特币区块在不改变大小的情况下可以容纳更多的交易。

另外,隔离见证可以解决交易可塑性,这一问题已经困扰比特币很长一段时间了。对交易重新签名以此改变交易ID将成为不可能。这为比特币转移提供了额外的安全性。

DEPLOYMENT_CSV

时间锁是只允许在一段时间后才允许支出的交易。比特币从一开始就有一个交易级的时间锁定功能。它由交易中的nLocktime字段实现。在2015年底和2016年中期推出了两个新的时间锁定功能,提供UTXO级别的时间锁定功能。这些是CHECKLOCKTIMEVERIFY和CHECKSEQUENCEVERIFY。

nLocktime和CLTV都是绝对时间锁定,它们指定绝对时间点。相对时间锁定,将消耗输出的条件指定为从块链接中的输出确认起的经过时间。

相对时间锁是有用的,因为它们允许将两个或多个相互依赖的交易链接在一起,同时对依赖于从先前交易的确认所经过的时间的一个交易施加时间约束。换句话说,在UTXO被记录在块状块之前,时钟不开始计数。

相对时间锁定可以在每个输入中设置好,其方法是在每个输入中加多一个nSequence字段。

由于BIP-68的激活,新的共识规则适用于任何包含nSequence值小于2^31的输入的交易。以编程方式,这意味着如果没有设置最高有效,它是一个表示“相对锁定时间”的标志。否则,nSequence值被保留用于其他用途。

就像CLTV和nLocktime一样,有一个脚本操作码用于相对时间锁定,它利用脚本中的nSequence值。该操作码是CHECKSEQUENCEVERIFY,通常简称为CSV。 在UTXO的赎回脚本中评估时,CSV操作码仅允许在输入nSequence值大于或等于CSV参数的交易中进行消耗。实质上,这限制了UTXO的消耗,直到UTXO开采时间过了一定数量的块或秒。