Morph Channel Explained: Separating Value, State Evidence, and Fee Responsibility on CKB

(This is a general-public-facing companion to the June 2026 Morph Channel paper. The paper is the canonical specification; this article is an audience-friendly explainer. Also there is an original draft proposal written in Chinese )

The one-line summary: Morph Channel is a payment-channel design for Nervos CKB. It does three things at once:

  • splits the “money box” from the “evidence box” ,
  • pays transaction fees from a separate sponsor wallet instead of from the channel itself,
  • keeps the channel’s books in five strictly separated ledgers.

Around that central design, it then builds dispute resolution, channel resizing, and multi-party factories. The result is a channel protocol that is auditable in the manner of a strictly organised accounting system.

01 Why payment channels exist at all

Imagine you and a friend split coffee every morning. If every latte had to settle on a bank wire that takes ten minutes, you’d stop doing it. Payment channels solve the same problem on a blockchain: they let two parties exchange many small updates quickly, and only touch the chain when they open the channel or close it.

The general idea has been around for nearly a decade. Open a channel by locking some funds into a multisignature contract on-chain. Then exchange signed “balance updates” off-chain, as fast as you can sign them. If both of you stay cooperative, you never touch the chain again until you decide to close. If one of you goes silent — or worse, tries to cheat — the other party can publish the most recent signed state and let the chain enforce it.

That second part is the hard one. “Enforce it on-chain” means: take the latest signed evidence, build a transaction that follows whatever settlement rules the channel protocol defined, and get it confirmed before any deadline. The protocol’s job is to make sure that

(a) you can always publish the truth,
(b) a stale state cannot become final if a newer valid state is published in time.

The Lightning Network on Bitcoin is the canonical implementation of this idea. It works. Millions of people use it. But it has structural problems that come from Bitcoin’s data model, not from anyone’s engineering mistake. Morph Channel is an attempt to get the same guarantees on a different kind of ledger — CKB , while sidestepping those structural problems at the root.

02 How Bitcoin’s UTXO approach works - and where it shows its age

Bitcoin’s ledger is a forest of “unspent transaction outputs” (UTXOs). A UTXO is essentially a coin: it has an amount and a spending condition (a script). To “update a channel state” in Lightning, both parties create a new set of transactions that describe how the locked funds would be split in the future. Each new “commitment transaction” reshapes the spending paths on the funding output.

This of course works, but it has a fundamental coupling here: the same object holds the money and represents the contract. Every state update is a new arrangement of future spends over the same funding output. To “replace” an old state, you have to either invalidate it with a penalty transaction (Lightning’s current approach) or have the chain recognise a newer signed version (the eltoo idea).

03 CKB’s Cell model: a different design space

CKB is a UTXO-style chain too, but its “unspent object” (the Cell) is much richer. Think of a Cell as a small transparent locker:

  • data: arbitrary bytes stored in the locker
  • lock script: the rule for who can open (spend) it
  • type script: the rule for what must be true about it when it is created or modified
  • capacity: the locker’s size, denominated in CKB. Capacity is the native resource used to occupy on-chain storage. Transaction fees are paid as the difference between input capacity and output capacity. Execution cost, separately, is measured in CKB-VM cycles. So CKB is a fee medium, but it is not an EVM-style “gas” model.

That last bullet is the part most newcomers find confusing, so let me restate it carefully: 1 CKB is not just a unit of value. It also represents the capacity required for a live Cell to occupy on-chain state. A Cell must carry enough capacity for as long as it remains live. Every Cell needs enough capacity to cover its own on-chain footprint. Any extra capacity above that minimum is the “user-visible” balance that the owner can actually spend. This is why “channel reserve” is a thing — it is the slice of capacity a channel Cell must keep around just to stay alive.

The deeper design point: because Cells can carry typed data and run scripts against it, a CKB protocol can give different Cells completely different responsibilities. One Cell can hold value; another can carry the evidence or policy that governs how that value may later move. They evolve on different schedules, and the scripts can verify one against the other.

For a payment channel, this means you can do something Bitcoin can’t easily do: keep the “money box” sitting still forever, while a separate “evidence box” rolls forward every time the parties update their state. That’s the whole architectural insight Morph Channel builds on.

04 The three “old problems” Morph Channel is trying to fix

The paper is unusually candid about what’s broken in current channel designs. It names three problems by name, and the rest of the construction is essentially a layered fix for each one.

4.1 The funding-state coupling problem

In many UTXO channel designs, the locked value and the channel state are operationally the same thing. The “state” is literally a new set of spending paths over the locked value. That’s fine for Bitcoin, but a CKB native channel protocol design probably doesn’t have to follow that pattern.

Morph’s answer is to stop treating the funding object as the state object.The funding bundle remains stable; the State Cell is the only rolling evidence track. Because those roles are separated, force-close templates can stop mixing settlement authorisation, fee selection, and asset accounting into a single tangled check.

