diff --git a/go.mod b/go.mod index 429b258..0ecb9d7 100644 --- a/go.mod +++ b/go.mod @@ -7,9 +7,9 @@ require ( github.com/btcsuite/btcd/btcutil/psbt v1.1.8 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb + github.com/btcsuite/btcwallet v0.16.10-0.20240410030101-6fe19a472a62 github.com/btcsuite/btcwallet/wtxmgr v1.5.3 - github.com/lightningnetwork/lnd v0.18.0-beta + github.com/lightningnetwork/lnd v0.18.0-beta.rc3.0.20240604145823-53dbd1ee66d0 github.com/lightningnetwork/lnd/kvdb v1.4.8 github.com/stretchr/testify v1.9.0 google.golang.org/grpc v1.59.0 @@ -95,12 +95,12 @@ require ( github.com/lightninglabs/neutrino/cache v1.1.2 // indirect github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f // indirect github.com/lightningnetwork/lnd/clock v1.1.1 // indirect - github.com/lightningnetwork/lnd/fn v1.0.5 // indirect + github.com/lightningnetwork/lnd/fn v1.0.8 // indirect github.com/lightningnetwork/lnd/healthcheck v1.2.4 // indirect github.com/lightningnetwork/lnd/queue v1.1.1 // indirect github.com/lightningnetwork/lnd/sqldb v1.0.2 // indirect github.com/lightningnetwork/lnd/ticker v1.1.1 // indirect - github.com/lightningnetwork/lnd/tlv v1.2.3 // indirect + github.com/lightningnetwork/lnd/tlv v1.2.6 // indirect github.com/lightningnetwork/lnd/tor v1.1.2 // indirect github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 // indirect github.com/mattn/go-isatty v0.0.20 // indirect diff --git a/go.sum b/go.sum index f816720..09c1d10 100644 --- a/go.sum +++ b/go.sum @@ -83,8 +83,8 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb h1:qoIOlBPRZWtfpcbQlNFf67Wz8ZlXo+mxQc9Pnbm/iqU= -github.com/btcsuite/btcwallet v0.16.10-0.20240404104514-b2f31f9045fb/go.mod h1:2C3Q/MhYAKmk7F+Tey6LfKtKRTdQsrCf8AAAzzDPmH4= +github.com/btcsuite/btcwallet v0.16.10-0.20240410030101-6fe19a472a62 h1:MtcTVTcDbGdTJhfDc7LLikojyl0PYtSRNLwoRaLVbWI= +github.com/btcsuite/btcwallet v0.16.10-0.20240410030101-6fe19a472a62/go.mod h1:2C3Q/MhYAKmk7F+Tey6LfKtKRTdQsrCf8AAAzzDPmH4= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4 h1:poyHFf7+5+RdxNp5r2T6IBRD7RyraUsYARYbp/7t4D8= github.com/btcsuite/btcwallet/wallet/txauthor v1.3.4/go.mod h1:GETGDQuyq+VFfH1S/+/7slLM/9aNa4l7P4ejX6dJfb0= github.com/btcsuite/btcwallet/wallet/txrules v1.2.1 h1:UZo7YRzdHbwhK7Rhv3PO9bXgTxiOH45edK5qdsdiatk= @@ -429,12 +429,12 @@ github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display h1:pRdza2wl github.com/lightninglabs/protobuf-go-hex-display v1.30.0-hex-display/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f h1:Pua7+5TcFEJXIIZ1I2YAUapmbcttmLj4TTi786bIi3s= github.com/lightningnetwork/lightning-onion v1.2.1-0.20230823005744-06182b1d7d2f/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI= -github.com/lightningnetwork/lnd v0.18.0-beta h1:3cH7npkUh156FI5kb6bZbiO+Fl3YD+Bu2UbFKoLZ4lo= -github.com/lightningnetwork/lnd v0.18.0-beta/go.mod h1:1SA9iv9rZddNAcfP38SN9lNSVT1zf5aqmukLUoomjDU= +github.com/lightningnetwork/lnd v0.18.0-beta.rc3.0.20240604145823-53dbd1ee66d0 h1:5AhC7M7KvlFMBmGSdedps2CrsAoB8+rXM3zQ78ovxpw= +github.com/lightningnetwork/lnd v0.18.0-beta.rc3.0.20240604145823-53dbd1ee66d0/go.mod h1:ZZ8c08GgxS6bbtPQv8hPZYB4m2SrhBQJa3N+JgnpR0o= github.com/lightningnetwork/lnd/clock v1.1.1 h1:OfR3/zcJd2RhH0RU+zX/77c0ZiOnIMsDIBjgjWdZgA0= github.com/lightningnetwork/lnd/clock v1.1.1/go.mod h1:mGnAhPyjYZQJmebS7aevElXKTFDuO+uNFFfMXK1W8xQ= -github.com/lightningnetwork/lnd/fn v1.0.5 h1:ffDgMSn83avw6rNzxhbt6w5/2oIrwQKTPGfyaLupZtE= -github.com/lightningnetwork/lnd/fn v1.0.5/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U= +github.com/lightningnetwork/lnd/fn v1.0.8 h1:gwzzcUyeDXVIm5S6KgJ9iCQ9wLQGf367k7O3bn/BEvs= +github.com/lightningnetwork/lnd/fn v1.0.8/go.mod h1:P027+0CyELd92H9gnReUkGGAqbFA1HwjHWdfaDFD51U= github.com/lightningnetwork/lnd/healthcheck v1.2.4 h1:lLPLac+p/TllByxGSlkCwkJlkddqMP5UCoawCj3mgFQ= github.com/lightningnetwork/lnd/healthcheck v1.2.4/go.mod h1:G7Tst2tVvWo7cx6mSBEToQC5L1XOGxzZTPB29g9Rv2I= github.com/lightningnetwork/lnd/kvdb v1.4.8 h1:xH0a5Vi1yrcZ5BEeF2ba3vlKBRxrL9uYXlWTjOjbNTY= @@ -445,8 +445,8 @@ github.com/lightningnetwork/lnd/sqldb v1.0.2 h1:PfuYzScYMD9/QonKo/QvgsbXfTnH5Dfl github.com/lightningnetwork/lnd/sqldb v1.0.2/go.mod h1:V2Xl6JNWLTKE97WJnwfs0d0TYJdIQTqK8/3aAwkd3qI= github.com/lightningnetwork/lnd/ticker v1.1.1 h1:J/b6N2hibFtC7JLV77ULQp++QLtCwT6ijJlbdiZFbSM= github.com/lightningnetwork/lnd/ticker v1.1.1/go.mod h1:waPTRAAcwtu7Ji3+3k+u/xH5GHovTsCoSVpho0KDvdA= -github.com/lightningnetwork/lnd/tlv v1.2.3 h1:If5ibokA/UoCBGuCKaY6Vn2SJU0l9uAbehCnhTZjEP8= -github.com/lightningnetwork/lnd/tlv v1.2.3/go.mod h1:zDkmqxOczP6LaLTvSFDQ1SJUfHcQRCMKFj93dn3eMB8= +github.com/lightningnetwork/lnd/tlv v1.2.6 h1:icvQG2yDr6k3ZuZzfRdG3EJp6pHurcuh3R6dg0gv/Mw= +github.com/lightningnetwork/lnd/tlv v1.2.6/go.mod h1:/CmY4VbItpOldksocmGT4lxiJqRP9oLxwSZOda2kzNQ= github.com/lightningnetwork/lnd/tor v1.1.2 h1:3zv9z/EivNFaMF89v3ciBjCS7kvCj4ZFG7XvD2Qq0/k= github.com/lightningnetwork/lnd/tor v1.1.2/go.mod h1:j7T9uJ2NLMaHwE7GiBGnpYLn4f7NRoTM6qj+ul6/ycA= github.com/ltcsuite/ltcd v0.0.0-20190101042124-f37f8bf35796 h1:sjOGyegMIhvgfq5oaue6Td+hxZuf3tDC8lAPrFldqFw= diff --git a/invoices_client.go b/invoices_client.go index b44af5a..0b93cc8 100644 --- a/invoices_client.go +++ b/invoices_client.go @@ -12,9 +12,33 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnwire" "google.golang.org/grpc" ) +type InvoiceHtlcModifyRequest struct { + Invoice *lnrpc.Invoice + + CircuitKey invpkg.CircuitKey + + ExitHtlcAmt lnwire.MilliSatoshi + + ExitHtlcExpiry uint32 + + CurrentHeight uint32 + + WireCustomRecords lnwire.CustomRecords +} + +type InvoiceHtlcModifyResponse struct { + CircuitKey invpkg.CircuitKey + + AmtPaid lnwire.MilliSatoshi +} + +type InvoiceHtlcModifyHandler func(context.Context, + InvoiceHtlcModifyRequest) (*InvoiceHtlcModifyResponse, error) + // InvoicesClient exposes invoice functionality. type InvoicesClient interface { SubscribeSingleInvoice(ctx context.Context, hash lntypes.Hash) ( @@ -26,6 +50,14 @@ type InvoicesClient interface { AddHoldInvoice(ctx context.Context, in *invoicesrpc.AddInvoiceData) ( string, error) + + // HtlcModifier is a bidirectional streaming RPC that allows a client to + // intercept and modify the HTLCs that attempt to settle the given + // invoice. The server will send HTLCs of invoices to the client and the + // client can modify some aspects of the HTLC in order to pass the + // invoice acceptance tests. + HtlcModifier(ctx context.Context, + handler InvoiceHtlcModifyHandler) error } // InvoiceUpdate contains a state update for an invoice. @@ -38,6 +70,8 @@ type invoicesClient struct { client invoicesrpc.InvoicesClient invoiceMac serializedMacaroon timeout time.Duration + quitOnce sync.Once + quit chan struct{} wg sync.WaitGroup } @@ -48,10 +82,15 @@ func newInvoicesClient(conn grpc.ClientConnInterface, client: invoicesrpc.NewInvoicesClient(conn), invoiceMac: invoiceMac, timeout: timeout, + quit: make(chan struct{}), } } func (s *invoicesClient) WaitForFinished() { + s.quitOnce.Do(func() { + close(s.quit) + }) + s.wg.Wait() } @@ -184,3 +223,143 @@ func fromRPCInvoiceState(state lnrpc.Invoice_InvoiceState) ( return 0, errors.New("unknown state") } + +// HtlcModifier is a bidirectional streaming RPC that allows a client to +// intercept and modify the HTLCs that attempt to settle the given invoice. The +// server will send HTLCs of invoices to the client and the client can modify +// some aspects of the HTLC in order to pass the invoice acceptance tests. +func (s *invoicesClient) HtlcModifier(ctx context.Context, + handler InvoiceHtlcModifyHandler) error { + + // Create a child context that will be canceled when this function + // exits. We use this context to be able to cancel goroutines when we + // exit on errors, because the parent context won't be canceled in that + // case. + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + stream, err := s.client.HtlcModifier( + s.invoiceMac.WithMacaroonAuth(ctx), + ) + if err != nil { + return err + } + + // Create an error channel that we'll send errors on if any of our + // goroutines fail. We buffer by 1 so that the goroutine doesn't depend + // on the stream being read, and select on context cancellation and + // quit channel so that we do not block in the case where we exit with + // multiple errors. + errChan := make(chan error, 1) + + sendErr := func(err error) { + select { + case errChan <- err: + case <-ctx.Done(): + case <-s.quit: + } + } + + // Start a goroutine that consumes interception requests from lnd and + // sends them into our requests channel for handling. The requests + // channel is not buffered because we expect all requests to be handled + // until this function exits, at which point we expect our context to + // be canceled or quit channel to be closed. + requestChan := make(chan InvoiceHtlcModifyRequest) + s.wg.Add(1) + go func() { + defer s.wg.Done() + + for { + // Do a quick check whether our client context has been + // canceled so that we can exit sooner if needed. + if ctx.Err() != nil { + return + } + + req, err := stream.Recv() + if err != nil { + sendErr(err) + return + } + + wireCustomRecords := req.ExitHtlcWireCustomRecords + interceptReq := InvoiceHtlcModifyRequest{ + Invoice: req.Invoice, + CircuitKey: invpkg.CircuitKey{ + ChanID: lnwire.NewShortChanIDFromInt( + req.ExitHtlcCircuitKey.ChanId, + ), + HtlcID: req.ExitHtlcCircuitKey.HtlcId, + }, + ExitHtlcAmt: lnwire.MilliSatoshi( + req.ExitHtlcAmt, + ), + ExitHtlcExpiry: req.ExitHtlcExpiry, + CurrentHeight: req.CurrentHeight, + WireCustomRecords: wireCustomRecords, + } + + // Try to send our interception request, failing on + // context cancel or router exit. + select { + case requestChan <- interceptReq: + + case <-s.quit: + sendErr(ErrRouterShuttingDown) + return + + case <-ctx.Done(): + sendErr(ctx.Err()) + return + } + } + }() + + for { + select { + case request := <-requestChan: + // Handle requests in a goroutine so that the handler + // provided to this function can be blocking. If we + // get an error, send it into our error channel to + // shut down the interceptor. + s.wg.Add(1) + go func() { + defer s.wg.Done() + + // Get a response from handler, this may block + // for a while. + resp, err := handler(ctx, request) + if err != nil { + sendErr(err) + return + } + + key := resp.CircuitKey + rpcResp := &invoicesrpc.HtlcModifyResponse{ + CircuitKey: &invoicesrpc.CircuitKey{ + ChanId: key.ChanID.ToUint64(), + HtlcId: key.HtlcID, + }, + AmtPaid: uint64(resp.AmtPaid), + } + + if err := stream.Send(rpcResp); err != nil { + sendErr(err) + return + } + }() + + // If one of our goroutines fails, exit with the error that + // occurred. + case err := <-errChan: + return err + + case <-s.quit: + return ErrRouterShuttingDown + + case <-ctx.Done(): + return ctx.Err() + } + } +} diff --git a/lightning_client.go b/lightning_client.go index 8460f24..3ca22b5 100644 --- a/lightning_client.go +++ b/lightning_client.go @@ -424,6 +424,10 @@ type ChannelInfo struct { // AliasScids contains a list of alias short channel identifiers that // may be used for this channel. This array can be empty. AliasScids []uint64 + + // CustomChannelData is an optional field that can be used to store + // data for custom channels. + CustomChannelData []byte } func (s *lightningClient) newChannelInfo(channel *lnrpc.Channel) (*ChannelInfo, @@ -465,8 +469,9 @@ func (s *lightningClient) newChannelInfo(channel *lnrpc.Channel) (*ChannelInfo, RemoteConstraints: newChannelConstraint( channel.RemoteConstraints, ), - ZeroConf: channel.ZeroConf, - ZeroConfScid: channel.ZeroConfConfirmedScid, + ZeroConf: channel.ZeroConf, + ZeroConfScid: channel.ZeroConfConfirmedScid, + CustomChannelData: channel.CustomChannelData, } chanInfo.AliasScids = make([]uint64, len(channel.AliasScids)) @@ -834,6 +839,10 @@ type ChannelBalance struct { // PendingBalance is the sum of all pending channel balances. PendingBalance btcutil.Amount + + // CustomChannelData is an optional field that can be used to store + // data for custom channels. + CustomChannelData []byte } // Node describes a node in the network. @@ -3422,8 +3431,11 @@ func (s *lightningClient) ChannelBalance(ctx context.Context) (*ChannelBalance, } return &ChannelBalance{ - Balance: btcutil.Amount(resp.Balance), // nolint:staticcheck - PendingBalance: btcutil.Amount(resp.PendingOpenBalance), // nolint:staticcheck + //nolint:staticcheck + Balance: btcutil.Amount(resp.Balance), + //nolint:staticcheck + PendingBalance: btcutil.Amount(resp.PendingOpenBalance), + CustomChannelData: resp.CustomChannelData, }, nil } diff --git a/lnd_services.go b/lnd_services.go index d1a573c..40a6c66 100644 --- a/lnd_services.go +++ b/lnd_services.go @@ -152,6 +152,10 @@ type LndServicesConfig struct { // calls to lnd. If this value is not set, it will default to 30 // seconds. RPCTimeout time.Duration + + // ChainSyncPollInterval is the interval in which we poll the GetInfo + // call to find out if lnd is fully synced to its chain backend. + ChainSyncPollInterval time.Duration } // DialerFunc is a function that is used as grpc.WithContextDialer(). @@ -285,7 +289,8 @@ func NewLndServices(cfg *LndServicesConfig) (*GrpcLndServices, error) { readonlyMac = serializedMacaroon(cfg.CustomMacaroonHex) } else { readonlyMac, err = loadMacaroon( - macaroonDir, string(ReadOnlyServiceMac), cfg.CustomMacaroonPath, + macaroonDir, string(ReadOnlyServiceMac), + cfg.CustomMacaroonPath, ) if err != nil { return nil, err @@ -297,6 +302,10 @@ func NewLndServices(cfg *LndServicesConfig) (*GrpcLndServices, error) { timeout = cfg.RPCTimeout } + if cfg.ChainSyncPollInterval == 0 { + cfg.ChainSyncPollInterval = chainSyncPollInterval + } + basicClient := lnrpc.NewLightningClient(conn) stateClient := newStateClient(conn, readonlyMac) versionerClient := newVersionerClient(conn, readonlyMac, timeout) @@ -413,7 +422,9 @@ func NewLndServices(cfg *LndServicesConfig) (*GrpcLndServices, error) { log.Infof("Waiting for lnd to be fully synced to its chain " + "backend, this might take a while") - err := services.waitForChainSync(cfg.CallerCtx, timeout) + err := services.waitForChainSync( + cfg.CallerCtx, timeout, cfg.ChainSyncPollInterval, + ) if err != nil { cleanup() return nil, fmt.Errorf("error waiting for chain to "+ @@ -453,7 +464,7 @@ func (s *GrpcLndServices) Close() { // synced to its chain backend. This could theoretically take hours if the // initial block download is still in progress. func (s *GrpcLndServices) waitForChainSync(ctx context.Context, - timeout time.Duration) error { + timeout, pollInterval time.Duration) error { mainCtx := ctx if mainCtx == nil { @@ -488,7 +499,7 @@ func (s *GrpcLndServices) waitForChainSync(ctx context.Context, select { // If we're not yet done, let's now wait a few seconds. - case <-time.After(chainSyncPollInterval): + case <-time.After(pollInterval): // If the user cancels the context, we should also // abort the wait. diff --git a/router_client.go b/router_client.go index 5cc841d..74fed92 100644 --- a/router_client.go +++ b/router_client.go @@ -73,6 +73,20 @@ type RouterClient interface { // (enabled, disabled, or auto). UpdateChanStatus(ctx context.Context, channel *wire.OutPoint, action routerrpc.ChanStatusAction) error + + // XAddLocalChanAlias is an experimental method that allows the caller + // to add a local channel alias to the router. This is only a locally + // stored alias, and will not be communicated to the channel peer via + // any message. Therefore, routing over such an alias will only work if + // the peer also calls this same RPC on their end. + XAddLocalChanAlias(ctx context.Context, alias, + baseScid lnwire.ShortChannelID) error + + // XDeleteLocalChanAlias is an experimental method that allows the + // caller to remove a local channel alias in the router. The deletion + // will not be communicated to the channel peer via any message. + XDeleteLocalChanAlias(ctx context.Context, alias, + baseScid lnwire.ShortChannelID) error } // PaymentStatus describe the state of a payment. @@ -319,6 +333,10 @@ type InterceptedHtlc struct { // OnionBlob is the onion blob for the next hop. OnionBlob []byte + + // WireCustomRecords are custom records sent by the sender that were + // only present in the wire message and not the onion itself. + WireCustomRecords map[uint64][]byte } // HtlcInterceptHandler is a function signature for handling code for htlc @@ -342,6 +360,10 @@ const ( // InterceptorActionResume indicates that an intercepted hltc should be // resumed as normal. InterceptorActionResume + + // InterceptorActionResumeModified indicates that an intercepted hltc + // should be resumed as normal, but with modifications. + InterceptorActionResumeModified ) // InterceptedHtlcResponse contains the actions that must be taken for an @@ -354,6 +376,19 @@ type InterceptedHtlcResponse struct { // Action is the action that should be taken for the htlc that is // intercepted. Action InterceptorAction + + // IncomingAmount is the amount that should be used to validate the + // incoming htlc. This might be different from the actual HTLC amount + // for custom channels. + IncomingAmount lnwire.MilliSatoshi + + // OutgoingAmount is the amount that should be set on the HTLC that is + // forwarded. + OutgoingAmount lnwire.MilliSatoshi + + // CustomRecords are the custom records that should be added to the + // outgoing/forwarded HTLC. + CustomRecords map[uint64][]byte } // routerClient is a wrapper around the generated routerrpc proxy. @@ -771,6 +806,7 @@ func (r *routerClient) InterceptHtlcs(ctx context.Context, chanOut := lnwire.NewShortChanIDFromInt( request.OutgoingRequestedChanId, ) + customRecords := request.IncomingHtlcWireCustomRecords req := InterceptedHtlc{ IncomingCircuitKey: invpkg.CircuitKey{ @@ -789,6 +825,7 @@ func (r *routerClient) InterceptHtlcs(ctx context.Context, OutgoingChannelID: chanOut, CustomRecords: request.CustomRecords, OnionBlob: request.OnionBlob, + WireCustomRecords: customRecords, } // Try to send our interception request, failing on @@ -888,6 +925,13 @@ func rpcInterceptorResponse(request InterceptedHtlc, case InterceptorActionResume: rpcResp.Action = routerrpc.ResolveHoldForwardAction_RESUME + case InterceptorActionResumeModified: + rpcResp.Action = routerrpc.ResolveHoldForwardAction_RESUME_MODIFIED + + rpcResp.IncomingAmountMsat = uint64(response.IncomingAmount) + rpcResp.OutgoingAmountMsat = uint64(response.OutgoingAmount) + rpcResp.OutgoingHtlcWireCustomRecords = response.CustomRecords + default: return nil, fmt.Errorf("unknown action: %v", response.Action) } @@ -1050,3 +1094,55 @@ func (r *routerClient) UpdateChanStatus(ctx context.Context, ) return err } + +// XAddLocalChanAlias is an experimental method that allows the caller +// to add a local channel alias to the router. This is only a locally +// stored alias, and will not be communicated to the channel peer via +// any message. Therefore, routing over such an alias will only work if +// the peer also calls this same RPC on their end. +func (r *routerClient) XAddLocalChanAlias(ctx context.Context, alias, + baseScid lnwire.ShortChannelID) error { + + rpcCtx, cancel := context.WithTimeout(ctx, r.timeout) + defer cancel() + + _, err := r.client.XAddLocalChanAliases( + r.routerKitMac.WithMacaroonAuth(rpcCtx), + &routerrpc.AddAliasesRequest{ + AliasMaps: []*lnrpc.AliasMap{ + { + BaseScid: baseScid.ToUint64(), + Aliases: []uint64{ + alias.ToUint64(), + }, + }, + }, + }, + ) + return err +} + +// XDeleteLocalChanAlias is an experimental method that allows the +// caller to remove a local channel alias in the router. The deletion +// will not be communicated to the channel peer via any message. +func (r *routerClient) XDeleteLocalChanAlias(ctx context.Context, alias, + baseScid lnwire.ShortChannelID) error { + + rpcCtx, cancel := context.WithTimeout(ctx, r.timeout) + defer cancel() + + _, err := r.client.XDeleteLocalChanAliases( + r.routerKitMac.WithMacaroonAuth(rpcCtx), + &routerrpc.DeleteAliasesRequest{ + AliasMaps: []*lnrpc.AliasMap{ + { + BaseScid: baseScid.ToUint64(), + Aliases: []uint64{ + alias.ToUint64(), + }, + }, + }, + }, + ) + return err +} diff --git a/testdata/permissions.json b/testdata/permissions.json index e3cc55b..d385379 100644 --- a/testdata/permissions.json +++ b/testdata/permissions.json @@ -144,6 +144,14 @@ } ] }, + "/invoicesrpc.Invoices/HtlcModifier": { + "permissions": [ + { + "entity": "invoices", + "action": "write" + } + ] + }, "/lnrpc.Lightning/AbandonChannel": { "permissions": [ { @@ -880,6 +888,22 @@ } ] }, + "/routerrpc.Router/XAddLocalChanAlias": { + "permissions": [ + { + "entity": "offchain", + "action": "write" + } + ] + }, + "/routerrpc.Router/XDeleteLocalChanAlias": { + "permissions": [ + { + "entity": "offchain", + "action": "write" + } + ] + }, "/signrpc.Signer/ComputeInputScript": { "permissions": [ {