Skip to content

Commit ea3e4b9

Browse files
Roasbeefguggero
authored andcommitted
lnwallet+peer: move internalKeyForAddr to lnwallet package
This way we can re-use it. We also make it slightly more generalized.
1 parent 9915134 commit ea3e4b9

File tree

5 files changed

+160
-77
lines changed

5 files changed

+160
-77
lines changed

lnwallet/interface.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/btcsuite/btcd/btcutil"
1212
"github.com/btcsuite/btcd/btcutil/hdkeychain"
1313
"github.com/btcsuite/btcd/btcutil/psbt"
14+
"github.com/btcsuite/btcd/chaincfg"
1415
"github.com/btcsuite/btcd/chaincfg/chainhash"
1516
"github.com/btcsuite/btcd/txscript"
1617
"github.com/btcsuite/btcd/wire"
@@ -21,6 +22,7 @@ import (
2122
"github.com/lightningnetwork/lnd/fn"
2223
"github.com/lightningnetwork/lnd/keychain"
2324
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
25+
"github.com/lightningnetwork/lnd/lnwire"
2426
)
2527

2628
const (
@@ -594,6 +596,67 @@ type MessageSigner interface {
594596
doubleHash bool) (*ecdsa.Signature, error)
595597
}
596598

599+
// AddrWithKey wraps a normal addr, but also includes the internal key for the
600+
// delivery addr if known.
601+
type AddrWithKey struct {
602+
lnwire.DeliveryAddress
603+
604+
InternalKey fn.Option[btcec.PublicKey]
605+
606+
// TODO(roasbeef): consolidate w/ instance in chan closer
607+
}
608+
609+
// InternalKeyForAddr returns the internal key associated with a taproot
610+
// address.
611+
func InternalKeyForAddr(wallet WalletController, netParams *chaincfg.Params,
612+
deliveryScript []byte) (fn.Option[keychain.KeyDescriptor], error) {
613+
614+
none := fn.None[keychain.KeyDescriptor]()
615+
616+
pkScript, err := txscript.ParsePkScript(deliveryScript)
617+
if err != nil {
618+
return none, err
619+
}
620+
addr, err := pkScript.Address(netParams)
621+
if err != nil {
622+
return none, err
623+
}
624+
625+
walletAddr, err := wallet.AddressInfo(addr)
626+
if err != nil {
627+
return none, err
628+
}
629+
630+
// No wallet addr. No error, but we'll return an nil error value here,
631+
// as callers can use the .Option() method to get an option value.
632+
if walletAddr == nil {
633+
return none, nil
634+
}
635+
636+
// If it's not a taproot address, we don't require to know the internal
637+
// key in the first place. So we don't return an error here, but also no
638+
// internal key.
639+
if walletAddr.AddrType() != waddrmgr.TaprootPubKey {
640+
return none, nil
641+
}
642+
643+
pubKeyAddr, ok := walletAddr.(waddrmgr.ManagedPubKeyAddress)
644+
if !ok {
645+
return none, fmt.Errorf("expected pubkey addr, got %T",
646+
pubKeyAddr)
647+
}
648+
649+
_, derivationPath, _ := pubKeyAddr.DerivationInfo()
650+
651+
return fn.Some[keychain.KeyDescriptor](keychain.KeyDescriptor{
652+
KeyLocator: keychain.KeyLocator{
653+
Family: keychain.KeyFamily(derivationPath.Account),
654+
Index: derivationPath.Index,
655+
},
656+
PubKey: pubKeyAddr.PubKey(),
657+
}), nil
658+
}
659+
597660
// WalletDriver represents a "driver" for a particular concrete
598661
// WalletController implementation. A driver is identified by a globally unique
599662
// string identifier along with a 'New()' method which is responsible for

peer/brontide.go

