Spark Program | HashThis Project

Hi @oiclid,我是 Spark 委员会的成员 Hanssen。我无意对新增的技术内容作出反馈,虽然这本来应该是我要做的事情。

AI 是强大的工具,而且我们鼓励开发者们使用 AI 来更高效地实现点子,但它不意味着你可以对你的产品毫无概念。你至少需要知道你在做什么,目标用户希望从你的工作中得到什么,从而在 AI 犯错的时候将其纠正回到它应有的方向上。

委员会成员在每位申请者的成果上都需要投入时间和精力,希望能为申请者提供足够的帮助,将项目以更好的形态推向社区。在 AI 普及的当下,诸如 OpenClaw 的项目已经为使用者们提供了亮眼的成果,在 CKB 社区中也已经崭露头角,而以人工为中继和 AI 沟通只会让所有人感到沮丧。

希望能收到更有意义的更新,祝好。


Hi @oiclid, this is Hanssen from the Spark Committee. I have no intention of providing feedback on the newly added technical content, even though that is technically what I’m here to do.

AI is a powerful tool, and we encourage developers to use it to bring their ideas to life more efficiently. However, this does not mean you can afford to have zero conceptual grasp of your own product. You must, at the very least, understand what you are building and what your target users expect from your work. This is the only way you can steer AI back in the right direction when it inevitably veers off course.

Committee members invest significant time and effort into every applicant’s submission, hoping to provide enough support to push projects into the community in their best possible form. In this era of AI ubiquity, projects like OpenClaw have already delivered impressive results and are making a name for themselves within the CKB community. Acting merely as a “human relay” to communicate with AI only leads to frustration for everyone involved.

I look forward to seeing more meaningful updates. Best regards.

8 Likes

Hi @Hanssen

Thank you for being direc. I am glad for the feedback you provided

I want to be transparent about how I actually used AI in this project, because I think the picture is more nuanced than it may appear. The core architecture, the CKB cell model decisions, the CCC migration, and the debugging process were work I drove myself. Where I used AI was in two specific ways: as a pair programmer to help implement, refactor, and debug code I had already reasoned through, and to polish my written reports and translate them into Chinese for broader accessibility in the CKB community.

That said, your point lands. There were moments (especially during the committee fixes) that I may have leaned on AI more heavily than I should have, and the gaps in my ability to course-correct it quickly enough were visible. That’s on me, and it’s something I’m actively working on.

I’m going back to the fundamentals, iethe CKB cell model, how CCC constructs and signs transactions, and what proof-of-existence actually guarantees cryptographically. I want to reach a point where AI accelerates work I already understand rather than compensating for understanding I haven’t built yet.

I appreciate the committee’s time and I intend to make better use of it going forward.

Best regards

4 Likes

你好 @Hanssen

感谢您的直言不讳,您提供的反馈让我受益匪浅。

我想坦诚地说明我在这个项目中实际使用 AI 的方式,因为我认为实际情况比表面看起来更为复杂。核心架构、CKB Cell 模型的决策、CCC 迁移以及调试过程,都是我自己主导完成的工作。我使用 AI 的方式体现在两个具体方面:一是作为结对编程工具,帮助实现、重构和调试我已经独立思考过的代码;二是润色我的书面报告,并将其翻译成中文,以便在 CKB 社区中获得更广泛的传播。

话虽如此,您的观点确实触动了我。在某些时刻(尤其是在委员会修复阶段),我对 AI 的依赖可能超出了应有的程度,而我在及时纠正其方向方面的不足也暴露无遗。这是我自身的问题,也是我正在积极改进的地方。

我将重新回归基础——深入理解 CKB Cell 模型、CCC 如何构建和签署交易,以及存在性证明在密码学层面究竟能保证什么。我希望达到这样一种状态:AI 加速的是我已经理解的工作,而不是弥补我尚未建立的知识基础。

感谢委员会投入的时间与精力,我会在今后的工作中更好地珍惜这份支持。

此致

4 Likes

感谢你的回复,我相信事情会变得更好。

对于 HashThis,我建议你考虑如何实现用户的文件/哈希存在性证明。我们引入区块链是为了让用户能够在不披露文件内容的情况下,证明自己在某个时间节点之前已经知晓了这份文件。而区块链将哈希打包上链的时间是让这个证明有意义的关键,因此我不认为依赖客户端或者服务器的数据是可以接受的做法。

