diff --git a/docs/release-notes/release-notes-0.15.0.md b/docs/release-notes/release-notes-0.15.0.md index e8c3c3e08..fcee2e324 100644 --- a/docs/release-notes/release-notes-0.15.0.md +++ b/docs/release-notes/release-notes-0.15.0.md @@ -84,6 +84,10 @@ then watch it on chain. Taproot script spends are also supported through the * [Fixed race condition resulting in MPP payments sometimes getting stuck in-flight](https://github.com/lightningnetwork/lnd/pull/6352). +* [Fixed a panic in the Taproot signing part of the `SignOutputRaw` RPC that + occurred when not all UTXO information was + specified](https://github.com/lightningnetwork/lnd/pull/6407). + ## Misc * [An example systemd service file](https://github.com/lightningnetwork/lnd/pull/6033) diff --git a/lnrpc/signrpc/signer_server.go b/lnrpc/signrpc/signer_server.go index 1474c0ec9..b191176b3 100644 --- a/lnrpc/signrpc/signer_server.go +++ b/lnrpc/signrpc/signer_server.go @@ -376,6 +376,24 @@ func (s *Server) SignOutputRaw(_ context.Context, in *SignReq) (*SignResp, InputIndex: int(signDesc.InputIndex), PrevOutputFetcher: prevOutputFetcher, }) + + // Are we trying to sign for a Taproot output? Then we need all + // previous outputs being declared, otherwise we'd run into a + // panic later on. + if txscript.IsPayToTaproot(signDesc.Output.PkScript) { + for idx, txIn := range txToSign.TxIn { + utxo := prevOutputFetcher.FetchPrevOutput( + txIn.PreviousOutPoint, + ) + if utxo == nil { + return nil, fmt.Errorf("error signing "+ + "taproot output, transaction "+ + "input %d is missing its "+ + "previous outpoint information", + idx) + } + } + } } // Now that we've mapped all the proper sign descriptors, we can diff --git a/lntest/itest/lnd_taproot_test.go b/lntest/itest/lnd_taproot_test.go index cb0510a49..20d5d37dc 100644 --- a/lntest/itest/lnd_taproot_test.go +++ b/lntest/itest/lnd_taproot_test.go @@ -232,6 +232,29 @@ func testTaprootScriptSpend(ctxt context.Context, t *harnessTest, PkScript: p2trPkScript, Value: 800_000, }} + + // Before we actually sign, we want to make sure that we get an error + // when we try to sign for a Taproot output without specifying all UTXO + // information. + _, err = net.Alice.SignerClient.SignOutputRaw( + ctxt, &signrpc.SignReq{ + RawTxBytes: buf.Bytes(), + SignDescs: []*signrpc.SignDescriptor{{ + Output: utxoInfo[0], + InputIndex: 0, + KeyDesc: keyDesc, + Sighash: uint32(txscript.SigHashDefault), + WitnessScript: leaf2.Script, + }}, + }, + ) + require.Error(t.t, err) + require.Contains( + t.t, err.Error(), "error signing taproot output, transaction "+ + "input 0 is missing its previous outpoint information", + ) + + // Do the actual signing now. signResp, err := net.Alice.SignerClient.SignOutputRaw( ctxt, &signrpc.SignReq{ RawTxBytes: buf.Bytes(), diff --git a/rpcserver.go b/rpcserver.go index 6c768d0f9..21e975587 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -2539,6 +2539,7 @@ func createRPCCloseUpdate(update interface{}) ( Update: &lnrpc.CloseStatusUpdate_ChanClose{ ChanClose: &lnrpc.ChannelCloseUpdate{ ClosingTxid: u.ClosingTxid, + Success: u.Success, }, }, }, nil