← Back to NIP Index

Unidirectional Payment Channel Protocol

NIP: 4 | Author: jolestar(@jolestar) | Status: Draft | Created: May 13, 2025


Abstract

This NIP specifies a general-purpose unidirectional payment channel protocol for high-frequency, low-value micropayments between two parties.
The protocol enables one party (the Payer) to lock funds on a blockchain and stream incremental payments to another party (the Payee) off-chain, using cryptographically signed receipts that can be settled on-chain at any time.

To support concurrent payment flows (e.g., multi-device or multi-session scenarios), a single channel can contain multiple sub-channels, each maintaining independent state with monotonic nonce and accumulated amount values.

The protocol is ledger-agnostic: core semantics and message structures are defined abstractly, allowing implementation on any blockchain that can enforce collateral locking, signature verification, and dispute resolution. Specific ledger bindings define concrete encoding formats, on-chain contract interfaces, and identity resolution mechanisms.

Motivation

Protocol-level agent interactions—such as message relaying, API gateway access, or other infrastructure services—often involve high-frequency, low-value payments. Recording every payment directly on-chain is cost-prohibitive. A standard A2A payment channel enables:

Core Concepts

Invariant: onChainConfirmedNonce/Amount ≤ offChainLastAcceptedNonce/Amount

High-Level Flow

The protocol supports two channel initialization modes:

Mode 1: Direct Initialization (Payer-initiated)

In this mode, the payer directly interacts with the blockchain to create and fund the channel before beginning off-chain payments.

sequenceDiagram
    participant Payer
    participant Payee
    participant Blockchain

    Payer->>Blockchain: Open channel (specify payee, asset type)
    Note over Blockchain: Channel created on-chain
    Payer->>Blockchain: Deposit to hub (lock collateral)

    loop Authorize sub-channels (once per sub-channel)
        Payer->>Blockchain: Authorize sub-channel (subChannelId, public key)
        Note over Blockchain: Sub-channel authorized on-chain
    end

    loop Micropayments (off-chain)
        Payer->>Payee: Signed Receipt (accumulatedAmount, nonce)
        Note over Payee: Verify receipt and update off-chain state
        Payee-->>Payer: Proposal for next receipt
        Note over Payee: Optionally settle on-chain when delta >= threshold
        Payee->>Blockchain: Settle receipt (transfer delta)
    end

    alt Cooperative Close
        Payer->>Payee: Notify channel closure
        Payee->>Blockchain: Settle final receipts
        Payer->>Blockchain: Close channel
    else Unilateral Close
        Payer->>Blockchain: Initiate cancellation
        Payee->>Blockchain: Dispute with newer receipt (if applicable)
        Note over Blockchain: Challenge period elapses
        Payer->>Blockchain: Finalize cancellation
    end

Mode 2: Lazy Initialization (Facilitator-assisted)

In this mode, the payer begins sending receipts immediately, and channel creation is deferred until the first receipt is settled. A facilitator (typically the payee or a third-party service) handles on-chain operations and pays gas fees.

sequenceDiagram
    participant Payer
    participant Payee
    participant Facilitator
    participant Blockchain

    Payer->>Payee: Request resource (no receipt)
    Payee-->>Payer: 402 Payment Required (channel requirements)

    Payer->>Payee: Request with Receipt (epoch=0, nonce=0, amount=0)
    Note over Payee: Verify receipt, delta=0
    Payee->>Facilitator: Settle request (create channel)
    Facilitator->>Blockchain: Create channel on-chain (lock collateral)
    Note over Blockchain: Channel created, epoch=0
    Blockchain-->>Facilitator: txHash
    Facilitator-->>Payee: Settlement confirmed
    Note over Payee: Process request, compute cost
    Payee-->>Payer: 200 OK + Proposal (nonce=1, amount=cost)

    loop Micropayments (off-chain)
        Payer->>Payee: Signed Receipt (nonce, accumulatedAmount)
        Note over Payee: Verify receipt, compute delta
        alt delta > 0
            Payee-->>Payer: 200 OK + Proposal (next nonce, next amount)
            par Async settlement
                Payee->>Facilitator: Settle receipt (delta > 0)
                Facilitator->>Blockchain: Transfer delta on-chain
                Blockchain-->>Facilitator: txHash
                Facilitator-->>Payee: Settlement confirmed
            end
        else delta = 0 (idempotent retry)
            Payee-->>Payer: 200 OK (no settlement)
        end
    end

    alt Cooperative Close
        Payer->>Payee: Notify channel closure
        Payee->>Facilitator: Settle final receipts
        Facilitator->>Blockchain: Close channel
    else Unilateral Close
        Facilitator->>Blockchain: Initiate cancellation
        Payee->>Facilitator: Dispute with newer receipt
        Facilitator->>Blockchain: Submit dispute receipt
        Note over Blockchain: Challenge period elapses
        Facilitator->>Blockchain: Finalize cancellation
    end

