Skip to content

docs(blockchain) Channel Participation in PoS#364

Merged
thomaslavaur merged 27 commits into
masterfrom
tl/make_channels_participate_in_pos
Jul 20, 2026
Merged

docs(blockchain) Channel Participation in PoS#364
thomaslavaur merged 27 commits into
masterfrom
tl/make_channels_participate_in_pos

Conversation

@thomaslavaur

@thomaslavaur thomaslavaur commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

[RFC] Channel Participation in PoS

Authors: Thomas Lavaur thomas@logos.co

Reviewer Orientation

Prerequisite: read Motivation and Proposal first. The whole PR hangs off one idea — bridged funds stop being an opaque per-channel scalar and become channel notes, on-ledger notes whose ownership stays with the channel while their PoS participation power is delegated through a ZkPublicKey. Read that ownership-vs-participation split before the individual operations.

# Priority Document / Change What to look for
1 Critical Start hereChannel notes and the ownership/participation split (Bedrock Mantle spec) new channel_notes set in the Ledger; channel notes are PoL-only and can never back a service stake; assert_spendable / execute_spending / execute_adding gain a channel_id argument
2 Critical CHANNEL_DEPOSIT marks inputs instead of re-minting (same spec) inputs are neither consumed nor re-created — they keep NoteId, value and ZkPublicKey and are registered in channel_notes
3 Critical CHANNEL_TRANSFER (new op 0x14) (same spec) sequencers consume and re-create channel notes under new ZkPublicKeys under a signature threshold, without ZkSignature; opcode/reserved-range change
4 Critical CHANNEL_WITHDRAW releases channel notes (same spec) new mechanism: payload is inputs only, no outputs, no nonce; execution just unregisters the notes from channel_notes, turning them back into regular notes under their current ZkPublicKey
5 High withdrawal_nonce removed — UTXO determinism (same spec) every channel op now takes inputs, so op_id uniqueness is guaranteed by the UTXO chain; confirm no op_id collision path remains
6 High transfer_threshold replaces withdraw_threshold (same spec) one threshold now gates both CHANNEL_WITHDRAW and CHANNEL_TRANSFER
7 High Encoding of the new/updated channel operations (Mantle Transaction Encoding) new ChannelTransfer production; ChannelWithdraw becomes ChannelId Inputs; ChannelConfig renames the threshold field
8 Medium Gas cost of the channel operations (Gas Cost Determination) new EXECUTION_CHANNEL_TRANSFER_GAS; withdraw/transfer costs scale linearly with the threshold — flag: the gas formulas still name stake_manipulation_threshold, not transfer_threshold
9 Low Cryptarchia test vectors (Cryptarchia Protocol) skim — block_root / block_id test vectors only

Status tracker

  • 🚧 Raw (when all below is checked)
    • Template applied
    • Authors filled in
    • Authors agree on the RFC content
  • 📘 Draft (when all below is checked)
    • All dependent specifications added (Notion backlinks checked)
    • Specifications to deprecate added, if applicable
    • Specifications to retire added, if applicable
    • Research Lead assigned, or Project Lead assigned if the Research Lead is an author
    • Relevant Research Domain Experts assigned (cannot be authors)
  • ⚙️ Verified (when all below is checked)
    • Researchers' comments addressed
    • All logical changes documented
    • All Research reviewers approve the latest version
    • Engineering Lead assigned
    • Relevant Engineering Domain Experts assigned
  • 🔀 Merged (when all below is checked)
    • Engineers' comments addressed
    • Every change added to the change log
    • All Engineering reviewers approve the latest version
    • Specification version numbers assigned
    • Implementation reviewed and merged
    • Branch updated to master and all conflicts resolved
    • PR merged

Change log

