From 5336f03ac64773a7a0fad11d7995c1adc1195ddd Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 19 Jan 2023 19:21:49 -0800 Subject: [PATCH] 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. --- lnwallet/channel.go | 62 ++++++++++++++++++++++++++++++++------------- lnwallet/sigpool.go | 6 +++-- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/lnwallet/channel.go b/lnwallet/channel.go index f348d150d..3f360e160 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -3297,7 +3297,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, // If the HTLC isn't dust, then we'll create an empty sign job // to add to the batch momentarily. - sigJob := SignJob{} + var sigJob SignJob sigJob.Cancel = cancelChan sigJob.Resp = make(chan SignJobResp, 1) @@ -3324,21 +3324,35 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, 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 // signature to give to the remote party for this commitment // transaction. Note we use the raw HTLC amount. - txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex] sigJob.SignDesc = input.SignDescriptor{ - KeyDesc: localChanCfg.HtlcBasePoint, - SingleTweak: keyRing.LocalHtlcKeyTweak, - WitnessScript: htlc.theirWitnessScript, - Output: txOut, - HashType: sigHashType, - SigHashes: input.NewTxSigHashesV0Only(sigJob.Tx), - InputIndex: 0, + KeyDesc: localChanCfg.HtlcBasePoint, + SingleTweak: keyRing.LocalHtlcKeyTweak, + WitnessScript: htlc.theirWitnessScript, + Output: txOut, + PrevOutputFetcher: prevFetcher, + HashType: sigHashType, + SigHashes: hashCache, + InputIndex: 0, } 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) } for _, htlc := range remoteCommitView.outgoingHTLCs { @@ -3378,21 +3392,35 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing, 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 // signature to give to the remote party for this commitment // transaction. Note we use the raw HTLC amount. - txOut := remoteCommitView.txn.TxOut[htlc.remoteOutputIndex] sigJob.SignDesc = input.SignDescriptor{ - KeyDesc: localChanCfg.HtlcBasePoint, - SingleTweak: keyRing.LocalHtlcKeyTweak, - WitnessScript: htlc.theirWitnessScript, - Output: txOut, - HashType: sigHashType, - SigHashes: input.NewTxSigHashesV0Only(sigJob.Tx), - InputIndex: 0, + KeyDesc: localChanCfg.HtlcBasePoint, + SingleTweak: keyRing.LocalHtlcKeyTweak, + WitnessScript: htlc.theirWitnessScript, + Output: txOut, + PrevOutputFetcher: prevFetcher, + HashType: sigHashType, + SigHashes: hashCache, + InputIndex: 0, } 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) } diff --git a/lnwallet/sigpool.go b/lnwallet/sigpool.go index 0ebc3a931..2424757f9 100644 --- a/lnwallet/sigpool.go +++ b/lnwallet/sigpool.go @@ -113,8 +113,6 @@ type SignJobResp struct { Err error } -// TODO(roasbeef); fix description - // SigPool is a struct that is meant to allow the current channel state // machine to parallelize all signature generation and verification. This // 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) + select { case sigMsg.Resp <- SignJobResp{ Sig: sig,