lightningnetwork / lnd

Lightning Network Daemon ⚡️
MIT License
7.65k stars 2.07k forks source link

[epic]: Payment and Router separation #8834

Open yyforyongyu opened 3 months ago

yyforyongyu commented 3 months ago

paymentLifecyle is the main struct to handle sending payments and can be moved out of routing package, which has the benefits,

Current State

As of today, multiple components are involved when sending payments, as shown below,

flowchart LR
        pay_req-->paymentLifecycle

        subgraph paymentLifecycle
        p[resumePayment]
    end

    subgraph PaymentSession
        RequestRoute-->p
        p-->UpdateAdditionalEdge
        p-->GetAdditionalEdgePolicy
    end

    subgraph MissionControl
      p-->ReportPaymentSuccess
      p-->ReportPaymentFailure
    end

    subgraph PaymentAttemptDispatcher
        p-->SendHTLC
        GetAttemptResult-->p
    end

    subgraph ControlTower
        crud[DB operations]-->p
        FetchPayment
        FailPayment
        more[...]
    end

    subgraph ChannelRouter
        p--->ChannelRouter.applyChannelUpdate
    end

The components are,

Proposed Design

The proposed architecture,

flowchart LR
    pay_req-->paymentLifecycle

    subgraph paymentLifecycle
      p[resumePayment]
      ct
    end

    subgraph ct[ControlTower]
      crud[DB operations]
      FetchPayment
      FailPayment
      more[...]
    end

    subgraph cg[ChannelRouter]
      p-->sa[SendAttempt]
      ps
      mc
      pad
    end

    subgraph ps[PaymentSession]
      RequestRoute
      UpdateAdditionalEdge
      GetAdditionalEdgePolicy
    end

    subgraph mc[MissionControl]
      ReportPaymentSuccess
      ReportPaymentFailure
    end

    subgraph pad[PaymentAttemptDispatcher]
      SendHTLC
      GetHTLCResult
    end

Some highlights,

By adding SendAttempt, htlcswitch is no longer exposed to paymentLifecycle. Instead, an HTLC attempt always goes through the graph managed by ChannelRouter first, and it's up to ChannelRouter to decide whether a route can be used or not, which solves the race condition when two HTLC attempts are using the same route without being aware of each other, as manifested in itest flakes.

Plan