
两种标识先看送入计算的字节
区块链交易哈希并没有一套适用于所有链的命名规则。本文限定比特币BIP141中的txid和wtxid:前者保留传统交易序列化的标识定义,后者把见证数据纳入新的序列化范围。两者使用的都是双SHA256,差别首先在输入字节,而不是一个使用旧算法、另一个换了新算法。
把字段组成横向对照,txid的输入依次为版本、交易输入集合、交易输出集合、锁定时间。输入和输出集合本身仍有数量及各项内容的编码规则。这里讲的是按规则排好的字节序列,不能把网页上几段字段文字直接拼接后,就当成相同的计算对象。
Wtxid包含见证,也保留其他交易字段
用于wtxid的新序列化依次包含版本、标记字节、标志字节、输入集合、输出集合、见证、锁定时间。与前一种排列相比,见证并非简单写到整份旧数据的最后,标记和标志也有规定位置。因此,wtxid不是“只对签名做哈希”,也不是给已经得到的txid再追加一段文字。
BIP141还说明,交易的每个输入都有对应的见证字段,字段中按数量和长度组织栈元素。理解这一点,可以避免把见证看成整个交易只有一份、长度固定的签名附件。传统输入中的脚本仍有自己的序列化位置;不能为了得到不含见证的形式,就把所有看起来像脚本的数据一起删去。

两个定义不代表结果一定不同
无见证情况是阅读定义时不能省略的例外。BIP141规定,如果所有输入都不是见证程序,交易的wtxid等于txid。因而一份资料同时列出两个名称,却显示相同值,并不足以说明其中一个字段填错了;先确认对应交易是否具有见证数据,才能解释这种相等关系。
可以设想两份只用于理解字段的资料:甲明确不含见证,乙明确包含见证。整理甲时,应记录两个定义在这种情况下返回相同结果;整理乙时,则应分别保留两种字节范围。不能为了让表格看上去有两列不同标识,给甲补造见证,或凭字段名称判断乙采用了哪种编码。
实现代码显示分支在哪里发生
btcsuite的btcd v0.24.2提供了一个独立实现对照。其TxHash使用SerializeNoWitness;WitnessHash则先调用HasWitness,存在见证时使用Serialize,没有见证时直接返回TxHash。这个分支把规范中的输入范围差异和无见证例外,落实为可以定位的函数关系。
继续看该文件的编码函数,只有选择见证编码且交易实际具有见证时,才写入标记、标志及每个输入的见证。两条哈希路径因此不能只靠相似函数名猜测。阅读同类库时,应留下版本、调用函数与实际序列化范围,确保这些记录能够彼此对应,再核对结果含义;本文仅作规范和代码阅读,没有计算或查询真实交易。