@@ -13,11 +13,13 @@ import (
1313 "time"
1414
1515 "github.com/btcsuite/btcd/btcec/v2"
16+ "github.com/btcsuite/btcd/btcutil"
1617 "github.com/btcsuite/btcd/chaincfg/chainhash"
1718 "github.com/btcsuite/btcd/connmgr"
1819 "github.com/btcsuite/btcd/txscript"
1920 "github.com/btcsuite/btcd/wire"
2021 "github.com/btcsuite/btclog"
22+ "github.com/btcsuite/btcwallet/waddrmgr"
2123 "github.com/davecgh/go-spew/spew"
2224 "github.com/lightningnetwork/lnd/buffer"
2325 "github.com/lightningnetwork/lnd/build"
@@ -885,6 +887,73 @@ func (p *Brontide) QuitSignal() <-chan struct{} {
885887 return p .quit
886888}
887889
890+ // internalKeyForAddr returns the internal key associated with a taproot
891+ // address.
892+ func internalKeyForAddr (wallet * lnwallet.LightningWallet ,
893+ deliveryScript []byte ) (fn.Option [btcec.PublicKey ], error ) {
894+
895+ none := fn .None [btcec.PublicKey ]()
896+
897+ pkScript , err := txscript .ParsePkScript (deliveryScript )
898+ if err != nil {
899+ return none , err
900+ }
901+ addr , err := pkScript .Address (& wallet .Cfg .NetParams )
902+ if err != nil {
903+ return none , err
904+ }
905+
906+ // If it's not a taproot address, we don't require to know the internal
907+ // key in the first place. So we don't return an error here, but also no
908+ // internal key.
909+ _ , isTaproot := addr .(* btcutil.AddressTaproot )
910+ if ! isTaproot {
911+ return none , nil
912+ }
913+
914+ walletAddr , err := wallet .AddressInfo (addr )
915+ if err != nil {
916+ return none , err
917+ }
918+
919+ // If the address isn't known to the wallet, we can't determine the
920+ // internal key.
921+ if walletAddr == nil {
922+ return none , nil
923+ }
924+
925+ pubKeyAddr , ok := walletAddr .(waddrmgr.ManagedPubKeyAddress )
926+ if ! ok {
927+ return none , fmt .Errorf ("expected pubkey addr, got %T" ,
928+ pubKeyAddr )
929+ }
930+
931+ return fn .Some (* pubKeyAddr .PubKey ()), nil
932+ }
933+
934+ // addrWithInternalKey takes a delivery script, then attempts to supplement it
935+ // with information related to the internal key for the addr, but only if it's
936+ // a taproot addr.
937+ func (p * Brontide ) addrWithInternalKey (
938+ deliveryScript []byte ) fn.Result [chancloser.DeliveryAddrWithKey ] {
939+
940+ // TODO(roasbeef): not compatible with external shutdown addr?
941+ // Currently, custom channels cannot be created with external upfront
942+ // shutdown addresses, so this shouldn't be an issue. We only require
943+ // the internal key for taproot addresses to be able to provide a non
944+ // inclusion proof of any scripts.
945+
946+ internalKey , err := internalKeyForAddr (p .cfg .Wallet , deliveryScript )
947+ if err != nil {
948+ return fn.Err [chancloser.DeliveryAddrWithKey ](err )
949+ }
950+
951+ return fn .Ok (chancloser.DeliveryAddrWithKey {
952+ DeliveryAddress : deliveryScript ,
953+ InternalKey : internalKey ,
954+ })
955+ }
956+
888957// loadActiveChannels creates indexes within the peer for tracking all active
889958// channels returned by the database. It returns a slice of channel reestablish
890959// messages that should be sent to the peer immediately, in case we have borked
@@ -1125,9 +1194,16 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
11251194 return
11261195 }
11271196
1197+ addr , err := p .addrWithInternalKey (
1198+ info .DeliveryScript .Val ,
1199+ ).Unpack ()
1200+ if err != nil {
1201+ shutdownInfoErr = fmt .Errorf ("unable to make " +
1202+ "delivery addr: %w" , err )
1203+ return
1204+ }
11281205 chanCloser , err := p .createChanCloser (
1129- lnChan , info .DeliveryScript .Val , feePerKw , nil ,
1130- info .Closer (),
1206+ lnChan , addr , feePerKw , nil , info .Closer (),
11311207 )
11321208 if err != nil {
11331209 shutdownInfoErr = fmt .Errorf ("unable to " +
@@ -2886,8 +2962,12 @@ func (p *Brontide) fetchActiveChanCloser(chanID lnwire.ChannelID) (
28862962 return nil , fmt .Errorf ("unable to estimate fee" )
28872963 }
28882964
2965+ addr , err := p .addrWithInternalKey (deliveryScript ).Unpack ()
2966+ if err != nil {
2967+ return nil , fmt .Errorf ("unable to parse addr: %w" , err )
2968+ }
28892969 chanCloser , err = p .createChanCloser (
2890- channel , deliveryScript , feePerKw , nil , lntypes .Remote ,
2970+ channel , addr , feePerKw , nil , lntypes .Remote ,
28912971 )
28922972 if err != nil {
28932973 p .log .Errorf ("unable to create chan closer: %v" , err )
@@ -3129,8 +3209,12 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
31293209 closingParty = lntypes .Local
31303210 }
31313211
3212+ addr , err := p .addrWithInternalKey (deliveryScript ).Unpack ()
3213+ if err != nil {
3214+ return nil , fmt .Errorf ("unable to parse addr: %w" , err )
3215+ }
31323216 chanCloser , err := p .createChanCloser (
3133- lnChan , deliveryScript , feePerKw , nil , closingParty ,
3217+ lnChan , addr , feePerKw , nil , closingParty ,
31343218 )
31353219 if err != nil {
31363220 p .log .Errorf ("unable to create chan closer: %v" , err )
@@ -3157,8 +3241,8 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
31573241// createChanCloser constructs a ChanCloser from the passed parameters and is
31583242// used to de-duplicate code.
31593243func (p * Brontide ) createChanCloser (channel * lnwallet.LightningChannel ,
3160- deliveryScript lnwire. DeliveryAddress , fee chainfee. SatPerKWeight ,
3161- req * htlcswitch.ChanClose ,
3244+ deliveryScript chancloser. DeliveryAddrWithKey ,
3245+ fee chainfee. SatPerKWeight , req * htlcswitch.ChanClose ,
31623246 closer lntypes.ChannelParty ) (* chancloser.ChanCloser , error ) {
31633247
31643248 _ , startingHeight , err := p .cfg .ChainIO .GetBestBlock ()
@@ -3179,6 +3263,7 @@ func (p *Brontide) createChanCloser(channel *lnwallet.LightningChannel,
31793263 MusigSession : NewMusigChanCloser (channel ),
31803264 FeeEstimator : & chancloser.SimpleCoopFeeEstimator {},
31813265 BroadcastTx : p .cfg .Wallet .PublishTransaction ,
3266+ AuxCloser : p .cfg .AuxChanCloser ,
31823267 DisableChannel : func (op wire.OutPoint ) error {
31833268 return p .cfg .ChanStatusMgr .RequestDisable (
31843269 op , false ,
@@ -3250,10 +3335,17 @@ func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
32503335 return
32513336 }
32523337 }
3338+ addr , err := p .addrWithInternalKey (deliveryScript ).Unpack ()
3339+ if err != nil {
3340+ err = fmt .Errorf ("unable to parse addr for channel " +
3341+ "%v: %w" , req .ChanPoint , err )
3342+ p .log .Errorf (err .Error ())
3343+ req .Err <- err
32533344
3345+ return
3346+ }
32543347 chanCloser , err := p .createChanCloser (
3255- channel , deliveryScript , req .TargetFeePerKw , req ,
3256- lntypes .Local ,
3348+ channel , addr , req .TargetFeePerKw , req , lntypes .Local ,
32573349 )
32583350 if err != nil {
32593351 p .log .Errorf (err .Error ())
0 commit comments