@@ -896,11 +896,9 @@ func (b *batch) publishBatchCoop(ctx context.Context) (btcutil.Amount,
896
896
return fee , err , false
897
897
}
898
898
899
- prevOutputFetcher := txscript .NewMultiPrevOutFetcher (prevOuts )
900
-
901
899
// Attempt to cooperatively sign the batch tx with the server.
902
900
err = b .coopSignBatchTx (
903
- ctx , packet , sweeps , prevOutputFetcher , prevOuts , psbtBuf ,
901
+ ctx , packet , sweeps , prevOuts , psbtBuf . Bytes () ,
904
902
)
905
903
if err != nil {
906
904
return fee , err , false
@@ -942,138 +940,148 @@ func (b *batch) debugLogTx(msg string, tx *wire.MsgTx) {
942
940
// coopSignBatchTx collects the necessary signatures from the server in order
943
941
// to cooperatively sweep the funds.
944
942
func (b * batch ) coopSignBatchTx (ctx context.Context , packet * psbt.Packet ,
945
- sweeps []sweep , prevOutputFetcher * txscript. MultiPrevOutFetcher ,
946
- prevOuts map [wire. OutPoint ] * wire. TxOut , psbtBuf bytes. Buffer ) error {
943
+ sweeps []sweep , prevOuts map [wire. OutPoint ] * wire. TxOut ,
944
+ psbt [] byte ) error {
947
945
948
946
for i , sweep := range sweeps {
949
947
sweep := sweep
950
948
951
- sigHashes := txscript .NewTxSigHashes (
952
- packet .UnsignedTx , prevOutputFetcher ,
953
- )
954
-
955
- sigHash , err := txscript .CalcTaprootSignatureHash (
956
- sigHashes , txscript .SigHashDefault , packet .UnsignedTx ,
957
- i , prevOutputFetcher ,
949
+ finalSig , err := b .musig2sign (
950
+ ctx , i , sweep , packet .UnsignedTx , prevOuts , psbt ,
958
951
)
959
952
if err != nil {
960
953
return err
961
954
}
962
955
963
- var (
964
- signers [][]byte
965
- muSig2Version input.MuSig2Version
966
- )
967
-
968
- // Depending on the MuSig2 version we either pass 32 byte
969
- // Schnorr public keys or normal 33 byte public keys.
970
- if sweep .protocolVersion >= loopdb .ProtocolVersionMuSig2 {
971
- muSig2Version = input .MuSig2Version100RC2
972
- signers = [][]byte {
973
- sweep .htlcKeys .SenderInternalPubKey [:],
974
- sweep .htlcKeys .ReceiverInternalPubKey [:],
975
- }
976
- } else {
977
- muSig2Version = input .MuSig2Version040
978
- signers = [][]byte {
979
- sweep .htlcKeys .SenderInternalPubKey [1 :],
980
- sweep .htlcKeys .ReceiverInternalPubKey [1 :],
981
- }
956
+ packet .UnsignedTx .TxIn [i ].Witness = wire.TxWitness {
957
+ finalSig ,
982
958
}
959
+ }
983
960
984
- htlcScript , ok := sweep .htlc .HtlcScript .(* swap.HtlcScriptV3 )
985
- if ! ok {
986
- return fmt .Errorf ("invalid htlc script version" )
987
- }
961
+ return nil
962
+ }
988
963
989
- // Now we're creating a local MuSig2 session using the receiver
990
- // key's key locator and the htlc's root hash.
991
- musig2SessionInfo , err := b .signerClient .MuSig2CreateSession (
992
- ctx , muSig2Version ,
993
- & sweep .htlcKeys .ClientScriptKeyLocator , signers ,
994
- lndclient .MuSig2TaprootTweakOpt (
995
- htlcScript .RootHash [:], false ,
996
- ),
997
- )
998
- if err != nil {
999
- return fmt .Errorf ("signerClient.MuSig2CreateSession " +
1000
- "failed: %w" , err )
1001
- }
964
+ // musig2sign signs one sweep using musig2.
965
+ func (b * batch ) musig2sign (ctx context.Context , inputIndex int , sweep sweep ,
966
+ unsignedTx * wire.MsgTx , prevOuts map [wire.OutPoint ]* wire.TxOut ,
967
+ psbt []byte ) ([]byte , error ) {
1002
968
1003
- // With the session active, we can now send the server our
1004
- // public nonce and the sig hash, so that it can create it's own
1005
- // MuSig2 session and return the server side nonce and partial
1006
- // signature.
1007
- serverNonce , serverSig , err := b .muSig2SignSweep (
1008
- ctx , sweep .protocolVersion , sweep .swapHash ,
1009
- sweep .swapInvoicePaymentAddr ,
1010
- musig2SessionInfo .PublicNonce [:], psbtBuf .Bytes (),
1011
- prevOuts ,
1012
- )
1013
- if err != nil {
1014
- return err
1015
- }
969
+ prevOutputFetcher := txscript .NewMultiPrevOutFetcher (prevOuts )
1016
970
1017
- var serverPublicNonce [musig2 .PubNonceSize ]byte
1018
- copy (serverPublicNonce [:], serverNonce )
971
+ sigHashes := txscript .NewTxSigHashes (unsignedTx , prevOutputFetcher )
1019
972
1020
- // Register the server's nonce before attempting to create our
1021
- // partial signature.
1022
- haveAllNonces , err := b .signerClient .MuSig2RegisterNonces (
1023
- ctx , musig2SessionInfo .SessionID ,
1024
- [][musig2 .PubNonceSize ]byte {serverPublicNonce },
1025
- )
1026
- if err != nil {
1027
- return err
1028
- }
973
+ sigHash , err := txscript .CalcTaprootSignatureHash (
974
+ sigHashes , txscript .SigHashDefault , unsignedTx , inputIndex ,
975
+ prevOutputFetcher ,
976
+ )
977
+ if err != nil {
978
+ return nil , err
979
+ }
1029
980
1030
- // Sanity check that we have all the nonces.
1031
- if ! haveAllNonces {
1032
- return fmt .Errorf ("invalid MuSig2 session: " +
1033
- "nonces missing" )
981
+ var (
982
+ signers [][]byte
983
+ muSig2Version input.MuSig2Version
984
+ )
985
+
986
+ // Depending on the MuSig2 version we either pass 32 byte
987
+ // Schnorr public keys or normal 33 byte public keys.
988
+ if sweep .protocolVersion >= loopdb .ProtocolVersionMuSig2 {
989
+ muSig2Version = input .MuSig2Version100RC2
990
+ signers = [][]byte {
991
+ sweep .htlcKeys .SenderInternalPubKey [:],
992
+ sweep .htlcKeys .ReceiverInternalPubKey [:],
993
+ }
994
+ } else {
995
+ muSig2Version = input .MuSig2Version040
996
+ signers = [][]byte {
997
+ sweep .htlcKeys .SenderInternalPubKey [1 :],
998
+ sweep .htlcKeys .ReceiverInternalPubKey [1 :],
1034
999
}
1000
+ }
1035
1001
1036
- var digest [32 ]byte
1037
- copy (digest [:], sigHash )
1002
+ htlcScript , ok := sweep .htlc .HtlcScript .(* swap.HtlcScriptV3 )
1003
+ if ! ok {
1004
+ return nil , fmt .Errorf ("invalid htlc script version" )
1005
+ }
1038
1006
1039
- // Since our MuSig2 session has all nonces, we can now create
1040
- // the local partial signature by signing the sig hash.
1041
- _ , err = b .signerClient .MuSig2Sign (
1042
- ctx , musig2SessionInfo .SessionID , digest , false ,
1043
- )
1044
- if err != nil {
1045
- return err
1046
- }
1007
+ // Now we're creating a local MuSig2 session using the receiver key's
1008
+ // key locator and the htlc's root hash.
1009
+ keyLocator := & sweep .htlcKeys .ClientScriptKeyLocator
1010
+ musig2SessionInfo , err := b .signerClient .MuSig2CreateSession (
1011
+ ctx , muSig2Version , keyLocator , signers ,
1012
+ lndclient .MuSig2TaprootTweakOpt (htlcScript .RootHash [:], false ),
1013
+ )
1014
+ if err != nil {
1015
+ return nil , fmt .Errorf ("signerClient.MuSig2CreateSession " +
1016
+ "failed: %w" , err )
1017
+ }
1047
1018
1048
- // Now combine the partial signatures to use the final combined
1049
- // signature in the sweep transaction's witness.
1050
- haveAllSigs , finalSig , err := b .signerClient .MuSig2CombineSig (
1051
- ctx , musig2SessionInfo .SessionID , [][]byte {serverSig },
1052
- )
1053
- if err != nil {
1054
- return err
1055
- }
1019
+ // With the session active, we can now send the server our
1020
+ // public nonce and the sig hash, so that it can create it's own
1021
+ // MuSig2 session and return the server side nonce and partial
1022
+ // signature.
1023
+ serverNonce , serverSig , err := b .muSig2SignSweep (
1024
+ ctx , sweep .protocolVersion , sweep .swapHash ,
1025
+ sweep .swapInvoicePaymentAddr ,
1026
+ musig2SessionInfo .PublicNonce [:], psbt , prevOuts ,
1027
+ )
1028
+ if err != nil {
1029
+ return nil , err
1030
+ }
1056
1031
1057
- if ! haveAllSigs {
1058
- return fmt .Errorf ("failed to combine signatures" )
1059
- }
1032
+ var serverPublicNonce [musig2 .PubNonceSize ]byte
1033
+ copy (serverPublicNonce [:], serverNonce )
1060
1034
1061
- // To be sure that we're good, parse and validate that the
1062
- // combined signature is indeed valid for the sig hash and the
1063
- // internal pubkey.
1064
- err = b . verifySchnorrSig (
1065
- htlcScript . TaprootKey , sigHash , finalSig ,
1066
- )
1067
- if err != nil {
1068
- return err
1069
- }
1035
+ // Register the server's nonce before attempting to create our
1036
+ // partial signature.
1037
+ haveAllNonces , err := b . signerClient . MuSig2RegisterNonces (
1038
+ ctx , musig2SessionInfo . SessionID ,
1039
+ [][ musig2 . PubNonceSize ] byte { serverPublicNonce } ,
1040
+ )
1041
+ if err != nil {
1042
+ return nil , err
1043
+ }
1070
1044
1071
- packet .UnsignedTx .TxIn [i ].Witness = wire.TxWitness {
1072
- finalSig ,
1073
- }
1045
+ // Sanity check that we have all the nonces.
1046
+ if ! haveAllNonces {
1047
+ return nil , fmt .Errorf ("invalid MuSig2 session: " +
1048
+ "nonces missing" )
1074
1049
}
1075
1050
1076
- return nil
1051
+ var digest [32 ]byte
1052
+ copy (digest [:], sigHash )
1053
+
1054
+ // Since our MuSig2 session has all nonces, we can now create
1055
+ // the local partial signature by signing the sig hash.
1056
+ _ , err = b .signerClient .MuSig2Sign (
1057
+ ctx , musig2SessionInfo .SessionID , digest , false ,
1058
+ )
1059
+ if err != nil {
1060
+ return nil , err
1061
+ }
1062
+
1063
+ // Now combine the partial signatures to use the final combined
1064
+ // signature in the sweep transaction's witness.
1065
+ haveAllSigs , finalSig , err := b .signerClient .MuSig2CombineSig (
1066
+ ctx , musig2SessionInfo .SessionID , [][]byte {serverSig },
1067
+ )
1068
+ if err != nil {
1069
+ return nil , err
1070
+ }
1071
+
1072
+ if ! haveAllSigs {
1073
+ return nil , fmt .Errorf ("failed to combine signatures" )
1074
+ }
1075
+
1076
+ // To be sure that we're good, parse and validate that the
1077
+ // combined signature is indeed valid for the sig hash and the
1078
+ // internal pubkey.
1079
+ err = b .verifySchnorrSig (htlcScript .TaprootKey , sigHash , finalSig )
1080
+ if err != nil {
1081
+ return nil , err
1082
+ }
1083
+
1084
+ return finalSig , nil
1077
1085
}
1078
1086
1079
1087
// updateRbfRate updates the fee rate we should use for the new batch
0 commit comments