而对于可持续性问题,我想提醒的是:在 CKB 上储存数据需要占用 CKB 原生代币。这意味着在当下的实现思路下,服务器需要一直锁定自己的原生代币,这显然是不可持续的。

祝好。


Thanks for your reply and I trust that things will improve.

Regarding HashThis, I suggest you consider how to implement the existence proof of user file/hash. We introduced the blockchain so that users can prove they were in possession of a specific file before a certain point in time, without disclosing the file’s content. The moment the blockchain packs the hash into a block is what makes this proof meaningful. Therefore, I do not think relying on client-side or server-side data is an acceptable approach.

As for the sustainability issue, I would like to remind you: storing data on CKB requires occupying native CKB tokens. This means that under the current implementation, the server would need to keep its own native tokens locked indefinitely, which is clearly unsustainable.

Best regards.

6 Likes

@Hanssen, proof-of-existence is operational. I am currently enhancing shareability and discoverability, while transitioning the core logic from the server to on-chain. I have also finalized the user-paid proof implementation; it is included in the most recent build.

5 Likes

@zz_tovarishch @Hanssen @yixiu.ckbfans.bit @xingtianchunyan
It’s now working, and all the issues have been fixed. I’ll share my report later.

4 Likes

HashThis — Issues & Fixes Report

Nervos CKB Proof-of-Existence · March 2026


Overview

This document covers every bug identified and resolved during the HashThis development cycle. Issues ranged from silent data failures deep in the blockchain service layer to test environment misconfigurations and UI edge cases. Each fix is described in plain terms — what was wrong, why it mattered, and how it was resolved.


1. Verified proofs returning empty transaction hash, block number, and timestamp

Severity: Critical — core feature broken

What happened: After verifying a file, the result screen showed “Awaiting confirmation” for the timestamp and “—” for the block number, even for transactions that had been confirmed on-chain for weeks.

Root cause (part 1): The CKB indexer returns cell objects where the transaction hash lives at cell.outPoint.txHash, not cell.txHash. The code was reading cell.txHash, which was always undefined. Because the frontend checks if (data.txHash) before calling the blocktime endpoint, it never attempted the timestamp fetch at all.

Root cause (part 2): Even when a valid txHash was passed, pollTransactionStatus was checking txResponse.status === "committed" — but @ckb-ccc/core’s getTransaction() actually returns { transaction, txStatus: { status, blockHash } }. The status was nested one level deeper than expected, so the equality check never matched, and the poller ran all 60 attempts (~5 minutes) before timing out on every single verification.

Fix: Changed both verifyHash and getUserProofs in ckb.service.ts to read cell.outPoint?.txHash. Updated pollTransactionStatus to read txResponse?.txStatus?.status and txResponse?.txStatus?.blockHash with a fallback chain for SDK version safety.

File: api-backend/api/hashes/ckb.service.ts


2. Certificate button showing “Generation failed” on valid proofs

Severity: High — confusing UX on every freshly verified proof

What happened: After verifying a file, clicking “Download Certificate” immediately showed “:cross_mark: Generation failed — txHash is required; blockNumber is required; timestamp is required” even though the proof was confirmed on-chain.

Root cause: The certificate validator correctly requires all three fields, but the button was always rendered regardless of whether the data was ready. For transactions still awaiting confirmation, blockTimestamp is empty — which is valid and expected — but the button let users click through to an instant failure rather than communicating why.

Fix: Added a canCertify check before rendering. When txHash, blockNumber, or timestamp are missing, a disabled greyed-out button renders instead with a hover tooltip explaining that a confirmed timestamp is needed. The JSON export button always remains active since its schema explicitly supports a null timestamp.

File: frontend/src/pages/Verify.tsx


3. Block number displaying as “#unknown” instead of a number or “—”

Severity: Medium — visually broken output

What happened: The Verify page displayed Block: #unknown instead of either a real block number or a clean dash.

Root cause: ckb.service.ts used cell.blockNumber?.toString() || "unknown" as a fallback. Since "unknown" is a truthy string, the frontend’s || "" guard didn’t catch it, and it was rendered literally as #unknown.

