lnwallet: update to genRemoteHtlcSigJobs to generate taproot jobs

In this commit, we update the genRemoteHtlcSigJobs function to be able
to generate taproot jobs. We also modify the sigpool to now use a
input.Signature everywhere. This'll allow us to pass around both ECDSA
and Schnorr signatures via the same interface.

We use a tapscript sighash in this case, as all the HTLC spends will
actually be script path spends.
This commit is contained in:
Olaoluwa Osuntokun
2023-01-19 19:21:49 -08:00
parent ca21c4bdb4
commit 5336f03ac6
2 changed files with 49 additions and 19 deletions

View File

@@ -3297,7 +3297,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
// If the HTLC isn't dust, then we'll create an empty sign job // If the HTLC isn't dust, then we'll create an empty sign job
// to add to the batch momentarily. // to add to the batch momentarily.
sigJob := SignJob{} var sigJob SignJob
sigJob.Cancel = cancelChan sigJob.Cancel = cancelChan
sigJob.Resp = make(chan SignJobResp, 1) sigJob.Resp = make(chan SignJobResp, 1)
@@ -3324,21 +3324,35 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
return nil, nil, err return nil, nil, err
} }
// Construct a full hash cache as we may be signing a segwit v1
// sighash.
txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex]
prevFetcher := txscript.NewCannedPrevOutputFetcher(
txOut.PkScript, int64(htlc.Amount.ToSatoshis()),
)
hashCache := txscript.NewTxSigHashes(sigJob.Tx, prevFetcher)
// Finally, we'll generate a sign descriptor to generate a // Finally, we'll generate a sign descriptor to generate a
// signature to give to the remote party for this commitment // signature to give to the remote party for this commitment
// transaction. Note we use the raw HTLC amount. // transaction. Note we use the raw HTLC amount.
txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex]
sigJob.SignDesc = input.SignDescriptor{ sigJob.SignDesc = input.SignDescriptor{
KeyDesc: localChanCfg.HtlcBasePoint, KeyDesc: localChanCfg.HtlcBasePoint,
SingleTweak: keyRing.LocalHtlcKeyTweak, SingleTweak: keyRing.LocalHtlcKeyTweak,
WitnessScript: htlc.theirWitnessScript, WitnessScript: htlc.theirWitnessScript,
Output: txOut, Output: txOut,
PrevOutputFetcher: prevFetcher,
HashType: sigHashType, HashType: sigHashType,
SigHashes: input.NewTxSigHashesV0Only(sigJob.Tx), SigHashes: hashCache,
InputIndex: 0, InputIndex: 0,
} }
sigJob.OutputIndex = htlc.remoteOutputIndex sigJob.OutputIndex = htlc.remoteOutputIndex
// If this is a taproot channel, then we'll need to set the
// method type to ensure we generate a valid signature.
if chanType.IsTaproot() {
sigJob.SignDesc.SignMethod = input.TaprootScriptSpendSignMethod
}
sigBatch = append(sigBatch, sigJob) sigBatch = append(sigBatch, sigJob)
} }
for _, htlc := range remoteCommitView.outgoingHTLCs { for _, htlc := range remoteCommitView.outgoingHTLCs {
@@ -3378,21 +3392,35 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
return nil, nil, err return nil, nil, err
} }
// Construct a full hash cache as we may be signing a segwit v1
// sighash.
txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex]
prevFetcher := txscript.NewCannedPrevOutputFetcher(
txOut.PkScript, int64(htlc.Amount.ToSatoshis()),
)
hashCache := txscript.NewTxSigHashes(sigJob.Tx, prevFetcher)
// Finally, we'll generate a sign descriptor to generate a // Finally, we'll generate a sign descriptor to generate a
// signature to give to the remote party for this commitment // signature to give to the remote party for this commitment
// transaction. Note we use the raw HTLC amount. // transaction. Note we use the raw HTLC amount.
txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex]
sigJob.SignDesc = input.SignDescriptor{ sigJob.SignDesc = input.SignDescriptor{
KeyDesc: localChanCfg.HtlcBasePoint, KeyDesc: localChanCfg.HtlcBasePoint,
SingleTweak: keyRing.LocalHtlcKeyTweak, SingleTweak: keyRing.LocalHtlcKeyTweak,
WitnessScript: htlc.theirWitnessScript, WitnessScript: htlc.theirWitnessScript,
Output: txOut, Output: txOut,
PrevOutputFetcher: prevFetcher,
HashType: sigHashType, HashType: sigHashType,
SigHashes: input.NewTxSigHashesV0Only(sigJob.Tx), SigHashes: hashCache,
InputIndex: 0, InputIndex: 0,
} }
sigJob.OutputIndex = htlc.remoteOutputIndex sigJob.OutputIndex = htlc.remoteOutputIndex
// If this is a taproot channel, then we'll need to set the
// method type to ensure we generate a valid signature.
if chanType.IsTaproot() {
sigJob.SignDesc.SignMethod = input.TaprootScriptSpendSignMethod
}
sigBatch = append(sigBatch, sigJob) sigBatch = append(sigBatch, sigJob)
} }

View File

@@ -113,8 +113,6 @@ type SignJobResp struct {
Err error Err error
} }
// TODO(roasbeef); fix description
// SigPool is a struct that is meant to allow the current channel state // SigPool is a struct that is meant to allow the current channel state
// machine to parallelize all signature generation and verification. This // machine to parallelize all signature generation and verification. This
// struct is needed as _each_ HTLC when creating a commitment transaction // struct is needed as _each_ HTLC when creating a commitment transaction
@@ -206,7 +204,11 @@ func (s *SigPool) poolWorker() {
} }
} }
// Use the sig mapper to go from the input.Signature
// into the serialized lnwire.Sig that we'll send
// across the wire.
sig, err := lnwire.NewSigFromSignature(rawSig) sig, err := lnwire.NewSigFromSignature(rawSig)
select { select {
case sigMsg.Resp <- SignJobResp{ case sigMsg.Resp <- SignJobResp{
Sig: sig, Sig: sig,