Skip to content

Commit e0210d7

Browse files
committed
fixup! sphinx_test: add blinded onion message test
1 parent c3f8db7 commit e0210d7

File tree

1 file changed

+75
-31
lines changed

1 file changed

+75
-31
lines changed

path_test.go

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ const (
1717
blindedOnionMessageOnionTestFileName = "testdata/blinded-onion-message-onion-test.json"
1818
)
1919

20+
var (
21+
// bolt4PubKeys contains the public keys used in the Bolt 4 spec test
22+
// vectors. We convert them variables named after the commonly used
23+
// names in cryptography.
24+
alicePubKey = bolt4PubKeys[0]
25+
bobPubKey = bolt4PubKeys[1]
26+
)
27+
2028
// TestBuildBlindedRoute tests BuildBlindedRoute and decryptBlindedHopData against
2129
// the spec test vectors.
2230
func TestBuildBlindedRoute(t *testing.T) {
@@ -118,8 +126,35 @@ func TestBuildBlindedRoute(t *testing.T) {
118126
}
119127
}
120128

121-
// TestBuildOnionMessageBlindedRoute tests BuildBlindedRoute,
122-
// decryptBlindedHopData and NextEphemeral against the spec test vectors.
129+
// TestBuildOnionMessageBlindedRoute tests the construction of a blinded route
130+
// for an onion message, specifically the concatenation of two blinded paths,
131+
// against the spec test vectors in `blinded-onion-message-onion-test.json`. It
132+
// verifies the correctness of BuildBlindedPath, decryptBlindedHopData, and
133+
// NextEphemeral.
134+
//
135+
// The test setup involves several parties and two distinct blinded paths that
136+
// are combined to form the full route:
137+
//
138+
// 1. Path from Dave: Dave (the receiver) first constructs a blinded path for a
139+
// message to be sent from Bob to himself (Dave).
140+
// The path is: Bob -> Carol -> Dave
141+
//
142+
// 2. Path from Sender: Dave gives his blinded path to a Sender. The Sender
143+
// then creates their own blinded path from themselves to Bob, passing
144+
// through Alice. The path is: Sender -> Alice -> Bob
145+
//
146+
// 3. Path Concatenation: The Sender prepends their path to Dave's path,
147+
// creating a final, concatenated route:
148+
// Sender -> Alice -> Bob -> Carol -> Dave
149+
// To link the two paths, the Sender includes a `next_path_key_override`
150+
// in the payload for Alice. This override is set to the first path key
151+
// (blinding point) of Dave's path, instructing Alice to use it for the next
152+
// hop (Bob) instead of the key that she could derive herself.
153+
//
154+
// The test then asserts that the generated concatenated path matches the test
155+
// vector's expected route. Finally, it simulates the decryption process at each
156+
// hop, verifying that each node can correctly decrypt its payload and derive
157+
// the correct next ephemeral key.
123158
func TestBuildOnionMessageBlindedRoute(t *testing.T) {
124159
t.Parallel()
125160

@@ -128,43 +163,50 @@ func TestBuildOnionMessageBlindedRoute(t *testing.T) {
128163
require.NoError(t, err)
129164

130165
// Once we have the raw file, we'll unpack it into our
131-
// blindingJsonTestCase struct defined below.
166+
// onionMessageJsonTestCase struct defined below.
132167
testCase := &onionMessageJsonTestCase{}
133168
require.NoError(t, json.Unmarshal(jsonBytes, testCase))
134169
require.Len(t, testCase.Generate.Hops, 4)
135170

136171
// buildMessagePath is a helper closure used to convert
137172
// hopOnionMessageData objects into HopInfo objects.
138-
buildMessagePath := func(h []hopOnionMessageData, e string) []*HopInfo {
173+
buildMessagePath := func(h []hopOnionMessageData,
174+
initialHopID string) []*HopInfo {
175+
139176
path := make([]*HopInfo, len(h))
140-
currentHop := e
177+
// The json test vector doesn't properly specify the current
178+
// node id, so we need the initial Node ID as a starting point.
179+
currentHop := initialHopID
141180
for i, hop := range h {
142-
// The json test vector only specifies the current node
143-
// ID as the next node id in the payload of the previous
144-
// node, so we get that from the previous hop.
145-
nodeIDStr, _ := hex.DecodeString(
146-
currentHop,
147-
)
148-
nodeID, _ := btcec.ParsePubKey(nodeIDStr)
149-
payload, _ := hex.DecodeString(hop.EncryptedDataTlv)
181+
nodeIDStr, err := hex.DecodeString(currentHop)
182+
require.NoError(t, err)
183+
nodeID, err := btcec.ParsePubKey(nodeIDStr)
184+
require.NoError(t, err)
185+
payload, err := hex.DecodeString(hop.EncryptedDataTlv)
186+
require.NoError(t, err)
150187

151188
path[i] = &HopInfo{
152189
NodePub: nodeID,
153190
PlainText: payload,
154191
}
192+
193+
// The json test vector doesn't properly specify the
194+
// current node id. It does specify the next node id. So
195+
// to get the current node id for the next iteration, we
196+
// get the next node id here.
155197
currentHop = hop.EncodedOnionMessageTLVs.NextNodeID
156198
}
157199
return path
158200
}
159201

160202
// First, Dave will build a blinded path from Bob to itself.
161-
DaveSessKey := privKeyFromString(
203+
daveSessKey := privKeyFromString(
162204
testCase.Generate.Hops[1].PathKeySecret,
163205
)
164206
daveBobPath := buildMessagePath(
165-
testCase.Generate.Hops[1:], bolt4PubKeys[1],
207+
testCase.Generate.Hops[1:], bobPubKey,
166208
)
167-
pathDB, err := BuildBlindedPath(DaveSessKey, daveBobPath)
209+
daveBobBlindedPath, err := BuildBlindedPath(daveSessKey, daveBobPath)
168210
require.NoError(t, err)
169211

170212
// At this point, Dave will give his blinded path to the Sender who will
@@ -174,21 +216,27 @@ func TestBuildOnionMessageBlindedRoute(t *testing.T) {
174216
// to the first path key in Dave's blinded route. This will indicate to
175217
// Alice that she should use this point for the next path key instead of
176218
// the next path key that she derives.
219+
// Path created by Dave: Bob -> Carol -> Dave
220+
// Path that the Sender will build: Sender -> Alice -> Bob
177221
aliceBobPath := buildMessagePath(
178-
testCase.Generate.Hops[:1], bolt4PubKeys[0],
222+
testCase.Generate.Hops[:1], alicePubKey,
179223
)
180224
senderSessKey := privKeyFromString(
181225
testCase.Generate.Hops[0].PathKeySecret,
182226
)
183-
pathAB, err := BuildBlindedPath(senderSessKey, aliceBobPath)
227+
aliceBobBlindedPath, err := BuildBlindedPath(
228+
senderSessKey, aliceBobPath,
229+
)
184230
require.NoError(t, err)
185231

186232
// Construct the concatenated path.
187233
path := &BlindedPath{
188-
IntroductionPoint: pathAB.Path.IntroductionPoint,
189-
BlindingPoint: pathAB.Path.BlindingPoint,
190-
BlindedHops: append(pathAB.Path.BlindedHops,
191-
pathDB.Path.BlindedHops...),
234+
IntroductionPoint: aliceBobBlindedPath.Path.IntroductionPoint,
235+
BlindingPoint: aliceBobBlindedPath.Path.BlindingPoint,
236+
BlindedHops: append(
237+
aliceBobBlindedPath.Path.BlindedHops,
238+
daveBobBlindedPath.Path.BlindedHops...,
239+
),
192240
}
193241

194242
// Check that the constructed path is equal to the test vector path.
@@ -205,19 +253,15 @@ func TestBuildOnionMessageBlindedRoute(t *testing.T) {
205253
))
206254

207255
data, _ := hex.DecodeString(hop.EncryptedRecipientData)
208-
require.True(
209-
t, bytes.Equal(data, path.BlindedHops[i].CipherText),
210-
)
256+
require.Equal(t, data, path.BlindedHops[i].CipherText)
211257
}
212258

213259
// Assert that each hop is able to decode the encrypted data meant for
214260
// it.
215261
for i, hop := range testCase.Decrypt.Hops {
216262
genData := testCase.Generate.Hops[i]
217263
priv := privKeyFromString(hop.PrivKey)
218-
ephem := pubKeyFromString(
219-
genData.EphemeralPubKey,
220-
)
264+
ephem := pubKeyFromString(genData.EphemeralPubKey)
221265

222266
// Now we'll decrypt the blinded hop data using the private key
223267
// and the ephemeral public key.
@@ -227,9 +271,9 @@ func TestBuildOnionMessageBlindedRoute(t *testing.T) {
227271
)
228272
require.NoError(t, err)
229273

230-
// check if the decrypted data is what we expect it to be.
231-
decoded, _ := hex.DecodeString(genData.EncryptedDataTlv)
232-
require.True(t, bytes.Equal(data, decoded))
274+
// Check if the decrypted data is what we expect it to be.
275+
dataExpected, _ := hex.DecodeString(genData.EncryptedDataTlv)
276+
require.Equal(t, data, dataExpected)
233277

234278
nextEphem, err := NextEphemeral(&PrivKeyECDH{priv}, ephem)
235279
require.NoError(t, err)

0 commit comments

Comments
 (0)