diff --git a/channeldb/duplicate_payments.go b/channeldb/duplicate_payments.go index 1a1fdae7..7dad7df7 100644 --- a/channeldb/duplicate_payments.go +++ b/channeldb/duplicate_payments.go @@ -53,7 +53,7 @@ type duplicateHTLCAttemptInfo struct { attemptID uint64 // sessionKey is the ephemeral key used for this attempt. - sessionKey *btcec.PrivateKey + sessionKey [btcec.PrivKeyBytesLen]byte // route is the route attempted to send the HTLC. route route.Route diff --git a/channeldb/mp_payment.go b/channeldb/mp_payment.go index 8603c291..6c41647e 100644 --- a/channeldb/mp_payment.go +++ b/channeldb/mp_payment.go @@ -21,8 +21,10 @@ type HTLCAttemptInfo struct { // AttemptID is the unique ID used for this attempt. AttemptID uint64 - // sessionKey is the ephemeral key used for this attempt. - sessionKey *btcec.PrivateKey + // sessionKey is the raw bytes ephemeral key used for this attempt. + // These bytes are lazily read off disk to save ourselves the expensive + // EC operations used by btcec.PrivKeyFromBytes. + sessionKey [btcec.PrivKeyBytesLen]byte // Route is the route attempted to send the HTLC. Route route.Route @@ -43,18 +45,23 @@ func NewHtlcAttemptInfo(attemptID uint64, sessionKey *btcec.PrivateKey, route route.Route, attemptTime time.Time, hash *lntypes.Hash) *HTLCAttemptInfo { + var scratch [btcec.PrivKeyBytesLen]byte + copy(scratch[:], sessionKey.Serialize()) + return &HTLCAttemptInfo{ AttemptID: attemptID, - sessionKey: sessionKey, + sessionKey: scratch, Route: route, AttemptTime: attemptTime, Hash: hash, } } -// SessionKey returns the ephemeral key used for a htlc attempt. +// SessionKey returns the ephemeral key used for a htlc attempt. This function +// performs expensive ec-ops to obtain the session key. func (h *HTLCAttemptInfo) SessionKey() *btcec.PrivateKey { - return h.sessionKey + priv, _ := btcec.PrivKeyFromBytes(btcec.S256(), h.sessionKey[:]) + return priv } // HTLCAttempt contains information about a specific HTLC attempt for a given diff --git a/channeldb/mp_payment_test.go b/channeldb/mp_payment_test.go new file mode 100644 index 00000000..eb5f0f48 --- /dev/null +++ b/channeldb/mp_payment_test.go @@ -0,0 +1,27 @@ +package channeldb + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestLazySessionKeyDeserialize tests that we can read htlc attempt session +// keys that were previously serialized as a private key as raw bytes. +func TestLazySessionKeyDeserialize(t *testing.T) { + var b bytes.Buffer + + // Serialize as a private key. + err := WriteElements(&b, priv) + require.NoError(t, err) + + // Deserialize into [btcec.PrivKeyBytesLen]byte. + attempt := HTLCAttemptInfo{} + err = ReadElements(&b, &attempt.sessionKey) + require.NoError(t, err) + require.Zero(t, b.Len()) + + sessionKey := attempt.SessionKey() + require.Equal(t, priv, sessionKey) +} diff --git a/channeldb/payment_control_test.go b/channeldb/payment_control_test.go index a4e9c846..4c9fcf00 100644 --- a/channeldb/payment_control_test.go +++ b/channeldb/payment_control_test.go @@ -37,17 +37,15 @@ func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo, } rhash := sha256.Sum256(preimage[:]) + attempt := NewHtlcAttemptInfo( + 0, priv, *testRoute.Copy(), time.Time{}, nil, + ) return &PaymentCreationInfo{ - PaymentIdentifier: rhash, - Value: testRoute.ReceiverAmt(), - CreationTime: time.Unix(time.Now().Unix(), 0), - PaymentRequest: []byte("hola"), - }, - &HTLCAttemptInfo{ - AttemptID: 0, - sessionKey: priv, - Route: *testRoute.Copy(), - }, preimage, nil + PaymentIdentifier: rhash, + Value: testRoute.ReceiverAmt(), + CreationTime: time.Unix(time.Now().Unix(), 0), + PaymentRequest: []byte("hola"), + }, attempt, preimage, nil } // TestPaymentControlSwitchFail checks that payment status returns to Failed diff --git a/channeldb/payments_test.go b/channeldb/payments_test.go index 1ef0e7dd..37b20b51 100644 --- a/channeldb/payments_test.go +++ b/channeldb/payments_test.go @@ -68,13 +68,10 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) { PaymentRequest: []byte(""), } - a := &HTLCAttemptInfo{ - AttemptID: 44, - sessionKey: priv, - Route: testRoute, - AttemptTime: time.Unix(100, 0), - Hash: &hash, - } + a := NewHtlcAttemptInfo( + 44, priv, testRoute, time.Unix(100, 0), &hash, + ) + return c, a }