-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Channeldb: Store HTLC Extra TLVs in Onion Blob Varbytes #7710
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
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 |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ import ( | |
| "github.com/lightningnetwork/lnd/clock" | ||
| "github.com/lightningnetwork/lnd/keychain" | ||
| "github.com/lightningnetwork/lnd/kvdb" | ||
| "github.com/lightningnetwork/lnd/lnmock" | ||
| "github.com/lightningnetwork/lnd/lntest/channels" | ||
| "github.com/lightningnetwork/lnd/lnwire" | ||
| "github.com/lightningnetwork/lnd/shachain" | ||
|
|
@@ -366,12 +367,13 @@ func TestOpenChannelPutGetDelete(t *testing.T) { | |
| // Create the test channel state, with additional htlcs on the local | ||
| // and remote commitment. | ||
| localHtlcs := []HTLC{ | ||
| {Signature: testSig.Serialize(), | ||
| { | ||
| Signature: testSig.Serialize(), | ||
| Incoming: true, | ||
| Amt: 10, | ||
| RHash: key, | ||
| RefundTimeout: 1, | ||
| OnionBlob: []byte("onionblob"), | ||
| OnionBlob: lnmock.MockOnion(), | ||
| }, | ||
| } | ||
|
|
||
|
|
@@ -382,7 +384,7 @@ func TestOpenChannelPutGetDelete(t *testing.T) { | |
| Amt: 10, | ||
| RHash: key, | ||
| RefundTimeout: 1, | ||
| OnionBlob: []byte("onionblob"), | ||
| OnionBlob: lnmock.MockOnion(), | ||
| }, | ||
| } | ||
|
|
||
|
|
@@ -612,8 +614,10 @@ func TestChannelStateTransition(t *testing.T) { | |
| LogIndex: uint64(i * 2), | ||
| HtlcIndex: uint64(i), | ||
| } | ||
| htlc.OnionBlob = make([]byte, 10) | ||
| copy(htlc.OnionBlob[:], bytes.Repeat([]byte{2}, 10)) | ||
|
||
| copy( | ||
| htlc.OnionBlob[:], | ||
| bytes.Repeat([]byte{2}, lnwire.OnionPacketSize), | ||
| ) | ||
| htlcs = append(htlcs, htlc) | ||
| htlcAmt += htlc.Amt | ||
| } | ||
|
|
@@ -1527,3 +1531,105 @@ func TestFinalHtlcs(t *testing.T) { | |
| _, err = cdb.LookupFinalHtlc(chanID, unknownHtlcID) | ||
| require.ErrorIs(t, err, ErrHtlcUnknown) | ||
| } | ||
|
|
||
| // TestHTLCsExtraData tests serialization and deserialization of HTLCs | ||
| // combined with extra data. | ||
| func TestHTLCsExtraData(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| mockHtlc := HTLC{ | ||
| Signature: testSig.Serialize(), | ||
| Incoming: false, | ||
| Amt: 10, | ||
| RHash: key, | ||
| RefundTimeout: 1, | ||
| OnionBlob: lnmock.MockOnion(), | ||
| } | ||
|
|
||
| testCases := []struct { | ||
| name string | ||
| htlcs []HTLC | ||
| }{ | ||
| { | ||
| // Serialize multiple HLTCs with no extra data to | ||
| // assert that there is no regression for HTLCs with | ||
| // no extra data. | ||
| name: "no extra data", | ||
carlaKC marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| htlcs: []HTLC{ | ||
| mockHtlc, mockHtlc, | ||
| }, | ||
| }, | ||
| { | ||
| name: "mixed extra data", | ||
yyforyongyu marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| htlcs: []HTLC{ | ||
| mockHtlc, | ||
| { | ||
| Signature: testSig.Serialize(), | ||
| Incoming: false, | ||
| Amt: 10, | ||
| RHash: key, | ||
| RefundTimeout: 1, | ||
| OnionBlob: lnmock.MockOnion(), | ||
| ExtraData: []byte{1, 2, 3}, | ||
| }, | ||
| mockHtlc, | ||
| { | ||
| Signature: testSig.Serialize(), | ||
| Incoming: false, | ||
| Amt: 10, | ||
| RHash: key, | ||
| RefundTimeout: 1, | ||
| OnionBlob: lnmock.MockOnion(), | ||
| ExtraData: bytes.Repeat( | ||
| []byte{9}, 999, | ||
| ), | ||
| }, | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| for _, testCase := range testCases { | ||
| testCase := testCase | ||
|
|
||
| t.Run(testCase.name, func(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| var b bytes.Buffer | ||
| err := SerializeHtlcs(&b, testCase.htlcs...) | ||
| require.NoError(t, err) | ||
|
|
||
| r := bytes.NewReader(b.Bytes()) | ||
| htlcs, err := DeserializeHtlcs(r) | ||
| require.NoError(t, err) | ||
| require.Equal(t, testCase.htlcs, htlcs) | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| // TestOnionBlobIncorrectLength tests HTLC deserialization in the case where | ||
| // the OnionBlob saved on disk is of an unexpected length. This error case is | ||
| // only expected in the case of database corruption (or some severe protocol | ||
| // breakdown/bug). A HTLC is manually serialized because we cannot force a | ||
| // case where we write an onion blob of incorrect length. | ||
| func TestOnionBlobIncorrectLength(t *testing.T) { | ||
Roasbeef marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| t.Parallel() | ||
|
|
||
| var b bytes.Buffer | ||
|
|
||
| var numHtlcs uint16 = 1 | ||
| require.NoError(t, WriteElement(&b, numHtlcs)) | ||
|
|
||
| require.NoError(t, WriteElements( | ||
| &b, | ||
| // Number of HTLCs. | ||
| numHtlcs, | ||
| // Signature, incoming, amount, Rhash, Timeout. | ||
| testSig.Serialize(), false, lnwire.MilliSatoshi(10), key, | ||
| uint32(1), | ||
| // Write an onion blob that is half of our expected size. | ||
| bytes.Repeat([]byte{1}, lnwire.OnionPacketSize/2), | ||
| )) | ||
|
|
||
| _, err := DeserializeHtlcs(&b) | ||
| require.ErrorIs(t, err, ErrOnionBlobLength) | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.