lightningnetwork / lnd

Lightning Network Daemon ⚡️
MIT License
7.69k stars 2.08k forks source link

Structured Error Handling for BuildRoute #6861

Open kornpow opened 2 years ago

kornpow commented 2 years ago

Background

I would like to propose adding more structured error codes to the BuildRoute rpc, similar to what is available in SendToRouteV2. When building rebalancing software, you are often building routes, probing, and then deciding what route to actually send to. SendToRouteV2 provides nice error messaging, which allows me to be able to determine if there is no liquidity in a route, or if the probe has succeded. No Liquidity: TEMPORARY_CHANNEL_FAILURE Probe Succeeded: INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS

Example SendToRouteV2 probing command.

Yields INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS error.

fee rate ppm: 2.7999921600219517
status: FAILED
route {
  total_time_lock: 679
  total_fees: 7
  total_amt: 2500007
  hops {
    chan_id: 192414534926336
    chan_capacity: 5000000
    amt_to_forward: 2500003
    fee: 3
    expiry: 639
    amt_to_forward_msat: 2500003500
    fee_msat: 3500
    pub_key: "03c26cc9150b125ceed9f293354bab8a78ede73aeebc05fb8e5883b8cec52a2ec1"
    tlv_payload: true
  }
  hops {
    chan_id: 212205744226304
    chan_capacity: 5000000
    amt_to_forward: 2500000
    fee: 3
    expiry: 599
    amt_to_forward_msat: 2500000000
    fee_msat: 3500
    pub_key: "02d09397bde034627b4aaf68a62d785145aebd03ce54b5b55a6e8270326fa887f9"
    tlv_payload: true
  }
  hops {
    chan_id: 216603790802944
    chan_capacity: 5000000
    amt_to_forward: 2500000
    expiry: 599
    amt_to_forward_msat: 2500000000
    pub_key: "026ad2fe25313253de57f5242f8750bef8732799f987a45e7c9675a0397aac0be3"
    tlv_payload: true
    custom_records {
      key: 34349334
      value: "rebalance txn"
    }
    custom_records {
      key: 5482373484
      value: "&\372c Ld`Z3\213|N\252\231\241\336\250`W=\261\217*\325\004\332\253\220fQzi"
    }
  }
  total_fees_msat: 7000
  total_amt_msat: 2500007000
}
attempt_time_ns: 1661541105813051012
resolve_time_ns: 1661541106136519084
failure {
  code: INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS
  failure_source_index: 3
  height: 199
}
attempt_id: 1

image

Example BuildRoute rpc with lack of structured errors

>>> ln.lnd.build_route(amt_msat=1, oid=0, hop_pubkeys=list_pks)
<_InactiveRpcError of RPC that terminated with:
    status = StatusCode.UNKNOWN
    details = "no matching outgoing channel available for node 2 (02d09397bde034627b4aaf68a62d785145aebd03ce54b5b55a6e8270326fa887f9)"
    debug_error_string = "{"created":"@1661541716.345689597","description":"Error received from peer ipv4:127.0.0.1:10001","file":"src/core/lib/surface/call.cc","file_line":966,"grpc_message":"no matching outgoing channel available for node 2 (02d09397bde034627b4aaf68a62d785145aebd03ce54b5b55a6e8270326fa887f9)","grpc_status":2}"
>

Piece of code which generates this error code: https://github.com/lightningnetwork/lnd/blob/master/routing/router.go#L2691

Potential Different Error Types:

I've listed the errors in order of things to check first to things to check last: ROUTE_DOESNT_EXIST - the route "physically doesnt exist" ROUTE_CHAN_DISABLED - the route "exists", but one of the hops is disabled VIOLATED_CHANNEL_SIZE_CONSTRAINT - you cant send larger than your channel size VIOLATED_MIN_HTLC_CONSTRAINT - for example, sending 1 msat when default MIN_HTLC is 1000msat VIOLATED_MAX_HTLC_CONSTRAINT - people might actually set this to communicate liquidity

Conclusion

PATH 1:

Having these error codes will allow for building better programs for rebalancing liquidity. Currently when the status = StatusCode.UNKNOWN error is thrown, I am rather clueless until I do some digging why the route really failed to build.

PATH 2:

I also think it could be valid for BuildRoute to be far more lax about these above constaints. What is the harm of BuildRoute building an impossible route (disabled channel, sending too much, etc), as long as the hops exist on the graph. Once you send to it, it would error out anyways... This actually could make a lot of sense, since many of the failure cases I outline above, are standard spec errors anyways. In this case, the structured error codes for BuildRoute could be simply ROUTE_DOESNT_EXIST.

image

Your environment

guggero commented 2 years ago

Related:

Perhaps a more generic/general approach would be useful so we don't end up with a different error code system for the different RPCs?

kornpow commented 2 years ago

I think a general approach that can be applied project-wide would help a lot of people.

What do you think about PATH 2 in my issue? I think it would be helpful to allow BuildRoute to focus more on just the tedium of building a route if it exists, rather than throwing errors which would be bubbled up anyways in SendToRoute

guggero commented 2 years ago

I think it would make sense to allow enabling a "sandbox" mode that just builds the route without checking some of the liquidity or availability constraints. I would put it behind a flag in the RPC just to preserve backward compatibility with apps that rely on the checks and to avoid users getting potentially unusable routes without knowing why.

alexbosworth commented 2 years ago

Another approach to building routes if you don't care about the external data is to just derive the route yourself rather than doing it via API