4.2 The fee boundary problem

“There’s a fee cap of X” and “the channel pays zero fees” sound similar, but they are not equivalent.

A fee cap says channel value may be consumed up to a limit. Zero channel-paid fees says channel value does not participate in fee accounting at all. CKB makes the distinction particularly sharp because capacity is simultaneously storage resource, fee medium, and user-visible value. Morph’s invariant is the strict version: after funding, channel-owned capacity can never be reduced by a transaction fee. Publication fees are a property of the sponsor partition, and only of the sponsor partition.

4.3 The authority object problem

A well-designed protocol should have one source of truth for “what the current state is.” In practice, poorly separated designs let authority drift across several objects: the funding Cell, a plaintext witness, a local snapshot, a root commitment, a transaction body with sponsor inputs. When a script accepts more than one of these as authoritative, it opens attack surface. Morph’s rule is stark: the only authoritative object is the signed State Header, plus the witness or proof its mode requires. The transaction body is treated as a rebuildable wrapper, not as evidence.

Why this matters in practice: if you ever look at a post-mortem of a channel exploit, almost every one traces back to a moment where two authority sources disagreed, and a script accepted the wrong one. Morph’s design thesis is that on CKB, you can build a channel that has only one authority source by construction. That’s the whole paper in one sentence.

05 The central design: three separations

If you remember only one architectural idea from this article, make it this: Morph Channel separates three things that other designs fuse together. Once you see the three separations, every later mechanism falls out of them almost mechanically.

5.1 Separation #1 — Vaults vs. State Evidence

Separate the value-holding layer from the evidence-carrying layer.

  • Vault Cell(s) hold channel-owned value. They sit there, untouched, for the entire lifetime of the channel. Their lock script refuses to release value unless the spender can also present a current, authentic State Cell that authorises the spend.
  • State Cell carries the latest signed settlement evidence. Every time a unilateral publication happens, the State Cell is consumed and a successor is created. It’s a “rolling” object that lives in its own update track.

The benefit is operational, not only aesthetic. At force-close time, the settlement transaction only has to prove that a current State Cell authorises a particular descriptor over a particular vault set. It does not need to reshuffle the value holder, smuggle in fee policy, or treat the transaction body itself as settlement evidence.

5.2 Separation #2 — Sponsor vs. Channel

Separate publication funding from channel ownership.

Channel-owned value never pays a transaction fee. The carrier transaction that publishes a State Cell is funded by a separate party: the user’s normal wallet, a watchtower, or for the most safety-critical case, a bounded SponsorBudget Cell delegated to a fixed channel and a fixed state-number range.

This separation unlocks something subtle but important: the signed State Header does not commit to which sponsor inputs are used or what fee rate is paid. That means a watchtower can rebuild the publication transaction with different sponsor coins and a higher fee rate if the network gets congested, and it does not need fresh signatures from the channel participants. The signature is over the state, not over the carrier.

5.3 Separation #3 — Partition Conservation (the five-lane ledger)

Split the channel’s books into five ledgers that cannot borrow from each other.

Because this is the main accounting invariant, it deserves its own section.

06 The five-lane ledger (partition conservation)

Here’s the rule that makes everything else verifiable. Every cell in a post-funding transaction is classified into one of five categories, and each category has its own conservation rule. The categories are:

Lane Source Role Pays fees?
Sponsor standard wallet, watchtower, or budget Cells transaction fees and change Yes
State Carrier State Cell + carrier refund outputs storage capacity for the moving state track No
Channel Reserve channel-owned CKB capacity keeps vault Cells alive and pays reserve refunds No
Business CKB channel-owned CKB above reserve user-visible CKB that can be settled to participants No
Business xUDT channel-owned xUDT balances (per type script) user-visible token balances for each registered asset No

The conservation rule per lane, simplified:

  • PUBLISH / SUPERSEDE: channel_in == channel_out; carrier capacity is conserved; sponsor lane absorbs the fee difference.
  • FINALIZE: channel value flows into descriptor-authorised settlement outputs (which are themselves classified by lane); carrier capacity can be retired into a refund output that is also classified as State Carrier.
  • SPLICE: channel_out == channel_in + delta_in - delta_out, where every delta must be a signed protocol object binding asset type, amount, capacity, cell shape, and descriptor policy.
  • Always: carrier_in == carrier_out; sponsor_in - sponsor_out == tx_fee; the three sets (channel lanes, carrier, sponsor) are disjoint.

Five-lane conservation: inputs and outputs balance per laneInputsSponsorState CarrierChannel ReserveBusiness CKBxUDT (per type)each lane balances itself; no borrowing across lanesOutputsSponsor ChangeState / Carrier RefundReserve (or refund)Business CKBxUDT (per type)

