lnd/lnrpc/invoicesrpc/htlc_modifier.go
2024-10-24 12:59:28 +02:00

88 lines
2.4 KiB
Go

package invoicesrpc
import (
"fmt"
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lnwire"
)
// htlcModifier is a helper struct that handles the lifecycle of an RPC invoice
// HTLC modifier server instance.
//
// This struct handles passing send and receive RPC messages between the client
// and the invoice service.
type htlcModifier struct {
// chainParams is required to properly marshall an invoice for RPC.
chainParams *chaincfg.Params
// serverStream is a bidirectional RPC server stream to send invoices to
// a client and receive accept responses from the client.
serverStream Invoices_HtlcModifierServer
}
// newHtlcModifier creates a new RPC invoice HTLC modifier handler.
func newHtlcModifier(params *chaincfg.Params,
serverStream Invoices_HtlcModifierServer) *htlcModifier {
return &htlcModifier{
chainParams: params,
serverStream: serverStream,
}
}
// onIntercept is called when an invoice HTLC is intercepted by the invoice HTLC
// modifier. This method sends the invoice and the current HTLC to the client.
func (r *htlcModifier) onIntercept(
req invoices.HtlcModifyRequest) (*invoices.HtlcModifyResponse, error) {
// Convert the circuit key to an RPC circuit key.
rpcCircuitKey := &CircuitKey{
ChanId: req.ExitHtlcCircuitKey.ChanID.ToUint64(),
HtlcId: req.ExitHtlcCircuitKey.HtlcID,
}
// Convert the invoice to an RPC invoice.
rpcInvoice, err := CreateRPCInvoice(&req.Invoice, r.chainParams)
if err != nil {
return nil, err
}
// Send the modification request to the client.
err = r.serverStream.Send(&HtlcModifyRequest{
Invoice: rpcInvoice,
ExitHtlcCircuitKey: rpcCircuitKey,
ExitHtlcAmt: uint64(req.ExitHtlcAmt),
ExitHtlcExpiry: req.ExitHtlcExpiry,
CurrentHeight: req.CurrentHeight,
ExitHtlcWireCustomRecords: req.WireCustomRecords,
})
if err != nil {
return nil, err
}
// Then wait for the client to respond.
resp, err := r.serverStream.Recv()
if err != nil {
return nil, err
}
if resp.CircuitKey == nil {
return nil, fmt.Errorf("missing circuit key")
}
log.Tracef("Resolving invoice HTLC modifier response %v", resp)
// Pass the resolution to the modifier.
var amtPaid lnwire.MilliSatoshi
if resp.AmtPaid != nil {
amtPaid = lnwire.MilliSatoshi(*resp.AmtPaid)
}
return &invoices.HtlcModifyResponse{
AmountPaid: amtPaid,
CancelSet: resp.CancelSet,
}, nil
}