Key Differences:

Data Model

Receipt Structure

A receipt is a payment commitment containing the following logical fields:

Note: The concrete encoding of these fields (e.g., field names, data types, serialization format) is defined by implementation bindings. For example, some implementations may use vmIdFragment as the sub-channel identifier, while others may use different naming conventions.

Signed Receipt

A signed receipt bundles the receipt with its cryptographic signature:

{
  "receipt": { /* receipt fields */ },
  "signature": "<bytes>" // signature over canonical serialization of receipt
}

Canonical Serialization Requirements

Implementations MUST define:

  1. Serialization Format – The canonical byte representation of receipts for signing (e.g., BCS, EIP-712, CBOR, or canonical JSON)

  2. Signature Algorithm – The cryptographic algorithm(s) supported and how they map to key types (e.g., ECDSA with secp256k1/secp256r1, EdDSA with Ed25519)

  3. Key Discovery – How verifiers obtain the public key for signature verification (e.g., via DID resolution, on-chain storage, or certificate infrastructure)

Receipt Behavior Semantics

All receipts follow the same structure; their behavior is determined by the values and current channel state:

State Management

The protocol distinguishes between two types of state for each sub-channel:

Off-chain State (offChainLastAccepted)

The most recent receipt state that the payee has accepted and stored locally:

This state is used for:

On-chain State (onChainConfirmed)

The most recent receipt state that has been settled on the blockchain:

This state is used for:

State Invariant

The following invariant MUST hold at all times:

onChainConfirmedNonce ≤ offChainLastAcceptedNonce
onChainConfirmedAmount ≤ offChainLastAcceptedAmount

This ensures that off-chain state always leads or equals on-chain state, allowing for batched settlement strategies.

Verification Protocol

Implementations MUST perform the following verification steps when receiving a signed receipt:

1. Signature Validation

2. Channel State Check

3. Replay Protection and Monotonicity

For the target (channelId, epoch, subChannelId):

4. Delta Computation and Budget Validation

5. State Update

If all verifications pass:

Settlement Specification

Settlement is the process of confirming receipts on-chain and transferring funds. Implementations MUST support the following settlement modes:

Lazy Channel Creation (delta = 0, first receipt)

When receiving the first receipt for a channel:

Normal Settlement (delta > 0)

When settling a receipt with positive delta:

Idempotent Settlement

If a settlement transaction is submitted with nonce and accumulatedAmount equal to current on-chain state:

Settlement Timing Strategies

Implementations MAY choose when to trigger settlement:

Channel Lifecycle

Opening a Channel

  1. Payer locks collateral on-chain (via deposit or payment hub)
  2. Payer sends ChannelOpenRequest to payee (off-chain message)
  3. Payee validates and responds with ChannelOpenResponse
  4. Payer authorizes one or more sub-channels (via SubChannelAuthorize)
  5. Channel is ready for micropayments

Normal Operation

  1. Payer signs receipt for current payment
  2. Payee verifies receipt and updates off-chain state
  3. Payee generates proposal for next receipt
  4. Payee optionally settles receipts on-chain (batched or threshold-based)
  5. Repeat

Cooperative Closure

  1. Payer sends ChannelCloseRequest
  2. Payee settles all pending receipts on-chain
  3. Payee confirms closure (channel state becomes closed)
  4. Remaining collateral is returned to payer

Unilateral Closure

If the payee becomes unresponsive:

  1. Payer initiates cancellation on-chain
  2. Challenge period begins (implementation-defined duration)
  3. Payee MAY dispute with newer receipts during challenge period
  4. After challenge period expires, payer finalizes cancellation
  5. Outstanding delta (if any) is transferred, remaining collateral returned to payer

