Skip to content

Commit de780e8

Browse files
committed
lnwallet: hook up aux signer, add error
1 parent ae36554 commit de780e8

File tree

12 files changed

+161
-35
lines changed

12 files changed

+161
-35
lines changed

chainreg/chainregistry.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,14 @@ type Config struct {
6464
// state.
6565
ChanStateDB *channeldb.ChannelStateDB
6666

67+
// AuxLeafStore is an optional store that can be used to store auxiliary
68+
// leaves for certain custom channel types.
6769
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
6870

71+
// AuxSigner is an optional signer that can be used to sign auxiliary
72+
// leaves for certain custom channel types.
73+
AuxSigner fn.Option[lnwallet.AuxSigner]
74+
6975
// BlockCache is the main cache for storing block information.
7076
BlockCache *blockcache.BlockCache
7177

config_builder.go

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ type DatabaseBuilder interface {
107107
type WalletConfigBuilder interface {
108108
// BuildWalletConfig is responsible for creating or unlocking and then
109109
// fully initializing a wallet.
110-
BuildWalletConfig(context.Context, *DatabaseInstances,
110+
BuildWalletConfig(context.Context, *DatabaseInstances, *AuxComponents,
111111
*rpcperms.InterceptorChain,
112112
[]*ListenerWithSignal) (*chainreg.PartialChainControl,
113113
*btcwallet.Config, func(), error)
@@ -149,15 +149,31 @@ type ImplementationCfg struct {
149149
// implementation.
150150
ChainControlBuilder
151151

152+
// AuxComponents is a set of auxiliary components that can be used by
153+
// lnd for certain custom channel types.
154+
AuxComponents
155+
}
156+
157+
// AuxComponents is a set of auxiliary components that can be used by lnd for
158+
// certain custom channel types.
159+
type AuxComponents struct {
160+
// AuxLeafStore is an optional data source that can be used by custom
161+
// channels to fetch+store various data.
162+
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
163+
152164
// MsgRouter is an optional message router that if set will be used in
153165
// place of a new balnk default message router.
154166
MsgRouter fn.Option[protofsm.MsgRouter]
155167

156168
// AuxFundingController is an optional controller that can be used to
157-
// modify the way we handle certain custom chanenl types. It's also
169+
// modify the way we handle certain custom channel types. It's also
158170
// able to automatically handle new custom protocol messages related to
159171
// the funding process.
160172
AuxFundingController fn.Option[funding.AuxFundingController]
173+
174+
// AuxSigner is an optional signer that can be used to sign auxiliary
175+
// leaves for certain custom channel types.
176+
AuxSigner fn.Option[lnwallet.AuxSigner]
161177
}
162178

163179
// DefaultWalletImpl is the default implementation of our normal, btcwallet
@@ -242,7 +258,8 @@ func (d *DefaultWalletImpl) Permissions() map[string][]bakery.Op {
242258
//
243259
// NOTE: This is part of the WalletConfigBuilder interface.
244260
func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
245-
dbs *DatabaseInstances, interceptorChain *rpcperms.InterceptorChain,
261+
dbs *DatabaseInstances, aux *AuxComponents,
262+
interceptorChain *rpcperms.InterceptorChain,
246263
grpcListeners []*ListenerWithSignal) (*chainreg.PartialChainControl,
247264
*btcwallet.Config, func(), error) {
248265

@@ -561,7 +578,8 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
561578
BtcdMode: d.cfg.BtcdMode,
562579
HeightHintDB: dbs.HeightHintDB,
563580
ChanStateDB: dbs.ChanStateDB.ChannelStateDB(),
564-
AuxLeafStore: dbs.AuxLeafStore,
581+
AuxLeafStore: aux.AuxLeafStore,
582+
AuxSigner: aux.AuxSigner,
565583
NeutrinoCS: neutrinoCS,
566584
ActiveNetParams: d.cfg.ActiveNetParams,
567585
FeeURL: d.cfg.FeeURL,
@@ -621,8 +639,9 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
621639

622640
// proxyBlockEpoch proxies a block epoch subsections to the underlying neutrino
623641
// rebroadcaster client.
624-
func proxyBlockEpoch(notifier chainntnfs.ChainNotifier,
625-
) func() (*blockntfns.Subscription, error) {
642+
func proxyBlockEpoch(
643+
notifier chainntnfs.ChainNotifier) func() (*blockntfns.Subscription,
644+
error) {
626645

627646
return func() (*blockntfns.Subscription, error) {
628647
blockEpoch, err := notifier.RegisterBlockEpochNtfn(
@@ -714,6 +733,7 @@ func (d *DefaultWalletImpl) BuildChainControl(
714733
NetParams: *walletConfig.NetParams,
715734
CoinSelectionStrategy: walletConfig.CoinSelectionStrategy,
716735
AuxLeafStore: partialChainControl.Cfg.AuxLeafStore,
736+
AuxSigner: partialChainControl.Cfg.AuxSigner,
717737
}
718738

719739
// The broadcast is already always active for neutrino nodes, so we
@@ -893,10 +913,6 @@ type DatabaseInstances struct {
893913
// for native SQL queries for tables that already support it. This may
894914
// be nil if the use-native-sql flag was not set.
895915
NativeSQLStore *sqldb.BaseDB
896-
897-
// AuxLeafStore is an optional data source that can be used by custom
898-
// channels to fetch+store various data.
899-
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
900916
}
901917

902918
// DefaultDatabaseBuilder is a type that builds the default database backends

contractcourt/chain_arbitrator.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,13 @@ type ChainArbitratorConfig struct {
218218
// lower package.
219219
QueryIncomingCircuit func(circuit models.CircuitKey) *models.CircuitKey
220220

221+
// AuxLeafStore is an optional store that can be used to store auxiliary
222+
// leaves for certain custom channel types.
221223
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
224+
225+
// AuxSigner is an optional signer that can be used to sign auxiliary
226+
// leaves for certain custom channel types.
227+
AuxSigner fn.Option[lnwallet.AuxSigner]
222228
}
223229

224230
// ChainArbitrator is a sub-system that oversees the on-chain resolution of all
@@ -301,8 +307,16 @@ func (a *arbChannel) NewAnchorResolutions() (*lnwallet.AnchorResolutions,
301307
return nil, err
302308
}
303309

310+
var chanOpts []lnwallet.ChannelOpt
311+
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
312+
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
313+
})
314+
a.c.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
315+
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
316+
})
317+
304318
chanMachine, err := lnwallet.NewLightningChannel(
305-
a.c.cfg.Signer, channel, nil,
319+
a.c.cfg.Signer, channel, nil, chanOpts...,
306320
)
307321
if err != nil {
308322
return nil, err
@@ -350,11 +364,14 @@ func (a *arbChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error)
350364
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
351365
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
352366
})
367+
a.c.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
368+
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
369+
})
353370

354371
// Finally, we'll force close the channel completing
355372
// the force close workflow.
356373
chanMachine, err := lnwallet.NewLightningChannel(
357-
a.c.cfg.Signer, channel, nil,
374+
a.c.cfg.Signer, channel, nil, chanOpts...,
358375
)
359376
if err != nil {
360377
return nil, err

funding/manager.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,13 @@ type Config struct {
548548
// the funding process.
549549
AuxFundingController fn.Option[AuxFundingController]
550550

551+
// AuxLeafStore is an optional store that can be used to store auxiliary
552+
// leaves for certain custom channel types.
551553
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
554+
555+
// AuxSigner is an optional signer that can be used to sign auxiliary
556+
// leaves for certain custom channel types.
557+
AuxSigner fn.Option[lnwallet.AuxSigner]
552558
}
553559

554560
// Manager acts as an orchestrator/bridge between the wallet's
@@ -1078,6 +1084,9 @@ func (f *Manager) advanceFundingState(channel *channeldb.OpenChannel,
10781084
f.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
10791085
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
10801086
})
1087+
f.cfg.AuxSigner.WhenSome(func(s lnwallet.AuxSigner) {
1088+
chanOpts = append(chanOpts, lnwallet.WithAuxSigner(s))
1089+
})
10811090

10821091
// We create the state-machine object which wraps the database state.
10831092
lnChannel, err := lnwallet.NewLightningChannel(

lnd.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -437,7 +437,8 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
437437
defer cleanUp()
438438

439439
partialChainControl, walletConfig, cleanUp, err := implCfg.BuildWalletConfig(
440-
ctx, dbs, interceptorChain, grpcListeners,
440+
ctx, dbs, &implCfg.AuxComponents, interceptorChain,
441+
grpcListeners,
441442
)
442443
if err != nil {
443444
return mkErr("error creating wallet config: %v", err)

lnwallet/aux_signer.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package lnwallet
22

33
import (
4+
"github.com/btcsuite/btcd/wire"
5+
"github.com/lightningnetwork/lnd/channeldb"
46
"github.com/lightningnetwork/lnd/fn"
57
"github.com/lightningnetwork/lnd/input"
68
"github.com/lightningnetwork/lnd/tlv"
@@ -75,6 +77,9 @@ type AuxSigJobResp struct {
7577
// blob
7678
SigBlob fn.Option[tlv.Blob]
7779

80+
// HtlcIndex is the index of the HTLC that was signed.
81+
HtlcIndex uint64
82+
7883
// Err is the error that occurred when executing the specified
7984
// signature job. In the case that no error occurred, this value will
8085
// be nil.
@@ -122,19 +127,24 @@ func NewAuxVerifyJob(sig fn.Option[tlv.Blob], keyRing CommitmentKeyRing,
122127
type AuxSigner interface {
123128
// SubmitSecondLevelSigBatch takes a batch of aux sign jobs and
124129
// processes them asynchronously.
125-
SubmitSecondLevelSigBatch(sigJob []AuxSigJob)
130+
SubmitSecondLevelSigBatch(chanState *channeldb.OpenChannel,
131+
commitTx *wire.MsgTx, sigJob []AuxSigJob) error
126132

127133
// PackSigs takes a series of aux signatures and packs them into a
128134
// single blob that can be sent alongside the CommitSig messages.
129-
PackSigs([]fn.Option[tlv.Blob]) fn.Option[tlv.Blob]
135+
PackSigs(map[input.HtlcIndex]fn.Option[tlv.Blob]) (fn.Option[tlv.Blob],
136+
error)
130137

131138
// UnpackSigs takes a packed blob of signatures and returns the
132139
// original signatures for each HTLC, keyed by HTLC index.
133-
UnpackSigs(fn.Option[tlv.Blob]) map[input.HtlcIndex]fn.Option[tlv.Blob]
140+
UnpackSigs(
141+
fn.Option[tlv.Blob]) (map[input.HtlcIndex]fn.Option[tlv.Blob],
142+
error)
134143

135144
// VerifySecondLevelSigs attemps to synchronously verify a batch of aux
136145
// sig jobs.
137146
//
138147
// TODO(roasbeef): go w/ the same async model?
139-
VerifySecondLevelSigs(verifyJob []AuxVerifyJob) error
148+
VerifySecondLevelSigs(chanState *channeldb.OpenChannel,
149+
commitTx *wire.MsgTx, verifyJob []AuxVerifyJob) error
140150
}

lnwallet/channel.go

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,7 +1462,7 @@ func WithLeafStore(store AuxLeafStore) ChannelOpt {
14621462
}
14631463
}
14641464

1465-
// WithAuxsigner is used to specify a custom aux signer for the channel.
1465+
// WithAuxSigner is used to specify a custom aux signer for the channel.
14661466
func WithAuxSigner(signer AuxSigner) ChannelOpt {
14671467
return func(o *channelOpts) {
14681468
o.auxSigner = fn.Some[AuxSigner](signer)
@@ -3775,7 +3775,8 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
37753775
func (lc *LightningChannel) createCommitDiff(
37763776
newCommit *commitment, commitSig lnwire.Sig,
37773777
htlcSigs []lnwire.Sig,
3778-
auxSigs []fn.Option[tlv.Blob]) (*channeldb.CommitDiff, error) {
3778+
auxSigs map[input.HtlcIndex]fn.Option[tlv.Blob]) (*channeldb.CommitDiff,
3779+
error) {
37793780

37803781
// First, we need to convert the funding outpoint into the ID that's
37813782
// used on the wire to identify this channel. We'll use this shortly
@@ -3898,9 +3899,10 @@ func (lc *LightningChannel) createCommitDiff(
38983899
// disk.
38993900
diskCommit := newCommit.toDiskCommit(false)
39003901

3901-
auxSigBlob := fn.MapOptionZ(lc.auxSigner, func(a AuxSigner) tlv.Blob {
3902-
return a.PackSigs(auxSigs).UnwrapOr(nil)
3903-
})
3902+
auxSigBlob, err := packSigs(auxSigs, lc.auxSigner)
3903+
if err != nil {
3904+
return nil, fmt.Errorf("error packing aux sigs: %w", err)
3905+
}
39043906

39053907
return &channeldb.CommitDiff{
39063908
Commitment: *diskCommit,
@@ -4491,9 +4493,15 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) {
44914493
}
44924494
lc.sigPool.SubmitSignBatch(sigBatch)
44934495

4494-
lc.auxSigner.WhenSome(func(a AuxSigner) {
4495-
a.SubmitSecondLevelSigBatch(auxSigBatch)
4496+
err = fn.MapOptionZ(lc.auxSigner, func(a AuxSigner) error {
4497+
return a.SubmitSecondLevelSigBatch(
4498+
lc.channelState, newCommitView.txn, auxSigBatch,
4499+
)
44964500
})
4501+
if err != nil {
4502+
return nil, fmt.Errorf("error submitting second level sig "+
4503+
"batch: %w", err)
4504+
}
44974505

44984506
// While the jobs are being carried out, we'll Sign their version of
44994507
// the new commitment transaction while we're waiting for the rest of
@@ -4545,7 +4553,9 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) {
45454553
// With the jobs sorted, we'll now iterate through all the responses to
45464554
// gather each of the signatures in order.
45474555
htlcSigs = make([]lnwire.Sig, 0, len(sigBatch))
4548-
auxSigs := make([]fn.Option[tlv.Blob], 0, len(auxSigBatch))
4556+
auxSigs := make(
4557+
map[input.HtlcIndex]fn.Option[tlv.Blob], len(auxSigBatch),
4558+
)
45494559
for i := range sigBatch {
45504560
htlcSigJob := sigBatch[i]
45514561
jobResp := <-htlcSigJob.Resp
@@ -4573,7 +4583,7 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) {
45734583
return nil, auxJobResp.Err
45744584
}
45754585

4576-
auxSigs = append(auxSigs, auxJobResp.SigBlob)
4586+
auxSigs[auxJobResp.HtlcIndex] = auxJobResp.SigBlob
45774587
}
45784588

45794589
// As we're about to proposer a new commitment state for the remote
@@ -5116,11 +5126,11 @@ func genHtlcSigValidationJobs(chanState *channeldb.OpenChannel,
51165126

51175127
// If we have a sig blob, then we'll attempt to map that to individual
51185128
// blobs for each HTLC we might need a signature for.
5119-
auxHtlcSigs := fn.MapOptionZ(auxSigner,
5120-
func(a AuxSigner) map[input.HtlcIndex]fn.Option[tlv.Blob] {
5121-
return a.UnpackSigs(sigBlob)
5122-
},
5123-
)
5129+
auxHtlcSigs, err := unpackSigs(sigBlob, auxSigner)
5130+
if err != nil {
5131+
return nil, nil, fmt.Errorf("error unpacking aux sigs: %w",
5132+
err)
5133+
}
51245134

51255135
// We'll iterate through each output in the commitment transaction,
51265136
// populating the sigHash closure function if it's detected to be an
@@ -5682,7 +5692,9 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSigs *CommitSigs) error {
56825692
// Now that we know all the normal sigs are valid, we'll also verify
56835693
// the aux jobs, if any exist.
56845694
err = fn.MapOptionZ(lc.auxSigner, func(a AuxSigner) error {
5685-
return a.VerifySecondLevelSigs(auxVerifyJobs)
5695+
return a.VerifySecondLevelSigs(
5696+
lc.channelState, localCommitTx, auxVerifyJobs,
5697+
)
56865698
})
56875699
if err != nil {
56885700
return fmt.Errorf("unable to validate aux sigs: %w", err)

lnwallet/commitment.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,37 @@ func updateAuxBlob(chanState *channeldb.OpenChannel,
835835
)
836836
}
837837

838+
// packSigs is a helper function that attempts to pack a series of aux
839+
// signatures and packs them into a single blob that can be sent alongside the
840+
// CommitSig messages.
841+
func packSigs(auxSigs map[input.HtlcIndex]fn.Option[tlv.Blob],
842+
signer fn.Option[AuxSigner]) (tlv.Blob, error) {
843+
844+
if signer.IsNone() {
845+
return nil, nil
846+
}
847+
848+
blobOption, err := signer.UnsafeFromSome().PackSigs(auxSigs)
849+
if err != nil {
850+
return nil, fmt.Errorf("error packing aux sigs: %w", err)
851+
}
852+
853+
return blobOption.UnwrapOr(nil), nil
854+
}
855+
856+
// unpackSigs is a helper function that takes a packed blob of signatures and
857+
// returns the original signatures for each HTLC, keyed by HTLC index.
858+
func unpackSigs(blob fn.Option[tlv.Blob],
859+
signer fn.Option[AuxSigner]) (map[input.HtlcIndex]fn.Option[tlv.Blob],
860+
error) {
861+
862+
if signer.IsNone() {
863+
return nil, nil
864+
}
865+
866+
return signer.UnsafeFromSome().UnpackSigs(blob)
867+
}
868+
838869
// createUnsignedCommitmentTx generates the unsigned commitment transaction for
839870
// a commitment view and returns it as part of the unsignedCommitmentTx. The
840871
// passed in balances should be balances *before* subtracting any commitment

lnwallet/config.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,5 +64,11 @@ type Config struct {
6464
// coins when funding a transaction.
6565
CoinSelectionStrategy wallet.CoinSelectionStrategy
6666

67+
// AuxLeafStore is an optional store that can be used to store auxiliary
68+
// leaves for certain custom channel types.
6769
AuxLeafStore fn.Option[AuxLeafStore]
70+
71+
// AuxSigner is an optional signer that can be used to sign auxiliary
72+
// leaves for certain custom channel types.
73+
AuxSigner fn.Option[AuxSigner]
6874
}

lnwallet/wallet.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,6 +2550,9 @@ func (l *LightningWallet) ValidateChannel(channelState *channeldb.OpenChannel,
25502550
l.Cfg.AuxLeafStore.WhenSome(func(s AuxLeafStore) {
25512551
chanOpts = append(chanOpts, WithLeafStore(s))
25522552
})
2553+
l.Cfg.AuxSigner.WhenSome(func(s AuxSigner) {
2554+
chanOpts = append(chanOpts, WithAuxSigner(s))
2555+
})
25532556

25542557
// First, we'll obtain a fully signed commitment transaction so we can
25552558
// pass into it on the chanvalidate package for verification.

0 commit comments

Comments
 (0)