Fix: Changed both fallback expressions in ckb.service.ts to return "" (empty string). The UI then falls through to display cleanly.

File: api-backend/api/hashes/ckb.service.ts


4. Valid proofs hidden when getBlockTime threw an error

Severity: High — proofs appeared as errors instead of verified

What happened: If the blocktime fetch failed (e.g. the transaction hadn’t fully propagated to the queried node), the entire verify flow fell into the error state — even though the on-chain proof was valid.

Root cause: The getBlockTime call was inside the outer try/catch block. Any failure there set status = "error" and cleared the result, discarding the valid cell data that had already been found.

Fix: Wrapped getBlockTime in its own inner try/catch. The outer result is now set first, block number is stored as a fallback immediately, and a timestamp fetch failure only shows an amber warning banner — the proof is still shown as verified.

File: frontend/src/pages/Verify.tsx


5. Midnight rendered as “24:00:00” on PDF certificates

Severity: Medium — incorrect timestamp on generated documents

What happened: PDF certificates generated for transactions confirmed at or near midnight showed the time as 24:00:00 instead of 00:00:00.

Root cause: The PDF generator used hour12: false in the toLocaleString options. The h24 hour cycle maps midnight to hour 24 (end of day), not hour 0 (start of day).

Fix: Changed to hourCycle: 'h23', which uses the 0–23 range and correctly renders midnight as 00:00:00.

File: frontend/src/utils/pdfGenerator.ts


6. Test suite failing — document and navigator not defined

Severity: Medium — 8 tests broken, blocking CI

What happened: The proofExport.test.ts suite failed with ReferenceError: document is not defined and ReferenceError: navigator is not defined on all download and clipboard tests.

Root cause (part 1): The test file was running in Vitest’s default Node environment where browser globals don’t exist. The // @vitest-environment jsdom directive was present but wasn’t taking effect reliably in watch mode due to environment caching.

Root cause (part 2): Even with jsdom, vi.spyOn(document, 'createElement') and Object.defineProperty(navigator, 'clipboard', ...) require those globals to already exist as real objects — they can’t create them from scratch.

Root cause (part 3): copyProofToClipboard accessed navigator.clipboard.writeText before entering the try/catch, so when navigator was undefined it threw a ReferenceError that propagated upward rather than being caught and returning false.

Fix: Replaced all browser global usage in the test with (globalThis as any).document = {...} and (globalThis as any).navigator = {...} set in beforeEach and cleaned up in afterEach. This works in any environment. Also added a typeof navigator !== 'undefined' guard in copyProofToClipboard before accessing it.

Files: frontend/src/utils/proofExport.test.ts, frontend/src/utils/proofExport.ts


7. History endpoint crashing in tests — req.headers.host undefined

Severity: Medium — all 24 history tests failing

What happened: Every test in history.test.ts that expected a 400 validation error was instead getting a 500 internal server error.

