主页 > imtoken苹果测试版 > 关于隔离见证交易权重的误解

关于隔离见证交易权重的误解

imtoken苹果测试版 2023-05-29 05:31:18

本文为作者在 TABcof 2022 的演讲实录。由 Bryan Bishop 录制。

衡量交易的权重:贴现见证数据

正如你应该从其他人那里听到的那样,我的演讲将有更多的互动。 我可能不会涵盖我准备的所有内容。 如果您在聆听时有任何疑问,请举手以便我们立即解决问题。 我将向您介绍非隔离见证交易和隔离见证交易的序列化。 希望在演讲之后你能理解交易权重是如何计算的,以及见证数据的折扣是如何应用的。 最后,我们应该看看一些不同的输出类型。

隔离见证之前

在 SegWit 激活之前,一笔交易是这样的:它至少有一个输入和一个输出。 此交易有一个 P2PKH 输入,但有 4 个输出,一个包装的 Segwit 输入和一个传统输入。 到目前为止,没什么大不了的。 估计你见过这种交易。

交易序列化

打开引擎盖,让我们仔细看看。 如果你序列化一个交易,或者观察一个交易的序列化形式,yogh.io 对不同的数据进行着色,你可以看到所有数据都被编码为一个十六进制字符串,并且这些字符串使用不同的函数进行处理。

我们将首先查看交易的元数据。 每个交易都有一个“交易头”,其中包含一个 4 字节的版本字段、输入容器(告诉你这个交易有多少输入)和输出容器(告诉你这个交易有多少输出)和一个 4 字节的时间锁定字段。

如果有人一直在关注 v3 交易的最新发展,这是交易版本字段。 如您所见,1 在前,因为该值是小端,而不是大端。

在查看交易标头之后,让我们看看输入。

输入序列化

比特币价格数据下载_比特币蚁池的ht/s是什么数据_比特币全节点的数据量有多大

如果我们想要花费一个输入,我们首先必须告诉每个人我们想要花费哪个 UTXO。 为了唯一定位一个UTXO比特币全节点的数据量有多大,我们使用outpoint(“输出点”),它是一个交易索引号(txid)和UTXO在本次交易的输出列表中的位置。 在我的幻灯片中,txid 是深蓝色的。 这是这个 UTXO 的原始交易。 作为计算机科学家,我们从零开始计数。

要花费一个 UTXO,我们必须满足这个 UTXO 中编码的条件脚本。 这是通过“输入脚本”完成的。 输入脚本的长度是任意的,取决于我们希望脚本满足的条件类型。 因此,我们必须将输入脚本的长度(“输入脚本长度”)编码到输入中。

在这个值之后是输入脚本本身。 以P2PKH输入为例,这是一个众所周知的脚本。 P2PKH 条件脚本意味着资金被锁定在公钥的散列中。 为了满足 P2PKH 脚本,我们提供这个公钥,然后运行哈希计算,证明哈希值与条件脚本中存储的哈希值匹配,然后提供公钥的签名。

输入的最后一个字段是“sequence”。 使用这个字段,我们可以指定这个交易是否可以被替换。 只要一个交易的输入序列值小于最大可能值,这个交易就不会被认为是最终版本,可以被替换。 它只需要在输入中指定,足以使交易可替换。 如果这个字段的值小于最大值 - 1 怎么办? 这意味着它启用了时间锁定。 这里我就不细说了。

输出序列化

这个示例交易有 4 个输出。 我将采取其中一个并详细描述它。 输出中的第一个字段是“面额”,这是进入这个锁定资金的条件脚本的 satoshis 的数量。 输出会创建一个新的 UTXO,而 UTXO 将具有准确的面额。 然后,UTXO还有一个锁定脚本,是一个条件脚本,表示这个UTXO在什么条件下可以被花费。

问:您可以在一笔交易中分配的最大金额是多少?

A:面额字段有8个字节长,我觉得2100万个BTC足够了。

问:为什么使用整数?

比特币价格数据下载_比特币蚁池的ht/s是什么数据_比特币全节点的数据量有多大

