github.com/decred/dcrlnd@v0.7.6/tlv/tlv_test.go (about) 1 package tlv_test 2 3 import ( 4 "bytes" 5 "io" 6 "reflect" 7 "testing" 8 9 "github.com/decred/dcrd/dcrec/secp256k1/v4" 10 "github.com/decred/dcrlnd/tlv" 11 ) 12 13 type nodeAmts struct { 14 nodeID *secp256k1.PublicKey 15 amt1 uint64 16 amt2 uint64 17 } 18 19 func ENodeAmts(w io.Writer, val interface{}, buf *[8]byte) error { 20 if t, ok := val.(*nodeAmts); ok { 21 if err := tlv.EPubKey(w, &t.nodeID, buf); err != nil { 22 return err 23 } 24 if err := tlv.EUint64T(w, t.amt1, buf); err != nil { 25 return err 26 } 27 return tlv.EUint64T(w, t.amt2, buf) 28 } 29 return tlv.NewTypeForEncodingErr(val, "nodeAmts") 30 } 31 32 func DNodeAmts(r io.Reader, val interface{}, buf *[8]byte, l uint64) error { 33 if t, ok := val.(*nodeAmts); ok && l == 49 { 34 if err := tlv.DPubKey(r, &t.nodeID, buf, 33); err != nil { 35 return err 36 } 37 if err := tlv.DUint64(r, &t.amt1, buf, 8); err != nil { 38 return err 39 } 40 return tlv.DUint64(r, &t.amt2, buf, 8) 41 } 42 return tlv.NewTypeForDecodingErr(val, "nodeAmts", l, 49) 43 } 44 45 type N1 struct { 46 amt uint64 47 scid uint64 48 nodeAmts nodeAmts 49 cltvDelta uint16 50 51 alias []byte 52 53 stream *tlv.Stream 54 } 55 56 func (n *N1) sizeAmt() uint64 { 57 return tlv.SizeTUint64(n.amt) 58 } 59 60 func NewN1() *N1 { 61 n := new(N1) 62 63 n.stream = tlv.MustNewStream( 64 tlv.MakeDynamicRecord( 65 1, &n.amt, n.sizeAmt, tlv.ETUint64, tlv.DTUint64, 66 ), 67 tlv.MakePrimitiveRecord(2, &n.scid), 68 tlv.MakeStaticRecord(3, &n.nodeAmts, 49, ENodeAmts, DNodeAmts), 69 tlv.MakePrimitiveRecord(254, &n.cltvDelta), 70 tlv.MakePrimitiveRecord(401, &n.alias), 71 ) 72 73 return n 74 } 75 76 func (n *N1) Encode(w io.Writer) error { 77 return n.stream.Encode(w) 78 } 79 80 func (n *N1) Decode(r io.Reader) error { 81 return n.stream.Decode(r) 82 } 83 84 type N2 struct { 85 amt uint64 86 cltvExpiry uint32 87 88 stream *tlv.Stream 89 } 90 91 func (n *N2) sizeAmt() uint64 { 92 return tlv.SizeTUint64(n.amt) 93 } 94 95 func (n *N2) sizeCltv() uint64 { 96 return tlv.SizeTUint32(n.cltvExpiry) 97 } 98 99 func NewN2() *N2 { 100 n := new(N2) 101 102 n.stream = tlv.MustNewStream( 103 tlv.MakeDynamicRecord( 104 0, &n.amt, n.sizeAmt, tlv.ETUint64, tlv.DTUint64, 105 ), 106 tlv.MakeDynamicRecord( 107 11, &n.cltvExpiry, n.sizeCltv, tlv.ETUint32, tlv.DTUint32, 108 ), 109 ) 110 111 return n 112 } 113 114 func (n *N2) Encode(w io.Writer) error { 115 return n.stream.Encode(w) 116 } 117 118 func (n *N2) Decode(r io.Reader) error { 119 return n.stream.Decode(r) 120 } 121 122 var tlvDecodingFailureTests = []struct { 123 name string 124 bytes []byte 125 expErr error 126 127 // skipN2 if true, will cause the test to only be executed on N1. 128 skipN2 bool 129 }{ 130 { 131 name: "type truncated", 132 bytes: []byte{0xfd}, 133 expErr: io.ErrUnexpectedEOF, 134 }, 135 { 136 name: "type truncated", 137 bytes: []byte{0xfd, 0x01}, 138 expErr: io.ErrUnexpectedEOF, 139 }, 140 { 141 name: "not minimally encoded type", 142 bytes: []byte{0xfd, 0x00, 0x01}, // spec has trailing 0x00 143 expErr: tlv.ErrVarIntNotCanonical, 144 }, 145 { 146 name: "missing length", 147 bytes: []byte{0xfd, 0x01, 0x01}, 148 expErr: io.ErrUnexpectedEOF, 149 }, 150 { 151 name: "length truncated", 152 bytes: []byte{0x0f, 0xfd}, 153 expErr: io.ErrUnexpectedEOF, 154 }, 155 { 156 name: "length truncated", 157 bytes: []byte{0x0f, 0xfd, 0x26}, 158 expErr: io.ErrUnexpectedEOF, 159 }, 160 { 161 name: "missing value", 162 bytes: []byte{0x0f, 0xfd, 0x26, 0x02}, 163 expErr: io.ErrUnexpectedEOF, 164 }, 165 { 166 name: "not minimally encoded length", 167 bytes: []byte{0x0f, 0xfd, 0x00, 0x01}, // spec has trailing 0x00 168 expErr: tlv.ErrVarIntNotCanonical, 169 }, 170 { 171 name: "value truncated", 172 bytes: []byte{0x0f, 0xfd, 0x02, 0x01, 173 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 175 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 176 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 177 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 178 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 179 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 184 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 185 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 202 }, 203 expErr: io.ErrUnexpectedEOF, 204 }, 205 { 206 name: "greater than encoding length for n1's amt", 207 bytes: []byte{0x01, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 208 expErr: tlv.NewTypeForDecodingErr(new(uint64), "uint64", 9, 8), 209 skipN2: true, 210 }, 211 { 212 name: "encoding for n1's amt is not minimal", 213 bytes: []byte{0x01, 0x01, 0x00}, 214 expErr: tlv.ErrTUintNotMinimal, 215 skipN2: true, 216 }, 217 { 218 name: "encoding for n1's amt is not minimal", 219 bytes: []byte{0x01, 0x02, 0x00, 0x01}, 220 expErr: tlv.ErrTUintNotMinimal, 221 skipN2: true, 222 }, 223 { 224 name: "encoding for n1's amt is not minimal", 225 bytes: []byte{0x01, 0x03, 0x00, 0x01, 0x00}, 226 expErr: tlv.ErrTUintNotMinimal, 227 skipN2: true, 228 }, 229 { 230 name: "encoding for n1's amt is not minimal", 231 bytes: []byte{0x01, 0x04, 0x00, 0x01, 0x00, 0x00}, 232 expErr: tlv.ErrTUintNotMinimal, 233 skipN2: true, 234 }, 235 { 236 name: "encoding for n1's amt is not minimal", 237 bytes: []byte{0x01, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00}, 238 expErr: tlv.ErrTUintNotMinimal, 239 skipN2: true, 240 }, 241 { 242 name: "encoding for n1's amt is not minimal", 243 bytes: []byte{0x01, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}, 244 expErr: tlv.ErrTUintNotMinimal, 245 skipN2: true, 246 }, 247 { 248 name: "encoding for n1's amt is not minimal", 249 bytes: []byte{0x01, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, 250 expErr: tlv.ErrTUintNotMinimal, 251 skipN2: true, 252 }, 253 { 254 name: "encoding for n1's amt is not minimal", 255 bytes: []byte{0x01, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 256 expErr: tlv.ErrTUintNotMinimal, 257 skipN2: true, 258 }, 259 { 260 name: "less than encoding length for n1's scid", 261 bytes: []byte{0x02, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 262 expErr: tlv.NewTypeForDecodingErr(new(uint64), "uint64", 7, 8), 263 skipN2: true, 264 }, 265 { 266 name: "less than encoding length for n1's scid", 267 bytes: []byte{0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}, 268 expErr: tlv.NewTypeForDecodingErr(new(uint64), "uint64", 9, 8), 269 skipN2: true, 270 }, 271 { 272 name: "less than encoding length for n1's nodeAmts", 273 bytes: []byte{0x03, 0x29, 274 0x02, 0x3d, 0xa0, 0x92, 0xf6, 0x98, 0x0e, 0x58, 0xd2, 275 0xc0, 0x37, 0x17, 0x31, 0x80, 0xe9, 0xa4, 0x65, 0x47, 276 0x60, 0x26, 0xee, 0x50, 0xf9, 0x66, 0x95, 0x96, 0x3e, 277 0x8e, 0xfe, 0x43, 0x6f, 0x54, 0xeb, 0x00, 0x00, 0x00, 278 0x00, 0x00, 0x00, 0x00, 0x01, 279 }, 280 expErr: tlv.NewTypeForDecodingErr(new(nodeAmts), "nodeAmts", 41, 49), 281 skipN2: true, 282 }, 283 { 284 name: "less than encoding length for n1's nodeAmts", 285 bytes: []byte{0x03, 0x30, 286 0x02, 0x3d, 0xa0, 0x92, 0xf6, 0x98, 0x0e, 0x58, 0xd2, 287 0xc0, 0x37, 0x17, 0x31, 0x80, 0xe9, 0xa4, 0x65, 0x47, 288 0x60, 0x26, 0xee, 0x50, 0xf9, 0x66, 0x95, 0x96, 0x3e, 289 0x8e, 0xfe, 0x43, 0x6f, 0x54, 0xeb, 0x00, 0x00, 0x00, 290 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 291 0x00, 0x00, 0x01, 292 }, 293 expErr: tlv.NewTypeForDecodingErr(new(nodeAmts), "nodeAmts", 48, 49), 294 skipN2: true, 295 }, 296 { 297 name: "n1's node_id is not a valid point", 298 bytes: []byte{0x03, 0x31, 299 0x04, 0x3d, 0xa0, 0x92, 0xf6, 0x98, 0x0e, 0x58, 0xd2, 300 0xc0, 0x37, 0x17, 0x31, 0x80, 0xe9, 0xa4, 0x65, 0x47, 301 0x60, 0x26, 0xee, 0x50, 0xf9, 0x66, 0x95, 0x96, 0x3e, 302 0x8e, 0xfe, 0x43, 0x6f, 0x54, 0xeb, 0x00, 0x00, 0x00, 303 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 304 0x00, 0x00, 0x00, 0x02, 305 }, 306 expErr: secp256k1.Error{Err: secp256k1.ErrPubKeyInvalidFormat, 307 Description: "invalid public key: unsupported format: 4"}, 308 skipN2: true, 309 }, 310 { 311 name: "greater than encoding length for n1's nodeAmts", 312 bytes: []byte{0x03, 0x32, 313 0x02, 0x3d, 0xa0, 0x92, 0xf6, 0x98, 0x0e, 0x58, 0xd2, 314 0xc0, 0x37, 0x17, 0x31, 0x80, 0xe9, 0xa4, 0x65, 0x47, 315 0x60, 0x26, 0xee, 0x50, 0xf9, 0x66, 0x95, 0x96, 0x3e, 316 0x8e, 0xfe, 0x43, 0x6f, 0x54, 0xeb, 0x00, 0x00, 0x00, 317 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 318 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 319 }, 320 expErr: tlv.NewTypeForDecodingErr(new(nodeAmts), "nodeAmts", 50, 49), 321 skipN2: true, 322 }, 323 { 324 name: "less than encoding length for n1's cltvDelta", 325 bytes: []byte{0xfd, 0x00, 0x0fe, 0x00}, 326 expErr: tlv.NewTypeForDecodingErr(new(uint16), "uint16", 0, 2), 327 skipN2: true, 328 }, 329 { 330 name: "less than encoding length for n1's cltvDelta", 331 bytes: []byte{0xfd, 0x00, 0xfe, 0x01, 0x01}, 332 expErr: tlv.NewTypeForDecodingErr(new(uint16), "uint16", 1, 2), 333 skipN2: true, 334 }, 335 { 336 name: "greater than encoding length for n1's cltvDelta", 337 bytes: []byte{0xfd, 0x00, 0xfe, 0x03, 0x01, 0x01, 0x01}, 338 expErr: tlv.NewTypeForDecodingErr(new(uint16), "uint16", 3, 2), 339 skipN2: true, 340 }, 341 { 342 name: "valid records but invalid ordering", 343 bytes: []byte{0x02, 0x08, 344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x26, 0x01, 345 0x01, 0x2a, 346 }, 347 expErr: tlv.ErrStreamNotCanonical, 348 skipN2: true, 349 }, 350 { 351 name: "duplicate tlv type", 352 bytes: []byte{0x02, 0x08, 353 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x31, 0x02, 354 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51, 355 }, 356 expErr: tlv.ErrStreamNotCanonical, 357 skipN2: true, 358 }, 359 { 360 name: "duplicate ignored tlv type", 361 bytes: []byte{0x1f, 0x00, 0x1f, 0x01, 0x2a}, 362 expErr: tlv.ErrStreamNotCanonical, 363 skipN2: true, 364 }, 365 { 366 name: "type wraparound", 367 bytes: []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00}, 368 expErr: tlv.ErrStreamNotCanonical, 369 }, 370 { 371 name: "absurd record length", 372 bytes: []byte{0xfd, 0x01, 0x91, 0xfe, 0xff, 0xff, 0xff, 0xff}, 373 expErr: tlv.ErrRecordTooLarge, 374 skipN2: true, 375 }, 376 } 377 378 // TestTLVDecodingSuccess asserts that the TLV parser fails to decode invalid 379 // TLV streams. 380 func TestTLVDecodingFailures(t *testing.T) { 381 for _, test := range tlvDecodingFailureTests { 382 t.Run(test.name, func(t *testing.T) { 383 n1 := NewN1() 384 r := bytes.NewReader(test.bytes) 385 386 err := n1.Decode(r) 387 if !reflect.DeepEqual(err, test.expErr) { 388 t.Fatalf("expected N1 decoding failure: %v, "+ 389 "got: %v %t", test.expErr, err, err) 390 } 391 392 if test.skipN2 { 393 return 394 } 395 396 n2 := NewN2() 397 r = bytes.NewReader(test.bytes) 398 399 err = n2.Decode(r) 400 if !reflect.DeepEqual(err, test.expErr) { 401 t.Fatalf("expected N2 decoding failure: %v, "+ 402 "got: %v", test.expErr, err) 403 } 404 }) 405 } 406 } 407 408 var tlvDecodingSuccessTests = []struct { 409 name string 410 bytes []byte 411 skipN2 bool 412 }{ 413 { 414 name: "empty", 415 }, 416 { 417 name: "unknown odd type", 418 bytes: []byte{0x21, 0x00}, 419 }, 420 { 421 name: "unknown odd type", 422 bytes: []byte{0xfd, 0x02, 0x01, 0x00}, 423 }, 424 { 425 name: "unknown odd type", 426 bytes: []byte{0xfd, 0x00, 0xfd, 0x00}, 427 }, 428 { 429 name: "unknown odd type", 430 bytes: []byte{0xfd, 0x00, 0xff, 0x00}, 431 }, 432 { 433 name: "unknown odd type", 434 bytes: []byte{0xfe, 0x02, 0x00, 0x00, 0x01, 0x00}, 435 }, 436 { 437 name: "unknown odd type", 438 bytes: []byte{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, 439 }, 440 { 441 name: "N1 amt=0", 442 bytes: []byte{0x01, 0x00}, 443 skipN2: true, 444 }, 445 { 446 name: "N1 amt=1", 447 bytes: []byte{0x01, 0x01, 0x01}, 448 skipN2: true, 449 }, 450 { 451 name: "N1 amt=256", 452 bytes: []byte{0x01, 0x02, 0x01, 0x00}, 453 skipN2: true, 454 }, 455 { 456 name: "N1 amt=65536", 457 bytes: []byte{0x01, 0x03, 0x01, 0x00, 0x00}, 458 skipN2: true, 459 }, 460 { 461 name: "N1 amt=16777216", 462 bytes: []byte{0x01, 0x04, 0x01, 0x00, 0x00, 0x00}, 463 skipN2: true, 464 }, 465 { 466 name: "N1 amt=4294967296", 467 bytes: []byte{0x01, 0x05, 0x01, 0x00, 0x00, 0x00, 0x00}, 468 skipN2: true, 469 }, 470 { 471 name: "N1 amt=1099511627776", 472 bytes: []byte{0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00}, 473 skipN2: true, 474 }, 475 { 476 name: "N1 amt=281474976710656", 477 bytes: []byte{0x01, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 478 skipN2: true, 479 }, 480 { 481 name: "N1 amt=72057594037927936", 482 bytes: []byte{0x01, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 483 skipN2: true, 484 }, 485 { 486 name: "N1 scid=0x0x550", 487 bytes: []byte{0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x26}, 488 skipN2: true, 489 }, 490 { 491 name: "N1 node_id=023da092f6980e58d2c037173180e9a465476026ee50f96695963e8efe436f54eb amount_msat_1=1 amount_msat_2=2", 492 bytes: []byte{0x03, 0x31, 493 0x02, 0x3d, 0xa0, 0x92, 0xf6, 0x98, 0x0e, 0x58, 0xd2, 494 0xc0, 0x37, 0x17, 0x31, 0x80, 0xe9, 0xa4, 0x65, 0x47, 495 0x60, 0x26, 0xee, 0x50, 0xf9, 0x66, 0x95, 0x96, 0x3e, 496 0x8e, 0xfe, 0x43, 0x6f, 0x54, 0xeb, 0x00, 0x00, 0x00, 497 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 498 0x00, 0x00, 0x00, 0x02}, 499 skipN2: true, 500 }, 501 { 502 name: "N1 cltv_delta=550", 503 bytes: []byte{0xfd, 0x00, 0xfe, 0x02, 0x02, 0x26}, 504 skipN2: true, 505 }, 506 } 507 508 // TestTLVDecodingSuccess asserts that the TLV parser is able to successfully 509 // decode valid TLV streams. 510 func TestTLVDecodingSuccess(t *testing.T) { 511 for _, test := range tlvDecodingSuccessTests { 512 t.Run(test.name, func(t *testing.T) { 513 n1 := NewN1() 514 r := bytes.NewReader(test.bytes) 515 516 err := n1.Decode(r) 517 if err != nil { 518 t.Fatalf("expected N1 decoding success, got: %v", 519 err) 520 } 521 522 if test.skipN2 { 523 return 524 } 525 526 n2 := NewN2() 527 r = bytes.NewReader(test.bytes) 528 529 err = n2.Decode(r) 530 if err != nil { 531 t.Fatalf("expected N2 decoding succes, got: %v", 532 err) 533 } 534 }) 535 } 536 }