Skip to content

Commit 47a5d93

Browse files
committed
fixup! multi: Support custom size onion packets
1 parent da5f4f3 commit 47a5d93

File tree

1 file changed

+88
-18
lines changed

1 file changed

+88
-18
lines changed

sphinx_test.go

Lines changed: 88 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,17 @@ var (
4545
var (
4646
// ErrInsufficientHops is returned when there are not enough hops to
4747
// create a route.
48-
ErrInsufficientHops = errors.New("at least 2 hops are required to " +
48+
ErrInsufficientHops = errors.New("at least 1 hop is required to " +
4949
"create an onion message route")
5050
)
5151

52+
// Session keys used in onion message tests.
53+
var (
54+
sessionKeyA = bytes.Repeat([]byte{'A'}, 32)
55+
sessionKeyB = bytes.Repeat([]byte{'B'}, 32)
56+
sessionKeyC = bytes.Repeat([]byte{'C'}, 32)
57+
)
58+
5259
// encodeTLVRecord encodes a TLV record with the given type and value.
5360
func encodeTLVRecord(recordType uint64, value []byte) []byte {
5461
var buf bytes.Buffer
@@ -159,7 +166,7 @@ func newTestRoute(numHops int) ([]*Router, *PaymentPath, *[]HopData, *OnionPacke
159166
func newOnionMessageRoute(numHops int) (*OnionPacket, *PaymentPath, []*Router,
160167
error) {
161168

162-
if numHops < 2 {
169+
if numHops < 1 {
163170
return nil, nil, nil, ErrInsufficientHops
164171
}
165172

@@ -178,8 +185,8 @@ func newOnionMessageRoute(numHops int) (*OnionPacket, *PaymentPath, []*Router,
178185
secondPathNodes := nodes[mid:]
179186

180187
// Create the sessions keys for the two blinded paths.
181-
firstSessionKey, _ := btcec.NewPrivateKey()
182-
secondSessionKey, _ := btcec.NewPrivateKey()
188+
firstSessionKey, _ := btcec.PrivKeyFromBytes(sessionKeyA)
189+
secondSessionKey, _ := btcec.PrivKeyFromBytes(sessionKeyB)
183190

184191
// Create the first blinded path, adding a next_path_key_override TLV
185192
// at the last node.
@@ -227,7 +234,7 @@ func newOnionMessageRoute(numHops int) (*OnionPacket, *PaymentPath, []*Router,
227234
}
228235

229236
// Generate the onion packet.
230-
sessionKey, _ := btcec.NewPrivateKey()
237+
sessionKey, _ := btcec.PrivKeyFromBytes(sessionKeyC)
231238

232239
onionPacket, err := NewOnionPacket(
233240
&route, sessionKey, nil, DeterministicPacketFiller,
@@ -267,11 +274,18 @@ func createBlindedPath(firstPathNodes []*Router, secondPathNodes []*Router,
267274
}
268275
}
269276

270-
firstBlindedPath, err := BuildBlindedPath(
271-
firstSessionKey, firstPathInfos,
272-
)
273-
if err != nil {
274-
return nil, err
277+
// The first blinded path may be empty if the sender has a direct
278+
// channel with the introduction point.
279+
var firstBlindedPath *BlindedPathInfo
280+
if len(firstPathNodes) > 0 {
281+
var err error
282+
283+
firstBlindedPath, err = BuildBlindedPath(
284+
firstSessionKey, firstPathInfos,
285+
)
286+
if err != nil {
287+
return nil, err
288+
}
275289
}
276290

277291
// Create the second blinded path, omitting the next_node_id TLV for the
@@ -308,13 +322,26 @@ func createBlindedPath(firstPathNodes []*Router, secondPathNodes []*Router,
308322
return nil, err
309323
}
310324

311-
blindedPath := &BlindedPath{
312-
IntroductionPoint: firstBlindedPath.Path.IntroductionPoint,
313-
BlindingPoint: firstBlindedPath.Path.BlindingPoint,
314-
BlindedHops: append(
315-
firstBlindedPath.Path.BlindedHops,
316-
secondBlindedPath.Path.BlindedHops...,
317-
),
325+
var blindedPath *BlindedPath
326+
if len(firstPathNodes) == 0 {
327+
// If the sender has a direct channel to the introduction point
328+
// of the blinded path the receiver gave us, then the sender
329+
// doesn't need to create its own blinded path. We can just use
330+
// the receiver's blinded path as is.
331+
blindedPath = secondBlindedPath.Path
332+
} else {
333+
// Otherwise, we use the introduction point of the blinded path
334+
// created by the sender and concatenate the hops of both paths.
335+
introductionPoint := firstBlindedPath.Path.IntroductionPoint
336+
blindingPoint := firstBlindedPath.Path.BlindingPoint
337+
blindedPath = &BlindedPath{
338+
IntroductionPoint: introductionPoint,
339+
BlindingPoint: blindingPoint,
340+
BlindedHops: append(
341+
firstBlindedPath.Path.BlindedHops,
342+
secondBlindedPath.Path.BlindedHops...,
343+
),
344+
}
318345
}
319346

320347
return blindedPath, nil
@@ -601,7 +628,7 @@ func TestSphinxSingleHop(t *testing.T) {
601628
// The destination node should detect that the packet is destined for
602629
// itself.
603630
if processedPacket.Action != ExitNode {
604-
t.Fatalf("processed action is correct, is %v should be %v",
631+
t.Fatalf("processed action is incorrect, is %v should be %v",
605632
processedPacket.Action, ExitNode)
606633
}
607634
}
@@ -903,6 +930,49 @@ func TestPaymentPathTotalPayloadSizeExceeds1300(t *testing.T) {
903930
"MaxOnionMessagePayloadSize")
904931
}
905932

933+
// TestSingleHopOnionMessage test that we can create and encode a single-hop
934+
// onion message packet.
935+
func TestSingleHopOnionMessage(t *testing.T) {
936+
t.Parallel()
937+
938+
packet, route, nodes, err := newOnionMessageRoute(1)
939+
require.NoError(t, err, "newOnionMessageRoute should not return an "+
940+
"error")
941+
942+
require.Equal(t, 1, route.TrueRouteLength())
943+
944+
// Start the ReplayLog and defer shutdown
945+
err = nodes[0].log.Start()
946+
require.NoError(t, err, "unable to start ReplayLog")
947+
948+
defer func() {
949+
require.NoError(t, nodes[0].log.Stop())
950+
}()
951+
952+
// In a single-hop onion message the blinding point is the session key
953+
// used by the receiver to create its blinded path. The sender didn't
954+
// need to create a blinded path since it has a direct channel to the
955+
// receiver/introduction point. Knowing this we use the session key that
956+
// the receiver used.
957+
blindingPoint, _ := btcec.PrivKeyFromBytes(sessionKeyB)
958+
959+
// Simulating a direct single-hop onion message, send the sphinx packet
960+
// to the destination node, making it process the packet fully.
961+
processedPacket, err := nodes[0].ProcessOnionPacket(
962+
packet, nil, 1, WithBlindingPoint(blindingPoint.PubKey()),
963+
)
964+
if err != nil {
965+
t.Fatalf("unable to process sphinx packet: %v", err)
966+
}
967+
968+
// The destination node should detect that the packet is destined for
969+
// itself.
970+
if processedPacket.Action != ExitNode {
971+
t.Fatalf("processed action is incorrect, is %v should be %v",
972+
processedPacket.Action, ExitNode)
973+
}
974+
}
975+
906976
// TestCustomPayloadSize tests that we can create an onion packet with any size
907977
// of routing info.
908978
func TestCustomPayloadSize(t *testing.T) {

0 commit comments

Comments
 (0)