A:你们中的一些人可能已经知道这一点,但我们在协议开发中从不使用浮点数。 比特币协议的本机单位是“聪”。 我们在这里分配整数个聪。 我们不使用 BTC,因为浮点数很糟糕,会导致我们在金融协议中不希望出现的舍入错误。

因此,我们使用一个 8 字节的字段来对面额进行编码。 这也是小端。 我们有输出脚本,首先是输出脚本的长度,然后是输出脚本本身。 这是一个 P2SH(pay to script hash)脚本。 脚本中的散列长度为 20 个字节,是一个 hash160 散列。

本地隔离见证

我应该首先解释什么是原生隔离见证。 许多人将第一种本地隔离见证输出称为“本地隔离见证输出”。 您可能熟悉 P2WPKH 输出,其地址以“pc1q”开头。 它们是版本 0 的原生 Segwit 输出。 大约一年前,也就是 2021 年 11 月,我们又进行了一次软分叉,引入了另一种称为“pay to taproot (P2TR)”的输出类型,这也是一种原生隔离见证输出 ranch native segregate Witness v1 输出,其地址以“bc1p”开头。 “p”在 bech32 编码中表示 1。 我的情况是 P2TR 输出。

问:封装的隔离见证输出如何? 它是另一个输出类型代码吗?

A:封装后的隔离见证输出有点像混合体,因为封装后的隔离见证输出是通过满足P2SH的规则来实现向后兼容的,但是它的见证数据部分和原来的隔离见证输出是完全一样的。 在封装的隔离见证交易的见证数据中,您将使用与原始隔离见证交易完全相同的修正数据。 稍后我们将更详细地讨论它。

封装的隔离见证输出和本地隔离见证输出之间的唯一区别是(前者有)一种转发脚本,它说去查看见证数据字段,这就是我们满足支出条件的方式。 (…) 我们也没有为原生 taproot 输出实现嵌套隔离见证输出,所以只有 v0 隔离见证输出以封装形式提供。 现在,人们可以区分原生 SegWit 输出。

本地隔离见证 v1

这是比特币区块链上的第一笔 P2TR 交易。 它还附带一条消息“我喜欢 Schnorr 签名,我不能说谎”。 这是一个 bc1p 地址,表明这是一个 P2TR 输出,它也将 change 分配给 P2TR 输出。 我们来看看它的连载形式。

比特币价格数据下载_比特币蚁池的ht/s是什么数据_比特币全节点的数据量有多大

看起来与我们上面的示例类似,只是这里有一大片橙色。 此处以橙色标记的所有内容都是见证数据。 其他方面也存在一些差异。 比如这个交易的输入脚本长度为0,因为原来隔离见证输入类型中根本没有输入脚本,我们把满足消费条件的数据放到见证数据类型中。 所有本机 Segwit 输入都可以立即识别,因为它们具有零长度输入脚本。

我们再来看看见证数据。 谁还记得非隔离见证交易中版本号后面应该跟什么数据? 没错,进入容器,记录输入的数量。 一开始我说一笔交易至少要有一个输入和一个输出。 如果一个节点不理解本机隔离验证输出的格式,然后发现一个输入为 0 的交易,它会怎么做? 他会认为交易无效,将其丢弃,并让给他垃圾的同行静音。 我们在这里放一个标签说,嘿,这是一种新格式,旧节点不应该读取这些东西,你是偶然得到的,不要费心去解析它。 然后,这个标签意味着交易有一个见证数据(…)。

问:这里的“无效”是什么意思? 交易池没有标准吗? 有些交易是否有效,即使它们不符合条件? 或者这是一种转发策略?

A: ... 这个交易的这种表达方式貌似是无效的,因为网络中基本没有非隔离见证节点,最后的非隔离见证比特币核心版本是0.12,已经是10个版本之前了,大约是5年前发布的,我们维护版的生命周期一般是两年。 因此,解释非 SegWit 节点如何处理 SegWit 交易在很大程度上是一个纯粹的理论问题,不再是一个有意义的问题。 我将使用两张幻灯片来回答您的问题。 无效意味着如果我们将这种交易表示形式发送到非隔离见证节点,该节点会认为这是一堆垃圾。

