Skip to content

Commit 9f4677d

Browse files
Roasbeefguggero
authored andcommitted
lnwallet: thread thru input.AuxTapleaf to all relevant areas
In this commit, we start to thread thru the new aux tap leaf structures to all relevant areas. This includes: commitment outputs, resolution creation, breach handling, and also HTLC scripts. Given the aux leaf store, and a struct that describes the current commitment, we can obtain the CommitAuxLeaves struct, then use that to derive the aux leaves for the commitment outputs and also HTLCs as well. When restoring commitments and pay descs from disk, we'll store the aux leaves as custom TLV blobs on disk, then use the aux leaf store to map back to the concrete aux leaves when needed.
1 parent b199e9b commit 9f4677d

File tree

16 files changed

+444
-114
lines changed

16 files changed

+444
-114
lines changed

chainreg/chainregistry.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify"
2525
"github.com/lightningnetwork/lnd/channeldb"
2626
"github.com/lightningnetwork/lnd/channeldb/models"
27+
"github.com/lightningnetwork/lnd/fn"
2728
"github.com/lightningnetwork/lnd/input"
2829
"github.com/lightningnetwork/lnd/keychain"
2930
"github.com/lightningnetwork/lnd/kvdb"
@@ -63,6 +64,10 @@ type Config struct {
6364
// state.
6465
ChanStateDB *channeldb.ChannelStateDB
6566

67+
// AuxLeafStore is an optional store that can be used to store auxiliary
68+
// leaves for certain custom channel types.
69+
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
70+
6671
// BlockCache is the main cache for storing block information.
6772
BlockCache *blockcache.BlockCache
6873

config_builder.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/lightningnetwork/lnd/chainreg"
3535
"github.com/lightningnetwork/lnd/channeldb"
3636
"github.com/lightningnetwork/lnd/clock"
37+
"github.com/lightningnetwork/lnd/fn"
3738
"github.com/lightningnetwork/lnd/invoices"
3839
"github.com/lightningnetwork/lnd/keychain"
3940
"github.com/lightningnetwork/lnd/kvdb"
@@ -104,7 +105,7 @@ type DatabaseBuilder interface {
104105
type WalletConfigBuilder interface {
105106
// BuildWalletConfig is responsible for creating or unlocking and then
106107
// fully initializing a wallet.
107-
BuildWalletConfig(context.Context, *DatabaseInstances,
108+
BuildWalletConfig(context.Context, *DatabaseInstances, *AuxComponents,
108109
*rpcperms.InterceptorChain,
109110
[]*ListenerWithSignal) (*chainreg.PartialChainControl,
110111
*btcwallet.Config, func(), error)
@@ -145,6 +146,17 @@ type ImplementationCfg struct {
145146
// ChainControlBuilder is a type that can provide a custom wallet
146147
// implementation.
147148
ChainControlBuilder
149+
// AuxComponents is a set of auxiliary components that can be used by
150+
// lnd for certain custom channel types.
151+
AuxComponents
152+
}
153+
154+
// AuxComponents is a set of auxiliary components that can be used by lnd for
155+
// certain custom channel types.
156+
type AuxComponents struct {
157+
// AuxLeafStore is an optional data source that can be used by custom
158+
// channels to fetch+store various data.
159+
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
148160
}
149161

150162
// DefaultWalletImpl is the default implementation of our normal, btcwallet
@@ -229,7 +241,8 @@ func (d *DefaultWalletImpl) Permissions() map[string][]bakery.Op {
229241
//
230242
// NOTE: This is part of the WalletConfigBuilder interface.
231243
func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
232-
dbs *DatabaseInstances, interceptorChain *rpcperms.InterceptorChain,
244+
dbs *DatabaseInstances, aux *AuxComponents,
245+
interceptorChain *rpcperms.InterceptorChain,
233246
grpcListeners []*ListenerWithSignal) (*chainreg.PartialChainControl,
234247
*btcwallet.Config, func(), error) {
235248

@@ -549,6 +562,7 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
549562
HeightHintDB: dbs.HeightHintDB,
550563
ChanStateDB: dbs.ChanStateDB.ChannelStateDB(),
551564
NeutrinoCS: neutrinoCS,
565+
AuxLeafStore: aux.AuxLeafStore,
552566
ActiveNetParams: d.cfg.ActiveNetParams,
553567
FeeURL: d.cfg.FeeURL,
554568
Dialer: func(addr string) (net.Conn, error) {
@@ -607,8 +621,9 @@ func (d *DefaultWalletImpl) BuildWalletConfig(ctx context.Context,
607621

608622
// proxyBlockEpoch proxies a block epoch subsections to the underlying neutrino
609623
// rebroadcaster client.
610-
func proxyBlockEpoch(notifier chainntnfs.ChainNotifier,
611-
) func() (*blockntfns.Subscription, error) {
624+
func proxyBlockEpoch(
625+
notifier chainntnfs.ChainNotifier) func() (*blockntfns.Subscription,
626+
error) {
612627

613628
return func() (*blockntfns.Subscription, error) {
614629
blockEpoch, err := notifier.RegisterBlockEpochNtfn(
@@ -699,6 +714,7 @@ func (d *DefaultWalletImpl) BuildChainControl(
699714
ChainIO: walletController,
700715
NetParams: *walletConfig.NetParams,
701716
CoinSelectionStrategy: walletConfig.CoinSelectionStrategy,
717+
AuxLeafStore: partialChainControl.Cfg.AuxLeafStore,
702718
}
703719

704720
// The broadcast is already always active for neutrino nodes, so we
@@ -878,6 +894,10 @@ type DatabaseInstances struct {
878894
// for native SQL queries for tables that already support it. This may
879895
// be nil if the use-native-sql flag was not set.
880896
NativeSQLStore *sqldb.BaseDB
897+
898+
// AuxLeafStore is an optional data source that can be used by custom
899+
// channels to fetch+store various data.
900+
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
881901
}
882902

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

contractcourt/breach_arbitrator_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/go-errors/errors"
2323
"github.com/lightningnetwork/lnd/chainntnfs"
2424
"github.com/lightningnetwork/lnd/channeldb"
25+
"github.com/lightningnetwork/lnd/fn"
2526
"github.com/lightningnetwork/lnd/input"
2627
"github.com/lightningnetwork/lnd/keychain"
2728
"github.com/lightningnetwork/lnd/lntest/channels"
@@ -1590,6 +1591,7 @@ func testBreachSpends(t *testing.T, test breachTest) {
15901591
// Notify the breach arbiter about the breach.
15911592
retribution, err := lnwallet.NewBreachRetribution(
15921593
alice.State(), height, 1, forceCloseTx,
1594+
fn.None[lnwallet.AuxLeafStore](),
15931595
)
15941596
require.NoError(t, err, "unable to create breach retribution")
15951597

@@ -1799,6 +1801,7 @@ func TestBreachDelayedJusticeConfirmation(t *testing.T) {
17991801
// Notify the breach arbiter about the breach.
18001802
retribution, err := lnwallet.NewBreachRetribution(
18011803
alice.State(), height, uint32(blockHeight), forceCloseTx,
1804+
fn.None[lnwallet.AuxLeafStore](),
18021805
)
18031806
require.NoError(t, err, "unable to create breach retribution")
18041807

contractcourt/chain_arbitrator.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,10 @@ type ChainArbitratorConfig struct {
217217
// meanwhile, turn `PaymentCircuit` into an interface or bring it to a
218218
// lower package.
219219
QueryIncomingCircuit func(circuit models.CircuitKey) *models.CircuitKey
220+
221+
// AuxLeafStore is an optional store that can be used to store auxiliary
222+
// leaves for certain custom channel types.
223+
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
220224
}
221225

222226
// ChainArbitrator is a sub-system that oversees the on-chain resolution of all
@@ -299,8 +303,13 @@ func (a *arbChannel) NewAnchorResolutions() (*lnwallet.AnchorResolutions,
299303
return nil, err
300304
}
301305

306+
var chanOpts []lnwallet.ChannelOpt
307+
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
308+
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
309+
})
310+
302311
chanMachine, err := lnwallet.NewLightningChannel(
303-
a.c.cfg.Signer, channel, nil,
312+
a.c.cfg.Signer, channel, nil, chanOpts...,
304313
)
305314
if err != nil {
306315
return nil, err
@@ -344,10 +353,15 @@ func (a *arbChannel) ForceCloseChan() (*lnwallet.LocalForceCloseSummary, error)
344353
return nil, err
345354
}
346355

356+
var chanOpts []lnwallet.ChannelOpt
357+
a.c.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
358+
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
359+
})
360+
347361
// Finally, we'll force close the channel completing
348362
// the force close workflow.
349363
chanMachine, err := lnwallet.NewLightningChannel(
350-
a.c.cfg.Signer, channel, nil,
364+
a.c.cfg.Signer, channel, nil, chanOpts...,
351365
)
352366
if err != nil {
353367
return nil, err

contractcourt/chain_watcher.go

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,9 @@ type chainWatcherConfig struct {
188188
// obfuscater. This is used by the chain watcher to identify which
189189
// state was broadcast and confirmed on-chain.
190190
extractStateNumHint func(*wire.MsgTx, [lnwallet.StateHintSize]byte) uint64
191+
192+
// auxLeafStore can be used to fetch information for custom channels.
193+
auxLeafStore fn.Option[lnwallet.AuxLeafStore]
191194
}
192195

193196
// chainWatcher is a system that's assigned to every active channel. The duty
@@ -421,15 +424,30 @@ func (c *chainWatcher) handleUnknownLocalState(
421424
&c.cfg.chanState.LocalChanCfg, &c.cfg.chanState.RemoteChanCfg,
422425
)
423426

427+
auxLeaves, err := lnwallet.AuxLeavesFromCommit(
428+
c.cfg.chanState, c.cfg.chanState.LocalCommitment,
429+
c.cfg.auxLeafStore, *commitKeyRing,
430+
)
431+
if err != nil {
432+
return false, fmt.Errorf("unable to fetch aux leaves: %w", err)
433+
}
434+
424435
// With the keys derived, we'll construct the remote script that'll be
425436
// present if they have a non-dust balance on the commitment.
426437
var leaseExpiry uint32
427438
if c.cfg.chanState.ChanType.HasLeaseExpiration() {
428439
leaseExpiry = c.cfg.chanState.ThawHeight
429440
}
441+
442+
remoteAuxLeaf := fn.MapOption(
443+
func(l lnwallet.CommitAuxLeaves) input.AuxTapLeaf {
444+
return l.RemoteAuxLeaf
445+
},
446+
)(auxLeaves)
430447
remoteScript, _, err := lnwallet.CommitScriptToRemote(
431448
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
432-
commitKeyRing.ToRemoteKey, leaseExpiry, input.NoneTapLeaf(),
449+
commitKeyRing.ToRemoteKey, leaseExpiry,
450+
fn.FlattenOption(remoteAuxLeaf),
433451
)
434452
if err != nil {
435453
return false, err
@@ -438,11 +456,16 @@ func (c *chainWatcher) handleUnknownLocalState(
438456
// Next, we'll derive our script that includes the revocation base for
439457
// the remote party allowing them to claim this output before the CSV
440458
// delay if we breach.
459+
localAuxLeaf := fn.MapOption(
460+
func(l lnwallet.CommitAuxLeaves) input.AuxTapLeaf {
461+
return l.LocalAuxLeaf
462+
},
463+
)(auxLeaves)
441464
localScript, err := lnwallet.CommitScriptToSelf(
442465
c.cfg.chanState.ChanType, c.cfg.chanState.IsInitiator,
443466
commitKeyRing.ToLocalKey, commitKeyRing.RevocationKey,
444467
uint32(c.cfg.chanState.LocalChanCfg.CsvDelay), leaseExpiry,
445-
input.NoneTapLeaf(),
468+
fn.FlattenOption(localAuxLeaf),
446469
)
447470
if err != nil {
448471
return false, err
@@ -862,7 +885,7 @@ func (c *chainWatcher) handlePossibleBreach(commitSpend *chainntnfs.SpendDetail,
862885
spendHeight := uint32(commitSpend.SpendingHeight)
863886
retribution, err := lnwallet.NewBreachRetribution(
864887
c.cfg.chanState, broadcastStateNum, spendHeight,
865-
commitSpend.SpendingTx,
888+
commitSpend.SpendingTx, c.cfg.auxLeafStore,
866889
)
867890

868891
switch {
@@ -1073,8 +1096,8 @@ func (c *chainWatcher) dispatchLocalForceClose(
10731096
"detected", c.cfg.chanState.FundingOutpoint)
10741097

10751098
forceClose, err := lnwallet.NewLocalForceCloseSummary(
1076-
c.cfg.chanState, c.cfg.signer,
1077-
commitSpend.SpendingTx, stateNum,
1099+
c.cfg.chanState, c.cfg.signer, commitSpend.SpendingTx, stateNum,
1100+
c.cfg.auxLeafStore,
10781101
)
10791102
if err != nil {
10801103
return err
@@ -1167,7 +1190,7 @@ func (c *chainWatcher) dispatchRemoteForceClose(
11671190
// channel on-chain.
11681191
uniClose, err := lnwallet.NewUnilateralCloseSummary(
11691192
c.cfg.chanState, c.cfg.signer, commitSpend,
1170-
remoteCommit, commitPoint,
1193+
remoteCommit, commitPoint, c.cfg.auxLeafStore,
11711194
)
11721195
if err != nil {
11731196
return err

funding/manager.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,10 @@ type Config struct {
538538
// AliasManager is an implementation of the aliasHandler interface that
539539
// abstracts away the handling of many alias functions.
540540
AliasManager aliasHandler
541+
542+
// AuxLeafStore is an optional store that can be used to store auxiliary
543+
// leaves for certain custom channel types.
544+
AuxLeafStore fn.Option[lnwallet.AuxLeafStore]
541545
}
542546

543547
// Manager acts as an orchestrator/bridge between the wallet's
@@ -1056,9 +1060,14 @@ func (f *Manager) advanceFundingState(channel *channeldb.OpenChannel,
10561060
}
10571061
}
10581062

1063+
var chanOpts []lnwallet.ChannelOpt
1064+
f.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
1065+
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
1066+
})
1067+
10591068
// We create the state-machine object which wraps the database state.
10601069
lnChannel, err := lnwallet.NewLightningChannel(
1061-
nil, channel, nil,
1070+
nil, channel, nil, chanOpts...,
10621071
)
10631072
if err != nil {
10641073
log.Errorf("Unable to create LightningChannel(%v): %v",

input/size_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,7 +1386,7 @@ func genTimeoutTx(t *testing.T,
13861386
// Create the unsigned timeout tx.
13871387
timeoutTx, err := lnwallet.CreateHtlcTimeoutTx(
13881388
chanType, false, testOutPoint, testAmt, testCLTVExpiry,
1389-
testCSVDelay, 0, testPubkey, testPubkey,
1389+
testCSVDelay, 0, testPubkey, testPubkey, input.NoneTapLeaf(),
13901390
)
13911391
require.NoError(t, err)
13921392

@@ -1455,7 +1455,7 @@ func genSuccessTx(t *testing.T, chanType channeldb.ChannelType) *wire.MsgTx {
14551455
// Create the unsigned success tx.
14561456
successTx, err := lnwallet.CreateHtlcSuccessTx(
14571457
chanType, false, testOutPoint, testAmt, testCSVDelay, 0,
1458-
testPubkey, testPubkey,
1458+
testPubkey, testPubkey, input.NoneTapLeaf(),
14591459
)
14601460
require.NoError(t, err)
14611461

lnd.go

Lines changed: 3 additions & 2 deletions
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)
@@ -580,7 +581,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
580581
server, err := newServer(
581582
cfg, cfg.Listeners, dbs, activeChainControl, &idKeyDesc,
582583
activeChainControl.Cfg.WalletUnlockParams.ChansToRestore,
583-
multiAcceptor, torController, tlsManager,
584+
multiAcceptor, torController, tlsManager, implCfg,
584585
)
585586
if err != nil {
586587
return mkErr("unable to create server: %v", err)

0 commit comments

Comments
 (0)