@@ -42,7 +42,7 @@ use io_extras::read_to_end;
42
42
43
43
use util:: events:: MessageSendEventsProvider ;
44
44
use util:: logger;
45
- use util:: ser:: { LengthReadable , Readable , ReadableArgs , Writeable , Writer , FixedLengthReader , HighZeroBytesDroppedVarInt , Hostname } ;
45
+ use util:: ser:: { BigSize , LengthReadable , Readable , ReadableArgs , Writeable , Writer , FixedLengthReader , HighZeroBytesDroppedVarInt , Hostname } ;
46
46
47
47
use ln:: { PaymentPreimage , PaymentHash , PaymentSecret } ;
48
48
@@ -1418,16 +1418,11 @@ impl Writeable for OnionHopData {
1418
1418
}
1419
1419
1420
1420
impl Readable for OnionHopData {
1421
- fn read < R : Read > ( mut r : & mut R ) -> Result < Self , DecodeError > {
1422
- use bitcoin:: consensus:: encode:: { Decodable , Error , VarInt } ;
1423
- let v: VarInt = Decodable :: consensus_decode ( & mut r)
1424
- . map_err ( |e| match e {
1425
- Error :: Io ( ioe) => DecodeError :: from ( ioe) ,
1426
- _ => DecodeError :: InvalidValue
1427
- } ) ?;
1421
+ fn read < R : Read > ( r : & mut R ) -> Result < Self , DecodeError > {
1422
+ let b: BigSize = Readable :: read ( r) ?;
1428
1423
const LEGACY_ONION_HOP_FLAG : u64 = 0 ;
1429
- let ( format, amt, cltv_value) = if v . 0 != LEGACY_ONION_HOP_FLAG {
1430
- let mut rd = FixedLengthReader :: new ( r, v . 0 ) ;
1424
+ let ( format, amt, cltv_value) = if b . 0 != LEGACY_ONION_HOP_FLAG {
1425
+ let mut rd = FixedLengthReader :: new ( r, b . 0 ) ;
1431
1426
let mut amt = HighZeroBytesDroppedVarInt ( 0u64 ) ;
1432
1427
let mut cltv_value = HighZeroBytesDroppedVarInt ( 0u32 ) ;
1433
1428
let mut short_id: Option < u64 > = None ;
@@ -2824,4 +2819,40 @@ mod tests {
2824
2819
assert_eq ! ( gossip_timestamp_filter. first_timestamp, 1590000000 ) ;
2825
2820
assert_eq ! ( gossip_timestamp_filter. timestamp_range, 0xffff_ffff ) ;
2826
2821
}
2822
+
2823
+ #[ test]
2824
+ fn decode_onion_hop_data_len_as_bigsize ( ) {
2825
+ // Tests that we can decode an onion payload that is >253 bytes.
2826
+ // Previously, receiving a payload of this size could've caused us to fail to decode a valid
2827
+ // payload, because we were decoding the length (a BigSize, big-endian) as a VarInt
2828
+ // (little-endian).
2829
+
2830
+ // Encode a test onion payload with a big custom TLV such that it's >253 bytes, forcing the
2831
+ // payload length to be encoded over multiple bytes rather than a single u8.
2832
+ let big_payload = encode_big_payload ( ) . unwrap ( ) ;
2833
+ let mut rd = Cursor :: new ( & big_payload[ ..] ) ;
2834
+ <msgs:: OnionHopData as Readable >:: read ( & mut rd) . unwrap ( ) ;
2835
+ }
2836
+ // see above test, needs to be a separate method for use of the serialization macros.
2837
+ fn encode_big_payload ( ) -> Result < Vec < u8 > , std:: io:: Error > {
2838
+ use util:: ser:: HighZeroBytesDroppedVarInt ;
2839
+ let payload = msgs:: OnionHopData {
2840
+ format : OnionHopDataFormat :: NonFinalNode {
2841
+ short_channel_id : 0xdeadbeef1bad1dea ,
2842
+ } ,
2843
+ amt_to_forward : 1000 ,
2844
+ outgoing_cltv_value : 0xffffffff ,
2845
+ } ;
2846
+ let mut encoded_payload = Vec :: new ( ) ;
2847
+ let test_bytes = vec ! [ 42 as u8 ; 1000 ] ;
2848
+ if let OnionHopDataFormat :: NonFinalNode { short_channel_id } = payload. format {
2849
+ encode_varint_length_prefixed_tlv ! ( & mut encoded_payload, {
2850
+ ( 1 , test_bytes, vec_type) ,
2851
+ ( 2 , HighZeroBytesDroppedVarInt ( payload. amt_to_forward) , required) ,
2852
+ ( 4 , HighZeroBytesDroppedVarInt ( payload. outgoing_cltv_value) , required) ,
2853
+ ( 6 , short_channel_id, required)
2854
+ } ) ;
2855
+ }
2856
+ Ok ( encoded_payload)
2857
+ }
2827
2858
}
0 commit comments