A programmable safety net for CKB self-custody
Applicant: SalmanDev (Developer behind Fiber checkout) Funding requested: $1,600 USD Timeline: 8 weeks Category: CKB Infrastructure / Security / Self-Custody
1. Summary
On CKB today, non-custodial funds answer to exactly one key. Lose it and the money is gone forever. Share it and you’ve handed one person total control. And there is no native, on-chain way to pass assets to an heir without doing one of those two things.
Tranfr adds a programmable recovery path: stay active and retain full control, but if you stop checking in for a defined period, a designated recovery recipient can claim the funds — enforced on-chain, without a custodian. A user creates a Tranfr, designates a recovery recipient, and sets an inactivity period (90, 180, or 365 days, or custom) fixed at creation. While the Tranfr is active, the owner can send a heartbeat to reset the timer, or update the recovery recipient — which also resets the timer. If no heartbeat or policy update occurs before the deadline, the owner path freezes and the recovery path becomes eligible: the recipient’s signature, combined with the expired timelock, becomes sufficient to claim the assets.
The mechanism is enforced entirely by CKB scripts and transaction rules — no custodian, oracle, or centralized service is involved.
This grant is scoped to validating and implementing a reusable CKB recovery primitive, then providing the minimum SDK and testnet reference implementation necessary to prove it is integrable/
2. The Problem
A private key can be lost, destroyed, forgotten, or held by someone who becomes incapacitated or unavailable. When that happens, the blockchain has no way of knowing the legitimate owner is gone — the Cell and its assets remain valid, but nobody may be able to satisfy the spending conditions.
Existing approaches each have tradeoffs: multisig requires multiple parties during normal operation; custodians introduce a trusted intermediary; manual inheritance arrangements rely on off-chain coordination; application-specific recovery systems aren’t reusable; and a conventional single-key lock has no fallback at all.
CKB provides programmable ownership conditions and transaction-level timelocks through since. Tranfr uses these existing primitives to build a recovery path without any protocol changes.
3. How It Works
Terminology, used consistently throughout:
-
Owner — the person currently controlling the Tranfr.
-
Recovery recipient — the person/address designated to receive the assets if the owner becomes inactive.
-
Heartbeat — an owner-signed transaction confirming continued control; resets the timer, leaves policy unchanged.
-
Policy update — an owner-signed transaction changing the recovery recipient, inactivity period, or other supported parameters; resets the timer and changes policy.
-
Recovery transaction — executed by the recipient after expiry.
Setup. The owner sets a recovery recipient and an inactivity period. The inactivity period is fixed at creation for this version — only the recovery recipient can be changed later via a policy update.
Active state. While active, the owner retains full control: they can heartbeat at any time to reset the timer without changing anything, or issue a policy update to change the recovery recipient, which also resets the timer. Ordinary CKB transactions (spends, Fiber activity, DeFi interactions) do not count as activity and do not reset the timer only an explicit heartbeat or policy update does. This avoids ambiguity about what constitutes “still active” and keeps the contract logic simple to audit.
Expiry. This is the critical state transition. Once the inactivity period lapses without a heartbeat or policy update, the recovery policy becomes eligible and can no longer be modified by the owner the owner can no longer heartbeat, change the recipient, or extend the timer. Eligibility isn’t automatic execution: the Cell isn’t transferred on its own. The recovery recipient must submit a recovery transaction, which the script validates against two conditions — the recipient’s signature, and the since-enforced expiry, both of which must hold. Before expiry, the recipient’s signature alone is insufficient regardless of validity; after expiry, it becomes sufficient. No centralized approval is needed either way.
4. Technical Architecture
Tranfr Lock Script — a lock script for CKB-VM with two logical operation groups:
-
Owner operations (while active): normal spend, heartbeat, and policy update (recovery recipient only, in this version). Heartbeat and policy update are kept as distinct state transitions — a heartbeat only resets the timer, a policy update changes the recipient and resets the timer. Keeping these separate.
-
Recovery operation (after expiry): a recovery transaction validated against the recipient’s signature and the elapsed since condition.
Key technical point: the owner-side freeze after expiry is enforced by an independent chain-time check in the lock script (via a header dependency), not by since alone — since only gates the recovery path’s minimum-time condition. Milestone 1 validates this mechanism against CKB’s actual transaction/header semantics before the lock script implementation is finalized, and functions as a hard technical gate: if the header-time mechanism cannot establish the required irreversible expiry invariant under CKB semantics, the implementation design is revised before substantial coding begins.
Policy state. Each Tranfr commits to an owner, a recovery recipient, an inactivity period (fixed at creation), and a recovery deadline. The inactivity timer represents the maximum permitted period since the owner’s last valid heartbeat or policy update — nothing else resets it.
TypeScript SDK — createTranfr(), getTranfrPolicy(), getTranfrStatus(), buildHeartbeat(), buildPolicyUpdate(), buildRecovery(), isRecoveryEligible(). Handles transaction construction while keeping the underlying policy transparent and independently verifiable.
State machine:
CREATE → ACTIVE ⇄ (heartbeat / policy update, timer resets)
ACTIVE → (no activity before deadline) → EXPIRED → RECOVERY ELIGIBLE → RECOVERY TX → CLAIMED
5. Security Model
The recovery recipient cannot claim before expiry — the since timelock is enforced at the script level regardless of signature validity. After expiry, the owner path is frozen by an independent chain-time check in the lock script rather than by since alone: the script rejects any owner heartbeat or policy update once current chain time passes the stored deadline, so the recovery state is immutable once reached.
While the Tranfr is active, the owner is intentionally authorized to modify the recovery, this means the owner retains full control over who can eventually recover the assets for as long as they’re demonstrably present and active. That authority ends the moment expiry is reached.
Securing the recovery recipient’s own key is the recipient’s responsibility, on the same terms as any other CKB key — Tranfr doesn’t introduce new custody requirements on that side, it uses the recipient’s existing signing capability.
This POC is scoped to a single designated recipient as the entire v1 model. Social or threshold multi-party recovery is real added complexity, better suited to a future development if the core primitive is validated.
The entire security boundary is the CKB lock script itself. Since this POC has no off-chain notification component, there’s no off-chain trust surface to reason about in this phase — every guarantee is enforced by the script and independently verifiable.
6. Deliverables
-
Tranfr Lock Script — Implement with owner operations (spend, heartbeat, policy update) and the recovery operation, plus a comprehensive test suite covering both state transitions, adversarial cases, expiry-boundary conditions, and the frozen-after-expiry invariant.
-
Tranfr SDK — open-source TypeScript library for policy creation, inspection, heartbeat and policy-update construction, recovery transaction construction, and status calculation.
-
Testnet Demo — an CLI/reference script demonstrating the full lifecycle on testnet: create Tranfr, heartbeat, policy update, expiry, recovery. Its purpose is to prove the SDK and script work end-to-end, not to be an application — no UI polish, no broader integration surface.
-
Documentation — technical specification, security model, threat model, transaction flow, integration guide, test vectors.
All code will be open-sourced.
POC Scope
one owner + one recovery recipient + one immutable inactivity period + heartbeat + recipient update + recovery.
Out of scope for this grant:
Multiple recovery recipients, social recovery, configurable activity sources, automatic notifications, production wallet integration, production security audit
7. Roadmap
| Milestone | Timeline | Work |
|---|---|---|
| 1. Protocol & feasibility | Week 1 | State machine, threat model, transaction model, and proof that expiry/freeze semantics work as intended. If the header-time expiry-enforcement mechanism cannot be validated against CKB semantics, the implementation design is revised before substantial coding begins. |
| 2. Core CKB primitive | Weeks 2–4 | Lock script + owner ops (spend/heartbeat/policy update) + recovery op + owner-side expiry check + adversarial and expiry-boundary tests |
| 3. SDK | Weeks 5–6 | Minimal TypeScript SDK for policy creation, inspection, and transaction construction |
| 4. Testnet validation | Week 7 | Thin CLI/reference demo exercising the complete lifecycle |
| 5. Release | Week 8 | Documentation, test vectors, integration example, open-source release |
8. Budget — $1,600 USD
| Area | Amount |
|---|---|
| CKB scripts + policy/state enforcement + testing | $1,050 |
| TypeScript SDK | $350 |
| Testnet demo + documentation | $200 |
9. Success Criteria
A developer should be able to: create a Tranfr, set a recovery recipient and inactivity period, change the recipient while active and verify the timer resets, send a heartbeat and verify it resets the timer without altering policy, allow the timer to expire, verify that both heartbeat and policy updates are rejected after expiry, execute recovery with the designated recipient, and confirm recovery is invalid before expiry and valid after. Most importantly, a third-party wallet or application should be able to integrate Tranfr via the SDK without depending on the reference application’s own architecture.
The critical security test: an owner must not be able to extend or modify an expired Tranfr by submitting a heartbeat or policy update after the recovery deadline has passed.
10. Ecosystem Value
Tranfr is built as a primitive that any CKB wallet or app can integrate, rather than a single-purpose inheritance app. The same mechanism can eventually support personal wallet recovery, inheritance, business continuity, DAO treasury recovery, lost-device protection, and long-term cold storage — but the first version implements only the simplest model: one owner, one recovery recipient, one inactivity period fixed at creation, with recipient-only policy control while active. That keeps the POC achievable while establishing a foundation other applications can build on rather than reimplementing their own version.
CKB’s Cell Model and since mechanism make this possible without any protocol changes: ownership conditions and temporal conditions are both expressible directly on-chain, so the recovery guarantee doesn’t require a third party to enforce it.