签署交易
签名证明账户密钥的持有者逐字节地认可了一笔交易。在 ZooBC 上,签名者从不直接对裸交易签名:它签署的是一个同时覆盖链身份的摘要,因此签名只在一条链上有效。多种密钥类型的账户都可以签名,各自使用其原链的方案,这让比特币、以太坊或 Solana 密钥可以直接控制一个 ZooBC 账户。
签署的内容
签名者取未签名的信封(即除签名之外的所有字段),并签署以下摘要:
digest = SHA3-256( "ZBC-TX" ‖ genesis block hash ‖ unsigned bytes )
“ZBC-TX”是一个 ASCII 标签,‖ 表示“后接”。只有这个链绑定摘要会被接受。在版本 3 交易中,4 个到期字节属于未签名字节的一部分,因此它们与其他所有字段一样被签署。
创世区块哈希就是链的身份。ZooBC 没有网络 id 字段:devnet、testnet 和 mainnet 各有自己的创世哈希,因此为 mainnet 生成的签名在 devnet 或 testnet 上无法通过验证,即使同一密钥在这三条链上都持有资金。节点在相互连接之前也会比对创世哈希。这堵住了跨链重放,即有人把你的交易从一条链复制到另一条链;见 链绑定签名。
哈希与 id
交易签名之后,由它的哈希和 id 来标识:
hash = SHA3-256( unsigned bytes ‖ signature )
id = the first 8 bytes of the hash, read as a little-endian signed 64-bit integer
节点会拒绝已经确认过的 id,从而阻止同一条链上的重放。IssueToken 交易的 id 同时也是它所创建代币的 id(见 发行代币)。
可以签名的密钥类型
地址以一个类型编号开头,类型决定了其签名的校验方式:
| 密钥类型(编号) | 签名方案 |
|---|---|
| ZooBC(0)、Solana(11) | Ed25519 |
| Cardano(13)、Tezos(16) | Ed25519,公钥携带在一个 98 字节的签名字段中 |
| 比特币传统格式(1)、P2PKH(5)、P2SH 封装的 P2WPKH(6)、P2WPKH(7)、Ripple(14) | 对摘要做两次 SHA-256 后进行 secp256k1 ECDSA 签名,并携带公钥 |
| 以太坊(4)、Tron(15) | 对摘要的 Keccak-256 进行 secp256k1 签名;密钥从 65 字节的 r‖s‖v 签名中恢复 |
| 比特币 Taproot(9) | BIP-340 Schnorr |
| Polkadot(12) | sr25519 |
ECDSA 签名必须采用 low-s 形式。无论哪种方案,每把密钥签署的都是同一个链绑定摘要。
有些地址类型永远不能签名:Empty(2)、爱沙尼亚 eID(3,没有验证器)、比特币 P2WSH 脚本(8)和数据集(10)。P2WSH 地址代表的是一段脚本而不是单个密钥,数据集地址指向的是数据而不是签名者。无密钥账户,例如系统资金池、账户组和多重签名账户,根本没有密钥,只能通过各自的规则来花费。
用外部链的钱包签名
外部链的钱包还可以签署一笔其本链的交易,并让它作为消息,被携带在对应的 ZooBC 交易中:
- 以太坊:一笔传统(legacy)、EIP-2930 或 EIP-1559 交易,且访问列表为空;
- Solana:一笔 System 转账;
- 比特币:一个输入、一到两个输出,且手续费为零。
节点会检查发送方、接收方和金额是否与 ZooBC 交易一致,并且同一份外部载荷只能被花费一次。这样的消息最多可容纳 4,096 字节。以太坊式访问见 MetaMask 与以太坊式访问。
其他签名摘要
同样的链绑定模式(每次使用各自的标签)也用于其他同意操作:
- 把地址关联到组,以及移交组的控制权(“ZBC-GROUP-LINK”和“ZBC-GROUP-CONTROL”);
- 请求节点取消其交易池中一笔待处理的交易(“ZBC-CANCEL”);
- 多方托管的联署签名。
链下消息不是交易,它们用 Ed25519 密钥按 SHA3-256("ZBC-MSG-v2" ‖ genesis hash ‖ message) 签名;见 签名消息与加密消息。