Each lane balances itself. The fee deficit is always absorbed by the Sponsor lane, never by Channel Reserve or Business CKB or Business xUDT.

There are two non-obvious things in this scheme that are worth lingering on.

First, “channel reserve” and “business CKB” are not the same thing. This is the earlier capacity point showing up inside the channel ledger. A CKB Cell needs capacity to exist; that capacity is the reserve. Anything above the reserve is “business CKB” that the user can actually move around. The two are kept in separate lanes because conflating them is exactly how channels leak user value into fees or into reserve refunds the user did not expect. A State Cell that looks as if it merely shrank by a few shannons might have consumed business balance as a hidden fee — partition conservation makes that impossible to hide.

Second, xUDT (CKB’s extensible user-defined token standard) accounting is per-type-script, not per-symbol or per-name. If two tokens claim the same ticker, they are different assets for partition conservation purposes because their type scripts differ. A sponsor change output that smuggles a registered xUDT back to the user will be rejected. The accounting is by cryptographic identity, not by human label.

The headline invariant: “If partition conservation holds for a post-funding transaction, then publication fees cannot reduce channel-owned value.” This is Proposition 1 in the paper and it’s the single most useful sentence to memorize. Proof sketch: transaction fees are input_capacity - output_capacity. Each lane is conserved under its own rules. Therefore the only lane that can have a deficit is the sponsor lane. Therefore channel-owned value is never the fee payer.

07 The State Header: the authoritative envelope

If partition conservation is the accounting rule, the State Header is the contract. It is a single canonical record that says, in effect: “I am the current state of channel X, dated at funding epoch Y, locking value into vault set Z, governed by settlement descriptor D, and I have been signed by the required participants.” The header lives inside a State Cell. The State Cell is not consumed during ordinary off-chain updates. It is consumed and recreated only when state evidence is published on-chain, superseded, spliced, or finalised under the relevant script branch. The header is what gets carried forward (with a higher state number) at those on-chain transitions.

The canonical State Header has roughly these fields:

// Slightly simplified — see paper Section 5.3 for the full struct.
struct StateHeader {
  protocol_version            // which version of the protocol parses this
  chain_id                    // prevents cross-chain replay
  signature_scheme_id         // which signature algorithm is in use
  channel_id                  // the channel's immutable genesis identity
  funding_epoch               // advances on splice; prevents old-sig reuse
  funding_anchor_identity     // outpoint of the current funding Cell
  vault_set_commitment        // hash of the current set of vault Cells
  state_number                // strictly monotonic; bigger wins
  mode                        // bilateral plaintext vs factory proof
  phase                       // active / settling / closed
  participants_commitment
  asset_registry_commitment   // which xUDT type scripts are recognised
  settlement_descriptor_commitment
  descriptor_version          // grammar version, not descriptor instance
  payload_commitment          // hash of balances, HTLCs, etc.
  challenge_policy_commitment
  state_layout_version
}

The signature is computed over a domain-separated hash:

mn = H("CKB_MORPH_CHANNEL_STATE_V1" || canonical(Header_n))

That string prefix is doing real work. Without it, an attacker could try to feed the signed bytes into a different protocol or a different chain that happens to use the same signature scheme. With it, the signature is bound to this protocol, this version, this chain, this channel, and this funding context. Replay across any of those dimensions is impossible by construction.

Two design choices in the header deserve their own emphasis.

7.1 The funding_epoch field

Funding epoch is a monotonic counter that advances every time the channel is resized (a “splice”). It exists to solve a specific attack: suppose Alice signed State 100 when the channel had 1000 CKB. Then you splice the channel up to 5000 CKB. Alice’s old signature still says State 100, but it now refers to an outdated funding context. If scripts accepted it, Alice could try to claim her old 1000-CKB settlement out of a 5000-CKB vault. The funding_epoch field — and the matching funding_anchor_identity and vault_set_commitment fields — are part of the signed domain, so the moment you splice, every prior signature becomes invalid. Watchtower packages from before the splice are inert. This is what the paper calls “splice freshness.”

7.2 The settlement descriptor is bounded

The settlement descriptor is a small structured object that says “given this header and this payload, the settlement outputs are these specific Cells, with these locks, these capacities, and these type scripts.” It is not a Turing-complete program. It is a versioned grammar with a fixed output count, a fixed role vocabulary, and no dynamic dispatch. This is deliberate. If you let people put arbitrary scripts in the witness, you’ve turned the channel into a general smart-contract platform, with all the verification cost and attack surface that implies. By keeping the descriptor narrow, the protocol stays auditable and the CKB-VM cycles stay predictable.

The State Cell’s type script is the script-level enforcement point. Every time a transaction tries to consume the current State Cell and create a successor, the type script runs through a check list: header format is canonical, state number strictly increases, funding context unchanged (for normal updates), signatures are valid, payload matches the payload commitment, partition conservation holds, output capacity is sufficient to host the new State Cell. A transaction that fails any one of these checks is rejected before it ever reaches consensus.

