mirror of
https://github.com/lightninglabs/loop.git
synced 2026-08-13 12:33:03 +02:00
instantout: verify finalized MuSig2 witnesses
Run script validation for every combined signature before accepting a finalized transaction, surfacing invalid witnesses immediately.
This commit is contained in:
parent
b3776e92f4
commit
6853e69a05
2 changed files with 54 additions and 0 deletions
|
|
@ -364,6 +364,9 @@ func (i *InstantOut) finalizeMusig2Transaction(ctx context.Context,
|
||||||
"expected %d, got %d", len(inputs), len(serverSigs))
|
"expected %d, got %d", len(inputs), len(serverSigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevOutFetcher := inputs.GetPrevoutFetcher()
|
||||||
|
sigHashes := txscript.NewTxSigHashes(tx, prevOutFetcher)
|
||||||
|
|
||||||
for idx := range inputs {
|
for idx := range inputs {
|
||||||
if musig2Sessions[idx] == nil {
|
if musig2Sessions[idx] == nil {
|
||||||
return nil, fmt.Errorf("MuSig2 session %d is nil", idx)
|
return nil, fmt.Errorf("MuSig2 session %d is nil", idx)
|
||||||
|
|
@ -382,6 +385,20 @@ func (i *InstantOut) finalizeMusig2Transaction(ctx context.Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.TxIn[idx].Witness = wire.TxWitness{finalSig}
|
tx.TxIn[idx].Witness = wire.TxWitness{finalSig}
|
||||||
|
|
||||||
|
vm, err := txscript.NewEngine(
|
||||||
|
inputs[idx].PkScript, tx, idx,
|
||||||
|
txscript.StandardVerifyFlags, nil, sigHashes,
|
||||||
|
int64(inputs[idx].Value), prevOutFetcher,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to verify final MuSig2 "+
|
||||||
|
"signature for input %d: %w", idx, err)
|
||||||
|
}
|
||||||
|
if err := vm.Execute(); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid final MuSig2 signature "+
|
||||||
|
"for input %d: %w", idx, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx, nil
|
return tx, nil
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,22 @@ import (
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightninglabs/lndclient"
|
||||||
"github.com/lightninglabs/loop/instantout/reservation"
|
"github.com/lightninglabs/loop/instantout/reservation"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type invalidFinalSigSigner struct {
|
||||||
|
lndclient.SignerClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *invalidFinalSigSigner) MuSig2CombineSig(context.Context, [32]byte,
|
||||||
|
[][]byte) (bool, []byte, error) {
|
||||||
|
|
||||||
|
return true, make([]byte, 64), nil
|
||||||
|
}
|
||||||
|
|
||||||
// TestMuSig2VectorLengthValidation verifies that malformed server-controlled
|
// TestMuSig2VectorLengthValidation verifies that malformed server-controlled
|
||||||
// vectors are rejected before they can be indexed.
|
// vectors are rejected before they can be indexed.
|
||||||
func TestMuSig2VectorLengthValidation(t *testing.T) {
|
func TestMuSig2VectorLengthValidation(t *testing.T) {
|
||||||
|
|
@ -45,3 +56,29 @@ func TestMuSig2VectorLengthValidation(t *testing.T) {
|
||||||
require.ErrorContains(t, err, "server signatures")
|
require.ErrorContains(t, err, "server signatures")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestFinalizeMuSig2TransactionVerifiesSignature verifies that a combined
|
||||||
|
// signature is validated locally before the transaction can be used as the
|
||||||
|
// instant-out safety net.
|
||||||
|
func TestFinalizeMuSig2TransactionVerifiesSignature(t *testing.T) {
|
||||||
|
_, pubKey := btcec.PrivKeyFromBytes([]byte{1})
|
||||||
|
res := &reservation.Reservation{
|
||||||
|
ClientPubkey: pubKey,
|
||||||
|
ServerPubkey: pubKey,
|
||||||
|
Value: btcutil.Amount(100_000),
|
||||||
|
Expiry: 200,
|
||||||
|
Outpoint: &wire.OutPoint{},
|
||||||
|
}
|
||||||
|
instantOut := &InstantOut{
|
||||||
|
Reservations: []*reservation.Reservation{res},
|
||||||
|
}
|
||||||
|
tx := wire.NewMsgTx(2)
|
||||||
|
tx.AddTxIn(&wire.TxIn{PreviousOutPoint: *res.Outpoint})
|
||||||
|
tx.AddTxOut(&wire.TxOut{Value: 90_000})
|
||||||
|
|
||||||
|
_, err := instantOut.finalizeMusig2Transaction(
|
||||||
|
context.Background(), &invalidFinalSigSigner{},
|
||||||
|
[]*input.MuSig2SessionInfo{{}}, tx, [][]byte{{1}},
|
||||||
|
)
|
||||||
|
require.ErrorContains(t, err, "invalid final MuSig2 signature")
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue