@@ -18,6 +18,7 @@ import (
18
18
"github.com/btcsuite/btcd/txscript"
19
19
"github.com/btcsuite/btcd/wire"
20
20
"github.com/btcsuite/btclog"
21
+ "github.com/btcsuite/btcwallet/waddrmgr"
21
22
"github.com/davecgh/go-spew/spew"
22
23
"github.com/lightningnetwork/lnd/buffer"
23
24
"github.com/lightningnetwork/lnd/build"
@@ -885,6 +886,72 @@ func (p *Brontide) QuitSignal() <-chan struct{} {
885
886
return p .quit
886
887
}
887
888
889
+ // internalKeyForAddr returns the internal key associated with a taproot
890
+ // address.
891
+ func internalKeyForAddr (wallet * lnwallet.LightningWallet ,
892
+ deliveryScript []byte ) (fn.Option [btcec.PublicKey ], error ) {
893
+
894
+ none := fn .None [btcec.PublicKey ]()
895
+
896
+ pkScript , err := txscript .ParsePkScript (deliveryScript )
897
+ if err != nil {
898
+ return none , err
899
+ }
900
+ addr , err := pkScript .Address (& wallet .Cfg .NetParams )
901
+ if err != nil {
902
+ return none , err
903
+ }
904
+
905
+ walletAddr , err := wallet .AddressInfo (addr )
906
+ if err != nil {
907
+ return none , err
908
+ }
909
+
910
+ // If the address isn't known to the wallet, we can't determine the
911
+ // internal key.
912
+ if walletAddr == nil {
913
+ return none , nil
914
+ }
915
+
916
+ // If it's not a taproot address, we don't require to know the internal
917
+ // key in the first place. So we don't return an error here, but also no
918
+ // internal key.
919
+ if walletAddr .AddrType () != waddrmgr .TaprootPubKey {
920
+ return none , nil
921
+ }
922
+
923
+ pubKeyAddr , ok := walletAddr .(waddrmgr.ManagedPubKeyAddress )
924
+ if ! ok {
925
+ return none , fmt .Errorf ("expected pubkey addr, got %T" ,
926
+ pubKeyAddr )
927
+ }
928
+
929
+ return fn .Some (* pubKeyAddr .PubKey ()), nil
930
+ }
931
+
932
+ // addrWithInternalKey takes a delivery script, then attempts to supplement it
933
+ // with information related to the internal key for the addr, but only if it's
934
+ // a taproot addr.
935
+ func (p * Brontide ) addrWithInternalKey (
936
+ deliveryScript []byte ) fn.Result [chancloser.DeliveryAddrWithKey ] {
937
+
938
+ // TODO(roasbeef): not compatible with external shutdown addr?
939
+ // Currently, custom channels cannot be created with external upfront
940
+ // shutdown addresses, so this shouldn't be an issue. We only require
941
+ // the internal key for taproot addresses to be able to provide a non
942
+ // inclusion proof of any scripts.
943
+
944
+ internalKey , err := internalKeyForAddr (p .cfg .Wallet , deliveryScript )
945
+ if err != nil {
946
+ return fn.Err [chancloser.DeliveryAddrWithKey ](err )
947
+ }
948
+
949
+ return fn .Ok (chancloser.DeliveryAddrWithKey {
950
+ DeliveryAddress : deliveryScript ,
951
+ InternalKey : internalKey ,
952
+ })
953
+ }
954
+
888
955
// loadActiveChannels creates indexes within the peer for tracking all active
889
956
// channels returned by the database. It returns a slice of channel reestablish
890
957
// messages that should be sent to the peer immediately, in case we have borked
@@ -1125,9 +1192,16 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
1125
1192
return
1126
1193
}
1127
1194
1195
+ addr , err := p .addrWithInternalKey (
1196
+ info .DeliveryScript .Val ,
1197
+ ).Unpack ()
1198
+ if err != nil {
1199
+ shutdownInfoErr = fmt .Errorf ("unable to make " +
1200
+ "delivery addr: %w" , err )
1201
+ return
1202
+ }
1128
1203
chanCloser , err := p .createChanCloser (
1129
- lnChan , info .DeliveryScript .Val , feePerKw , nil ,
1130
- info .Closer (),
1204
+ lnChan , addr , feePerKw , nil , info .Closer (),
1131
1205
)
1132
1206
if err != nil {
1133
1207
shutdownInfoErr = fmt .Errorf ("unable to " +
@@ -2886,8 +2960,12 @@ func (p *Brontide) fetchActiveChanCloser(chanID lnwire.ChannelID) (
2886
2960
return nil , fmt .Errorf ("unable to estimate fee" )
2887
2961
}
2888
2962
2963
+ addr , err := p .addrWithInternalKey (deliveryScript ).Unpack ()
2964
+ if err != nil {
2965
+ return nil , fmt .Errorf ("unable to parse addr: %w" , err )
2966
+ }
2889
2967
chanCloser , err = p .createChanCloser (
2890
- channel , deliveryScript , feePerKw , nil , lntypes .Remote ,
2968
+ channel , addr , feePerKw , nil , lntypes .Remote ,
2891
2969
)
2892
2970
if err != nil {
2893
2971
p .log .Errorf ("unable to create chan closer: %v" , err )
@@ -3129,8 +3207,12 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
3129
3207
closingParty = lntypes .Local
3130
3208
}
3131
3209
3210
+ addr , err := p .addrWithInternalKey (deliveryScript ).Unpack ()
3211
+ if err != nil {
3212
+ return nil , fmt .Errorf ("unable to parse addr: %w" , err )
3213
+ }
3132
3214
chanCloser , err := p .createChanCloser (
3133
- lnChan , deliveryScript , feePerKw , nil , closingParty ,
3215
+ lnChan , addr , feePerKw , nil , closingParty ,
3134
3216
)
3135
3217
if err != nil {
3136
3218
p .log .Errorf ("unable to create chan closer: %v" , err )
@@ -3157,8 +3239,8 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
3157
3239
// createChanCloser constructs a ChanCloser from the passed parameters and is
3158
3240
// used to de-duplicate code.
3159
3241
func (p * Brontide ) createChanCloser (channel * lnwallet.LightningChannel ,
3160
- deliveryScript lnwire. DeliveryAddress , fee chainfee. SatPerKWeight ,
3161
- req * htlcswitch.ChanClose ,
3242
+ deliveryScript chancloser. DeliveryAddrWithKey ,
3243
+ fee chainfee. SatPerKWeight , req * htlcswitch.ChanClose ,
3162
3244
closer lntypes.ChannelParty ) (* chancloser.ChanCloser , error ) {
3163
3245
3164
3246
_ , startingHeight , err := p .cfg .ChainIO .GetBestBlock ()
@@ -3179,6 +3261,7 @@ func (p *Brontide) createChanCloser(channel *lnwallet.LightningChannel,
3179
3261
MusigSession : NewMusigChanCloser (channel ),
3180
3262
FeeEstimator : & chancloser.SimpleCoopFeeEstimator {},
3181
3263
BroadcastTx : p .cfg .Wallet .PublishTransaction ,
3264
+ AuxCloser : p .cfg .AuxChanCloser ,
3182
3265
DisableChannel : func (op wire.OutPoint ) error {
3183
3266
return p .cfg .ChanStatusMgr .RequestDisable (
3184
3267
op , false ,
@@ -3250,10 +3333,17 @@ func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
3250
3333
return
3251
3334
}
3252
3335
}
3336
+ addr , err := p .addrWithInternalKey (deliveryScript ).Unpack ()
3337
+ if err != nil {
3338
+ err = fmt .Errorf ("unable to parse addr for channel " +
3339
+ "%v: %w" , req .ChanPoint , err )
3340
+ p .log .Errorf (err .Error ())
3341
+ req .Err <- err
3253
3342
3343
+ return
3344
+ }
3254
3345
chanCloser , err := p .createChanCloser (
3255
- channel , deliveryScript , req .TargetFeePerKw , req ,
3256
- lntypes .Local ,
3346
+ channel , addr , req .TargetFeePerKw , req , lntypes .Local ,
3257
3347
)
3258
3348
if err != nil {
3259
3349
p .log .Errorf (err .Error ())
0 commit comments