Status Description Date
Draft Draft status set 2026-05-29
- Channel Config updating the sequencer_zk_id set now reset the stake of every one and not only the removed sequencers guaranteeing perpetual equality of stake. - The number of note minted per sequencer and epoch is increased from 0 to 10 (see Number of notes per epoch and sequencer) 2026-06-12
Moved to a version where there is no balance, everything is channel notes, manages by classic internal channel transfer or authoritative channel config-style assignation/withdraw 2026-06-24
Changed the deposit execution to create the channel note to the first consumed input public key instead of 0 and removed CHANNEL_STAKE_TRANSFER operation 2026-07-06
Changed the deposit behavior from a single note creation to one note per input. withdraw also enforce perfect equality 2026-07-07
Changed the deposit behavior to not consume and create notes but just mark the old notes as channel notes directly 2026-07-10
Explicitly defined the bridging section to make it clearer 2026-07-13
Restructured the description to follow the RFC-PR specification-change template 2026-07-13
Renamed CHANNEL_STAKE_ASSIGNATION to CHANNEL_TRANSFER and the channel threshold to transfer_threshold; simplified CHANNEL_WITHDRAW to release notes back to regular notes (inputs only). 2026-07-15

Motivation

The blockchain token currently serves two distinct purposes:

  • Securing the network through Proof-of-Stake (PoS) for leader selection and staking-based services.
  • Being bridged into Sovereign Zones so it can be used by applications outside the L1.

Today these uses are mutually exclusive. Once bridged, funds are represented as a per-channel scalar balance rather than as ledger notes, and therefore cannot participate in PoS. This shrinks the amount of stake that can contribute to consensus, weakening network security, and forces token holders and channels into an unnecessary trade-off between security and application use.

This RFC removes that trade-off by letting bridged funds retain PoS eligibility while remaining owned and spend-controlled by the channel. Rewards earned from PoS participation can be redistributed by channel sequencers, in whole or in part, to the users of the channel.

Proposal

Channel bridge funds are currently stored as a per-channel scalar token amount. Because a scalar is not a note, it cannot participate in Proof-of-Stake. This RFC represents channel bridge funds as on-ledger channel notes so they stay PoS-eligible while bridged.

The design rests on a strict separation between two rights that a normal note bundles together:

  • Ownership of the bridged funds stays with the channel, enforced by the channel's normal authorization rules (a signature threshold of the channel's accredited keys) rather than by a user ZkSignature.
  • PoS participation power is what gets delegated. Assigning a note to a ZkPublicKey grants that key the right to create PoLs from the note, and nothing more. It confers no right to transfer the note or to lock it as a service stake.

Concretely, a CHANNEL_DEPOSIT marks the input notes as channel notes owned by the depositing channel, so the depositor keeps the PoS participation power they had before bridging. A new CHANNEL_TRANSFER operation lets the sequencers consume and re-create channel notes under any ZkPublicKey (redelegating the participation power) under a signature threshold, and CHANNEL_WITHDRAW releases channel notes back into regular notes on the channel's authority alone. The full normative changes are specified in Details.

Discussion

Yield redistribution (out of scope)

This RFC does not specify what channels do with the PoS yield earned on bridged funds. The choice — fee rebates, user rewards, sequencer compensation, retention policies, PoS delegation to users — is a channel-level policy decision that can vary across channels. Because leadership and PoS participation are private, external observers cannot reliably attribute yield to specific sequencers, so any transparency or redistribution mechanism is expected to live at the application layer.

Decentralization vs security trade-off

Letting bridged funds participate in PoS increases total effective stake and improves financial security. The risk is that if most tokens concentrate in a few channels, PoS participation could concentrate around those channels' sequencers. The working assumption is that a healthy ecosystem of many distinct channels distributes bridged stake across independent users, mitigating this risk. Stake distribution should be monitored as channel adoption evolves.

A step toward Native Zones

This RFC introduces a unified ledger for Channels and Mantles that partitions notes by the channel they belong to, moving a step closer to Native Zones. The two new/updated operations let users move notes into an isolated channel and let sequencers agree on a new representation of their ledger, relocating notes without user authorization. Once Native Zones are in place and sequencers lose that control through zk integration, the ledger will be nearly ready to hand full control over notes back to users, provided they meet the zone requirements (enforced via zk).