Transport Bindings

The protocol is transport-agnostic. This section provides informative guidelines for common transport profiles. Detailed specifications SHOULD be defined in separate binding documents.

HTTP Gateway Profile (Informative)

HTTP services can support payment channels using a dedicated header (e.g., X-Payment-Channel-Data) to carry payment data encoded as Base64 JSON.

Request Payload (Payer → Payee):

{
  "version": <number>,              // Protocol version
  "payerId": "<identifier>",        // Optional payer identifier
  "clientTxRef": "<string>",        // Idempotency key
  "maxAmount": "<amount>",          // Optional spending limit for this request
  "signedReceipt": {                // Optional; required for paid routes
    "receipt": { /* ... */ },
    "signature": "<bytes>"
  }
}

Response Payload (Payee → Payer):

{
  "version": <number>,              // Protocol version
  "proposal": { /* ... */ },        // Unsigned receipt for next request
  "cost": "<amount>",               // Cost incurred for this request
  "serviceTxRef": "<string>",       // Service reference ID
  "error": {                        // Protocol-level error (if any)
    "code": "<string>",
    "message": "<string>"
  }
}

Interaction Pattern:

  1. Client sends request with signed receipt (or omits for free/discovery endpoints)
  2. Service verifies receipt, processes request, computes cost
  3. Service generates proposal (unsigned receipt with incremented nonce and accumulated amount)
  4. Service returns response with proposal in header
  5. Client verifies proposal, signs it for next request

Error Handling:

Condition Recommended HTTP Status
Payment required / missing receipt 402 Payment Required
Invalid signature 403 Forbidden
Receipt conflict (nonce/epoch mismatch) 409 Conflict
Channel not found 404 Not Found
Malformed header 400 Bad Request

MCP Profile (Informative)

For Model Context Protocol integrations:

A2A Profile (Informative)

For Agent-to-Agent messaging:

Security Considerations

Replay Protection

State Integrity

Signature Security

Denial of Service

Asset Binding

Extensibility

The protocol supports evolution through:

Terminology

Term Definition
Channel A unidirectional payment relation (Payer → Payee) for a specific asset
Receipt A cryptographically signed payment commitment containing channel, sub-channel, amount, and nonce information
Proposal An unsigned receipt generated by the payee for the payer to sign, representing the next expected payment state
Signed Receipt A receipt bundled with its cryptographic signature
Sub-channel A logical concurrent payment stream within a channel, with independent nonce and accumulated amount
Sub-channel ID (subChannelId) Identifier for a sub-channel (implementation-specific; may reference DID verification methods or other identifiers)
Epoch Channel lifecycle version number that increments on each close/reopen cycle
Nonce Monotonically increasing counter per sub-channel, must increment by 1 for each new receipt
Accumulated Amount Total amount ever sent through a sub-channel since epoch began
Delta Incremental payment amount computed as receipt.accumulatedAmount - lastAcceptedAmount
Off-chain State Latest receipt state accepted by payee and stored locally (offChainLastAccepted)
On-chain State Latest receipt state confirmed on blockchain through settlement (onChainConfirmed)
Settlement The process of confirming a receipt on-chain and transferring funds
Facilitator An optional third-party service that verifies receipts, handles on-chain settlement operations, and pays gas fees on behalf of participants (typically the payee or a dedicated service)
Lazy Channel Creation Creating a channel on-chain using the first receipt (typically with delta=0) via a facilitator rather than requiring the payer to initialize the channel directly
Idempotent Retry Submitting a receipt with values equal to the last accepted state; results in no state change

Appendix A: Implementation Bindings (Non-normative)

Specific blockchain implementations SHOULD provide binding documents that define:

Required Specifications

Optional Specifications

Example Bindings

Implementation bindings may be developed for various blockchain ecosystems:

Each binding should be documented in a separate specification that references this core NIP-4 protocol.

Reference Implementations

This protocol has been implemented on the Rooch blockchain with the following components:

These implementations demonstrate concrete bindings of the abstract protocol defined in this specification and can serve as references for implementations on other blockchains.


This NIP defines the core protocol semantics for unidirectional payment channels. Implementations on specific blockchains should provide binding documents that specify concrete encoding formats, on-chain interfaces, and identity resolution mechanisms while maintaining compatibility with the abstract protocol defined herein.