Root cause: The history.ts handler used new URL(req.url, \https://${req.headers.host}`)to parse query parameters. Test mocks don't populatereq.headers, so req.headers.hostwasundefined`, throwing inside the handler before any validation logic ran. The try/catch caught it and returned 500.

Fix: Reverted to const { userAddress, limit } = req.query — consistent with every other handler in the codebase.

File: api-backend/api/hashes/history.ts


8. Build failing — unused React import

Severity: High — deployment blocked

What happened: The Vercel build failed with error TS6133: 'React' is declared but its value is never read.

Root cause: History.tsx imported React as a default import. The project uses the new JSX transform ("jsx": "react-jsx" in tsconfig.json) which doesn’t require React in scope. With noUnusedLocals: true enabled, TypeScript treats this as a hard error.

Fix: Removed React from the import, keeping only the named hooks: import { useState, useEffect } from 'react'.

File: frontend/src/pages/History.tsx


9. Wrong hex constant for 95 CKB in tests

Severity: Low — test assertion incorrect, masking potential regressions

What happened: A test assertion for the 95 CKB anchor capacity was using the wrong hex value and would have passed even with an incorrect capacity calculation.

Root cause: 95 CKB = 9,500,000,000 shannons = 0x2363e7f00. The test had 0x236223e800, which is a different value.

Fix: Corrected the constant in the test.

File: api-backend/api/hashes/batch.test.ts


10. Wrong import path in batch tests

Severity: Low — tests failed to run entirely

What happened: batch.test.ts couldn’t find ckb.service and crashed at import time.

Root cause: The import path was '../api/hashes/ckb.service.js' — referencing a path relative to the wrong directory.

Fix: Corrected to './ckb.service.js'.

File: api-backend/api/hashes/batch.test.ts


11. Main bundle too large — build warning

Severity: Low — performance issue, not a functional bug

What happened: Vite warned that the main JavaScript bundle was 1.6 MB after minification, well above the 500 KB threshold.

Root cause: jsPDF and qrcode — only needed when a user generates a PDF certificate — were bundled into the main chunk loaded on every page visit.

Fix: Added manualChunks to vite.config.ts splitting jsPDF and qrcode into a separate pdf-vendor chunk loaded lazily on demand. Also split React and CKB vendor code into their own stable chunks for better long-term caching.

File: frontend/vite.config.ts


Summary

# Issue File Severity
1 Empty txHash, blockNumber, timestamp on verified proofs ckb.service.ts Critical
2 Certificate button “Generation failed” on valid proofs Verify.tsx High
3 Block number showing as #unknown ckb.service.ts Medium
4 Valid proofs hidden when blocktime fetch failed Verify.tsx High
5 Midnight rendered as 24:00:00 on certificates pdfGenerator.ts Medium
6 document/navigator not defined in test suite proofExport.test.ts, proofExport.ts Medium
7 History endpoint returning 500 instead of 400 in tests history.ts Medium
8 Build failing — unused React import History.tsx High
9 Wrong hex constant for 95 CKB batch.test.ts Low
10 Wrong import path in batch tests batch.test.ts Low
11 Main bundle 1.6 MB — performance warning vite.config.ts Low


中文版 — HashThis 问题修复报告

Nervos CKB 存在性证明 · 2026 年 3 月


概述

本文档涵盖 HashThis 开发周期中发现并解决的所有缺陷。问题涉及区块链服务层中的静默数据错误、测试环境配置问题和 UI 边界情况。每个修复均以通俗语言描述——哪里出了问题、为什么重要、以及如何解决。


1. 已验证证明返回空的交易哈希、区块号和时间戳

严重程度: 严重——核心功能失效

现象: 验证文件后,结果页面显示"等待确认"和"—",即使该交易已在链上确认数周。

根本原因(一): CKB 索引器返回的 Cell 对象中,交易哈希位于 cell.outPoint.txHash,而非 cell.txHash。代码读取的是 cell.txHash,该值始终为 undefined。由于前端在调用 blocktime 接口前会检查 if (data.txHash),因此从未发起时间戳获取请求。

根本原因(二): 即使传入了有效的 txHash,pollTransactionStatus 也在检查 txResponse.status === "committed"——但 @ckb-ccc/coregetTransaction() 实际返回 { transaction, txStatus: { status, blockHash } }。状态嵌套了一层,导致判断永远不匹配,轮询器每次都跑完全部 60 次尝试(约 5 分钟)后超时。

修复:verifyHashgetUserProofs 中的 cell.txHash 改为 cell.outPoint?.txHash;将 pollTransactionStatus 中的状态读取路径改为 txResponse?.txStatus?.statustxResponse?.txStatus?.blockHash

文件: api-backend/api/hashes/ckb.service.ts


2. 证书按钮对有效证明显示"生成失败"

严重程度: 高——每次验证后都出现令人困惑的 UX

现象: 验证文件后点击"下载证书",立即显示":cross_mark: 生成失败——txHash 为必填项;blockNumber 为必填项;timestamp 为必填项"。

根本原因: 证书验证器正确地要求三个字段都存在,但按钮始终被渲染,无论数据是否就绪。对于仍在等待确认的交易,blockTimestamp 为空是正常且预期的,但按钮让用户点进去后立即失败,而没有说明原因。

修复: 在渲染前添加 canCertify 检查。当 txHashblockNumbertimestamp 缺失时,改为渲染一个禁用的灰色按钮,并附带悬浮提示说明需要已确认的时间戳。JSON 导出按钮始终可用,因为其 schema 明确支持空时间戳。

文件: frontend/src/pages/Verify.tsx


3. 区块号显示为 #unknown 而非数字或"—"

严重程度: 中——输出显示异常

现象: 验证页面显示 Block: #unknown

根本原因: ckb.service.ts 使用 cell.blockNumber?.toString() || "unknown" 作为回退值。由于 "unknown" 是真值字符串,前端的 || "" 保护没有生效,被直接渲染为 #unknown

修复:ckb.service.ts 中两处回退表达式改为返回 ""(空字符串),UI 则显示

文件: api-backend/api/hashes/ckb.service.ts


4. getBlockTime 抛出异常时隐藏有效证明

严重程度: 高——证明被误判为错误

现象: 若 blocktime 获取失败,整个验证流程进入错误状态——即使链上证明是有效的。

根本原因: getBlockTime 调用位于外层 try/catch 内,任何失败都会将 status 设置为 "error" 并清除已找到的有效 Cell 数据。

修复:getBlockTime 包裹在独立的内层 try/catch 中。外层结果优先设置,区块号作为回退值立即存储,时间戳获取失败仅显示一个琥珀色警告横幅,证明仍显示为已验证。

文件: frontend/src/pages/Verify.tsx


5. PDF 证书中午夜显示为 24:00:00

严重程度: 中——生成文档中时间戳错误

现象: 在午夜前后确认的交易生成的 PDF 证书显示时间为 24:00:00 而非 00:00:00

根本原因: PDF 生成器使用了 hour12: false 选项。h24 小时制将午夜映射为第 24 小时(当天结束),而非第 0 小时(次日开始)。

修复: 改用 hourCycle: 'h23',使用 0–23 范围,正确将午夜渲染为 00:00:00

文件: frontend/src/utils/pdfGenerator.ts


6. 测试套件失败——document 和 navigator 未定义

严重程度: 中——8 个测试失败,阻塞 CI

现象: proofExport.test.ts 中所有下载和剪贴板测试抛出 ReferenceError: document is not definedReferenceError: navigator is not defined

根本原因(一): 测试文件在 Vitest 默认的 Node 环境中运行,该环境中浏览器全局变量不存在。// @vitest-environment jsdom 指令在 watch 模式下因环境缓存而未能可靠生效。

根本原因(二): vi.spyOn(document, ...)Object.defineProperty(navigator, ...) 要求这些全局变量作为真实对象已存在,无法凭空创建。

根本原因(三): copyProofToClipboard 在进入 try/catch 之前就访问了 navigator.clipboard.writeText,当 navigatorundefined 时会向上抛出 ReferenceError 而非被捕获后返回 false

修复: 将测试中所有浏览器全局变量的使用替换为在 beforeEach 中设置 (globalThis as any).document = {...}(globalThis as any).navigator = {...},并在 afterEach 中清理。同时在 copyProofToClipboard 中访问 navigator 前添加 typeof navigator !== 'undefined' 检查。

文件: frontend/src/utils/proofExport.test.tsfrontend/src/utils/proofExport.ts


7. History 接口在测试中返回 500 而非 400

严重程度: 中——24 个历史测试全部失败

现象: history.test.ts 中所有期望 400 验证错误的测试均收到 500 内部服务器错误。

根本原因: history.ts 处理器使用 new URL(req.url, \https://${req.headers.host}`)解析查询参数。测试 mock 不填充req.headers,导致 req.headers.hostundefined`,在任何验证逻辑执行前就在处理器内部抛出异常,被 try/catch 捕获后返回 500。

修复: 回退至 const { userAddress, limit } = req.query——与代码库中其他所有处理器保持一致。

文件: api-backend/api/hashes/history.ts


8. 构建失败——未使用的 React 导入

严重程度: 高——部署被阻断

现象: Vercel 构建失败,报错 error TS6133: 'React' is declared but its value is never read

根本原因: History.tsx 以默认导入方式引入了 React。该项目使用新的 JSX 转换(tsconfig.json 中配置 "jsx": "react-jsx"),不需要 React 在作用域中。启用 noUnusedLocals: true 后,TypeScript 将此视为硬性错误。

修复: 从导入中移除 React,仅保留具名 hooks:import { useState, useEffect } from 'react'

文件: frontend/src/pages/History.tsx


9. 测试中 95 CKB 的十六进制常量错误

严重程度: 低——测试断言不正确

现象: 95 CKB 锚定容量的测试断言使用了错误的十六进制值,即使容量计算有误也能通过。

根本原因: 95 CKB = 9,500,000,000 shannons = 0x2363e7f00。测试中写的是 0x236223e800,值不同。

修复: 更正测试中的常量值。

文件: api-backend/api/hashes/batch.test.ts


10. batch 测试中导入路径错误

严重程度: 低——测试完全无法运行

现象: batch.test.ts 在导入时找不到 ckb.service,直接崩溃。

根本原因: 导入路径为 '../api/hashes/ckb.service.js'——相对于错误目录进行了引用。

修复: 更正为 './ckb.service.js'

文件: api-backend/api/hashes/batch.test.ts


11. 主包体积过大——构建警告

严重程度: 低——性能问题,非功能性缺陷

现象: Vite 警告主 JavaScript 包压缩后体积达 1.6 MB,远超 500 KB 阈值。

根本原因: jsPDF 和 qrcode——仅在用户生成 PDF 证书时才需要——被打包进了每次访问页面时都会加载的主 chunk 中。

修复:vite.config.ts 中添加 manualChunks,将 jsPDF 和 qrcode 分割为按需懒加载的独立 pdf-vendor chunk。同时将 React 和 CKB 厂商代码分割为各自独立的稳定 chunk,以获得更好的长期缓存效果。

文件: frontend/vite.config.ts


汇总

# 问题 文件 严重程度
1 已验证证明返回空的交易哈希、区块号和时间戳 ckb.service.ts 严重
2 证书按钮对有效证明显示"生成失败" Verify.tsx
3 区块号显示为 #unknown ckb.service.ts
4 getBlockTime 失败时隐藏有效证明 Verify.tsx
5 PDF 证书中午夜显示为 24:00:00 pdfGenerator.ts
6 测试中 document/navigator 未定义 proofExport.test.tsproofExport.ts
7 History 接口在测试中返回 500 而非 400 history.ts
8 构建失败——未使用的 React 导入 History.tsx
9 95 CKB 十六进制常量错误 batch.test.ts
10 batch 测试中导入路径错误 batch.test.ts
11 主包体积 1.6 MB——性能警告 vite.config.ts

@zz_tovarishch @Hanssen @yixiu.ckbfans.bit @xingtianchunyan

4 Likes

Spark Program: Termination of Funding for HashThis Project

星火计划致力于支持社区开发者和创新项目。我们始终以透明、公正和负责任的态度管理每一笔资助。经过委员会的慎重评估,我们遗憾地宣布,对 HashThis 项目的资助已正式终止。

The Spark Program is committed to supporting community developers and innovative projects. We always manage every grant with transparency, fairness, and responsibility. After careful evaluation by the committee, we regret to announce that the funding for the HashThis project has been officially terminated.

项目基本信息 / Project Basic Information

  • 项目名称 / Project Name:HashThis

  • 开发者/团队 / Developer/Team:oïclid、shaaibu、Paul

  • 项目简介(提案内容) / Project Description (Proposal Content)

    HashThis 是一个轻量级 dApp,允许用户证明数据在特定时间存在且未被篡改。用户在本地对数据进行哈希,将哈希锚定到 CKB 上,之后可验证其完整性和时间戳。该项目专注于单一、明确的工作流程:hash → anchor → verify。它是一个应用级原型,而非基础设施。

    HashThis is a lightweight dApp that lets users prove that data existed at a apecific time and has not been altered. Users hash data locally, anchor the hash on CKB, and later verify its integrity and timestamp. The project focuses on a single, clear workflow: hash → anchor → verify. It is an application-level prototype, not infrastructure.

终止决定及原因 / Termination Decision and Reasons

星火计划委员会在项目后续验证与周同步跟踪中发现,该项目核心功能——交易构造与上链流程——持续处于未能成功构建的状态。经过多轮技术沟通、代码审查、建议优化与修复尝试后,基础的不可用问题仍然存在,未能达到可验证、可使用的基本要求,严重偏离原提案承诺的核心价值主张(可靠的链上数据锚定与完整性证明)。

The Spark Initiative Committee discovered during subsequent validation and weekly tracking that the project’s core functions—transaction construction and on-chain processes—have continuously failed to build successfully. After multiple rounds of technical communication, code reviews, suggested optimizations, and repair attempts, the fundamental unavailability persists and does not meet the basic requirements for verifiability and usability, seriously deviating from the core value proposition promised in the original proposal (reliable on-chain data anchoring and integrity proofs).

具体情况梳理 / The specific situation

问题演进经历了三个主要阶段,委员会在每个阶段均给予了明确的反馈与修复建议,但核心可用性与价值主张问题始终未能得到根本解决。

The issue evolved through three main stages; the committee provided clear feedback and remediation suggestions at each stage, but the core usability and value proposition problems were never fundamentally resolved.

  1. 初始审查阶段(首次反馈)/ Initial Review Stage (First Feedback)
    项目提交的原型在使用过时的 Lumos SDK 实现交易构建逻辑。在多用户并发场景下,存在潜在的交易冲突与构建失败风险。

    The prototype submitted by the project implements transaction construction logic using an outdated Lumos SDK. In multi-user concurrent scenarios, there is a potential risk of transaction conflicts and construction failures.

    委员会于相关帖子中明确指出后端服务已崩溃、SDK 版本过时,并建议尽快升级至最新 CCC 库(@ckb-ccc/core)以提升稳定性和兼容性。

    The committee explicitly noted in related posts that the backend service had crashed and the SDK version was outdated, and recommended upgrading as soon as possible to the latest CCC library (@ckb-ccc/core) to improve stability and compatibility.

    链接 / Link:Spark Program | HashThis Project - #14 by xingtianchunyan

    开发者随后响应并完成了 CCC 库的迁移,委员会对此表示认可。

    The developer later responded and completed the migration of the CCC library, which was acknowledged by the committee.

  2. 第二次审查阶段(功能验证后反馈)/ Second review stage (feedback after functionality verification)

    项目核心流程在迁移 CCC 后可基本运行,但暴露了两个重大设计缺陷:

    After migrating CCC, the project’s core processes could basically run, but two major design flaws were exposed:

  • 时间戳完整性问题(严重)/ Timestamp integrity issue (critical)

    链上记录的时间戳由用户在客户端自行填写并提交,而非来源于区块打包时间。这导致时间戳可被任意编辑,彻底破坏了“在特定时间点前已知晓该数据”的存在性证明价值,证明力为零。

    The timestamps recorded on-chain are filled in and submitted by users on the client side, rather than coming from block packing time. This allows timestamps to be arbitrarily edited, completely destroying the evidentiary value of proving that data was known before a specific point in time — the proof is worthless.

  • 费用模型不可持续

    所有交易费用与 Cell 容量成本由项目服务端钱包承担,主网上线后将因费用快速耗尽而无法长期运行。

    委员会明确指出:区块链引入的核心价值在于利用区块时间提供不可篡改的时间证明,任何依赖客户端或服务器可控数据的时间戳方案均不符合 Web5 与去中心化原则。同时强调当前费用模型在主网不可持续。

    建议方案包括:集成钱包连接让用户自行签名支付费用、采用 Merkle 树等批量方案降低成本,并重新设计证明机制以依赖真实的区块时间戳。

    链接 / link:Spark Program | HashThis Project - #17 by zz_tovarishch

  1. 本次最终验证阶段(第三次结果)/ Final verification stage (third result)

    尽管开发者对建议进行了响应,但在委员会独立验证中,项目核心功能——哈希锚定交易的构造与上链——仍处于持续失败状态。

    Although the developers responded to the recommendations, in the committee’s independent validation the project’s core functionality—constructing and anchoring hash-anchored transactions—remained consistently failing.

    交易构建环节反复出现交易被网络拒绝的报错。即使在测试网环境下,也无法稳定完成“本地哈希 → 构建交易 → 广播上链 → 可查询验证”的完整闭环。

    The transaction construction phase repeatedly produced errors where transactions were rejected by the network. Even in the testnet environment, it was not possible to reliably complete the full loop “local hash → construct transaction → broadcast on-chain → queryable verification.”

    这意味着项目未能交付任何可实际使用的链上数据完整性证明功能,与原提案“轻量级、可靠的 CKB 锚定存在性证明”价值主张严重不符。

    This means the project failed to deliver any practically usable on-chain data integrity proof functionality, which is severely inconsistent with the original proposal’s value proposition of a “lightweight, reliable CKB anchoring existence proof.”

委员会的最终决议 / Committee’s Final Resolution

根据《星火计划小额资助方案》“3.3 完成政策”的相关规定:

According to the “3.3 Completion Policy” of the Spark Plan small grants program:

  • 连续较长时间(两周)无实质性进展且无合理原因
    Continuous lack of substantial progress for an extended period (2 weeks) without reasonable cause

  • 项目方向完全偏离原申请目标 / 资金使用严重偏离项目计划,且未经 Committee 批准
    Project direction completely deviates from the original application goals / fund usage severely deviates from the project plan without Committee approval

  • 发现存在材料造假等诚信问题
    Discovery of material falsification or other integrity issues

委员会认定,HashThis 项目虽在早期展现了创意与响应态度,但经过多轮技术迁移、逻辑优化与修复尝试后,仍未能交付可实际验证的核心链上功能,继续资助已无法保障原定生态价值实现,也不符合星火计划对项目基本可用性与资金一致性的要求。为维护计划的公信力与资源分配效率,最终遗憾地决定终止对该项目的资助支持。

The Committee has determined that although the HashThis project demonstrated creativity and responsiveness in its early stages, after multiple rounds of technical migrations, logic optimizations, and repair attempts it still failed to deliver verifiable core on-chain functionality. Continued funding can no longer ensure the realization of the intended ecosystem value and does not meet the Spark Plan’s requirements for basic project usability and funding consistency. To preserve the program’s credibility and resource allocation efficiency, we have regrettably decided to terminate funding support for this project.

资金处理情况 / Fund Handling Situation

  • 已发放资金 / Funds Already Disbursed

    • 首笔资助 / First installment funding(20%):36,765 CKB
      • 交易哈希 / Tx Hash: 0xdb13002433fbdcccf0bdf7a65106b35fb56c19c16f7888e3616d2b8a5cea4e49
      • 多签钱包地址 / Multi-signature wallet address:ckb1qrg6n7rh4mfltcruh8zjkcdtjmgx7fg2u6yre3ls5fprmvyhdlyzzqdya8pe5la39gr9n57wgyhfrlc3h8kf24q4wv8wy
  • 剩余资金:不再发放,将从项目多签钱包退回 Spark Program 主钱包。

    Remaining funds: No longer to be distributed, will be returned from the project’s multi-signature wallet to the Spark Program main wallet.

致社区 / To Community

星火计划的核心原则是透明与负责。我们对 HashThis 项目早期提出的“用户本地哈希 + CKB 锚定”的创意表示认可,但遗憾项目未能解决基础交易构造的可用性问题。此次终止决定是基于充分的事实验证、技术审查和多轮沟通记录做出的,旨在保护社区资源并维护计划的可持续性。

The Spark Program’s core principles are transparency and accountability. We recognize the “user local hash + CKB anchoring” idea proposed early by the HashThis project, but regret that the project failed to resolve usability issues in basic transaction construction. This termination decision was made based on thorough fact verification, technical review, and multiple rounds of communication, with the aim of protecting community resources and preserving the program’s sustainability.

我们鼓励开发者在项目执行中保持与委员会的紧密沟通,对技术瓶颈及时求助并接受建议;也欢迎有志于数据完整性方向的开发者重新整理方案、以更稳健的方式再次申请。

We encourage developers to maintain close communication with the committee during project execution, to seek help and accept advice promptly on technical bottlenecks; we also welcome developers focused on data integrity to reorganize their proposals and reapply in a more robust manner.

星火计划将继续秉持“低门槛、快节奏、真支持”的理念,欢迎更多务实、可落地的创新项目加入。我们相信,通过更扎实的执行与协作,社区将诞生更多真正可靠的成果。

The Spark Program will continue to uphold the principles of “low barrier, fast pace, real support,” and welcomes more pragmatic, implementable innovation projects to join. We believe that through more solid execution and collaboration, the community will produce more truly reliable outcomes.

如对本决定有任何疑问,可在 Nervos Network Discord 的 Spark Program 频道或本帖下留言,委员会将及时回应。

If you have any questions about this decision, please leave a message in the Spark Program channel on Nervos Network Discord or under this post, and the committee will respond promptly.

2026-03-19
xingtian
On behalf of the Spark Program Committee

5 Likes