08 Disputes and the challenge window

Now the messy part.

Suppose Alice and Bob are running a channel. They sign State 100 offline and stop talking. Alice goes rogue and publishes State 95 (which is older and more favourable to her). What happens?

Morph’s rule is the eltoo-style “newer state wins” rule, but implemented with CKB primitives rather than a Bitcoin sighash change:

  1. Alice’s publish transaction consumes the currently live active State Cell, or the currently live settling State Cell if the channel is already in dispute, and creates a settling State Cell at number 95.
  2. The channel is now in the settling phase. A challenge window starts, encoded as a CKB relative since on the State Cell input.
  3. Bob has State 100 in his back pocket. He builds a “supersession” transaction that consumes Alice’s State 95 and creates a successor at State 100.
  4. If Bob’s transaction confirms before the challenge window expires, the new live State Cell is 100. Alice’s 95 is gone.
  5. If the challenge window expires with no supersession, the chain lets anyone finalise Alice’s 95 by presenting the live State Cell and the elapsed time.

Challenge window timelineAlice publishes 95Bob detects staleBob builds tx for 100100 confirmedFinalisation allowedchallenge window Δ = relative since on State Cell

The newer state must confirm on-chain before the challenge window expires, or the stale state becomes final.

The challenge window’s length Δ is a deployment parameter, not a hard-coded constant. The paper gives a budget equation:

Δ ≥ Δ_detect   // confirmations before a watchtower treats stale state as actionable
  + Δ_poll      // watchtower service interval
  + Δ_build     // time to construct and broadcast a replacement tx
  + Δ_confirm   // time for the newer-state tx to confirm
  + Δ_margin    // safety margin for fee bumps and reorg risk

Each of those terms has to be measured on the actual network. A deployment profile has to record its assumptions (detection depth, polling interval, sponsor budget multiple for fee bumps, conservative reorg margin) and verify them periodically. The paper is explicit that “naked integer comparison” — treating a raw integer in the since field as if it were a delay — is not a valid challenge-window check. The script must parse the since as an encoded relative-block condition that matches the committed challenge policy. Otherwise a challenger could craft a malicious since value that the script accepts but the network interprets differently.

One more subtlety: fee bumping in CKB is not Bitcoin’s “replace-by-fee.” It means rebuilding the publication transaction against the currently live State Cell, using different sponsor inputs and a higher fee rate. Because the State Header doesn’t commit to which sponsor inputs are used, the watchtower can do this without re-signing. If the original tx is stuck because fees spiked, the watchtower builds a fresh one. The only invariant is that the new tx must consume the current live State Cell — CKB’s single-spend rule guarantees that a stuck tx and a new tx cannot both succeed.

09 Splice: resizing a live channel

Then life goes on, your business grows, and the channel needs more liquidity. Or a participant wants to withdraw some. Morph handles this with a splice: a signed re-anchoring event that consumes the current funding context, advances the funding epoch, and creates a new funding context with a new vault set.

And there are two flavours of Splice.

Splice-in admits external value into the channel — Alice puts in another 1000 CKB, the channel’s locked value grows.

Splice-out releases value while keeping enough post-splice vault value to satisfy the latest signed settlement descriptor.

Either way, the splice transaction must bind: the old funding anchor, the new funding anchor, the old vault-set commitment, the new vault-set commitment, the per-asset deltas, and the required participant signatures. CKB and xUDT are tracked separately, not lumped together as “value.”

The crucial property: a watchtower package from before the splice is not automatically valid after it, even if the package has a higher state number than the live State Cell, because its signed funding epoch and vault-set commitment refer to a different enforceable value object. This is splice freshness, and it is the only thing standing between you and the “I have a better signature” attack after a channel resize.

10 Factory mode: many participants, one liquidity pool

A bilateral channel is two people. A factory is many people sharing one liquidity pool, each with their own balances, sub-channels, and exit paths. Factories are useful for the same reason shared ledgers are useful: you can put one big pot of money on-chain and let many small relationships draw from it without each relationship having to lock up its own capital.

But factories have a problem bilateral channels don’t: disclosure. If every local exit has to publish the entire factory state, you leak everyone’s balances to the world, and the witness size grows with factory size. So Morph adopts a commitment-first design for factories.

10.1 The factory state is a header plus roots

A factory’s authoritative state is a State Header plus a few Merkle roots: a balances root, a sub-channels root, a membership root, a reserve root. Each root commits to a tree of leaves that describe the relevant factory data. To prove that your local action is valid, you don’t publish the whole tree; you publish a Merkle proof that touches only the leaves you care about.

10.2 Envelope-first admission

This is where the envelope-first design does most of its work. A factory transaction is admissible in two stages.