Details

Ordered from highest to lowest review impact. All changes below are normative and land in the Bedrock v1.1 Mantle Specification unless noted otherwise.

1. Channel notes: a new, owned-by-channel note type (Mantle spec)

The ledger now tracks three kinds of notes: regular notes, locked notes (collateral for service declarations), and channel notes (channel bridge funds, PoS-eligible only). The Ledger gains a channel_notes set mapping every active channel NoteId to its ChannelId:

 class Ledger:
     # ... unchanged fields elided
+    channel_notes: dict[NoteId, ChannelId]

Ownership and PoS participation power are split. Ownership of a channel note stays with the channel: the channel is recorded as the note's owner in channel_notes and keeps full control over it. The ZkPublicKey carried by the note does not confer ownership — it only delegates the note's value for PoL creation, so whoever controls that key is the one allowed to turn the note into a PoL. A channel note can be used for PoL creation only and can never back a service stake. Any mechanism that locks notes as service stake must reject channel notes.

Spending and note bookkeeping become channel-aware — the helpers take an optional channel_id so a channel note can only be spent in the context of its owning channel, and so marking/spending keeps channel_notes in sync:

-    def assert_spendable(inputs: list[NoteId]):
+    def assert_spendable(inputs: list[NoteId], channel_id: ChannelId | None):
             # ...
+                if channel_id is not None:
+                    assert ledger.channel_notes[note_id] == channel_id
+                else:
+                    assert note_id not in ledger.channel_notes

execute_spending and execute_adding gain the same channel_id argument to pop or register notes in channel_notes. The Bridging section of the spec now states this ownership/participation boundary explicitly, including what the delegated-key holder may do (create a PoL, earn its leader rewards) versus what the channel sequencers may do (reassign or withdraw the note without a user signature, but never use it as a service stake or earn PoL rewards without first assigning the note to their own key).

2. CHANNEL_DEPOSIT marks inputs as channel notes (Mantle spec)

Before this change, a deposit increased an opaque per-channel scalar balance and left no ledger notes behind. The bridged value now lives on-ledger: a deposit marks its input notes as channel notes in place, without creating any new note. Each input keeps its NoteId, value and ZkPublicKey, and is registered in channel_notes under the depositing channel.

# CHANNEL_DEPOSIT execution
# Mark the inputs as channel notes owned by the channel. The notes keep their
# NoteId, value and ZkPublicKey; only their ownership is recorded on-ledger.
for note_id in deposit.inputs:
    ledger.channel_notes[note_id] = deposit.channel

Because the input notes keep their ZkPublicKey, the depositor retains the PoS participation power over the deposited value until the sequencers reassign it.

3. CHANNEL_TRANSFER — new operation (Mantle spec)

A new operation (opcode 0x14, formerly drafted as CHANNEL_STAKE_ASSIGNATION) lets the sequencers consume and re-create channel notes under any ZkPublicKey, redelegating their participation power without ownership ever leaving the channel. It is authorized by a signature threshold of the channel's accredited keys and requires no ZkSignature from the current key holder.

 | CHANNEL_WITHDRAW  | 0x13 | Withdraw assets from a channel |
-| *RESERVED*        | *0x14 - 0x1F* |  |
+| CHANNEL_TRANSFER  | 0x14 | Consume and create notes belonging to a channel |
+| *RESERVED*        | *0x15 - 0x1F* |  |
class ChannelTransfer:
    channel: ChannelId
    inputs: list[NoteId]
    outputs: list[Note]

class ChannelTransferOpProof:
    signatures: list[Ed25519Signature]  # exactly transfer_threshold signatures
    indexes: list[int]                   # accredited-key indexes, ascending, no duplicates

Execution spends the input channel notes and adds the output notes as channel notes under the same channel, after checking the threshold signatures against the channel's accredited keys. This lets the sequencers freely re-partition and re-key the channel's bridged value.

4. CHANNEL_WITHDRAW releases channel notes (Mantle spec)

