/ htlcswitch / interfaces.go
interfaces.go
1 package htlcswitch 2 3 import ( 4 "context" 5 6 "github.com/btcsuite/btcd/btcutil" 7 "github.com/btcsuite/btcd/wire" 8 "github.com/lightningnetwork/lnd/channeldb" 9 "github.com/lightningnetwork/lnd/fn/v2" 10 "github.com/lightningnetwork/lnd/graph/db/models" 11 "github.com/lightningnetwork/lnd/invoices" 12 "github.com/lightningnetwork/lnd/lntypes" 13 "github.com/lightningnetwork/lnd/lnwallet" 14 "github.com/lightningnetwork/lnd/lnwallet/chainfee" 15 "github.com/lightningnetwork/lnd/lnwire" 16 "github.com/lightningnetwork/lnd/record" 17 "github.com/lightningnetwork/lnd/routing/route" 18 "github.com/lightningnetwork/lnd/tlv" 19 ) 20 21 // InvoiceDatabase is an interface which represents the persistent subsystem 22 // which may search, lookup and settle invoices. 23 type InvoiceDatabase interface { 24 // LookupInvoice attempts to look up an invoice according to its 32 25 // byte payment hash. 26 LookupInvoice(context.Context, lntypes.Hash) (invoices.Invoice, error) 27 28 // NotifyExitHopHtlc attempts to mark an invoice as settled. If the 29 // invoice is a debug invoice, then this method is a noop as debug 30 // invoices are never fully settled. The return value describes how the 31 // htlc should be resolved. If the htlc cannot be resolved immediately, 32 // the resolution is sent on the passed in hodlChan later. The eob 33 // field passes the entire onion hop payload into the invoice registry 34 // for decoding purposes. 35 NotifyExitHopHtlc(payHash lntypes.Hash, paidAmount lnwire.MilliSatoshi, 36 expiry uint32, currentHeight int32, 37 circuitKey models.CircuitKey, hodlChan chan<- interface{}, 38 wireCustomRecords lnwire.CustomRecords, 39 payload invoices.Payload) (invoices.HtlcResolution, error) 40 41 // CancelInvoice attempts to cancel the invoice corresponding to the 42 // passed payment hash. 43 CancelInvoice(ctx context.Context, payHash lntypes.Hash) error 44 45 // SettleHodlInvoice settles a hold invoice. 46 SettleHodlInvoice(ctx context.Context, preimage lntypes.Preimage) error 47 48 // HodlUnsubscribeAll unsubscribes from all htlc resolutions. 49 HodlUnsubscribeAll(subscriber chan<- interface{}) 50 } 51 52 // packetHandler is an interface used exclusively by the Switch to handle 53 // htlcPacket and pass them to the link implementation. 54 type packetHandler interface { 55 // handleSwitchPacket handles the switch packets. These packets might 56 // be forwarded to us from another channel link in case the htlc 57 // update came from another peer or if the update was created by user 58 // initially. 59 // 60 // NOTE: This function should block as little as possible. 61 handleSwitchPacket(*htlcPacket) error 62 } 63 64 // dustHandler is an interface used exclusively by the Switch to evaluate 65 // whether a link has too much dust exposure. 66 type dustHandler interface { 67 // getDustSum returns the dust sum on either the local or remote 68 // commitment. An optional fee parameter can be passed in which is used 69 // to calculate the dust sum. 70 getDustSum(whoseCommit lntypes.ChannelParty, 71 fee fn.Option[chainfee.SatPerKWeight]) lnwire.MilliSatoshi 72 73 // getFeeRate returns the current channel feerate. 74 getFeeRate() chainfee.SatPerKWeight 75 76 // getDustClosure returns a closure that can evaluate whether a passed 77 // HTLC is dust. 78 getDustClosure() dustClosure 79 80 // getCommitFee returns the commitment fee in satoshis from either the 81 // local or remote commitment. This does not include dust. 82 getCommitFee(remote bool) btcutil.Amount 83 } 84 85 // scidAliasHandler is an interface that the ChannelLink implements so it can 86 // properly handle option_scid_alias channels. 87 type scidAliasHandler interface { 88 // attachFailAliasUpdate allows the link to properly fail incoming 89 // HTLCs on option_scid_alias channels. 90 attachFailAliasUpdate(failClosure func( 91 sid lnwire.ShortChannelID, 92 incoming bool) *lnwire.ChannelUpdate1) 93 94 // getAliases fetches the link's underlying aliases. This is used by 95 // the Switch to determine whether to forward an HTLC and where to 96 // forward an HTLC. 97 getAliases() []lnwire.ShortChannelID 98 99 // isZeroConf returns whether or not the underlying channel is a 100 // zero-conf channel. 101 isZeroConf() bool 102 103 // negotiatedAliasFeature returns whether the option-scid-alias feature 104 // bit was negotiated. 105 negotiatedAliasFeature() bool 106 107 // confirmedScid returns the confirmed SCID for a zero-conf channel. 108 confirmedScid() lnwire.ShortChannelID 109 110 // zeroConfConfirmed returns whether or not the zero-conf channel has 111 // confirmed. 112 zeroConfConfirmed() bool 113 } 114 115 // ChannelUpdateHandler is an interface that provides methods that allow 116 // sending lnwire.Message to the underlying link as well as querying state. 117 type ChannelUpdateHandler interface { 118 // HandleChannelUpdate handles the htlc requests as settle/add/fail 119 // which sent to us from remote peer we have a channel with. 120 // 121 // NOTE: This function MUST be non-blocking (or block as little as 122 // possible). 123 HandleChannelUpdate(lnwire.Message) 124 125 // ChanID returns the channel ID for the channel link. The channel ID 126 // is a more compact representation of a channel's full outpoint. 127 ChanID() lnwire.ChannelID 128 129 // Bandwidth returns the amount of milli-satoshis which current link 130 // might pass through channel link. The value returned from this method 131 // represents the up to date available flow through the channel. This 132 // takes into account any forwarded but un-cleared HTLC's, and any 133 // HTLC's which have been set to the over flow queue. 134 Bandwidth() lnwire.MilliSatoshi 135 136 // EligibleToForward returns a bool indicating if the channel is able 137 // to actively accept requests to forward HTLC's. A channel may be 138 // active, but not able to forward HTLC's if it hasn't yet finalized 139 // the pre-channel operation protocol with the remote peer. The switch 140 // will use this function in forwarding decisions accordingly. 141 EligibleToForward() bool 142 143 // MayAddOutgoingHtlc returns an error if we may not add an outgoing 144 // htlc to the channel, taking the amount of the htlc to add as a 145 // parameter. 146 MayAddOutgoingHtlc(lnwire.MilliSatoshi) error 147 148 // EnableAdds sets the ChannelUpdateHandler state to allow 149 // UpdateAddHtlc's in the specified direction. It returns true if the 150 // state was changed and false if the desired state was already set 151 // before the method was called. 152 EnableAdds(direction LinkDirection) bool 153 154 // DisableAdds sets the ChannelUpdateHandler state to allow 155 // UpdateAddHtlc's in the specified direction. It returns true if the 156 // state was changed and false if the desired state was already set 157 // before the method was called. 158 DisableAdds(direction LinkDirection) bool 159 160 // IsFlushing returns true when UpdateAddHtlc's are disabled in the 161 // direction of the argument. 162 IsFlushing(direction LinkDirection) bool 163 164 // OnFlushedOnce adds a hook that will be called the next time the 165 // channel state reaches zero htlcs. This hook will only ever be called 166 // once. If the channel state already has zero htlcs, then this will be 167 // called immediately. 168 OnFlushedOnce(func()) 169 170 // OnCommitOnce adds a hook that will be called the next time a 171 // CommitSig message is sent in the argument's LinkDirection. This hook 172 // will only ever be called once. If no CommitSig is owed in the 173 // argument's LinkDirection, then we will call this hook immediately. 174 OnCommitOnce(LinkDirection, func()) 175 176 // InitStfu allows us to initiate quiescence on this link. It returns 177 // a receive only channel that will block until quiescence has been 178 // achieved, or definitively fails. The return value is the 179 // ChannelParty who holds the role of initiator or Err if the operation 180 // fails. 181 // 182 // This operation has been added to allow channels to be quiesced via 183 // RPC. It may be removed or reworked in the future as RPC initiated 184 // quiescence is a holdover until we have downstream protocols that use 185 // it. 186 InitStfu() <-chan fn.Result[lntypes.ChannelParty] 187 } 188 189 // CommitHookID is a value that is used to uniquely identify hooks in the 190 // ChannelUpdateHandler's commitment update lifecycle. You should never need to 191 // construct one of these by hand, nor should you try. 192 type CommitHookID uint64 193 194 // FlushHookID is a value that is used to uniquely identify hooks in the 195 // ChannelUpdateHandler's flush lifecycle. You should never need to construct 196 // one of these by hand, nor should you try. 197 type FlushHookID uint64 198 199 // LinkDirection is used to query and change any link state on a per-direction 200 // basis. 201 type LinkDirection = bool 202 203 const ( 204 // Incoming is the direction from the remote peer to our node. 205 Incoming LinkDirection = false 206 207 // Outgoing is the direction from our node to the remote peer. 208 Outgoing LinkDirection = true 209 ) 210 211 // OptionalBandwidth is a type alias for the result of a bandwidth query that 212 // may return a bandwidth value or fn.None if the bandwidth is not available or 213 // not applicable. IsHandled is set to false if the external traffic shaper does 214 // not handle the channel in question. 215 type OptionalBandwidth struct { 216 // IsHandled is true if the external traffic shaper handles the channel. 217 // If this is false, then the bandwidth value is not applicable. 218 IsHandled bool 219 220 // Bandwidth is the available bandwidth for the channel, as determined 221 // by the external traffic shaper. If the external traffic shaper is not 222 // handling the channel, this value will be fn.None. 223 Bandwidth fn.Option[lnwire.MilliSatoshi] 224 } 225 226 // ChannelLink is an interface which represents the subsystem for managing the 227 // incoming htlc requests, applying the changes to the channel, and also 228 // propagating/forwarding it to htlc switch. 229 // 230 // abstraction level 231 // ^ 232 // | 233 // | - - - - - - - - - - - - Lightning - - - - - - - - - - - - - 234 // | 235 // | (Switch) (Switch) (Switch) 236 // | Alice <-- channel link --> Bob <-- channel link --> Carol 237 // | 238 // | - - - - - - - - - - - - - TCP - - - - - - - - - - - - - - - 239 // | 240 // | (Peer) (Peer) (Peer) 241 // | Alice <----- tcp conn --> Bob <---- tcp conn -----> Carol 242 // | 243 type ChannelLink interface { 244 // TODO(roasbeef): modify interface to embed mail boxes? 245 246 // Embed the packetHandler interface. 247 packetHandler 248 249 // Embed the ChannelUpdateHandler interface. 250 ChannelUpdateHandler 251 252 // Embed the dustHandler interface. 253 dustHandler 254 255 // Embed the scidAliasHandler interface. 256 scidAliasHandler 257 258 // IsUnadvertised returns true if the underlying channel is 259 // unadvertised. 260 IsUnadvertised() bool 261 262 // ChannelPoint returns the channel outpoint for the channel link. 263 ChannelPoint() wire.OutPoint 264 265 // ShortChanID returns the short channel ID for the channel link. The 266 // short channel ID encodes the exact location in the main chain that 267 // the original funding output can be found. 268 ShortChanID() lnwire.ShortChannelID 269 270 // UpdateShortChanID updates the short channel ID for a link. This may 271 // be required in the event that a link is created before the short 272 // chan ID for it is known, or a re-org occurs, and the funding 273 // transaction changes location within the chain. 274 UpdateShortChanID() (lnwire.ShortChannelID, error) 275 276 // UpdateForwardingPolicy updates the forwarding policy for the target 277 // ChannelLink. Once updated, the link will use the new forwarding 278 // policy to govern if it an incoming HTLC should be forwarded or not. 279 UpdateForwardingPolicy(models.ForwardingPolicy) 280 281 // CheckHtlcForward should return a nil error if the passed HTLC details 282 // satisfy the current forwarding policy fo the target link. Otherwise, 283 // a LinkError with a valid protocol failure message should be returned 284 // in order to signal to the source of the HTLC, the policy consistency 285 // issue. 286 CheckHtlcForward(payHash [32]byte, incomingAmt lnwire.MilliSatoshi, 287 amtToForward lnwire.MilliSatoshi, incomingTimeout, 288 outgoingTimeout uint32, inboundFee models.InboundFee, 289 heightNow uint32, scid lnwire.ShortChannelID, 290 customRecords lnwire.CustomRecords) *LinkError 291 292 // CheckHtlcTransit should return a nil error if the passed HTLC details 293 // satisfy the current channel policy. Otherwise, a LinkError with a 294 // valid protocol failure message should be returned in order to signal 295 // the violation. This call is intended to be used for locally initiated 296 // payments for which there is no corresponding incoming htlc. 297 CheckHtlcTransit(payHash [32]byte, amt lnwire.MilliSatoshi, 298 timeout uint32, heightNow uint32, 299 customRecords lnwire.CustomRecords) *LinkError 300 301 // Stats return the statistics of channel link. Number of updates, 302 // total sent/received milli-satoshis. 303 Stats() (uint64, lnwire.MilliSatoshi, lnwire.MilliSatoshi) 304 305 // PeerPubKey returns the serialized public key of remote peer with 306 // which we have the channel link opened. 307 PeerPubKey() [33]byte 308 309 // AttachMailBox delivers an active MailBox to the link. The MailBox may 310 // have buffered messages. 311 AttachMailBox(MailBox) 312 313 // FundingCustomBlob returns the custom funding blob of the channel that 314 // this link is associated with. The funding blob represents static 315 // information about the channel that was created at channel funding 316 // time. 317 FundingCustomBlob() fn.Option[tlv.Blob] 318 319 // CommitmentCustomBlob returns the custom blob of the current local 320 // commitment of the channel that this link is associated with. 321 CommitmentCustomBlob() fn.Option[tlv.Blob] 322 323 // AuxBandwidth returns the bandwidth that can be used for a channel, 324 // expressed in milli-satoshi. This might be different from the regular 325 // BTC bandwidth for custom channels. This will always return fn.None() 326 // for a regular (non-custom) channel. 327 AuxBandwidth(amount lnwire.MilliSatoshi, cid lnwire.ShortChannelID, 328 htlcBlob fn.Option[tlv.Blob], 329 ts AuxTrafficShaper) fn.Result[OptionalBandwidth] 330 331 // Start starts the channel link. 332 Start() error 333 334 // Stop requests the channel link to be shut down. 335 Stop() 336 } 337 338 // ForwardingLog is an interface that represents a time series database which 339 // keep track of all successfully completed payment circuits. Every few 340 // seconds, the switch will collate and flush out all the successful payment 341 // circuits during the last interval. 342 type ForwardingLog interface { 343 // AddForwardingEvents is a method that should write out the set of 344 // forwarding events in a batch to persistent storage. Outside 345 // sub-systems can then query the contents of the log for analysis, 346 // visualizations, etc. 347 AddForwardingEvents([]channeldb.ForwardingEvent) error 348 } 349 350 // TowerClient is the primary interface used by the daemon to backup pre-signed 351 // justice transactions to watchtowers. 352 type TowerClient interface { 353 // RegisterChannel persistently initializes any channel-dependent 354 // parameters within the client. This should be called during link 355 // startup to ensure that the client is able to support the link during 356 // operation. 357 RegisterChannel(lnwire.ChannelID, channeldb.ChannelType) error 358 359 // BackupState initiates a request to back up a particular revoked 360 // state. If the method returns nil, the backup is guaranteed to be 361 // successful unless the justice transaction would create dust outputs 362 // when trying to abide by the negotiated policy. 363 BackupState(chanID *lnwire.ChannelID, stateNum uint64) error 364 } 365 366 // InterceptableHtlcForwarder is the interface to set the interceptor 367 // implementation that intercepts htlc forwards. 368 type InterceptableHtlcForwarder interface { 369 // SetInterceptor sets a ForwardInterceptor. 370 SetInterceptor(interceptor ForwardInterceptor) 371 372 // Resolve resolves an intercepted packet. 373 Resolve(res *FwdResolution) error 374 } 375 376 // ForwardInterceptor is a function that is invoked from the switch for every 377 // incoming htlc that is intended to be forwarded. It is passed with the 378 // InterceptedForward that contains the information about the packet and a way 379 // to resolve it manually later in case it is held. 380 // The return value indicates if this handler will take control of this forward 381 // and resolve it later or let the switch execute its default behavior. 382 type ForwardInterceptor func(InterceptedPacket) error 383 384 // InterceptedPacket contains the relevant information for the interceptor about 385 // an HTLC. 386 type InterceptedPacket struct { 387 // IncomingCircuit contains the incoming channel and htlc id of the 388 // packet. 389 IncomingCircuit models.CircuitKey 390 391 // OutgoingChanID is the destination channel for this packet. 392 OutgoingChanID lnwire.ShortChannelID 393 394 // Hash is the payment hash of the htlc. 395 Hash lntypes.Hash 396 397 // OutgoingExpiry is the absolute block height at which the outgoing 398 // htlc expires. 399 OutgoingExpiry uint32 400 401 // OutgoingAmount is the amount to forward. 402 OutgoingAmount lnwire.MilliSatoshi 403 404 // IncomingExpiry is the absolute block height at which the incoming 405 // htlc expires. 406 IncomingExpiry uint32 407 408 // IncomingAmount is the amount of the accepted htlc. 409 IncomingAmount lnwire.MilliSatoshi 410 411 // InOnionCustomRecords are user-defined records in the custom type 412 // range that were included in the payload. 413 InOnionCustomRecords record.CustomSet 414 415 // OnionBlob is the onion packet for the next hop 416 OnionBlob [lnwire.OnionPacketSize]byte 417 418 // InWireCustomRecords are user-defined p2p wire message records that 419 // were defined by the peer that forwarded this HTLC to us. 420 InWireCustomRecords lnwire.CustomRecords 421 422 // AutoFailHeight is the block height at which this intercept will be 423 // failed back automatically. 424 AutoFailHeight int32 425 } 426 427 // InterceptedForward is passed to the ForwardInterceptor for every forwarded 428 // htlc. It contains all the information about the packet which accordingly 429 // the interceptor decides if to hold or not. 430 // In addition this interface allows a later resolution by calling either 431 // Resume, Settle or Fail. 432 type InterceptedForward interface { 433 // Packet returns the intercepted packet. 434 Packet() InterceptedPacket 435 436 // Resume notifies the intention to resume an existing hold forward. This 437 // basically means the caller wants to resume with the default behavior for 438 // this htlc which usually means forward it. 439 Resume() error 440 441 // ResumeModified notifies the intention to resume an existing hold 442 // forward with modified fields. 443 ResumeModified(inAmountMsat, 444 outAmountMsat fn.Option[lnwire.MilliSatoshi], 445 outWireCustomRecords fn.Option[lnwire.CustomRecords]) error 446 447 // Settle notifies the intention to settle an existing hold 448 // forward with a given preimage. 449 Settle(lntypes.Preimage) error 450 451 // Fail notifies the intention to fail an existing hold forward with an 452 // encrypted failure reason. 453 Fail(reason []byte) error 454 455 // FailWithCode notifies the intention to fail an existing hold forward 456 // with the specified failure code. 457 FailWithCode(code lnwire.FailCode) error 458 } 459 460 // htlcNotifier is an interface which represents the input side of the 461 // HtlcNotifier which htlc events are piped through. This interface is intended 462 // to allow for mocking of the htlcNotifier in tests, so is unexported because 463 // it is not needed outside of the htlcSwitch package. 464 type htlcNotifier interface { 465 // NotifyForwardingEvent notifies the HtlcNotifier than a htlc has been 466 // forwarded. 467 NotifyForwardingEvent(key HtlcKey, info HtlcInfo, 468 eventType HtlcEventType) 469 470 // NotifyLinkFailEvent notifies that a htlc has failed on our 471 // incoming link. It takes an isReceive bool to differentiate between 472 // our node's receives and forwards. 473 NotifyLinkFailEvent(key HtlcKey, info HtlcInfo, 474 eventType HtlcEventType, linkErr *LinkError, incoming bool) 475 476 // NotifyForwardingFailEvent notifies the HtlcNotifier that a htlc we 477 // forwarded has failed down the line. 478 NotifyForwardingFailEvent(key HtlcKey, eventType HtlcEventType) 479 480 // NotifySettleEvent notifies the HtlcNotifier that a htlc that we 481 // committed to as part of a forward or a receive to our node has been 482 // settled. 483 NotifySettleEvent(key HtlcKey, preimage lntypes.Preimage, 484 eventType HtlcEventType) 485 486 // NotifyFinalHtlcEvent notifies the HtlcNotifier that the final outcome 487 // for an htlc has been determined. 488 NotifyFinalHtlcEvent(key models.CircuitKey, 489 info channeldb.FinalHtlcInfo) 490 } 491 492 // AuxHtlcModifier is an interface that allows the sender to modify the outgoing 493 // HTLC of a payment by changing the amount or the wire message tlv records. 494 type AuxHtlcModifier interface { 495 // ProduceHtlcExtraData is a function that, based on the previous extra 496 // data blob of an HTLC, may produce a different blob or modify the 497 // amount of bitcoin this htlc should carry. 498 ProduceHtlcExtraData(totalAmount lnwire.MilliSatoshi, 499 htlcCustomRecords lnwire.CustomRecords, 500 peer route.Vertex) (lnwire.MilliSatoshi, lnwire.CustomRecords, 501 error) 502 } 503 504 // AuxTrafficShaper is an interface that allows the sender to determine if a 505 // payment should be carried by a channel based on the TLV records that may be 506 // present in the `update_add_htlc` message or the channel commitment itself. 507 type AuxTrafficShaper interface { 508 AuxHtlcModifier 509 510 // ShouldHandleTraffic is called in order to check if the channel 511 // identified by the provided channel ID may have external mechanisms 512 // that would allow it to carry out the payment. 513 ShouldHandleTraffic(cid lnwire.ShortChannelID, 514 fundingBlob, htlcBlob fn.Option[tlv.Blob]) (bool, error) 515 516 // PaymentBandwidth returns the available bandwidth for a custom channel 517 // decided by the given channel funding/commitment aux blob and HTLC 518 // blob. A return value of 0 means there is no bandwidth available. To 519 // find out if a channel is a custom channel that should be handled by 520 // the traffic shaper, the ShouldHandleTraffic method should be called 521 // first. 522 PaymentBandwidth(fundingBlob, htlcBlob, 523 commitmentBlob fn.Option[tlv.Blob], 524 linkBandwidth, htlcAmt lnwire.MilliSatoshi, 525 htlcView lnwallet.AuxHtlcView, 526 peer route.Vertex) (lnwire.MilliSatoshi, error) 527 528 // IsCustomHTLC returns true if the HTLC carries the set of relevant 529 // custom records to put it under the purview of the traffic shaper, 530 // meaning that it's from a custom channel. 531 IsCustomHTLC(htlcRecords lnwire.CustomRecords) bool 532 }