Skip to content

Commit d37df75

Browse files
committed
lnrpc+rpcserver: encode custom records as custom channel data
With this commit we encode the custom records as a TLV stream into the custom channel data field of the invoice HTLC. This allows the custom data parser to parse those records and replace it with human-readable JSON on the RPC interface.
1 parent bbae714 commit d37df75

File tree

9 files changed

+144
-5
lines changed

9 files changed

+144
-5
lines changed

lnrpc/invoicesrpc/config_active.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/lightningnetwork/lnd/lnwire"
1111
"github.com/lightningnetwork/lnd/macaroons"
1212
"github.com/lightningnetwork/lnd/netann"
13+
"google.golang.org/protobuf/proto"
1314
)
1415

1516
// Config is the primary configuration struct for the invoices RPC server. It
@@ -69,4 +70,8 @@ type Config struct {
6970
// GetAlias returns the peer's alias SCID if it exists given the
7071
// 32-byte ChannelID.
7172
GetAlias func(lnwire.ChannelID) (lnwire.ShortChannelID, error)
73+
74+
// ParseAuxData is a function that can be used to parse the auxiliary
75+
// data from the invoice.
76+
ParseAuxData func(message proto.Message) error
7277
}

lnrpc/invoicesrpc/invoices.swagger.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,11 @@
784784
"amp": {
785785
"$ref": "#/definitions/lnrpcAMP",
786786
"description": "Details relevant to AMP HTLCs, only populated if this is an AMP HTLC."
787+
},
788+
"custom_channel_data": {
789+
"type": "string",
790+
"format": "byte",
791+
"description": "Custom channel data that might be populated in custom channels."
787792
}
788793
},
789794
"title": "Details of an HTLC that paid to an invoice"