Stage 1 — the envelope. The transaction carries a small outer claim that says “I am a factory transition of kind local_exit, version 1, with these flags, and I commit to a body whose bytes are exactly body_len long with hash body_commitment.” The script checks the envelope first. If the envelope is malformed, the body is never even parsed. If the envelope is valid, the script knows which proof grammar to apply before it starts reading the body.


// The envelope is a tiny admission-control object:
struct FactoryEnvelope {
  magic            // identifies this as a factory transition
  version          // grammar version of the envelope itself
  kind             // local_exit | update | splice | reduced_right | ...
  flags            // e.g. asymmetric, one-sided, typed
  body_len         // hard byte bound; checked before parsing
  body_commitment  // hash of the canonical body bytes
}

// The body_commitment binds the envelope context, so swapping the body
// under a different envelope is detectable:
body_commitment = H("CKB_MORPH_FACTORY_BODY_V1"
                     || magic || version || kind || flags
                     || body_len || body_bytes)

Stage 2 — the body. Only after the envelope is verified does the script parse the body, which contains the access manifest (which leaves you claim to touch), the proof bundle, the touched leaf payloads, and the signatures.

Why two stages? Because it prevents the “re-skin” attack. Suppose a transition family A is conservatively authorised (needs all-participant signatures) and a transition family B is locally authorised (needs only the affected participants’ signatures). If the script simply looked at the body and decided which authority class to apply, an attacker could write a body that is actually a family-A operation but claim it is a family-B body, and the script would apply the lighter check. By fixing the family in the envelope and binding the body to the envelope, the script knows the authority class before it interprets the body. A transaction cannot claim to be a “local exit” while its body is in fact a “global update.”

10.3 What non-interference is and why it matters

The deepest property in factory mode is non-interference. The question it answers: “When I take a local action, am I sure I haven’t changed anything that some other participant has a right to?”

Factory rights are the things a participant might care about: their balance, their reserve claim, their membership, their exit path, their sponsor-budget claim. Some of these rights are obviously local — your balance is your balance. But others are not. A factory has shared reserve, shared exit paths, shared sponsor budgets. If you change your balance, you might also change the shared reserve available to fund other participants’ exit paths, even if you don’t directly touch those leaves.

Morph’s answer is a rights-dependency schema: a versioned declaration that says, for each right in the factory, “if I touch right X, these are the other rights that might also change as a consequence.” The schema is part of the protocol, not a per-deployment afterthought. A local transition must prove non-interference with respect to all untouched participants, which means: for every right that the schema says depends on something I’m touching, prove that the dependency is either unchanged or irrelevant. If you can’t prove it, the transition is global and requires all-participant signatures.

Proposition 2 in the paper is the safety statement for this: if a factory action cannot prove non-interference, a conservative profile requires signatures from all participants. If non-interference is proven, the signing set can be reduced — but only when the touched rights also satisfy participant authorisation, local validity, and value conservation. Non-interference doesn’t grant value rights on its own. It just lets you skip asking people who are provably unaffected.

A useful mental model: think of a factory as a corporate board meeting. A local action is like a committee making a decision: they need to show that the decision doesn’t change anything that other committees have authority over. If they can’t, the full board has to vote. Non-interference is the proof that “this is a committee decision,” and the rights-dependency schema is the corporate bylaws that say which decisions are committee-eligible.

Note that a Merkle proof of “I touched these leaves and no others” is not enough. The proof must also cover the dependencies named by the schema: shared reserve, membership, exit path, sponsor budget. A factory vault, for example, can be rebalanced by a local exit even if the exit only touches one balance leaf, because the vault rebalance is a side effect that the schema has to acknowledge. If the schema says the touched leaf’s effect on the vault is “change the participant’s reserve claim,” then the proof has to either leave that claim unchanged or fall back to full signatures.

This is also where envelope-first admission earns its keep. The envelope fixes the transition family before the body is read. That means the rights-dependency check happens under the right authority class. Without the envelope, a body that says “I’m a local update” could be interpreted as a body that says “I’m a value-mint” if the proof bytes happened to support it. Envelope-first removes that ambiguity at the protocol level.

11 What’s still unsolved

Let’s also be honest about Morph’s current limits.

The construction is a script-level design, it doesn’t change CKB consensus or introduce new transaction types. But that also means the heavy lifting is now in deployment engineering. The open questions are mostly empirical:

  • Witness size for bilateral plaintext mode in realistic payment states — does it fit, and at what cost?
  • Factory proof size under realistic touched-footprint distributions — is commitment-first actually cheaper than plaintext at scale?
  • CKB-VM cycles for signature, hash, and proof verification — what’s the actual cost?
  • Challenge reliability under realistic CKB confirmation behaviour, fee volatility, and watchtower-polling parameters.
  • Sponsor policy failure modes: insufficient budget, inadmissible script-level expiry, wrong change destination.
  • State Cell uniqueness under contention: what happens when two parties publish competing transactions in the same block?
  • Splice freshness tests: prove that pre-splice watchtower packages cannot govern post-splice vaults.
  • Descriptor grammar coverage: how many descriptor families do we need before deployment, and what are the version boundaries?
  • Factory acceptance: does the candidate deployment pass every positive and negative family in the matrix’s factory section?
  • Mechanised non-interference: the rights-dependency schema is informal today; it needs machine-checked coverage before reduced signing sets are safe in broader transition families.