Lines changed: 21 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/btcsuite/btcd/txscript"
1919
"github.com/btcsuite/btcd/wire"
2020
"github.com/btcsuite/btclog"
21-
"github.com/btcsuite/btcwallet/waddrmgr"
2221
"github.com/davecgh/go-spew/spew"
2322
"github.com/lightningnetwork/lnd/buffer"
2423
"github.com/lightningnetwork/lnd/build"
@@ -36,6 +35,7 @@ import (
3635
"github.com/lightningnetwork/lnd/htlcswitch/hop"
3736
"github.com/lightningnetwork/lnd/input"
3837
"github.com/lightningnetwork/lnd/invoices"
38+
"github.com/lightningnetwork/lnd/keychain"
3939
"github.com/lightningnetwork/lnd/lnpeer"
4040
"github.com/lightningnetwork/lnd/lntypes"
4141
"github.com/lightningnetwork/lnd/lnutils"
@@ -901,70 +901,31 @@ func (p *Brontide) QuitSignal() <-chan struct{} {
901901
return p.quit
902902
}
903903

904-
// internalKeyForAddr returns the internal key associated with a taproot
905-
// address.
906-
func internalKeyForAddr(wallet *lnwallet.LightningWallet,
907-
deliveryScript []byte) (fn.Option[btcec.PublicKey], error) {
908-
909-
none := fn.None[btcec.PublicKey]()
910-
911-
pkScript, err := txscript.ParsePkScript(deliveryScript)
912-
if err != nil {
913-
return none, err
914-
}
915-
addr, err := pkScript.Address(&wallet.Cfg.NetParams)
916-
if err != nil {
917-
return none, err
918-
}
919-
920-
walletAddr, err := wallet.AddressInfo(addr)
921-
if err != nil {
922-
return none, err
923-
}
924-
925-
// If the address isn't known to the wallet, we can't determine the
926-
// internal key.
927-
if walletAddr == nil {
928-
return none, nil
929-
}
930-
931-
// If it's not a taproot address, we don't require to know the internal
932-
// key in the first place. So we don't return an error here, but also no
933-
// internal key.
934-
if walletAddr.AddrType() != waddrmgr.TaprootPubKey {
935-
return none, nil
936-
}
937-
938-
pubKeyAddr, ok := walletAddr.(waddrmgr.ManagedPubKeyAddress)
939-
if !ok {
940-
return none, fmt.Errorf("expected pubkey addr, got %T",
941-
pubKeyAddr)
942-
}
943-
944-
return fn.Some(*pubKeyAddr.PubKey()), nil
945-
}
946-
947904
// addrWithInternalKey takes a delivery script, then attempts to supplement it
948905
// with information related to the internal key for the addr, but only if it's
949906
// a taproot addr.
950907
func (p *Brontide) addrWithInternalKey(
951-
deliveryScript []byte) fn.Result[chancloser.DeliveryAddrWithKey] {
908+
deliveryScript []byte) (*chancloser.DeliveryAddrWithKey, error) {
952909

953-
// TODO(roasbeef): not compatible with external shutdown addr?
954910
// Currently, custom channels cannot be created with external upfront
955911
// shutdown addresses, so this shouldn't be an issue. We only require
956912
// the internal key for taproot addresses to be able to provide a non
957913
// inclusion proof of any scripts.
958-
959-
internalKey, err := internalKeyForAddr(p.cfg.Wallet, deliveryScript)
914+
internalKeyDesc, err := lnwallet.InternalKeyForAddr(
915+
p.cfg.Wallet, &p.cfg.Wallet.Cfg.NetParams, deliveryScript,
916+
)
960917
if err != nil {
961-
return fn.Err[chancloser.DeliveryAddrWithKey](err)
918+
return nil, fmt.Errorf("unable to fetch internal key: %w", err)
962919
}
963920

964-
return fn.Ok(chancloser.DeliveryAddrWithKey{
921+
return &chancloser.DeliveryAddrWithKey{
965922
DeliveryAddress: deliveryScript,
966-
InternalKey: internalKey,
967-
})
923+
InternalKey: fn.MapOption(
924+
func(desc keychain.KeyDescriptor) btcec.PublicKey {
925+
return *desc.PubKey
926+
},
927+
)(internalKeyDesc),
928+
}, nil
968929
}
969930

970931
// loadActiveChannels creates indexes within the peer for tracking all active
@@ -1038,6 +999,8 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
1038999
}
10391000
}
10401001