lnrpc/invoicesrpc/invoices_server.go

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,9 @@ func (r *ServerShell) RegisterWithRestServer(ctx context.Context,
222222
// methods routed towards it.
223223
//
224224
// NOTE: This is part of the lnrpc.GrpcHandler interface.
225-
func (r *ServerShell) CreateSubServer(configRegistry lnrpc.SubServerConfigDispatcher) (
226-
lnrpc.SubServer, lnrpc.MacaroonPerms, error) {
225+
func (r *ServerShell) CreateSubServer(
226+
configRegistry lnrpc.SubServerConfigDispatcher) (lnrpc.SubServer,
227+
lnrpc.MacaroonPerms, error) {
227228

228229
subServer, macPermissions, err := createNewSubServer(configRegistry)
229230
if err != nil {
@@ -264,6 +265,14 @@ func (s *Server) SubscribeSingleInvoice(req *SubscribeSingleInvoiceRequest,
264265
return err
265266
}
266267

268+
// Give the aux data parser a chance to format the
269+
// custom data in the invoice HTLCs.
270+
err = s.cfg.ParseAuxData(rpcInvoice)
271+
if err != nil {
272+
return fmt.Errorf("error parsing custom data: "+
273+
"%w", err)
274+
}
275+
267276
if err := updateStream.Send(rpcInvoice); err != nil {
268277
return err
269278
}
@@ -451,7 +460,19 @@ func (s *Server) LookupInvoiceV2(ctx context.Context,
451460
return nil, err
452461
}
453462

454-
return CreateRPCInvoice(&invoice, s.cfg.ChainParams)
463+
rpcInvoice, err := CreateRPCInvoice(&invoice, s.cfg.ChainParams)
464+
if err != nil {
465+
return nil, err
466+
}
467+
468+
// Give the aux data parser a chance to format the custom data in the
469+
// invoice HTLCs.
470+
err = s.cfg.ParseAuxData(rpcInvoice)
471+
if err != nil {
472+
return nil, fmt.Errorf("error parsing custom data: %w", err)
473+
}
474+
475+
return rpcInvoice, nil
455476
}
456477

457478
// HtlcModifier is a bidirectional streaming RPC that allows a client to

lnrpc/invoicesrpc/utils.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ func CreateRPCInvoice(invoice *invoices.Invoice,
123123
MppTotalAmtMsat: uint64(htlc.MppTotalAmt),
124124
}
125125

126+
// The custom channel data is currently just the raw bytes of
127+
// the encoded custom records.
128+
customData, err := lnwire.CustomRecords(
129+
htlc.CustomRecords,
130+
).Serialize()
131+
if err != nil {
132+
return nil, err
133+
}
134+
rpcHtlc.CustomChannelData = customData
135+
126136
// Populate any fields relevant to AMP payments.
127137
if htlc.AMP != nil {
128138
rootShare := htlc.AMP.Record.RootShare()

lnrpc/lightning.pb.go

Lines changed: 13 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lnrpc/lightning.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3952,6 +3952,11 @@ message InvoiceHTLC {
39523952

39533953
// Details relevant to AMP HTLCs, only populated if this is an AMP HTLC.
39543954
AMP amp = 11;
3955+
3956+
/*
3957+
Custom channel data that might be populated in custom channels.
3958+
*/
3959+
bytes custom_channel_data = 12;
39553960
}
39563961

39573962
// Details specific to AMP HTLCs.

lnrpc/lightning.swagger.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5602,6 +5602,11 @@
56025602
"amp": {
56035603
"$ref": "#/definitions/lnrpcAMP",
56045604
"description": "Details relevant to AMP HTLCs, only populated if this is an AMP HTLC."
5605+
},
5606+
"custom_channel_data": {
5607+
"type": "string",
5608+
"format": "byte",
5609+
"description": "Custom channel data that might be populated in custom channels."
56055610
}
56065611
},
56075612
"title": "Details of an HTLC that paid to an invoice"

rpcserver.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,8 @@ func (r *rpcServer) addDeps(s *server, macService *macaroons.Service,
788788
s.sweeper, tower, s.towerClientMgr, r.cfg.net.ResolveTCPAddr,
789789
genInvoiceFeatures, genAmpInvoiceFeatures,
790790
s.getNodeAnnouncement, s.updateAndBrodcastSelfNode, parseAddr,
791-
rpcsLog, s.aliasMgr, invoiceHtlcModifier,
791+
rpcsLog, s.aliasMgr, r.implCfg.AuxDataParser,
792+
invoiceHtlcModifier,
792793
)
793794
if err != nil {
794795
return err
@@ -6117,6 +6118,19 @@ func (r *rpcServer) LookupInvoice(ctx context.Context,
61176118
return nil, err
61186119
}
61196120

6121+
// Give the aux data parser a chance to format the custom data in the
6122+
// invoice HTLCs.
6123+
err = fn.MapOptionZ(
6124+
r.server.implCfg.AuxDataParser,
6125+
func(parser AuxDataParser) error {
6126+
return parser.InlineParseCustomData(rpcInvoice)
6127+
},
6128+
)
6129+
if err != nil {
6130+
return nil, fmt.Errorf("error parsing custom data: %w",
6131+
err)
6132+
}
6133+
61206134
return rpcInvoice, nil
61216135
}
61226136

@@ -6172,6 +6186,21 @@ func (r *rpcServer) ListInvoices(ctx context.Context,
61726186
if err != nil {
61736187
return nil, err
61746188
}
6189+
6190+
// Give the aux data parser a chance to format the custom data
6191+
// in the invoice HTLCs.
6192+
err = fn.MapOptionZ(
6193+
r.server.implCfg.AuxDataParser,
6194+
func(parser AuxDataParser) error {
6195+
return parser.InlineParseCustomData(
6196+
resp.Invoices[i],
6197+
)
6198+
},
6199+
)
6200+
if err != nil {
6201+
return nil, fmt.Errorf("error parsing custom data: %w",
6202+
err)
6203+
}
61756204
}
61766205

61776206
return resp, nil
@@ -6200,6 +6229,21 @@ func (r *rpcServer) SubscribeInvoices(req *lnrpc.InvoiceSubscription,
62006229
return err
62016230
}
62026231

6232+
// Give the aux data parser a chance to format the
6233+
// custom data in the invoice HTLCs.
6234+
err = fn.MapOptionZ(
6235+
r.server.implCfg.AuxDataParser,
6236+
func(parser AuxDataParser) error {
6237+
return parser.InlineParseCustomData(
6238+
rpcInvoice,
6239+
)
6240+
},
6241+
)
6242+
if err != nil {
6243+
return fmt.Errorf("error parsing custom data: "+
6244+
"%w", err)
6245+
}
6246+
62036247
if err := updateStream.Send(rpcInvoice); err != nil {
62046248
return err
62056249
}
@@ -6212,6 +6256,21 @@ func (r *rpcServer) SubscribeInvoices(req *lnrpc.InvoiceSubscription,
62126256
return err
62136257
}
62146258

6259+
// Give the aux data parser a chance to format the
6260+
// custom data in the invoice HTLCs.
6261+
err = fn.MapOptionZ(
6262+
r.server.implCfg.AuxDataParser,
6263+
func(parser AuxDataParser) error {
6264+
return parser.InlineParseCustomData(
6265+
rpcInvoice,
6266+
)
6267+
},
6268+
)
6269+
if err != nil {
6270+
return fmt.Errorf("error parsing custom data: "+
6271+
"%w", err)
6272+
}
6273+
62156274
if err := updateStream.Send(rpcInvoice); err != nil {
62166275
return err
62176276
}

subrpcserver_config.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/lightningnetwork/lnd/autopilot"
1212
"github.com/lightningnetwork/lnd/chainreg"
1313
"github.com/lightningnetwork/lnd/channeldb"
14+
"github.com/lightningnetwork/lnd/fn"
1415
"github.com/lightningnetwork/lnd/htlcswitch"
1516
"github.com/lightningnetwork/lnd/invoices"
1617
"github.com/lightningnetwork/lnd/lncfg"
@@ -32,6 +33,7 @@ import (
3233
"github.com/lightningnetwork/lnd/sweep"
3334
"github.com/lightningnetwork/lnd/watchtower"
3435
"github.com/lightningnetwork/lnd/watchtower/wtclient"
36+
"google.golang.org/protobuf/proto"
3537
)
3638

3739
// subRPCServerConfigs is special sub-config in the main configuration that
@@ -123,6 +125,7 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
123125
modifiers ...netann.NodeAnnModifier) error,
124126
parseAddr func(addr string) (net.Addr, error),
125127
rpcLogger btclog.Logger, aliasMgr *aliasmgr.Manager,
128+
auxDataParser fn.Option[AuxDataParser],
126129
invoiceHtlcModifier *invoices.HtlcModificationInterceptor) error {
127130

128131
// First, we'll use reflect to obtain a version of the config struct
@@ -274,6 +277,20 @@ func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config,
274277
reflect.ValueOf(aliasMgr.GetPeerAlias),
275278
)
276279

280+
parseAuxData := func(m proto.Message) error {
281+
return fn.MapOptionZ(
282+
auxDataParser,
283+
func(p AuxDataParser) error {
284+
return p.InlineParseCustomData(
285+
m,
286+
)
287+
},
288+
)
289+
}
290+
subCfgValue.FieldByName("ParseAuxData").Set(
291+
reflect.ValueOf(parseAuxData),
292+
)
293+
277294
case *neutrinorpc.Config:
278295
subCfgValue := extractReflectValue(subCfg)
279296

0 commit comments

Comments
 (0)