There are also a few things I deliberately have not tried to solve in the thesis: routing, liquidity discovery, gossip, privacy networks, watchtower markets, factory governance. Those are meaningful real-world problems currently beyond this paper’s scope.

9 Likes

Great write-up.

I fully agree with the core direction: funding and state should be decoupled. This is the kind of design space where the Cell model is more expressive than the Bitcoin UTXO. Perun on CKB also adopts a decoupled approach, a comparison between Morph and Perun’s ways of decoupling would be interesting.

I also like the version-based design using state_number. It avoids much of the revoked-transaction machinery used in penalty-based channels, and it takes advantage of CKB’s programmability instead of working around missing transaction semantics. This is why Generic Payment Channel Construction and Its Composability uses a monotonically increasing nonce to manage state versions. It’s simple and very CKB-native.

One broader design question I find interesting is what to do in adversarial cases. Should the protocol only prevent an incorrect state from becoming the final settlement, or should it also punish the party who tried to publish the stale state?

  • Both approaches have trade-offs. For example, PoW does not have an explicit slashing penalty: failed or orphaned work is simply wasted. PoS systems usually do have explicit penalties, although in PoS this may be closer to a necessity than an optional UX choice. Payment channels sit somewhere else in the design space. A penalty mechanism gives stronger deterrence: if publishing an old state can make you lose a lot of money, you are less likely to try it. But the downside is that honest users can also be hurt by mistakes. The stronger the penalty, the more scary it is for normal users to participate.

  • Lightning is an example on the other side. Its penalty-based design gives strong anti-cheating incentives, but it also forces node operators to manage revoked transactions and old state very carefully. If a node database is corrupted, a backup is restored incorrectly, or a cloud host crashes and restarts from stale state, an honest user may accidentally publish an old transaction and suffer a major loss. That operational burden raises the participation cost. In the long run, higher participation cost can hurt decentralization.

  • So I think Morph’s “newer state wins” approach is attractive from a user-risk perspective. It focuses on preventing stale evidence from becoming final, rather than turning every stale publication into a slashable offence. But this also means the design must take griefing, watchtower reliability, sponsor budget exhaustion, and challenge-window sizing very seriously.

I also think the difference between Morph resizing and Lightning splicing is worth discussing more explicitly.

  • In Lightning, splicing is usually understood as combining “close the old channel” and “open a new channel with a different capacity” into one flow. Technically it’s a different channel after splicing. The term “splicing” makes intuitive sense here.

  • Morph’s operation seems slightly different. Morph SPLICE is more like updating the channel’s funding context under the same logical channel_id: the channel continues, the managed value increases or decreases, and the state/funding context advances. This is closer to “resize” or “re-anchor” than to a literal close-and-open splice.

  • That said, both require an on-chain transaction and a funding output change. So the difference could be subtle and perceptual. It may matter for users and external integrations - should wallets, explorers, watchtowers, indexers, and SDKs treat this as the same channel with a new funding context, or as a new funding object linked to an old one? Is channel_id the stable integration key, while (channel_id, funding_epoch) identifies the current funding context? Would a different wording like “resize” better reflect the difference?

  • Related to that, I am not fully convinced that StateHeader.funding_epoch is strictly necessary for protocol safety in the minimal design. It may make some checks simpler and logs/debugging/auditing easier. But it is still another signed field, another consistency condition, and more state cell data. It would be useful to analyze whether funding_epoch is a minimal safety requirement or an engineering/auditability convenience.

One more subtlety: fee bumping in CKB is not Bitcoin’s “replace-by-fee.” It means rebuilding the publication transaction against the currently live State Cell, using different sponsor inputs and a higher fee rate. Because the State Header doesn’t commit to which sponsor inputs are used, the watchtower can do this without re-signing. If the original tx is stuck because fees spiked, the watchtower builds a fresh one. The only invariant is that the new tx must consume the current live State Cell — CKB’s single-spend rule guarantees that a stuck tx and a new tx cannot both succeed.

  • CKB does support RBF : a higher-fee transaction can replace an old pending transaction if they share at least one input.
  • So I suppose the intended point here is not that Morph never uses RBF. Rather, Morph does not rely on the Lightning/Bitcoin style complicated fee-bump design, e.g. pre-signed fee-bump transactions. In Morph, the participant signatures authorize the StateHeader, not the sponsor coin selection or fee rate. Therefore a participant can simply rebuild a fresh publication/supersession transaction and choose different sponsor inputs freely to pay higher fee, thanks to that state evidence and fee-paying sponsor inputs are decoupled.