1002+
// TODO(roasbeef): also make aux resolver here
1003+
10411004
var chanOpts []lnwallet.ChannelOpt
10421005
p.cfg.AuxLeafStore.WhenSome(func(s lnwallet.AuxLeafStore) {
10431006
chanOpts = append(chanOpts, lnwallet.WithLeafStore(s))
@@ -1209,7 +1172,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
12091172

12101173
addr, err := p.addrWithInternalKey(
12111174
info.DeliveryScript.Val,
1212-
).Unpack()
1175+
)
12131176
if err != nil {
12141177
shutdownInfoErr = fmt.Errorf("unable to make "+
12151178
"delivery addr: %w", err)
@@ -2977,7 +2940,7 @@ func (p *Brontide) fetchActiveChanCloser(chanID lnwire.ChannelID) (
29772940
return nil, fmt.Errorf("unable to estimate fee")
29782941
}
29792942

2980-
addr, err := p.addrWithInternalKey(deliveryScript).Unpack()
2943+
addr, err := p.addrWithInternalKey(deliveryScript)
29812944
if err != nil {
29822945
return nil, fmt.Errorf("unable to parse addr: %w", err)
29832946
}
@@ -3224,7 +3187,7 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
32243187
closingParty = lntypes.Local
32253188
}
32263189

3227-
addr, err := p.addrWithInternalKey(deliveryScript).Unpack()
3190+
addr, err := p.addrWithInternalKey(deliveryScript)
32283191
if err != nil {
32293192
return nil, fmt.Errorf("unable to parse addr: %w", err)
32303193
}
@@ -3256,7 +3219,7 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
32563219
// createChanCloser constructs a ChanCloser from the passed parameters and is
32573220
// used to de-duplicate code.
32583221
func (p *Brontide) createChanCloser(channel *lnwallet.LightningChannel,
3259-
deliveryScript chancloser.DeliveryAddrWithKey,
3222+
deliveryScript *chancloser.DeliveryAddrWithKey,
32603223
fee chainfee.SatPerKWeight, req *htlcswitch.ChanClose,
32613224
closer lntypes.ChannelParty) (*chancloser.ChanCloser, error) {
32623225

@@ -3291,7 +3254,7 @@ func (p *Brontide) createChanCloser(channel *lnwallet.LightningChannel,
32913254
ChainParams: &p.cfg.Wallet.Cfg.NetParams,
32923255
Quit: p.quit,
32933256
},
3294-
deliveryScript,
3257+
*deliveryScript,
32953258
fee,
32963259
uint32(startingHeight),
32973260
req,
@@ -3350,7 +3313,7 @@ func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
33503313
return
33513314
}
33523315
}
3353-
addr, err := p.addrWithInternalKey(deliveryScript).Unpack()
3316+
addr, err := p.addrWithInternalKey(deliveryScript)
33543317
if err != nil {
33553318
err = fmt.Errorf("unable to parse addr for channel "+
33563319
"%v: %w", req.ChanPoint, err)

server.go

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/btcsuite/btcd/btcec/v2"
1919
"github.com/btcsuite/btcd/btcec/v2/ecdsa"
2020
"github.com/btcsuite/btcd/btcutil"
21+
"github.com/btcsuite/btcd/chaincfg"
2122
"github.com/btcsuite/btcd/chaincfg/chainhash"
2223
"github.com/btcsuite/btcd/connmgr"
2324
"github.com/btcsuite/btcd/txscript"
@@ -520,6 +521,8 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
520521
var serializedPubKey [33]byte
521522
copy(serializedPubKey[:], nodeKeyDesc.PubKey.SerializeCompressed())
522523

524+
netParams := cfg.ActiveNetParams.Params
525+
523526
// Initialize the sphinx router.
524527
replayLog := htlcswitch.NewDecayedLog(
525528
dbs.DecayedLogDB, cc.ChainNotifier,
@@ -1118,8 +1121,10 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
11181121
})
11191122

