2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-06 03:20:38 +00:00

sweepbatcher: factor out method musig2sign

It is long and is going to be even longer and hard to keep it inside a loop.
This commit is contained in:
Boris Nagaev 2024-06-23 13:34:03 -03:00
parent 822e4746c1
commit 3d5b7db1f7
No known key found for this signature in database

View File

@ -896,11 +896,9 @@ func (b *batch) publishBatchCoop(ctx context.Context) (btcutil.Amount,
return fee, err, false return fee, err, false
} }
prevOutputFetcher := txscript.NewMultiPrevOutFetcher(prevOuts)
// Attempt to cooperatively sign the batch tx with the server. // Attempt to cooperatively sign the batch tx with the server.
err = b.coopSignBatchTx( err = b.coopSignBatchTx(
ctx, packet, sweeps, prevOutputFetcher, prevOuts, psbtBuf, ctx, packet, sweeps, prevOuts, psbtBuf.Bytes(),
) )
if err != nil { if err != nil {
return fee, err, false return fee, err, false
@ -942,24 +940,44 @@ func (b *batch) debugLogTx(msg string, tx *wire.MsgTx) {
// coopSignBatchTx collects the necessary signatures from the server in order // coopSignBatchTx collects the necessary signatures from the server in order
// to cooperatively sweep the funds. // to cooperatively sweep the funds.
func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet, func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
sweeps []sweep, prevOutputFetcher *txscript.MultiPrevOutFetcher, sweeps []sweep, prevOuts map[wire.OutPoint]*wire.TxOut,
prevOuts map[wire.OutPoint]*wire.TxOut, psbtBuf bytes.Buffer) error { psbt []byte) error {
for i, sweep := range sweeps { for i, sweep := range sweeps {
sweep := sweep sweep := sweep
sigHashes := txscript.NewTxSigHashes( finalSig, err := b.musig2sign(
packet.UnsignedTx, prevOutputFetcher, ctx, i, sweep, packet.UnsignedTx, prevOuts, psbt,
)
sigHash, err := txscript.CalcTaprootSignatureHash(
sigHashes, txscript.SigHashDefault, packet.UnsignedTx,
i, prevOutputFetcher,
) )
if err != nil { if err != nil {
return err return err
} }
packet.UnsignedTx.TxIn[i].Witness = wire.TxWitness{
finalSig,
}
}
return nil
}
// musig2sign signs one sweep using musig2.
func (b *batch) musig2sign(ctx context.Context, inputIndex int, sweep sweep,
unsignedTx *wire.MsgTx, prevOuts map[wire.OutPoint]*wire.TxOut,
psbt []byte) ([]byte, error) {
prevOutputFetcher := txscript.NewMultiPrevOutFetcher(prevOuts)
sigHashes := txscript.NewTxSigHashes(unsignedTx, prevOutputFetcher)
sigHash, err := txscript.CalcTaprootSignatureHash(
sigHashes, txscript.SigHashDefault, unsignedTx, inputIndex,
prevOutputFetcher,
)
if err != nil {
return nil, err
}
var ( var (
signers [][]byte signers [][]byte
muSig2Version input.MuSig2Version muSig2Version input.MuSig2Version
@ -983,20 +1001,18 @@ func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
htlcScript, ok := sweep.htlc.HtlcScript.(*swap.HtlcScriptV3) htlcScript, ok := sweep.htlc.HtlcScript.(*swap.HtlcScriptV3)
if !ok { if !ok {
return fmt.Errorf("invalid htlc script version") return nil, fmt.Errorf("invalid htlc script version")
} }
// Now we're creating a local MuSig2 session using the receiver // Now we're creating a local MuSig2 session using the receiver key's
// key's key locator and the htlc's root hash. // key locator and the htlc's root hash.
keyLocator := &sweep.htlcKeys.ClientScriptKeyLocator
musig2SessionInfo, err := b.signerClient.MuSig2CreateSession( musig2SessionInfo, err := b.signerClient.MuSig2CreateSession(
ctx, muSig2Version, ctx, muSig2Version, keyLocator, signers,
&sweep.htlcKeys.ClientScriptKeyLocator, signers, lndclient.MuSig2TaprootTweakOpt(htlcScript.RootHash[:], false),
lndclient.MuSig2TaprootTweakOpt(
htlcScript.RootHash[:], false,
),
) )
if err != nil { if err != nil {
return fmt.Errorf("signerClient.MuSig2CreateSession "+ return nil, fmt.Errorf("signerClient.MuSig2CreateSession "+
"failed: %w", err) "failed: %w", err)
} }
@ -1007,11 +1023,10 @@ func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
serverNonce, serverSig, err := b.muSig2SignSweep( serverNonce, serverSig, err := b.muSig2SignSweep(
ctx, sweep.protocolVersion, sweep.swapHash, ctx, sweep.protocolVersion, sweep.swapHash,
sweep.swapInvoicePaymentAddr, sweep.swapInvoicePaymentAddr,
musig2SessionInfo.PublicNonce[:], psbtBuf.Bytes(), musig2SessionInfo.PublicNonce[:], psbt, prevOuts,
prevOuts,
) )
if err != nil { if err != nil {
return err return nil, err
} }
var serverPublicNonce [musig2.PubNonceSize]byte var serverPublicNonce [musig2.PubNonceSize]byte
@ -1024,12 +1039,12 @@ func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
[][musig2.PubNonceSize]byte{serverPublicNonce}, [][musig2.PubNonceSize]byte{serverPublicNonce},
) )
if err != nil { if err != nil {
return err return nil, err
} }
// Sanity check that we have all the nonces. // Sanity check that we have all the nonces.
if !haveAllNonces { if !haveAllNonces {
return fmt.Errorf("invalid MuSig2 session: " + return nil, fmt.Errorf("invalid MuSig2 session: " +
"nonces missing") "nonces missing")
} }
@ -1042,7 +1057,7 @@ func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
ctx, musig2SessionInfo.SessionID, digest, false, ctx, musig2SessionInfo.SessionID, digest, false,
) )
if err != nil { if err != nil {
return err return nil, err
} }
// Now combine the partial signatures to use the final combined // Now combine the partial signatures to use the final combined
@ -1051,29 +1066,22 @@ func (b *batch) coopSignBatchTx(ctx context.Context, packet *psbt.Packet,
ctx, musig2SessionInfo.SessionID, [][]byte{serverSig}, ctx, musig2SessionInfo.SessionID, [][]byte{serverSig},
) )
if err != nil { if err != nil {
return err return nil, err
} }
if !haveAllSigs { if !haveAllSigs {
return fmt.Errorf("failed to combine signatures") return nil, fmt.Errorf("failed to combine signatures")
} }
// To be sure that we're good, parse and validate that the // To be sure that we're good, parse and validate that the
// combined signature is indeed valid for the sig hash and the // combined signature is indeed valid for the sig hash and the
// internal pubkey. // internal pubkey.
err = b.verifySchnorrSig( err = b.verifySchnorrSig(htlcScript.TaprootKey, sigHash, finalSig)
htlcScript.TaprootKey, sigHash, finalSig,
)
if err != nil { if err != nil {
return err return nil, err
} }
packet.UnsignedTx.TxIn[i].Witness = wire.TxWitness{ return finalSig, nil
finalSig,
}
}
return nil
} }
// updateRbfRate updates the fee rate we should use for the new batch // updateRbfRate updates the fee rate we should use for the new batch