登记合约与上链
登记合约只做一件事:收到指纹,发出一条事件。法读取的是事件的格式。
接口
event Anchored(address indexed author, bytes32 indexed hash);
function anchor(bytes32 hash) external;
function anchorMany(bytes32[] calldata hashes) external;anchor 发出一条事件;anchorMany 为数组中的每个元素各发一条,空数组发出零条。事件中的 author 是调用者地址。合约零存储、零所有者、零升级入口,对所有调用者一视同仁。源码在 base/zikaron-core/contracts/src/ZikaronRegistry.sol,许可为 CC0-1.0。
已知部署
应用内置两处部署,同一份钉定的构建,代码哈希相同:
| 网络 | 链号 | 登记合约 | 起始区块 |
|---|---|---|---|
| 以太坊主网(默认) | 1 | 0x36Ea8A857a5FE813429d4D9947000C644A88809A | 26087229 |
| Sepolia 测试网 | 11155111 | 0xC29410B882c4C3b77e33659d2f06ac563e7B08a3 | 11715660 |
起始区块是扫描的起点,早于这个合约上的第一条上链记录。
两种上链形式
- 登记形式
- 交易成功,且回执中有一条由登记合约发出的日志:恰有三个主题、数据为空;主题 0 为
Anchored(address,bytes32)的 keccak256,主题 1 为交易发送者,主题 2 为指纹。同一指纹还须出现在交易的调用数据中,起始偏移为 32 的整数倍,或 4 加 32 的整数倍。 - 自转账形式
- 一笔发给自己的交易,调用数据长度为 32 的正整数倍,每 32 字节为一个指纹。只依赖交易本身,适用于任何 EVM 链。
两种形式效力相同。核验方在自己的扫描范围中写明认可哪些登记合约地址、哪些发送者、哪些自转账交易。
对发送者的三项要求
- 发送者是由交易签名恢复出的地址。经中继代发的交易,发送者为中继地址;由账户代码验证的交易,在法中发送者一项为空。
- 发送地址在上链所在区块前后均为普通地址。带有代码或 EIP-7702 委托的地址发出的上链记录,一律作废。
- 交易签名中写明链号。
这三项保证一条上链记录始终可以读作「这把密钥本人所为」。
代码哈希
合约的运行时字节码长 246 字节,其 keccak256 为:
它由固定的编译设置产生:solc 0.8.28,EVM 版本 cancun,开启优化(200 轮),开启 via_ir,字节码去除元数据。源码或设置的任何改动都会改变哈希。自行重算:
cd base/zikaron-core/contracts
forge build
cast keccak $(forge inspect ZikaronRegistry deployedBytecode)自行部署
任何人都可以在任一已完成上海升级的 EVM 链上部署相同的字节。部署后核对链上代码哈希与上表一致,再在应用的「设置 › 网络 › 编辑节点…」里填入链 ID、登记合约与起始区块。
forge create src/ZikaronRegistry.sol:ZikaronRegistry \
--rpc-url <节点> --private-key <部署用的密钥> --broadcast
cast keccak $(cast code <新地址> --rpc-url <节点>)部署请用专门的密钥;身份密钥只用于签署账本和发送上链交易。
这份固定构建使用 PUSH0 指令,适用于已完成上海升级的链。更早的链须另行构建,代码哈希也随之改变。法按核验方声明的合约地址读取日志,因此另一份构建只关乎部署的便利。
费用参考
| 调用 | 合约执行消耗的 gas |
|---|---|
anchor | 2,352 |
anchorMany,1 条 | 2,776 |
anchorMany,10 条 | 17,746 |
anchorMany,100 条 | 167,661 |
表中是在 forge 里测得的合约执行部分,交易的 21,000 基础费用与调用数据费用另计。条数越多,单条分摊越少。应用发送时 gas 上限定为 200,000。
经其他合约上链
任何合约只要发出同样格式的日志,都可充当登记合约。以下三个条件同时成立,该日志才算上链记录:交易由账本密钥亲自发出;指纹出现在该交易自身的调用数据中,且位置符合上述规定;日志由被调用的合约自身发出。合约在内部转而调用登记合约时,日志记录的是那个合约的地址,对任何账本而言都只是一条普通日志。
核验方只应把读过源码、代码固定的合约地址写入扫描范围。
自含上链证明
法 §9.7 定义了自含的上链证明,记录包的 proofs/ 目录用于携带。凭这样一份证明,核验方只需两个可信的区块哈希即可验证一条上链记录:区块头,交易与回执各自的默克尔证明,以及发送地址在前后两个区块中的账户证明。节点清理历史数据后,此类证明依然有效。