I’m also curious about liquidity management in channel factories - how should liquidity be transferred between members or between child channels within a factory? Does it require on-chain transactions? I think this topic deserves more analysis and explanation.

The Lightning Network on Bitcoin is the canonical implementation of this idea. It works. Millions of people use it. But it has structural problems that come from Bitcoin’s data model, not from anyone’s engineering mistake. Morph Channel is an attempt to get the same guarantees on a different kind of ledger — CKB , while sidestepping those structural problems at the root.

I want to highlight and applaud this paragraph: Bitcoin has taught us a huge amount, and Lightning is an impressive engineering achievement. But every time I see Bitcoin developers spend enormous effort on clever, fragile, sometimes even ugly workarounds for base-layer limitations, I cannot help feeling that a lot of human effort is being spent fighting the wrong battle.

Personally, I am pessimistic about endlessly stacking tricks on top of Bitcoin to make it do everything. Bitcoin’s most important job is store-of-value. The problems that really threaten that role are things like quantum-resistance and long-term economic sustainability. Many other applications should be solved with new designs that address the problem at the root, instead of forcing everything through Bitcoin’s constraints.

It’s great to see Morph asking what a channel should look like if we start from the Cell model directly.

3 Likes

Hi Jan,

Thanks for the thoughtful comment. I think you pointed at exactly the right pressure points, and this is very close to what any further refinement of Morph now needs.

The comparison with Perun on CKB and the earlier Generic Payment Channel Construction is especially useful. One possible way to frame it is through something like insular biogeography: similar channel ideas may evolve rather differently once they inhabit different base-layer environments.

I was not fully aware of the Perun-on-CKB work when I started writing Morph, and I have only read the generic CKB payment-channel construction more carefully quite recently. Morph’s original sources of inspiration were mainly Christian Decker’s eltoo proposal, my earlier attempt to enshrine channel vaults in a Kaspa-oriented fork design, and some prior experience around RGB/LN design questions. The RGB/LN side was mostly useful as a negative design lesson, so I share much of the concern in your last paragraph.

What I find interesting about CKB is that its richer primitive set changes the evolutionary landscape. Instead of being forced into Bitcoin’s transaction shape, CKB allows a more expressive separation between value, state evidence, and fee payment. That gives the design a different kind of room to evolve. In that respect, Morph is also a tribute to the foresight of CKB’s early designers.

I will try to address a few of your points below:

1. Penalty versus newer-state-wins

I broadly agree with your framing here. Morph deliberately treats stale publication as a failed claim rather than a slashable offence.

That gives up some deterrence. A party who tries to publish an old state is not punished beyond failing to settle with that stale evidence. But the upside is that honest users are less likely to suffer catastrophic loss from operational mistakes: stale backups, database corruption, node crashes, or watchtower misconfiguration.

So the burden shifts from punishment design to liveness engineering. Morph has to take challenge-window sizing, watchtower reliability, sponsor-budget exhaustion, griefing cost, fee volatility, and reorg assumptions seriously. I think this is the right trade-off for a CKB-native channel design, but it should be stated more explicitly.

A real deployment profile should also make those assumptions explicit: challenge-window length, watchtower polling interval, confirmation-depth assumption, sponsor-budget multiple, and reorg margin. These should probably be treated as profile parameters, not buried in prose.

2. funding_epoch

On funding_epoch , I would no longer describe StateHeader.funding_epoch as obviously necessary for the minimal safety argument. In the current design, the harder safety work is really done by the signed funding context:

  • funding_anchor_identity identifies the funding context at the script level;
  • vault_set_commitment binds the state to the vault set;
  • ordinary PUBLISH / SUPERSEDE transitions require the funding anchor and vault-set commitment to remain unchanged;
  • SPLICE / resize signs the old funding anchor, the new funding anchor, the old vault commitment, the new vault commitment, and the base state number;
  • CKB’s single-spend rule, together with the State Cell transition rules, prevents two competing funding-context transitions from both becoming current.

So if the minimal protocol is defined as:

a state is valid only for a specific (channel_id, funding_anchor_identity, vault_set_commitment) context, and resize is an explicit signed transition from one such context to another,

then funding_epoch is not carrying much unique cryptographic weight. The real anti-replay boundary is the signed funding context accepted by the Vault and State Cell scripts.

That said, I still see value in keeping funding_epoch in Morph’s current profile. A resize always changes the funding context. What may remain unchanged is the user-visible business state, such as balances, settlement terms, or channel-level accounting. That is why I still find it useful to keep two monotonic coordinates:

channel state version:    state_number
funding context version:  funding_epoch

