新的难度调整算法“aserti3-2d”(简称为“ASERT”)于BCH在2020年11月份的更新中被激活。激活方式基于MTP(median?? ),最后的前叉块将会被作为锚定块。
BCH在2017年十一月的更新中介绍了一种简单的移动平均方法作为难度调整算法。不幸的是,这次更新引入了周期性的难度波动,导致长时间无法确认交易后紧随而来的是一段时间的快速出块。这种出块的不稳定性降低了用户对BCH的期望并且对长时间挖掘BCH矿工不公平。
在对一类基于移动指数平均线(exponential moving average,EMA)的难度算法深入研究后,Mark Lundeberg在2019年发展了一种绝对进度指数上升目标(Absolutely Scheduled Exponentially Rising Targets,ASERT)算法[1],并在2020年对该算法进行了全面的描述。Jacob Eliosoff在2018年和Werner et. al[6]在2016年分别独立的发现了该算法的等价形式。
ASERT没有在2017年十一月更新中提出的DAA方法所具有的波动性,相反地,它在许多方面表现出了引人注目的性质,例如它不需要额外的规则就可以抵抗奇异性[15],不会产生舍入/近似误差的累积。
针对其它一系列稳定算法的仿真对比中[2],ASERT算法在以下所有条件下都有最佳的表现:
分叉块:根据新的共识规则挖出的第一个块
锚定块:分叉块的前一个块
当前区块的难度目标通过DAA机制进行调整。
aserti3-2d算法可以通过下面的公式来描述:
KaTeX parse error: Undefined control sequence: \- at position 52: …me\_delta-ideal\̲-̲block\_time*(he…
式中, a n c h o r _ t a r g e t − − 锚 定 区 块 头 中 以 无 符 号 256 整 数 表 示 的 n B i t s 值 anchor\_target--锚定区块头中以无符号256整数表示的nBits值 anchor_target−−锚定区块头中以无符号256整数表示的nBits值
t i m e _ d e l t a − − 以 秒 为 单 位 的 有 符 号 整 数 , 表 示 当 前 区 块 头 中 的 时 间 戳 与 锚 定 区 块 前 一 个 区 块 时 间 戳 的 差 值 time\_delta--以秒为单位的有符号整数,表示当前区块头中的时间戳与锚定区块前一个区块时间戳的差值 time_delta−−以秒为单位的有符号整数,表示当前区块头中的时间戳与锚定区块前一个区块时间戳的差值
i d e a l _ b l o c k _ t i m e − − 表 示 平 均 出 块 时 间 的 常 数 值 , 600 秒 ideal\_block\_time--表示平均出块时间的常数值,600秒 ideal_block_time−−表示平均出块时间的常数值,600秒
h e i g h t _ d e l t a − − 当 前 区 块 高 度 和 锚 定 区 块 高 度 的 差 值 height\_delta--当前区块高度和锚定区块高度的差值 height_delta−−当前区块高度和锚定区块高度的差值
h a l f l i f e − − 常 数 值 , 有 时 候 也 称 为 ′ t a u ′ , 主 网 取 值 为 172800 ( 秒 ) halflife--常数值,有时候也称为'tau',主网取值为172800(秒) halflife−−常数值,有时候也称为′tau′,主网取值为172800(秒)
n e x t _ t a r g e t − − 以 整 数 形 式 表 示 的 下 一 区 块 的 难 度 目 标 next\_target--以整数形式表示的下一区块的难度目标 next_target−−以整数形式表示的下一区块的难度目标
通过使用定点整数算法和对 2 x 2^x 2x项的三次多项式逼近来拟合上述公式。
用做输入和输出的“难度目标”是以256位整数目标值的紧凑形式表示,这是与区块头中的“nBits”字段一致的。
Python代码,使用Python3语法:
def next_target_aserti3_2d(
anchor_height: int, # height of the anchor block.
anchor_parent_time: int, # timestamp (nTime) of the parent of the anchor block.
anchor_bits: int, # 'nBits' value of the anchor block.
current_height: int, # height of the current block.
current_time: int, # timestamp of the current block.
) -> int: # 'target' nBits of the current block.
ideal_block_time = 600 # in seconds
halflife = 172_800 # 2 days (in seconds)
radix = 2**16 # 16 bits for decimal part of fixed-point integer arithmetic
max_bits = 0x1d00_ffff # maximum target in nBits representation
max_target = bits_to_target(max_bits) # maximum target as integer
anchor_target = bits_to_target(anchor_bits)
time_delta = current_time - anchor_parent_time
height_delta = current_height - anchor_height # can be negative
# `//` is truncating division (int.__floordiv__) - see note 3 below
exponent = time_delta - ideal_block_time * (height_delta + 1) // halflife
# Compute equivalent of `num_shifts = math.floor(exponent / 2**16)`
num_shifts = exponent >> 16
exponent = exponent - num_shifts * radix
factor = ((195_766_423_245_049 * exponent +
971_821_376 * exponent**2 +
5_127 * exponent**3 +
2**47) >> 48) + radix
next_target = anchor_target * factor
# Calculate `next_target = math.floor(next_target * 2**factor)`
if num_shifts < 0:
next_target >>= -num_shifts
else:
# Implementations should be careful of overflow here (see note 6 below).
next_target <<= num_shifts
next_target >>= 16
if next_target == 0:
return target_to_bits(1) # hardest valid target
if next_target > max_target:
return max_bits # limit on easiest target
return target_to_bits(next_target)
注意:
ASERT算法将根据顶级升级规范被激活[3]。
ASERT算法要求选择一个锚定区块来安排将来难度目标计算的进度。
MTP大于/等于激活时间的第一个块,将被用作后续ASERT计算的锚定块。
锚定区块对应于ASERT DAA之前的规则所挖出的最后一个区块。
注意:
在测试网中,将会包含一条额外的规则:任何区块的时间戳与父区块的时间戳如果超过1200秒就必须将难度值设置为: m a x _ b i t s ( 0 x 1 d 00 f f f f ) max\_bits(0x1d00ffff) max_bits(0x1d00ffff)。
选择过去足够久远的区块会略微降低编程难度,但可能导致在升级时难以改变难度调整机制。
原有的DAA算法挖出的最后一个区块被选做锚定区块,因为改区块是最接近新算法的锚点,可以平滑的过渡到新算法。
通常在编程语言上实现新的DAA调整机制是不保证符合IEEE-754浮点运算规则的。浮点计算的结果通常依赖于编译器、解释器或硬件。
因此强烈建议所有的运算都使用纯粹的整数和高度特定的运算符来保证在所有的实现中都获得相同的难度值。
半衰期选择两天( h a l f l i f e = 2 ∗ 24 ∗ 3600 halflife=2*24*3600 halflife=2∗24∗3600),等效于基于 e x e^x ex的时间常数 2 ∗ 144 ∗ l n ( 2 ) 2*144*ln(2) 2∗144∗ln(2)或者 a s e r t i 3 − 415.5 aserti3-415.5 aserti3−415.5。之所以如此选择,是因为 ,同时也便于理解:每时间表上区块时间戳的两天以前,难度值都会加倍(?怎么理解?)
难度调整机制是调节算力的控制系统反馈回路的一部分,指数函数和它的整数近似是系统传递函数的一部分。因此难度调整机制适用于确保控制系统稳定性的各项标准指南。在这些控制系统的传递函数中,往往对非线性微分要比分线性积分敏感的多。因此,我们要求传递函数具有如下性质:(a) 单调性,(b) 连续性,© 比我们的多块统计基底噪声具有更好的精度和微分非线性,(d) 具有简单的实现,(e) 不差于目前单块统计基底噪声的积分非线性。
一个简单的,快速计算 2 x , 0 ≤ x < 1 2^x,0\le x<1 2x,0≤x<1的立方近似满足我们的所有要求。在此范围内,他的绝对误差范围保持在 0.013 % 0.013\% 0.013%以下[8]。我们发现 2 x + n = 2 n ∗ 2 x 2^{x+n}=2^n*2^x 2x+n=2n∗2x的性质对于将其拓展到指数函数的完整定义域 ( ∞ , − ∞ ) (\infty,-\infty) (∞,−∞)是有用的。我们的立方近似给出了 f ( 0 ) = 1 f(0)=1 f(0)=1和 f ( 1 ) = 2 f(1)=2 f(1)=2的准确值,这意味着我们可以使用这个性质而不必担心近似函数定义域边缘的不连续性。
首先,有些非线性微分(DNL)方面的问题。我们的目标时确保我们的算法引入的噪声,不超过数据集中固有噪声的 25 % 25\% 25%。我们的算法通过使用两天(288个块)作为半衰期,尝试有效地估计最近一段时间算力的特征。我们期望块间隔的指数分布具有600秒的标准差。在两天半衰期的基础上,我们估计的算力中的基底噪声应该在 1 / 288 ∗ 600 \sqrt{1/288}*600 1/288∗600秒左右,或使用 35.5 35.5 35.5秒作为近似。由于在两个地方被16位运算符: 172800 sec / 65536 = 2.6367 sec 172800 \sec/65536=2.6367 \sec 172800sec/65536=2.6367sec限制,我们选定的近似方法能够在大多数情况下达到3秒的精度。受限于最坏情况下nBits值只有15位的精度,我们的近似方法此时的精度为 8 sec 8 \sec 8sec。8秒的最坏情况不属于本项工作讨论的范围,因为此时需要对区块头的结构做出更改。由于最坏情况下的15为nBIts值尾数问题,我们在最坏情况下的步长为 0.00305 % 0.00305\% 0.00305%[11]。在15位nBits值尾数范围之外,我们近似算法在最坏情况下的精度为 0.0021 % 0.0021\% 0.0021%。总体而言,我们认为这是令人满意的DNL性能。
其次,有些非线性积分(INL)方面的问题。仿真测试表明,难度值和算力调节性能对非线性积分非常不敏感。我们在 a s e r t i 1 aserti1 aserti1算法中发现即使使用 f ( x ) = 1 + x f(x)=1+x f(x)=1+x作为 2 x 2^x 2x的近似,在与 2 x + n = 2 n ∗ 2 x 2^{x+n}=2^n*2^x 2x+n=2n∗2x特性进行耦合时,尽管有 6 % 6\% 6%的最坏情况[12,13],也能获得令人满意的结果。一个近似函数的非线性积分性质较差时依然显示了很好的算力调节能力,不过对于指定的算力变化,其漂移量将有所不同,具体取决于指数(模数1)在[0,1)域中的位置。当INL变化 + / − 1 % +/- 1\% +/−1%,对于给定难度值或难度目标,一个区块的时间戳最终可能比计划提前或延后172800秒的 1 % 1\% 1%。然而,出于谨慎,并且由于实现更高精度是比较容易的,我们选择的目标是使INL等于或小于一个区块可能引起的典型漂移。在两天的半衰期窗口之外,一个区块的方差包含 600 / 172800 = 0.347 % 600/172800=0.347\% 600/172800=0.347%。我们立方近似的INL性能比要求的范围好于[14] 0.013 % 0.013\% 0.013%。
因为在ASERT算法中设计256位整数的计算相对较少,同时执行频率较低,所以更复杂的操作符类似于在难度算法的输入/输出数据,即紧凑形式表示的难度目标(nBits)上直接进行算术运行是没有必要的。
此外,在现有的实现中可以使用256位(甚至bignum)算法,并且可以在以前的DAA中使用它。 对性能的影响可以忽略不计。
nBIts字段的形式由8位以256为基底的指数和24位尾数组成。尾数值不能小于 0 x 008000 0\rm{x}008000 0x008000,这意味着最坏情况下尾数只提供15位精度。之所以选择16位精度是确保我们定点数运行中能够满足15位nBits的限制。
算法名称“aserti3-2d”的选择基于以下几点原因:
实现算法中的计算过程时必须避免引入任何舍入误差。舍入必须完全按照算法中指定的进行。 实际上,要保证这一点,您可能需要专门使用整数算术。
使用有符号整数并使用移位的实现必须确保该移位是算术移位。
注意:在C++编译器中,右移负号整数即将编程标准[5],但在C ++ 20之前是形式未指定的行为。实际上,C/C++编译器通常对有符号数执行算术移位。 建议实现者通过编译时声明或单元测试来验证良正确性。
适用于验证aserti3-2d算法其他实现的测试向量可在以下位置找到:
https://gitlab.com/bitcoin-cash-node/bchn-sw/qa-assets/-/tree/master/test_vectors/aserti3-2d
或者在:
https://download.bitcoincashnode.org/misc/data/asert/test_vectors
感谢Mark Lundeberg授予发表ASERT论文的许可,Jonathan Tooming初步在Python和C++上实现了ASERT算法,更新了仿真框架并且评估了不同的难度算法。
感谢Jacob Eliosoff, Tom Harding和Scott Roberts在EMA族和其它被考虑作为BCH难度调整机制替代算法上的评估工作,同时感谢以下评论以及他们提出的宝贵改进建议:
[1] “Static difficulty adjustments, with absolutely scheduled exponentially rising targets (DA-ASERT) – v2”, Mark B. Lundeberg, July 31, 2020
[2] “BCH upgrade proposal: Use ASERT as the new DAA”, Jonathan Toomim, 8 July 2020
[3] Bitcoin Cash November 15, 2020 Upgrade Specification.
[4] https://en.wikipedia.org/wiki/Arithmetic_shift
[5] https://en.cppreference.com/w/cpp/language/operator_arithmetic
[6] “Unstable Throughput: When the Difficulty Algorithm Breaks”, Sam M. Werner, Dragos I. Ilie, Iain Stewart, William J. Knottenbelt, June 2020
[7] “Different kinds of integer division”, Harry Garrood, blog, 2018
[8] Error in a cubic approximation of 2^x for 0 <= x < 1
[9] Jonathan Toomim adaptation of kyuupichan’s difficulty algorithm simulator: https://github.com/jtoomim/difficulty/tree/comparator
[10] “The Euclidean definition of the functions div and mod”, Raymond T. Boute, 1992, ACM Transactions on Programming Languages and Systems (TOPLAS). 14. 127-144. 10.1145/128861.128862
[11] http://toom.im/bch/aserti3_step_size.html
[12] [f(x) = (1 + x)/2^x for 0, WolframAlpha.
[13] https://github.com/zawy12/difficulty-algorithms/issues/62#issuecomment-647060200
[14] http://toom.im/bch/aserti3_approx_error.html
[15] https://github.com/zawy12/difficulty-algorithms/issues/62#issuecomment-646187957
该规范使用Creative Commons CC0 1.0 Universal和GNU All-Permissive双重许可。