The withdraw mechanism is reworked. The payload is now just the channel notes to release (inputs), with no outputs and no nonce. Execution unregisters those notes from channel_notes: they stay in the ledger with the same NoteId, value and ZkPublicKey, but are no longer channel notes, so they become regular notes controlled by their current ZkPublicKey holder.

 class ChannelWithdraw:
     channel: ChannelId
+    inputs: list[NoteId]
-    outputs: list[Note]
-    withdrawal_nonce: u32    # Nonce used to derive a channel OpId
# CHANNEL_WITHDRAW execution
# Release the inputs from the channel: they keep their NoteId, value and
# ZkPublicKey and simply stop being channel notes.
for note_id in withdrawal.inputs:
    ledger.channel_notes.pop(note_id)

Like CHANNEL_TRANSFER, it is gated by a transfer_threshold signature set and needs no ZkSignature. The intended user-exit flow is therefore two steps: sequencers CHANNEL_TRANSFER the value onto the user's ZkPublicKey, then CHANNEL_WITHDRAW releases it so the user controls an ordinary, spendable note.

5. Remove withdrawal_nonce (Mantle spec)

Every channel operation now consumes inputs, so the UTXO chain is never broken and each operation's payload is unique. That guarantees op_id uniqueness on its own, making the withdrawal nonce redundant. It is removed from the payload, from CHANNEL_CONFIG initialization, and from withdraw validation:

-      assert channels[withdrawal.channel].withdrawal_nonce == withdrawal.withdrawal_nonce
       # ...
-      channels[withdrawal.channel].withdrawal_nonce += 1

6. transfer_threshold replaces withdraw_threshold (Mantle spec)

CHANNEL_CONFIG carries a single transfer_threshold in place of withdraw_threshold. It serves the same role but now gates both CHANNEL_WITHDRAW and the new CHANNEL_TRANSFER.

-    withdraw_threshold: u16
+    transfer_threshold: u16
-assert config.withdraw_threshold > 0
+assert config.transfer_threshold > 0

7. Encoding updates (Mantle Transaction Encoding)

The encoding spec (version 1.5.0) adds the new operation to OpPayload and reworks the channel productions:

 OpPayload = Transfer /
             ChannelConfig /
             ChannelDeposit /
             ChannelWithdraw /
+            ChannelTransfer /
             SDPDeclare / ...
-ChannelConfig   = ChannelId KeyCount *Signer PostingTimeframe PostingTimeout ConfigThreshold WithdrawThreshold
+ChannelConfig   = ChannelId KeyCount *Signer PostingTimeframe PostingTimeout ConfigThreshold TransferThreshold

+ChannelTransfer = ChannelId Inputs Outputs
-ChannelWithdraw = ChannelId Outputs WithdrawNonce
+ChannelWithdraw = ChannelId Inputs

+Inputs          = InputCount *NoteId
+Outputs         = OutputCount *Note

Reviewer flag: the encoding version-history row still describes the operation as CHANNEL_STAKE_ASSIGNATION; the grammar itself uses ChannelTransfer.

8. Gas costs (Analysis: Gas Cost Determination)

The gas spec (version 1.5.0) adds EXECUTION_CHANNEL_TRANSFER_GAS (56) and expresses the withdraw and transfer costs as linear in the threshold:

  • CHANNEL_WITHDRAW: EXECUTION_CHANNEL_WITHDRAW_GAS * transfer_threshold
  • CHANNEL_TRANSFER: EXECUTION_CHANNEL_TRANSFER_GAS * transfer_threshold

Reviewer flag: in the gas spec the two formulas are still written against stake_manipulation_threshold, and the version-history row still names CHANNEL_STAKE_ASSIGNATION. These should be reconciled with the Mantle spec's transfer_threshold / CHANNEL_TRANSFER before merge.

PoS participation (aging, unchanged rule)

Channel notes follow the same aging rule as ordinary notes: a note first appears in the snapshot of the epoch following the one in which it was marked, and becomes PoS-eligible when the epoch after that snapshot starts. Once aged past the threshold, the note can be used by its current ZkPublicKey holder to create a PoL.