That separation is helpful for logs, watchtower cursors, SDKs, indexers, debugging, and audit reports. It also makes certain mistakes easier to detect: if a post-resize package has the expected anchor but an unexpected epoch, something in package construction, indexing, or recovery state is probably wrong.

So my current view is:

funding_epoch is not a minimal anti-replay primitive in the abstract protocol, but it is a consensus-checked, signed engineering namespace for funding-context evolution in Morph’s current profile.

A cleaner long-term design may be to make that layering more explicit: treat (channel_id, funding_anchor_identity, vault_set_commitment) as the minimal funding-context identity, derive a funding_context_id from it for tooling, and then decide whether funding_epoch should remain as a signed generation label or disappear from the signed state entirely.

3. SPLICE / resize

As you pointed out, this also affects the word “splice”. Lightning has already given that term a fairly specific meaning, while Morph’s current operation is narrower: it updates the funding context under the same logical channel_id .

So I think the user-facing term should probably be resize or re-anchor , rather than splice .

The name SPLICE is mostly historical in my implementation. Earlier on, I had considered a broader operation family that also included fork-like and rebalance-like cases. That is no longer how the protocol is structured. In the current bilateral channel design, SPLICE only means signed funding-context resize/re-anchor, with splice-in and splice-out variants.

The fork-like and rebalance-like ideas have mostly moved into the factory layer. A fork-like case is now closer to child-channel materialisation or local exit: an internal factory right becomes an independent State/Vault object. A rebalance-like case is closer to a factory rights update: reserve claims or child-channel capacities change, while the shared Factory Vault may remain unchanged.

So these are not separate FORK or REBALANCE opcodes. In the current code, the relevant mechanisms are factory local/reduced exits, factory rights updates, sparse-Merkle/reduced-right proofs, and factory splice/reduced-splice paths.

4. Factory liquidity

On factory liquidity, the Morph approach is that internal liquidity movement should not automatically imply an on-chain transaction. A Morph factory locks a shared Factory Vault, while the Factory State records enforceable rights against that vault: balances, reserve claims, membership, exit paths, sponsor-budget claims, and child-channel-related commitments.

So the first distinction is between a rights delta and a vault delta. A rights delta changes who can claim what inside the factory. A vault delta changes the actual assets locked by the Factory Vault.

In the current implementation, conservative factory updates can change the factory state with all-participant signatures. The reduced paths are deliberately narrower: reduced-rights updates, sparse-Merkle single-right updates, reduced exits, and reduced-splice paths. They are not a general-purpose “rebalance anything” mechanism.

That is the important point: factory liquidity transfer should be off-chain when it is only a properly authorised change to internal rights and the Factory Vault remains unchanged. But this cannot be waved away with “just use a Merkle proof”. A Merkle proof proves locality, not economic authority. For reduced-signing-set transitions, the protocol also has to know exactly which rights were touched, who authorised them, and why unrelated rights remain unaffected.

I would classify it roughly like this:

Operation On-chain? Current Morph status
Conservative factory state update No, while cooperative Supported with all-participant signatures
Narrow reduced-right update No, while cooperative Supported for bounded local changes
Single-right sparse-Merkle update No, while cooperative Supported, but not as general rebalance
General multi-right rebalance Ideally no Future proof family / conservative fallback today
Materialise a child channel as State/Vault cells Yes Supported through factory local/reduced exits
Local exit Yes Supported
Add funds to the factory Yes Factory splice-in / resize-in
Remove funds from the factory Yes Factory splice-out / resize-out
Reduced update without adequate proof No safe shortcut Needs full signatures or a specific proof family

By “No, while cooperative”, I mean that these updates can remain off-chain as long as the relevant parties continue to exchange and retain the latest signed factory state. They become on-chain only when that state needs script-level enforcement: unilateral exit, dispute, child-channel materialisation, a factory-boundary change, or some other transition that must be made visible to the base layer.

So the short version is: factory liquidity transfer does not inherently require an on-chain transaction. It requires one when liquidity crosses the factory boundary, when a child channel is materialised, or when cooperation fails and an exit/dispute path is used. For purely internal rebalancing, the correct abstraction is a factory rights update; the open design question is which reduced proof families are safe enough to admit beyond the conservative all-signature path.

Admittedly, this is probably the part Morph needs to explain better.

One small correction I should also acknowledge: you are right about CKB RBF. My intended point was not that CKB lacks replacement semantics, but that Morph’s safety argument does not depend on pre-signed fee-bump transactions. Since participant signatures authorise the State Header rather than the sponsor inputs or fee rate, a publication/supersession transaction can be rebuilt with different sponsor inputs while preserving the same signed state evidence.

I think a separate comparison of Perun-on-CKB, Morph, and the Generic Payment Channel Construction deserves its own thread. I will write that separately so this reply does not become too sprawling.

4 Likes