计算Arweave存储文件的Keccak哈希及本地文件适配问题
计算文件Keccak哈希的正确实现(跨Arweave/本地/IPFS)
原代码的核心问题
- 流处理不完整:
blob.stream().getReader().read()只读取了文件的第一块数据,未遍历读取全部内容,导致哈希基于不完整字节,结果完全错误。 - Blob转字节的方式冗余,Node.js环境下直接处理ArrayBuffer更高效可靠。
修正后的远程文件(Arweave/IPFS)哈希计算代码
以下代码可正确读取完整文件字节并计算Keccak哈希,保证结果可复现:
import { ethers } from "ethers"; async function calculateRemoteFileKeccak(imageUrl: string): Promise<string> { // 获取完整响应流并转换为ArrayBuffer const response = await fetch(imageUrl); if (!response.ok) throw new Error(`请求失败: ${response.status}`); // 读取完整的原始字节 const arrayBuffer = await response.arrayBuffer(); const rawBytes = new Uint8Array(arrayBuffer); // 使用ethers计算Solidity兼容的Keccak256哈希,"bytes"类型参数完全正确 const hash = ethers.utils.solidityKeccak256(["bytes"], [rawBytes]); return hash; }
本地文件哈希计算代码
使用Node.js的fs模块读取本地文件,逻辑与远程保持一致,确保哈希结果相同:
import { ethers } from "ethers"; import { readFile } from "fs/promises"; async function calculateLocalFileKeccak(filePath: string): Promise<string> { // 读取本地文件原始字节(默认Buffer类型,可直接转换为Uint8Array) const fileBuffer = await readFile(filePath); const rawBytes = new Uint8Array(fileBuffer); // 复用相同的哈希计算逻辑 const hash = ethers.utils.solidityKeccak256(["bytes"], [rawBytes]); return hash; }
跨存储哈希一致的关键要点
- 必须读取完整的原始文件字节:无论文件存储在Arweave、IPFS还是本地,都不能对内容做任何修改(如格式转换、压缩、编码调整)。
- 统一字节处理方式:始终将文件内容转换为
Uint8Array(或Node.js的Buffer,两者可互相转换)作为哈希输入,避免编码差异。 - 固定哈希计算逻辑:坚持使用
ethers.utils.solidityKeccak256(["bytes"], [rawBytes]),该方法完全对齐Solidity中keccak256(bytes)的计算逻辑,确保链上链下结果一致。
内容的提问来源于stack exchange,提问作者GGizmos
相关产品推荐
相关产品推荐

