-
Notifications
You must be signed in to change notification settings - Fork 2.2k
lnrpc: add HtlcIndex to ForwardingEvents #9813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
package channeldb | ||
|
||
import ( | ||
"bytes" | ||
"math/rand" | ||
"reflect" | ||
"testing" | ||
"time" | ||
|
||
"github.com/davecgh/go-spew/spew" | ||
"github.com/lightningnetwork/lnd/fn/v2" | ||
"github.com/lightningnetwork/lnd/kvdb" | ||
"github.com/lightningnetwork/lnd/lnwire" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
|
@@ -41,6 +44,8 @@ func TestForwardingLogBasicStorageAndQuery(t *testing.T) { | |
OutgoingChanID: lnwire.NewShortChanIDFromInt(uint64(rand.Int63())), | ||
AmtIn: lnwire.MilliSatoshi(rand.Int63()), | ||
AmtOut: lnwire.MilliSatoshi(rand.Int63()), | ||
IncomingHtlcID: fn.Some(uint64(i)), | ||
OutgoingHtlcID: fn.Some(uint64(i)), | ||
} | ||
|
||
timestamp = timestamp.Add(time.Minute * 10) | ||
|
@@ -109,6 +114,8 @@ func TestForwardingLogQueryOptions(t *testing.T) { | |
OutgoingChanID: lnwire.NewShortChanIDFromInt(uint64(rand.Int63())), | ||
AmtIn: lnwire.MilliSatoshi(rand.Int63()), | ||
AmtOut: lnwire.MilliSatoshi(rand.Int63()), | ||
IncomingHtlcID: fn.Some(uint64(i)), | ||
OutgoingHtlcID: fn.Some(uint64(i)), | ||
} | ||
|
||
endTime = endTime.Add(time.Minute * 10) | ||
|
@@ -208,6 +215,8 @@ func TestForwardingLogQueryLimit(t *testing.T) { | |
OutgoingChanID: lnwire.NewShortChanIDFromInt(uint64(rand.Int63())), | ||
AmtIn: lnwire.MilliSatoshi(rand.Int63()), | ||
AmtOut: lnwire.MilliSatoshi(rand.Int63()), | ||
IncomingHtlcID: fn.Some(uint64(i)), | ||
OutgoingHtlcID: fn.Some(uint64(i)), | ||
} | ||
|
||
endTime = endTime.Add(time.Minute * 10) | ||
|
@@ -317,6 +326,8 @@ func TestForwardingLogStoreEvent(t *testing.T) { | |
OutgoingChanID: lnwire.NewShortChanIDFromInt(uint64(rand.Int63())), | ||
AmtIn: lnwire.MilliSatoshi(rand.Int63()), | ||
AmtOut: lnwire.MilliSatoshi(rand.Int63()), | ||
IncomingHtlcID: fn.Some(uint64(i)), | ||
OutgoingHtlcID: fn.Some(uint64(i)), | ||
} | ||
} | ||
|
||
|
@@ -360,3 +371,107 @@ func TestForwardingLogStoreEvent(t *testing.T) { | |
} | ||
} | ||
} | ||
|
||
// TestForwardingLogDecodeForwardingEvent tests that we're able to decode | ||
// forwarding events that don't have the new incoming and outgoing htlc | ||
// indices. | ||
func TestForwardingLogDecodeForwardingEvent(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
t.Parallel() | ||
|
||
// First, we'll set up a test database, and use that to instantiate the | ||
// forwarding event log that we'll be using for the duration of the | ||
// test. | ||
db, err := MakeTestDB(t) | ||
require.NoError(t, err) | ||
|
||
log := ForwardingLog{ | ||
db: db, | ||
} | ||
|
||
initialTime := time.Unix(1234, 0) | ||
endTime := time.Unix(1234, 0) | ||
|
||
// We'll create forwarding events that don't have the incoming and | ||
// outgoing htlc indices. | ||
numEvents := 10 | ||
events := make([]ForwardingEvent, numEvents) | ||
for i := range numEvents { | ||
events[i] = ForwardingEvent{ | ||
Timestamp: endTime, | ||
IncomingChanID: lnwire.NewShortChanIDFromInt( | ||
uint64(rand.Int63()), | ||
), | ||
OutgoingChanID: lnwire.NewShortChanIDFromInt( | ||
uint64(rand.Int63()), | ||
), | ||
AmtIn: lnwire.MilliSatoshi(rand.Int63()), | ||
AmtOut: lnwire.MilliSatoshi(rand.Int63()), | ||
} | ||
|
||
endTime = endTime.Add(time.Minute * 10) | ||
} | ||
|
||
// Now that all of our events are constructed, we'll add them to the | ||
// database. | ||
err = writeOldFormatEvents(db, events) | ||
require.NoError(t, err) | ||
|
||
// With all of our events added, we'll now query for them and ensure | ||
// that the incoming and outgoing htlc indices are set to 0 (default | ||
// value) for all events. | ||
eventQuery := ForwardingEventQuery{ | ||
StartTime: initialTime, | ||
EndTime: endTime, | ||
IndexOffset: 0, | ||
NumMaxEvents: uint32(numEvents * 3), | ||
} | ||
timeSlice, err := log.Query(eventQuery) | ||
require.NoError(t, err) | ||
require.Equal(t, numEvents, len(timeSlice.ForwardingEvents)) | ||
|
||
for _, event := range timeSlice.ForwardingEvents { | ||
require.Equal(t, fn.None[uint64](), event.IncomingHtlcID) | ||
require.Equal(t, fn.None[uint64](), event.OutgoingHtlcID) | ||
} | ||
} | ||
|
||
// writeOldFormatEvents writes forwarding events to the database in the old | ||
// format (without incoming and outgoing htlc indices). This is used to test | ||
// backward compatibility. | ||
func writeOldFormatEvents(db *DB, events []ForwardingEvent) error { | ||
return kvdb.Batch(db.Backend, func(tx kvdb.RwTx) error { | ||
bucket, err := tx.CreateTopLevelBucket(forwardingLogBucket) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, event := range events { | ||
var timestamp [8]byte | ||
byteOrder.PutUint64(timestamp[:], uint64( | ||
event.Timestamp.UnixNano(), | ||
)) | ||
|
||
// Use the old event size (32 bytes) for writing old | ||
// format events. | ||
var eventBytes [32]byte | ||
eventBuf := bytes.NewBuffer(eventBytes[0:0:32]) | ||
|
||
// Write only the original fields without incoming and | ||
// outgoing htlc indices. | ||
if err := WriteElements( | ||
eventBuf, event.IncomingChanID, | ||
event.OutgoingChanID, event.AmtIn, event.AmtOut, | ||
); err != nil { | ||
return err | ||
} | ||
|
||
if err := bucket.Put( | ||
timestamp[:], eventBuf.Bytes(), | ||
); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
return nil | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -213,6 +213,21 @@ func testMultiHopPayments(ht *lntest.HarnessTest) { | |
require.Equal(ht, aliceAlias, event.PeerAliasOut) | ||
} | ||
|
||
// Verify HTLC IDs are not nil and unique across all forwarding events. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice addition! I think we can make this test more rigorous by asserting the htlc ids are exactly There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now using |
||
seenIDs := make(map[uint64]bool) | ||
for _, event := range fwdingHistory.ForwardingEvents { | ||
// We check that the incoming and outgoing htlc indices are not | ||
// set to nil. The indices are required for any forwarding event | ||
// recorded after v0.20. | ||
require.NotNil(ht, event.IncomingHtlcId) | ||
require.NotNil(ht, event.OutgoingHtlcId) | ||
|
||
require.False(ht, seenIDs[*event.IncomingHtlcId]) | ||
require.False(ht, seenIDs[*event.OutgoingHtlcId]) | ||
seenIDs[*event.IncomingHtlcId] = true | ||
seenIDs[*event.OutgoingHtlcId] = true | ||
} | ||
|
||
// We expect Carol to have successful forwards and settles for | ||
// her sends. | ||
ht.AssertHtlcEvents( | ||
|
Uh oh!
There was an error while loading. Please reload this page.