multi: update sweeping to allow different sighashes and claim scripts

Taproot spends require a different sighash, so we update our HtlcScript
interface to provide the appropriate sighash when sweeping. We also add
distinct Timeout/Success Script functions to allow for tapleaf spends
which have different locking scripts for different paths. Note that the
timeout and success paths will be the same for segwit v0 htlcs, because
it has a single branched script containing all spend paths.

In future iterations, this differentiation of claim scripts can also
be used to use musig2 to collaboratively keyspend P2TR htlcs with the
server. This script can be expressed as PriorityScript (because we'll
try to keyspend as a priority, and then fall back to a tap leaf spend).
As we've done here, segwit v0 spends would just return their single
script for PriorityScript, and the claim would be no different from
our other claims.
This commit is contained in:
Carla Kirk-Cohen 2022-03-29 13:17:19 +02:00 committed by Andras Banki-Horvath
parent 9610becebd
commit c7ef4297c0
No known key found for this signature in database
GPG key ID: 80E5375C094198D8
5 changed files with 121 additions and 39 deletions

View file

@ -23,7 +23,7 @@ type Sweeper struct {
func (s *Sweeper) CreateSweepTx(
globalCtx context.Context, height int32, sequence uint32,
htlc *swap.Htlc, htlcOutpoint wire.OutPoint,
keyBytes [33]byte,
keyBytes [33]byte, witnessScript []byte,
witnessFunc func(sig []byte) (wire.TxWitness, error),
amount, fee btcutil.Amount,
destAddr btcutil.Address) (*wire.MsgTx, error) {
@ -59,20 +59,30 @@ func (s *Sweeper) CreateSweepTx(
}
signDesc := lndclient.SignDescriptor{
WitnessScript: htlc.Script(),
WitnessScript: witnessScript,
Output: &wire.TxOut{
Value: int64(amount),
PkScript: htlc.PkScript,
},
HashType: txscript.SigHashAll,
HashType: htlc.SigHash(),
InputIndex: 0,
KeyDesc: keychain.KeyDescriptor{
PubKey: key,
},
}
// We need our previous outputs for taproot spends, and there's no
// harm including them for segwit v0, so we always include our prevOut.
prevOut := []*wire.TxOut{
{
Value: int64(amount),
PkScript: htlc.PkScript,
},
}
rawSigs, err := s.Lnd.Signer.SignOutputRaw(
globalCtx, sweepTx, []*lndclient.SignDescriptor{&signDesc}, nil,
globalCtx, sweepTx, []*lndclient.SignDescriptor{&signDesc},
prevOut,
)
if err != nil {
return nil, fmt.Errorf("signing: %v", err)