Q:这种情况非常独特和奇怪,但Segregated Witness恰好就是这样。 我的理解是旧的Segregated Witness节点会和non-Segregated Witness节点通信,他会构造不同的transaction vector和block。 所以不会有这样的时间。 此交易与有效的非 Segwit 交易之间存在同构。 所以这是一个非常混乱的“非无效交易”。

A:这笔交易还有另一种形式,可以被非隔离见证节点解析。 他们不需要见证数据,因为这就是软分叉的工作方式,而且他们根本不了解见证数据。

因此,这意味着这是一个 segwit 输出。 我们为什么不统计见证数据堆栈的数量? 因为在一个隔离的见证交易中,每个输入都必须有一个见证数据堆栈。 在这个交易中,我们只有一个输入,所以我们会有一堆见证数据来满足这个输入。 所以我们首先有见证数据的数量,然后是见证数据的长度,这里是第一个也是唯一一个见证数据的长度。

隔离见证的区块空间

在 Segwit 之前,块大小的上限为 1 MB。 我们只需要统计一个块中所有数据的原始字节数,最多只能是100万字节。 如果超过了,就说明这是一个无效块。 但是在Segregated Witness之后,我们对区块空间引入了一个“重量”限制,即400万个重量单位。 因为我们只把非见证数据传给老节点,老节点只能看到这个绿色的数据,而且这个数据总是小于1MB。 但是对于了解隔离见证规则的节点,我们会给他们见证数据,所以数据总量超过1MB。 8 月,我们看到了 2.77 MB 的新高块大小。

比特币价格数据下载_比特币全节点的数据量有多大_比特币蚁池的ht/s是什么数据

隔离见证节点看到完整的交易。 一个常见的误解是见证数据不是交易的一部分,不是区块的一部分。 然而,隔离见证节点可以看到完整的隔离见证交易。 对于不了解隔离见证规则的节点,交给他的数据是不包含见证数据的交易,看起来很像传统的输出交易,也会有版本号,输入容器,和输出点(通知交易该交易花费了哪个UTXO,因此节点可以将其从UTXO集合中删除),输入脚本(除了它的长度恰好为0),然后是序列字段,然后是输出脚本和锁定时间。 所有这些部分,对于非segwit节点来说,和之前的segwit交易是一样的,但是非segwit节点会更不安全,因为它们无法真正验证这些交易的签名。 我们剥离了见证数据的令牌和实体,并将剥离的交易移交给这些旧节点。 这些部分小于完整交易,因此旧节点可以继续执行 1MB 的块大小限制,但它们的安全性较低,因为输入脚本对这些节点不可用。

txid

如何在隔离见证和非隔离见证节点的同一笔交易中拥有相同的 txid? SegWit 引入的另一个变化是,在计算 SegWit 交易的 txid 时,只会使用剥离的交易部分。 我们使用剥离的交易来计算 txid,它是这个数据的哈希。 这一变化还允许我们实施像闪电网络这样的协议,我们需要在输出出现之前构建“退款交易”。 你不想把完整的、签署好的充值交易交给你的渠道对方,因为那样他们就可以确定资金已经到输出,即使他们以后不再同意后续的交易,资金也会一定要输入到双方共享的输出中。 我们必须同意后续交易,例如退款交易,否则资金会被锁定在双方的共享输出中并产生风险。

因此,同一笔交易在隔离见证和非隔离见证节点中具有相同的 txid,即使它在两个节点中的表示方式不同。

还有一个“witness txid”,缩写为“wtxid”。 为了让索引号提交给隔离见证节点看到的完整交易,我们需要提交完整的交易。 (...) 我们使用剥离的交易来获取 txid,这样我们就可以在块的 merkle 根中提交它并从中构建子交易。 这就是我们修复交易延展性的方式。 但是,对于隔离见证节点来说,为了保证他真的拿到了完整的交易,我们还需要在coinbase中放置一个见证数据承诺,承诺从完整的交易中计算出的wtxid值。

Q:如果一笔交易有多个输入,那么witness data中是否有东西可以标记一条witness data的终点和另一条witness data的起点?

答:没有这样的事情。 那么它是怎样工作的? 我们前面有一个输入计数器,它会告诉我们有多少见证数据堆栈。 每个输入都有一堆见证数据。 遗留类型输入的见证数据长度为 0。在我们的示例交易中,第二个见证数据堆栈将使用 P2TR。 我们不必说明有多少见证数据堆栈。

交易权重

为了得到交易的权重,我们只需将非见证数据的字节数乘以 4,将见证数据的字节数乘以 1,并将它们相加即可得到交易的权重。 (...) 选择这些系数纯粹是因为它们看起来不错。

比特币蚁池的ht/s是什么数据_比特币全节点的数据量有多大_比特币价格数据下载

没有见证数据的交易呢? 对于非见证数据部分的交易,我们将其字节数乘以4作为其权重; 我们之前的区块空间限制是100万字节,现在是400万重量单位。 如果我们将所有非见证数据的 1 个字节算作 4 个权重单元,这两个尺度是一样的:数据的大小变成了 4 倍,但是空间限制也变成了 4 倍。 非隔离见证交易对于旧节点来说总是相同的,因为它们看不到见证数据。 (因为见证数据)400万个权重大于100万个字节。 无论我们有多少 segwit 交易,剥离的部分都必须适合小于 1 MB 的块。

问:我听说有人建议取消见证数据折扣。 你能告诉我更多吗?

A:有些人在猜测,从长远来看,取消见证数据折扣的计划是否可以软分叉到协议中。 我的观点是,如果你把见证数据和非见证数据一样对待,那么交易的权重会严格变大——它会使用比当前规则下更少的块空间,所以我们应该能够软分叉。 如果我们有跨输入的签名聚合(多个输入的交易只使用一个签名),那么这将使签名聚合更具吸引力,因为它会从交易中消除更多成本,同时减少需要使用的区块空间; 有人认为这很好,因为我们的块空间似乎太大了。 我不同意这个想法,但我认为这是一个值得思考的理论场景。 这样的提议可能是鼓励采用签名聚合技术的好方法。

问:传统交易中的签名没有折扣,是吗?

A:传统签名会被算作非见证数据。 因为它们被放置在输入脚本中。 非隔离见证交易必须在输入脚本中提供见证数据——我们称它们为“脚本语句”——以满足条件脚本。 这是一个 P2PKH 输入比特币全节点的数据量有多大,在输入脚本中提供公钥和签名,输入脚本复制公钥,计算其哈希值,检查哈希值是否等于花费的 UTXO 匹配中的哈希值,然后检查是否签名属于公钥。 公钥和签名都在输入脚本中,所以都不算见证数据,所以它的字节数乘以4就是它的权重。

Q:为什么不说说见证数据折扣带来的最重要的特点? 它创造了创建更大交易的动力,因为这些交易的费用更低。 我以为您在讨论一个常见的误解,即这些交易更小或更容易编码。

答:好的,我们将在下一张幻灯片上讨论这个问题。

不同的输出类型

我现在将列举所有可能的输出类型。

隔离见证软分叉扩大了区块空间,因为它允许一个区块包含更多数据。 但在某种程度上,它也不会使交易变小,至少对于打包的 SegWit 交易而言是这样。 P2SH-P2WPKH 脚本是一个封装的隔离见证单签名脚本。 只有脚本语句放在见证数据部分,这会得到折扣。 在本页幻灯片中列出的 4 个输出中,P2TR 是最大的。 单从字节长度来看,一笔传统的两笔P2PKH输入和两笔P2PKH的交易与一笔输入一输出的原生Segregated Witness v0交易的大小基本相同。 本机 SegWit 交易并没有小得多。 然而,因为它有折扣,原生 Segwit 输入消耗 68 vbytes,而 P2PKH 输入消耗 148 vbytes,几乎翻倍。 事实上,P2TR 交易的字节数是最小的,加起来只有 312 字节,比原生的 Segregated Witness 交易和 P2PKH 交易小了 20% 左右。 所以,我部分同意旧的 segwit 类型没有针对带宽进行优化,但 P2TR 交易确实更小。

(结束)