11201123
s.sweeper = sweep.New(&sweep.UtxoSweeperConfig{
1121-
FeeEstimator: cc.FeeEstimator,
1122-
GenSweepScript: newSweepPkScriptGen(cc.Wallet),
1124+
FeeEstimator: cc.FeeEstimator,
1125+
GenSweepScript: newSweepPkScriptGen(
1126+
cc.Wallet, s.cfg.ActiveNetParams.Params,
1127+
),
11231128
Signer: cc.Wallet.Cfg.Signer,
11241129
Wallet: newSweeperWallet(cc.Wallet),
11251130
Mempool: cc.MempoolNotifier,
@@ -1162,10 +1167,19 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
11621167

11631168
s.breachArbitrator = contractcourt.NewBreachArbitrator(
11641169
&contractcourt.BreachConfig{
1165-
CloseLink: closeLink,
1166-
DB: s.chanStateDB,
1167-
Estimator: s.cc.FeeEstimator,
1168-
GenSweepScript: newSweepPkScriptGen(cc.Wallet),
1170+
CloseLink: closeLink,
1171+
DB: s.chanStateDB,
1172+
Estimator: s.cc.FeeEstimator,
1173+
GenSweepScript: func() ([]byte, error) {
1174+
addr, err := newSweepPkScriptGen(
1175+
cc.Wallet, netParams,
1176+
)().Unpack()
1177+
if err != nil {
1178+
return nil, err
1179+
}
1180+
1181+
return addr.DeliveryAddress, nil
1182+
},
11691183
Notifier: cc.ChainNotifier,
11701184
PublishTransaction: cc.Wallet.PublishTransaction,
11711185
ContractBreaches: contractBreaches,
@@ -1181,8 +1195,17 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
11811195
ChainHash: *s.cfg.ActiveNetParams.GenesisHash,
11821196
IncomingBroadcastDelta: lncfg.DefaultIncomingBroadcastDelta,
11831197
OutgoingBroadcastDelta: lncfg.DefaultOutgoingBroadcastDelta,
1184-
NewSweepAddr: newSweepPkScriptGen(cc.Wallet),
1185-
PublishTx: cc.Wallet.PublishTransaction,
1198+
NewSweepAddr: func() ([]byte, error) {
1199+
addr, err := newSweepPkScriptGen(
1200+
cc.Wallet, netParams,
1201+
)().Unpack()
1202+
if err != nil {
1203+
return nil, err
1204+
}
1205+
1206+
return addr.DeliveryAddress, nil
1207+
},
1208+
PublishTx: cc.Wallet.PublishTransaction,
11861209
DeliverResolutionMsg: func(msgs ...contractcourt.ResolutionMsg) error {
11871210
for _, msg := range msgs {
11881211
err := s.htlcSwitch.ProcessContractResolution(msg)
@@ -1659,8 +1682,17 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
16591682
return s.channelNotifier.
16601683
SubscribeChannelEvents()
16611684
},
1662-
Signer: cc.Wallet.Cfg.Signer,
1663-
NewAddress: newSweepPkScriptGen(cc.Wallet),
1685+
Signer: cc.Wallet.Cfg.Signer,
1686+
NewAddress: func() ([]byte, error) {
1687+
addr, err := newSweepPkScriptGen(
1688+
cc.Wallet, netParams,
1689+
)().Unpack()
1690+
if err != nil {
1691+
return nil, err
1692+
}
1693+
1694+
return addr.DeliveryAddress, nil
1695+
},
16641696
SecretKeyRing: s.cc.KeyRing,
16651697
Dial: cfg.net.Dial,
16661698
AuthDial: authDial,
@@ -4842,18 +4874,39 @@ func (s *server) SendCustomMessage(peerPub [33]byte, msgType lnwire.MessageType,
48424874
// Specifically, the script generated is a version 0, pay-to-witness-pubkey-hash
48434875
// (p2wkh) output.
48444876
func newSweepPkScriptGen(
4845-
wallet lnwallet.WalletController) func() ([]byte, error) {
4877+
wallet lnwallet.WalletController,
4878+
netParams *chaincfg.Params) func() fn.Result[lnwallet.AddrWithKey] {
48464879

4847-
return func() ([]byte, error) {
4880+
return func() fn.Result[lnwallet.AddrWithKey] {
48484881
sweepAddr, err := wallet.NewAddress(
48494882
lnwallet.TaprootPubkey, false,
48504883
lnwallet.DefaultAccountName,
48514884
)
48524885
if err != nil {
4853-
return nil, err
4886+
return fn.Err[lnwallet.AddrWithKey](err)
4887+
}
4888+
4889+
addr, err := txscript.PayToAddrScript(sweepAddr)
4890+
if err != nil {
4891+
return fn.Err[lnwallet.AddrWithKey](err)
48544892
}
48554893

4856-
return txscript.PayToAddrScript(sweepAddr)
4894+
internalKeyDesc, err := lnwallet.InternalKeyForAddr(
4895+
wallet, netParams, addr,
4896+
)
4897+
if err != nil {
4898+
return fn.Err[lnwallet.AddrWithKey](err)
4899+
}
4900+
4901+
return fn.Ok(lnwallet.AddrWithKey{
4902+
DeliveryAddress: addr,
4903+
InternalKey: fn.MapOption(func(
4904+
desc keychain.KeyDescriptor) btcec.PublicKey {
4905+
4906+
return *desc.PubKey
4907+
},
4908+
)(internalKeyDesc),
4909+
})
48574910
}
48584911
}
48594912

0 commit comments

Comments
 (0)