Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/release-notes/release-notes-0.20.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
in the mission control store. Now we skip over potential errors and also
delete them from the store.

* [Fixed an issue](https://github.com/lightningnetwork/lnd/pull/10399) where the
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to make this change in the release notes in the back port pr? I am assuming it was handled in the original merge to master

Copy link
Contributor Author

@mohamedawnallah mohamedawnallah Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to make this change in the release notes in the back port pr? I am assuming it was handled in the original merge to master

It mirrors this merged one: 2590593 as part of #10418

TLS manager would fail to start if only one of the TLS pair files (certificate
or key) existed. The manager now correctly regenerates both files when either
is missing, preventing "file not found" errors on startup.

# New Features

## Functional Enhancements
Expand Down
4 changes: 2 additions & 2 deletions tls_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,8 @@ func (t *TLSManager) generateOrRenewCert() (*tls.Config, error) {
// is already written to disk, this function overwrites the plaintext key with
// the encrypted form.
func (t *TLSManager) generateCertPair(keyRing keychain.SecretKeyRing) error {
// Ensure we create TLS key and certificate if they don't exist.
if lnrpc.FileExists(t.cfg.TLSCertPath) ||
// Ensure we create TLS key and certificate if they don't both exist.
if lnrpc.FileExists(t.cfg.TLSCertPath) &&
lnrpc.FileExists(t.cfg.TLSKeyPath) {

// Handle discrepencies related to the TLSEncryptKey setting.
Expand Down
89 changes: 89 additions & 0 deletions tls_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,92 @@ func newTestDirectory(t *testing.T) (string, string, string) {

return tempDir, certPath, keyPath
}

// TestGenerateCertPairWithPartialFiles tests that generateCertPair regenerates
// a cert/key pair when only one file exists.
func TestGenerateCertPairWithPartialFiles(t *testing.T) {
t.Parallel()

keyRing := &mock.SecretKeyRing{
RootKey: privKey,
}

testCases := []struct {
name string
setup func(t *testing.T, certPath, keyPath string)
}{
{
name: "only key exists",
setup: func(t *testing.T, certPath, keyPath string) {
// Create only a key file. It simulates leftover
// from previous run.
_, keyBytes := genCertPair(t, false)
keyBuf := &bytes.Buffer{}
err := pem.Encode(
keyBuf, &pem.Block{
Type: "EC PRIVATE KEY",
Bytes: keyBytes,
},
)
require.NoError(t, err)

err = os.WriteFile(
keyPath, keyBuf.Bytes(), 0600,
)
require.NoError(t, err)
},
},
{
name: "only cert exists",
setup: func(t *testing.T, certPath, keyPath string) {
// Create only a cert file. It simulates
// leftover from previous run.
certBytes, _ := genCertPair(t, false)
certBuf := &bytes.Buffer{}
err := pem.Encode(
certBuf, &pem.Block{
Type: "CERTIFICATE",
Bytes: certBytes,
},
)
require.NoError(t, err)

err = os.WriteFile(
certPath, certBuf.Bytes(), 0644,
)
require.NoError(t, err)
},
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()

tempDir := t.TempDir()
certPath := tempDir + "/tls.cert"
keyPath := tempDir + "/tls.key"

tc.setup(t, certPath, keyPath)

cfg := &TLSManagerCfg{
TLSCertPath: certPath,
TLSKeyPath: keyPath,
TLSCertDuration: testTLSCertDuration,
}
tlsManager := NewTLSManager(cfg)

err := tlsManager.generateCertPair(keyRing)
require.NoError(
t, err, "should generate new cert pair when %s",
tc.name,
)

_, _, err = cert.GetCertBytesFromPath(certPath, keyPath)
require.NoError(
t, err, "should be able to load cert pair",
)
})
}
}
Loading