Chores

  • Cryptarchia test vectors. Added block_root and block_id test vectors (empty block, one-transaction-per-operation-kind, and a full Header) in the Cryptarchia Test Vectors annex. The Cryptarchia version table is not bumped on this branch (still 1.0.2).
  • Added test vectors in the Mantle spec annex for OpId per operation and for the Mantle Transaction Hash.
  • Because Notion introduced an H4 header level, every Operation section previously rendered in bold was promoted to H4.

Implementation

Grouped by area, in implementation order. Each task is independently checkable.

Channel notes (ledger state)

  • Add the channel_notes: dict[NoteId, ChannelId] set to the Ledger.
  • Thread the optional channel_id argument through assert_spendable, execute_spending, and execute_adding so a channel note is only spendable in the context of its owning channel, and so marking/spending keeps channel_notes in sync.
  • Reject channel notes on every service-stake locking path (a channel note can back a PoL but never a service declaration).

Channel operations

  • CHANNEL_DEPOSIT: mark the input notes as channel notes in place (keep NoteId, value, ZkPublicKey), replacing the old per-channel scalar balance increment.
  • CHANNEL_TRANSFER (new, opcode 0x14): add the payload, the threshold-signature proof, and execution that spends the input channel notes and adds the output notes as channel notes under new ZkPublicKeys.
  • CHANNEL_WITHDRAW: take inputs: list[NoteId] only and release the notes by popping them from channel_notes, on the channel's authority, without ZkSignature verification.

Config and cleanup

  • Rename withdraw_threshold to transfer_threshold in CHANNEL_CONFIG and gate both CHANNEL_WITHDRAW and CHANNEL_TRANSFER on it.
  • Remove withdrawal_nonce from the withdraw payload, config initialization, and withdraw validation.

Encoding and gas

  • Update the Mantle Transaction Encoding grammar: add ChannelTransfer, change ChannelWithdraw to ChannelId Inputs, rename the config threshold field, and share the Inputs/Outputs productions.
  • Add EXECUTION_CHANNEL_TRANSFER_GAS and make the withdraw and transfer costs scale linearly with transfer_threshold (reconcile the lingering stake_manipulation_threshold naming in the gas spec).
  • Reconcile the stale CHANNEL_STAKE_ASSIGNATION naming in the encoding and gas spec version-history rows.

Tests and verification

  • Add or extend test vectors: OpId per operation, Mantle Transaction Hash, and the Cryptarchia block_root/block_id vectors.
  • Verify the implementation matches this specification — channel-note ownership rules, the three channel operations, threshold gating, and op_id uniqueness without the nonce.

Affected Specifications

Specification Status Note
Bedrock v1.1 Mantle Specification Modified Bumped to 1.8.0. New channel note type and channel_notes set; CHANNEL_DEPOSIT marks inputs in place; new CHANNEL_TRANSFER; CHANNEL_WITHDRAW releases notes (inputs only); withdrawal_nonce removed; withdraw_thresholdtransfer_threshold
Mantle Transaction Encoding Modified Version 1.5.0. Adds ChannelTransfer; reworks ChannelWithdraw/ChannelConfig. Version-history row still names the old CHANNEL_STAKE_ASSIGNATION
Analysis: Gas Cost Determination Modified Version 1.5.0. Adds EXECUTION_CHANNEL_TRANSFER_GAS; withdraw/transfer costs linear in the threshold. Formulas still reference stake_manipulation_threshold and the old operation name — reconcile before merge
Cryptarchia Protocol Modified Adds block_root/block_id test vectors only (non-normative). Version table not bumped (still 1.0.2); confirm whether a bump is expected

@thomaslavaur thomaslavaur self-assigned this Jun 26, 2026
@thomaslavaur
thomaslavaur marked this pull request as ready for review June 26, 2026 08:58
@thomaslavaur
thomaslavaur requested a review from davidrusu June 29, 2026 12:39
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated

