Merge pull request #5305 from carlaKC/sessionkey-deserialize
channeldb: read HtlcAttemptInfo session key raw bytes
This commit is contained in:
commit
f5ee874a0b
@ -53,7 +53,7 @@ type duplicateHTLCAttemptInfo struct {
|
|||||||
attemptID uint64
|
attemptID uint64
|
||||||
|
|
||||||
// sessionKey is the ephemeral key used for this attempt.
|
// 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 is the route attempted to send the HTLC.
|
||||||
route route.Route
|
route route.Route
|
||||||
@ -181,7 +181,7 @@ func fetchDuplicatePayment(bucket kvdb.RBucket) (*MPPayment, error) {
|
|||||||
HTLCAttemptInfo: HTLCAttemptInfo{
|
HTLCAttemptInfo: HTLCAttemptInfo{
|
||||||
AttemptID: attempt.attemptID,
|
AttemptID: attempt.attemptID,
|
||||||
Route: attempt.route,
|
Route: attempt.route,
|
||||||
SessionKey: attempt.sessionKey,
|
sessionKey: attempt.sessionKey,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,8 +21,15 @@ type HTLCAttemptInfo struct {
|
|||||||
// AttemptID is the unique ID used for this attempt.
|
// AttemptID is the unique ID used for this attempt.
|
||||||
AttemptID uint64
|
AttemptID uint64
|
||||||
|
|
||||||
// SessionKey is the ephemeral key used for this attempt.
|
// sessionKey is the raw bytes ephemeral key used for this attempt.
|
||||||
SessionKey *btcec.PrivateKey
|
// These bytes are lazily read off disk to save ourselves the expensive
|
||||||
|
// EC operations used by btcec.PrivKeyFromBytes.
|
||||||
|
sessionKey [btcec.PrivKeyBytesLen]byte
|
||||||
|
|
||||||
|
// cachedSessionKey is our fully deserialized sesionKey. This value
|
||||||
|
// may be nil if the attempt has just been read from disk and its
|
||||||
|
// session key has not been used yet.
|
||||||
|
cachedSessionKey *btcec.PrivateKey
|
||||||
|
|
||||||
// Route is the route attempted to send the HTLC.
|
// Route is the route attempted to send the HTLC.
|
||||||
Route route.Route
|
Route route.Route
|
||||||
@ -38,6 +45,36 @@ type HTLCAttemptInfo struct {
|
|||||||
Hash *lntypes.Hash
|
Hash *lntypes.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewHtlcAttemptInfo creates a htlc attempt.
|
||||||
|
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: scratch,
|
||||||
|
cachedSessionKey: sessionKey,
|
||||||
|
Route: route,
|
||||||
|
AttemptTime: attemptTime,
|
||||||
|
Hash: hash,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionKey returns the ephemeral key used for a htlc attempt. This function
|
||||||
|
// performs expensive ec-ops to obtain the session key if it is not cached.
|
||||||
|
func (h *HTLCAttemptInfo) SessionKey() *btcec.PrivateKey {
|
||||||
|
if h.cachedSessionKey == nil {
|
||||||
|
h.cachedSessionKey, _ = btcec.PrivKeyFromBytes(
|
||||||
|
btcec.S256(), h.sessionKey[:],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return h.cachedSessionKey
|
||||||
|
}
|
||||||
|
|
||||||
// HTLCAttempt contains information about a specific HTLC attempt for a given
|
// HTLCAttempt contains information about a specific HTLC attempt for a given
|
||||||
// payment. It contains the HTLCAttemptInfo used to send the HTLC, as well
|
// payment. It contains the HTLCAttemptInfo used to send the HTLC, as well
|
||||||
// as a timestamp and any known outcome of the attempt.
|
// as a timestamp and any known outcome of the attempt.
|
||||||
|
27
channeldb/mp_payment_test.go
Normal file
27
channeldb/mp_payment_test.go
Normal file
@ -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)
|
||||||
|
}
|
@ -37,17 +37,15 @@ func genInfo() (*PaymentCreationInfo, *HTLCAttemptInfo,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rhash := sha256.Sum256(preimage[:])
|
rhash := sha256.Sum256(preimage[:])
|
||||||
|
attempt := NewHtlcAttemptInfo(
|
||||||
|
0, priv, *testRoute.Copy(), time.Time{}, nil,
|
||||||
|
)
|
||||||
return &PaymentCreationInfo{
|
return &PaymentCreationInfo{
|
||||||
PaymentIdentifier: rhash,
|
PaymentIdentifier: rhash,
|
||||||
Value: testRoute.ReceiverAmt(),
|
Value: testRoute.ReceiverAmt(),
|
||||||
CreationTime: time.Unix(time.Now().Unix(), 0),
|
CreationTime: time.Unix(time.Now().Unix(), 0),
|
||||||
PaymentRequest: []byte("hola"),
|
PaymentRequest: []byte("hola"),
|
||||||
},
|
}, attempt, preimage, nil
|
||||||
&HTLCAttemptInfo{
|
|
||||||
AttemptID: 0,
|
|
||||||
SessionKey: priv,
|
|
||||||
Route: *testRoute.Copy(),
|
|
||||||
}, preimage, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestPaymentControlSwitchFail checks that payment status returns to Failed
|
// TestPaymentControlSwitchFail checks that payment status returns to Failed
|
||||||
|
@ -919,7 +919,7 @@ func deserializePaymentCreationInfo(r io.Reader) (*PaymentCreationInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error {
|
func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error {
|
||||||
if err := WriteElements(w, a.SessionKey); err != nil {
|
if err := WriteElements(w, a.sessionKey); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -945,7 +945,7 @@ func serializeHTLCAttemptInfo(w io.Writer, a *HTLCAttemptInfo) error {
|
|||||||
|
|
||||||
func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) {
|
func deserializeHTLCAttemptInfo(r io.Reader) (*HTLCAttemptInfo, error) {
|
||||||
a := &HTLCAttemptInfo{}
|
a := &HTLCAttemptInfo{}
|
||||||
err := ReadElements(r, &a.SessionKey)
|
err := ReadElements(r, &a.sessionKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -68,13 +68,10 @@ func makeFakeInfo() (*PaymentCreationInfo, *HTLCAttemptInfo) {
|
|||||||
PaymentRequest: []byte(""),
|
PaymentRequest: []byte(""),
|
||||||
}
|
}
|
||||||
|
|
||||||
a := &HTLCAttemptInfo{
|
a := NewHtlcAttemptInfo(
|
||||||
AttemptID: 44,
|
44, priv, testRoute, time.Unix(100, 0), &hash,
|
||||||
SessionKey: priv,
|
)
|
||||||
Route: testRoute,
|
|
||||||
AttemptTime: time.Unix(100, 0),
|
|
||||||
Hash: &hash,
|
|
||||||
}
|
|
||||||
return c, a
|
return c, a
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,9 +120,11 @@ func TestSentPaymentSerialization(t *testing.T) {
|
|||||||
newWireInfo.Route = route.Route{}
|
newWireInfo.Route = route.Route{}
|
||||||
s.Route = route.Route{}
|
s.Route = route.Route{}
|
||||||
|
|
||||||
|
// Call session key method to set our cached session key so we can use
|
||||||
|
// DeepEqual, and assert that our key equals the original key.
|
||||||
|
require.Equal(t, s.cachedSessionKey, newWireInfo.SessionKey())
|
||||||
|
|
||||||
if !reflect.DeepEqual(s, newWireInfo) {
|
if !reflect.DeepEqual(s, newWireInfo) {
|
||||||
s.SessionKey.Curve = nil
|
|
||||||
newWireInfo.SessionKey.Curve = nil
|
|
||||||
t.Fatalf("Payments do not match after "+
|
t.Fatalf("Payments do not match after "+
|
||||||
"serialization/deserialization %v vs %v",
|
"serialization/deserialization %v vs %v",
|
||||||
spew.Sdump(s), spew.Sdump(newWireInfo),
|
spew.Sdump(s), spew.Sdump(newWireInfo),
|
||||||
|
@ -331,11 +331,9 @@ func genInfo() (*channeldb.PaymentCreationInfo, *channeldb.HTLCAttemptInfo,
|
|||||||
CreationTime: time.Unix(time.Now().Unix(), 0),
|
CreationTime: time.Unix(time.Now().Unix(), 0),
|
||||||
PaymentRequest: []byte("hola"),
|
PaymentRequest: []byte("hola"),
|
||||||
},
|
},
|
||||||
&channeldb.HTLCAttemptInfo{
|
channeldb.NewHtlcAttemptInfo(
|
||||||
AttemptID: 1,
|
1, priv, testRoute, time.Time{}, nil,
|
||||||
SessionKey: priv,
|
), preimage, nil
|
||||||
Route: testRoute,
|
|
||||||
}, preimage, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func genPreimage() ([32]byte, error) {
|
func genPreimage() ([32]byte, error) {
|
||||||
|
@ -499,7 +499,7 @@ func (p *shardHandler) collectResult(attempt *channeldb.HTLCAttemptInfo) (
|
|||||||
|
|
||||||
// Regenerate the circuit for this attempt.
|
// Regenerate the circuit for this attempt.
|
||||||
_, circuit, err := generateSphinxPacket(
|
_, circuit, err := generateSphinxPacket(
|
||||||
&attempt.Route, hash[:], attempt.SessionKey,
|
&attempt.Route, hash[:], attempt.SessionKey(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -677,15 +677,11 @@ func (p *shardHandler) createNewPaymentAttempt(rt *route.Route, lastShard bool)
|
|||||||
rt.Hops[0].ChannelID,
|
rt.Hops[0].ChannelID,
|
||||||
)
|
)
|
||||||
|
|
||||||
// We now have all the information needed to populate
|
// We now have all the information needed to populate the current
|
||||||
// the current attempt information.
|
// attempt information.
|
||||||
attempt := &channeldb.HTLCAttemptInfo{
|
attempt := channeldb.NewHtlcAttemptInfo(
|
||||||
AttemptID: attemptID,
|
attemptID, sessionKey, *rt, p.router.cfg.Clock.Now(), &hash,
|
||||||
AttemptTime: p.router.cfg.Clock.Now(),
|
)
|
||||||
SessionKey: sessionKey,
|
|
||||||
Route: *rt,
|
|
||||||
Hash: &hash,
|
|
||||||
}
|
|
||||||
|
|
||||||
return firstHop, htlcAdd, attempt, nil
|
return firstHop, htlcAdd, attempt, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user