@@ -12,6 +12,7 @@ import (
12
12
13
13
"github.com/btcsuite/btcd/btcec/v2"
14
14
"github.com/davecgh/go-spew/spew"
15
+ "github.com/lightningnetwork/lnd/tlv"
15
16
"github.com/stretchr/testify/require"
16
17
)
17
18
@@ -162,6 +163,89 @@ func TestBolt4Packet(t *testing.T) {
162
163
}
163
164
}
164
165
166
+ func TestTLVPayloadMessagePacket (t * testing.T ) {
167
+ t .Parallel ()
168
+
169
+ // First, we'll read out the raw JSON file at the target location.
170
+ jsonBytes , err := os .ReadFile (testOnionMessageFileName )
171
+ require .NoError (t , err )
172
+
173
+ // Once we have the raw file, we'll unpack it into our jsonTestCase
174
+ // struct defined above.
175
+ testCase := & onionMessageJsonTestCase {}
176
+ require .NoError (t , json .Unmarshal (jsonBytes , testCase ))
177
+
178
+ // Next, we'll populate a new OnionHop using the information included
179
+ // in this test case.
180
+ var route PaymentPath
181
+ for i , hop := range testCase .Route .Hops {
182
+ pubKeyBytes , err := hex .DecodeString (hop .BlindedNodeID )
183
+ require .NoError (t , err )
184
+
185
+ pubKey , err := btcec .ParsePubKey (pubKeyBytes )
186
+ require .NoError (t , err )
187
+
188
+ EncryptedRecipientData , err := hex .DecodeString (
189
+ hop .EncryptedRecipientData ,
190
+ )
191
+ require .NoError (t , err )
192
+
193
+ // Manually encode our onion payload
194
+ records := []tlv.Record {}
195
+
196
+ if i == len (testCase .Route .Hops )- 1 {
197
+ helloBytes := []byte ("hello" )
198
+ records = append (records , tlv .MakePrimitiveRecord (
199
+ 1 , & helloBytes ,
200
+ ))
201
+ }
202
+
203
+ records = append (records , tlv .MakePrimitiveRecord (
204
+ 4 , & EncryptedRecipientData ,
205
+ ))
206
+
207
+ stream , err := tlv .NewStream (records ... )
208
+ require .NoError (t , err , "new stream" )
209
+
210
+ b := new (bytes.Buffer )
211
+ require .NoError (t , stream .Encode (b ), "encode" )
212
+
213
+ route [i ] = OnionHop {
214
+ NodePub : * pubKey ,
215
+ HopPayload : HopPayload {
216
+ Type : PayloadTLV ,
217
+ Payload : b .Bytes (),
218
+ },
219
+ }
220
+ }
221
+
222
+ finalPacket , err := hex .DecodeString (
223
+ testCase .OnionMessage .OnionMessagePacket ,
224
+ )
225
+ require .NoError (t , err )
226
+
227
+ sessionKeyBytes , err := hex .DecodeString (testCase .Generate .SessionKey )
228
+
229
+ require .NoError (t , err )
230
+
231
+ // With all the required data assembled, we'll craft a new packet.
232
+ sessionKey , _ := btcec .PrivKeyFromBytes (sessionKeyBytes )
233
+
234
+ pkt , err := NewOnionPacket (
235
+ & route , sessionKey , nil , DeterministicPacketFiller ,
236
+ )
237
+ require .NoError (t , err )
238
+
239
+ var b bytes.Buffer
240
+ require .NoError (t , pkt .Encode (& b ))
241
+
242
+ // Finally, we expect that our packet matches the packet included in
243
+ // the spec's test vectors.
244
+ require .Equalf (t , b .Bytes (), finalPacket , "final packet does not " +
245
+ "match expected BOLT 4 packet, want: %s, got %s" ,
246
+ hex .EncodeToString (finalPacket ), hex .EncodeToString (b .Bytes ()))
247
+ }
248
+
165
249
func TestSphinxCorrectness (t * testing.T ) {
166
250
nodes , _ , hopDatas , fwdMsg , err := newTestRoute (testLegacyRouteNumHops )
167
251
if err != nil {
@@ -755,6 +839,9 @@ const (
755
839
756
840
// testTLVFileName is the name of the tlv-payload-only onion test file.
757
841
testTLVFileName = "testdata/onion-test.json"
842
+
843
+ // testOnionMessageFileName is the name of the onion message test file.
844
+ testOnionMessageFileName = "testdata/blinded-onion-message-onion-test.json"
758
845
)
759
846
760
847
type jsonHop struct {
0 commit comments