@davidrusu davidrusu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My main reservation is that I don't think we need ChannelStakeTransfer, It seems that ChannelStakeAssignation is all we need

Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/cryptarchia-v1-protocol.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated

@madxor madxor left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good I left a couple of small comments. However, I think it might be better to extract locked->service rename into a separate PR, and bump the minor version of all updated documents (in that PR).

Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md Outdated
Comment thread docs/blockchain/raw/bedrock-v1.1-mantle-specification.md
| Holder of the note's `ZkPublicKey` (by default, the depositor) | Use the note to create a PoL and earn its leader rewards | Spend the note, withdraw it, reassign it, or use it as service stake |
| Channel sequencers (owner of the note) | Reassign the note to a different `ZkPublicKey` (`CHANNEL_TRANSFER`) and spend it to fund withdrawals (`CHANNEL_WITHDRAW`), both without `ZkSignature` verification | Use the note as service stake, or earn PoL rewards without first assigning the note to their own key |

This makes delegated staking explicit. Sequencers can assign a channel note to their own `ZkPublicKey` and earn the Proof of Leadership rewards it produces, but those rewards always follow the assigned key, so the channel earns nothing merely by owning the note. Conversely, ownership never leaving the channel is exactly what lets sequencers redelegate value or cover withdrawals at any time without a user signature.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we could emphasize (again) at the end (as a warning paragraph) that the channel note handling logic is fully defined by the channel and the depositor of the funds must be aware of that fact. I think it should be VERY clear for the reader that delegated funds are not his own and there is no return path if the funds are delegated to a scammy channel.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added another paragraph:

Warning: a deposit is a transfer of custody. Depositors must understand that channel note handling is fully defined by the channel. Once a CHANNEL_DEPOSIT is executed the note belongs to the channel, and its sequencers can reassign it to any ZkPublicKey with CHANNEL_TRANSFER or release it to whoever they choose with CHANNEL_WITHDRAW, at any time and without any signature from the depositor. The ledger enforces no return path to the original depositor. Holding the note's ZkPublicKey grants PoS participation power only and never a claim on the value, so it confers no ability to recover the funds. A user who deposits into a dishonest or faulty channel has no on-chain recourse. Deposit only into channels you trust to honour their own withdrawal policy.

```

Note that the Zone may wait for the deposit to be finalized before interpreting the deposit in order to guarantee that the deposit will occur on-chain and won't be removed due to reorganization of the chain.
Note that the Zone may wait for the deposit to be finalized before interpreting the deposit in order to guarantee that the deposit will occur on-chain and won't be removed due to reorganization of the chain.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should make this limitation clearer. That in order to execute channel transfers a channel note must be finalized, and then the channel transfer operation can be done, which also needs to be finalized. So the waiting time will be approximately 2 epochs until channel note can be delegated to the sequencer. This is fine as the stake continues to protect the network by the original delegator.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reworked this paragraph as:

A Zone that credits a deposit in its own state must be sure the deposit really lands on-chain. If the Zone reflects the deposit through a CHANNEL_INSCRIBE posted in a separate Mantle Transaction, a reorganization can reorder the two so that the inscription is included while the deposit is not, leaving the Zone crediting funds it never received. Two options avoid this:

  • Wait for the deposit to be finalized before interpreting it, at the cost of the finalization delay.
  • Make the inscription conditional on the deposit, by including a CHANNEL_TRANSFER that consumes the deposited note in the same Mantle Transaction as the inscription. Mantle Transactions execute atomically, so the inscription is included only if the deposited note exists and is consumed. This removes the waiting period entirely.

The second option resets the ageing of the value. A CHANNEL_TRANSFER consumes its inputs and creates new notes, so the resulting note starts the ageing process again and must age before it can create a PoL. CHANNEL_DEPOSIT and CHANNEL_WITHDRAW keep the NoteId of the notes they touch and therefore never reset ageing.

@thomaslavaur
thomaslavaur force-pushed the tl/make_channels_participate_in_pos branch from 82a85e9 to b5a2902 Compare July 17, 2026 12:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants