@@ -65,6 +65,7 @@ use core::{cmp, mem};
65
65
use core:: cell:: RefCell ;
66
66
use io:: { Cursor , Read } ;
67
67
use sync:: { Arc , Condvar , Mutex , MutexGuard , RwLock , RwLockReadGuard } ;
68
+ use core:: convert:: TryInto ;
68
69
use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
69
70
use core:: time:: Duration ;
70
71
#[ cfg( any( test, feature = "allow_wallclock_use" ) ) ]
@@ -2586,6 +2587,62 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2586
2587
}
2587
2588
}
2588
2589
2590
+ // Check that an inbound payment's `payment_data` field is sane.
2591
+ fn verify_inbound_payment_data ( & self , payment_hash : PaymentHash , payment_data : msgs:: FinalOnionHopData ) -> Result < Option < PaymentPreimage > , ( ) > {
2592
+ let ( iv_bytes, encrypted_metadata_bytes) = payment_data. payment_secret . 0 . split_at ( 16 ) ;
2593
+ let mut chacha = ChaCha20 :: new ( & self . our_network_key [ ..] , & iv_bytes[ ..12 ] ) ;
2594
+ let mut chacha_bytes = [ 0 ; 16 ] ;
2595
+ chacha. process_in_place ( & mut chacha_bytes) ;
2596
+
2597
+ let mut metadata_bytes: [ u8 ; 16 ] = [ 0 ; 16 ] ;
2598
+ for i in 0 ..16 {
2599
+ metadata_bytes[ i] = chacha_bytes[ i] ^ encrypted_metadata_bytes[ i] ;
2600
+ }
2601
+
2602
+ let expiry = u64:: from_be_bytes ( metadata_bytes[ 8 ..] . try_into ( ) . unwrap ( ) ) ;
2603
+ if expiry < self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 {
2604
+ log_trace ! ( self . logger, "Failing HTLC with payment_hash {}: expired payment" , log_bytes!( payment_hash. 0 ) ) ;
2605
+ return Err ( ( ) )
2606
+ }
2607
+
2608
+ let is_user_payment_hash = metadata_bytes[ 0 ] & 1 << 7 != 0 ;
2609
+ let mut payment_preimage = None ;
2610
+ if is_user_payment_hash {
2611
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & self . our_network_key [ ..] ) ;
2612
+ hmac. input ( & metadata_bytes[ ..] ) ;
2613
+ hmac. input ( & payment_hash. 0 [ ..] ) ;
2614
+ if iv_bytes != Hmac :: from_engine ( hmac) . into_inner ( ) . split_at_mut ( 16 ) . 0 {
2615
+ log_trace ! ( self . logger, "Failing HTLC with user-generated payment_hash {}: unexpected payment_secret" , log_bytes!( payment_hash. 0 ) ) ;
2616
+ return Err ( ( ) )
2617
+ }
2618
+ // Reset the bit that was set to indicate that the payment hash was user-generated.
2619
+ let mut amt_msat_bytes = [ 0 ; 8 ] ;
2620
+ amt_msat_bytes. copy_from_slice ( & metadata_bytes[ ..8 ] ) ;
2621
+ amt_msat_bytes[ 0 ] ^= 1 << 7 ;
2622
+ let min_amt_msat = u64:: from_be_bytes ( amt_msat_bytes. try_into ( ) . unwrap ( ) ) ;
2623
+ if payment_data. total_msat < min_amt_msat {
2624
+ log_trace ! ( self . logger, "Failing HTLC with user-generated payment_hash {} due to total_msat {} being less than the minimum amount of {} msat" , log_bytes!( payment_hash. 0 ) , payment_data. total_msat, min_amt_msat) ;
2625
+ return Err ( ( ) )
2626
+ }
2627
+ } else {
2628
+ let min_amt_msat = u64:: from_be_bytes ( metadata_bytes[ ..8 ] . try_into ( ) . unwrap ( ) ) ;
2629
+ if payment_data. total_msat < min_amt_msat {
2630
+ log_trace ! ( self . logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat" , log_bytes!( payment_hash. 0 ) , payment_data. total_msat, min_amt_msat) ;
2631
+ return Err ( ( ) )
2632
+ }
2633
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & self . our_network_key [ ..] ) ;
2634
+ hmac. input ( & iv_bytes) ;
2635
+ hmac. input ( & metadata_bytes) ;
2636
+ let decoded_payment_preimage = Hmac :: from_engine ( hmac) . into_inner ( ) ;
2637
+ if payment_hash. 0 != Sha256 :: hash ( & decoded_payment_preimage) . into_inner ( ) {
2638
+ log_trace ! ( self . logger, "Failing HTLC with payment_hash {}: payment preimage {} did not match" , log_bytes!( payment_hash. 0 ) , log_bytes!( decoded_payment_preimage) ) ;
2639
+ return Err ( ( ) )
2640
+ }
2641
+ payment_preimage = Some ( PaymentPreimage ( decoded_payment_preimage) ) ;
2642
+ }
2643
+ Ok ( payment_preimage)
2644
+ }
2645
+
2589
2646
/// Processes HTLCs which are pending waiting on random forward delay.
2590
2647
///
2591
2648
/// Should only really ever be called in response to a PendingHTLCsForwardable event.
@@ -2801,6 +2858,56 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2801
2858
}
2802
2859
}
2803
2860
2861
+ macro_rules! check_total_value {
2862
+ ( $payment_data_total_msat: expr, $payment_secret: expr, $payment_preimage: expr) => {
2863
+ let mut total_value = 0 ;
2864
+ let htlcs = channel_state. claimable_htlcs. entry( payment_hash)
2865
+ . or_insert( Vec :: new( ) ) ;
2866
+ if htlcs. len( ) == 1 {
2867
+ if let OnionPayload :: Spontaneous ( _) = htlcs[ 0 ] . onion_payload {
2868
+ log_trace!( self . logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash" , log_bytes!( payment_hash. 0 ) ) ;
2869
+ fail_htlc!( claimable_htlc) ;
2870
+ continue
2871
+ }
2872
+ }
2873
+ htlcs. push( claimable_htlc) ;
2874
+ for htlc in htlcs. iter( ) {
2875
+ total_value += htlc. value;
2876
+ match & htlc. onion_payload {
2877
+ OnionPayload :: Invoice ( htlc_payment_data) => {
2878
+ if htlc_payment_data. total_msat != $payment_data_total_msat {
2879
+ log_trace!( self . logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})" ,
2880
+ log_bytes!( payment_hash. 0 ) , $payment_data_total_msat, htlc_payment_data. total_msat) ;
2881
+ total_value = msgs:: MAX_VALUE_MSAT ;
2882
+ }
2883
+ if total_value >= msgs:: MAX_VALUE_MSAT { break ; }
2884
+ } ,
2885
+ _ => unreachable!( ) ,
2886
+ }
2887
+ }
2888
+ if total_value >= msgs:: MAX_VALUE_MSAT || total_value > $payment_data_total_msat {
2889
+ log_trace!( self . logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)" ,
2890
+ log_bytes!( payment_hash. 0 ) , total_value, $payment_data_total_msat) ;
2891
+ for htlc in htlcs. iter( ) {
2892
+ fail_htlc!( htlc) ;
2893
+ }
2894
+ } else if total_value == $payment_data_total_msat {
2895
+ new_events. push( events:: Event :: PaymentReceived {
2896
+ payment_hash,
2897
+ purpose: events:: PaymentPurpose :: InvoicePayment {
2898
+ payment_preimage: $payment_preimage,
2899
+ payment_secret: $payment_secret,
2900
+ } ,
2901
+ amt: total_value,
2902
+ } ) ;
2903
+ } else {
2904
+ // Nothing to do - we haven't reached the total
2905
+ // payment value yet, wait until we receive more
2906
+ // MPP parts.
2907
+ }
2908
+ }
2909
+ }
2910
+
2804
2911
// Check that the payment hash and secret are known. Note that we
2805
2912
// MUST take care to handle the "unknown payment hash" and
2806
2913
// "incorrect payment secret" cases here identically or we'd expose
@@ -2811,9 +2918,17 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2811
2918
match payment_secrets. entry ( payment_hash) {
2812
2919
hash_map:: Entry :: Vacant ( _) => {
2813
2920
match claimable_htlc. onion_payload {
2814
- OnionPayload :: Invoice ( _) => {
2815
- log_trace ! ( self . logger, "Failing new HTLC with payment_hash {} as we didn't have a corresponding inbound payment." , log_bytes!( payment_hash. 0 ) ) ;
2816
- fail_htlc ! ( claimable_htlc) ;
2921
+ OnionPayload :: Invoice ( ref payment_data) => {
2922
+ let payment_preimage = match self . verify_inbound_payment_data ( payment_hash, payment_data. clone ( ) ) {
2923
+ Ok ( payment_preimage) => payment_preimage,
2924
+ Err ( ( ) ) => {
2925
+ fail_htlc ! ( claimable_htlc) ;
2926
+ continue
2927
+ }
2928
+ } ;
2929
+ let payment_data_total_msat = payment_data. total_msat ;
2930
+ let payment_secret = payment_data. payment_secret . clone ( ) ;
2931
+ check_total_value ! ( payment_data_total_msat, payment_secret, payment_preimage) ;
2817
2932
} ,
2818
2933
OnionPayload :: Spontaneous ( preimage) => {
2819
2934
match channel_state. claimable_htlcs . entry ( payment_hash) {
@@ -2850,55 +2965,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2850
2965
log_bytes!( payment_hash. 0 ) , payment_data. total_msat, inbound_payment. get( ) . min_value_msat. unwrap( ) ) ;
2851
2966
fail_htlc ! ( claimable_htlc) ;
2852
2967
} else {
2853
- let mut total_value = 0 ;
2854
- let htlcs = channel_state. claimable_htlcs . entry ( payment_hash)
2855
- . or_insert ( Vec :: new ( ) ) ;
2856
- if htlcs. len ( ) == 1 {
2857
- if let OnionPayload :: Spontaneous ( _) = htlcs[ 0 ] . onion_payload {
2858
- log_trace ! ( self . logger, "Failing new HTLC with payment_hash {} as we already had an existing keysend HTLC with the same payment hash" , log_bytes!( payment_hash. 0 ) ) ;
2859
- fail_htlc ! ( claimable_htlc) ;
2860
- continue
2861
- }
2862
- }
2863
- htlcs. push ( claimable_htlc) ;
2864
- for htlc in htlcs. iter ( ) {
2865
- total_value += htlc. value ;
2866
- match & htlc. onion_payload {
2867
- OnionPayload :: Invoice ( htlc_payment_data) => {
2868
- if htlc_payment_data. total_msat != payment_data. total_msat {
2869
- log_trace ! ( self . logger, "Failing HTLCs with payment_hash {} as the HTLCs had inconsistent total values (eg {} and {})" ,
2870
- log_bytes!( payment_hash. 0 ) , payment_data. total_msat, htlc_payment_data. total_msat) ;
2871
- total_value = msgs:: MAX_VALUE_MSAT ;
2872
- }
2873
- if total_value >= msgs:: MAX_VALUE_MSAT { break ; }
2874
- } ,
2875
- _ => unreachable ! ( ) ,
2876
- }
2877
- }
2878
- if total_value >= msgs:: MAX_VALUE_MSAT || total_value > payment_data. total_msat {
2879
- log_trace ! ( self . logger, "Failing HTLCs with payment_hash {} as the total value {} ran over expected value {} (or HTLCs were inconsistent)" ,
2880
- log_bytes!( payment_hash. 0 ) , total_value, payment_data. total_msat) ;
2881
- for htlc in htlcs. iter ( ) {
2882
- fail_htlc ! ( htlc) ;
2883
- }
2884
- } else if total_value == payment_data. total_msat {
2885
- new_events. push ( events:: Event :: PaymentReceived {
2886
- payment_hash,
2887
- purpose : events:: PaymentPurpose :: InvoicePayment {
2888
- payment_preimage : inbound_payment. get ( ) . payment_preimage ,
2889
- payment_secret : payment_data. payment_secret ,
2890
- } ,
2891
- amt : total_value,
2892
- } ) ;
2893
- // Only ever generate at most one PaymentReceived
2894
- // per registered payment_hash, even if it isn't
2895
- // claimed.
2896
- inbound_payment. remove_entry ( ) ;
2897
- } else {
2898
- // Nothing to do - we haven't reached the total
2899
- // payment value yet, wait until we receive more
2900
- // MPP parts.
2901
- }
2968
+ check_total_value ! ( payment_data. total_msat, payment_data. payment_secret, inbound_payment. get( ) . payment_preimage) ;
2902
2969
}
2903
2970
} ,
2904
2971
} ;
@@ -4522,38 +4589,11 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
4522
4589
}
4523
4590
}
4524
4591
4525
- fn set_payment_hash_secret_map ( & self , payment_hash : PaymentHash , payment_preimage : Option < PaymentPreimage > , min_value_msat : Option < u64 > , invoice_expiry_delta_secs : u32 ) -> Result < PaymentSecret , APIError > {
4526
- assert ! ( invoice_expiry_delta_secs <= 60 * 60 * 24 * 365 ) ; // Sadly bitcoin timestamps are u32s, so panic before 2106
4527
-
4528
- let payment_secret = PaymentSecret ( self . keys_manager . get_secure_random_bytes ( ) ) ;
4529
-
4530
- let _persistence_guard = PersistenceNotifierGuard :: notify_on_drop ( & self . total_consistency_lock , & self . persistence_notifier ) ;
4531
- let mut payment_secrets = self . pending_inbound_payments . lock ( ) . unwrap ( ) ;
4532
- match payment_secrets. entry ( payment_hash) {
4533
- hash_map:: Entry :: Vacant ( e) => {
4534
- e. insert ( PendingInboundPayment {
4535
- payment_secret, min_value_msat, payment_preimage,
4536
- user_payment_id : 0 , // For compatibility with version 0.0.103 and earlier
4537
- // We assume that highest_seen_timestamp is pretty close to the current time -
4538
- // its updated when we receive a new block with the maximum time we've seen in
4539
- // a header. It should never be more than two hours in the future.
4540
- // Thus, we add two hours here as a buffer to ensure we absolutely
4541
- // never fail a payment too early.
4542
- // Note that we assume that received blocks have reasonably up-to-date
4543
- // timestamps.
4544
- expiry_time : self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 + invoice_expiry_delta_secs as u64 + 7200 ,
4545
- } ) ;
4546
- } ,
4547
- hash_map:: Entry :: Occupied ( _) => return Err ( APIError :: APIMisuseError { err : "Duplicate payment hash" . to_owned ( ) } ) ,
4548
- }
4549
- Ok ( payment_secret)
4550
- }
4551
-
4552
4592
/// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
4553
4593
/// to pay us.
4554
4594
///
4555
4595
/// This differs from [`create_inbound_payment_for_hash`] only in that it generates the
4556
- /// [`PaymentHash`] and [`PaymentPreimage`] for you, returning the first and storing the second .
4596
+ /// [`PaymentHash`] and [`PaymentPreimage`] for you.
4557
4597
///
4558
4598
/// The [`PaymentPreimage`] will ultimately be returned to you in the [`PaymentReceived`], which
4559
4599
/// will have the [`PaymentReceived::payment_preimage`] field filled in. That should then be
@@ -4566,12 +4606,47 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
4566
4606
/// [`PaymentReceived::payment_preimage`]: events::Event::PaymentReceived::payment_preimage
4567
4607
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
4568
4608
pub fn create_inbound_payment ( & self , min_value_msat : Option < u64 > , invoice_expiry_delta_secs : u32 ) -> ( PaymentHash , PaymentSecret ) {
4569
- let payment_preimage = PaymentPreimage ( self . keys_manager . get_secure_random_bytes ( ) ) ;
4570
- let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage. 0 ) . into_inner ( ) ) ;
4609
+ let min_amt_msat_bytes: [ u8 ; 8 ] = match min_value_msat {
4610
+ Some ( amt) => amt. to_be_bytes ( ) ,
4611
+ None => [ 0 ; 8 ] ,
4612
+ } ;
4613
+ // We assume that highest_seen_timestamp is pretty close to the current time - its updated when
4614
+ // we receive a new block with the maximum time we've seen in a header. It should never be more
4615
+ // than two hours in the future. Thus, we add two hours here as a buffer to ensure we
4616
+ // absolutely never fail a payment too early.
4617
+ // Note that we assume that received blocks have reasonably up-to-date timestamps.
4618
+ let expiry_bytes = ( self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 + invoice_expiry_delta_secs as u64 + 7200 ) . to_be_bytes ( ) ;
4619
+ let mut metadata_bytes: [ u8 ; 16 ] = [ 0 ; 16 ] ;
4620
+ {
4621
+ let ( min_amt_msat_slice, expiry_slice) = metadata_bytes. split_at_mut ( 8 ) ;
4622
+ min_amt_msat_slice. copy_from_slice ( & min_amt_msat_bytes) ;
4623
+ expiry_slice. copy_from_slice ( & expiry_bytes) ;
4624
+ }
4625
+
4626
+ let rand_bytes = self . keys_manager . get_secure_random_bytes ( ) ;
4627
+ let iv_bytes = & rand_bytes[ ..16 ] ;
4628
+
4629
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & self . our_network_key [ ..] ) ;
4630
+ hmac. input ( iv_bytes) ;
4631
+ hmac. input ( & metadata_bytes) ;
4632
+ let payment_preimage_bytes = Hmac :: from_engine ( hmac) . into_inner ( ) ;
4571
4633
4572
- ( payment_hash,
4573
- self . set_payment_hash_secret_map ( payment_hash, Some ( payment_preimage) , min_value_msat, invoice_expiry_delta_secs)
4574
- . expect ( "RNG Generated Duplicate PaymentHash" ) )
4634
+ let mut payment_secret_bytes: [ u8 ; 32 ] = [ 0 ; 32 ] ;
4635
+ {
4636
+ let ( iv_slice, encrypted_metadata_slice) = payment_secret_bytes. split_at_mut ( 16 ) ;
4637
+ iv_slice. copy_from_slice ( iv_bytes) ;
4638
+
4639
+ let mut chacha = ChaCha20 :: new ( & self . our_network_key [ ..] , & iv_bytes[ ..12 ] ) ;
4640
+ let mut chacha_bytes = [ 0 ; 16 ] ;
4641
+ chacha. process_in_place ( & mut chacha_bytes) ;
4642
+
4643
+ for i in 0 ..16 {
4644
+ encrypted_metadata_slice[ i] = chacha_bytes[ i] ^ metadata_bytes[ i] ;
4645
+ }
4646
+ }
4647
+
4648
+ let payment_hash = PaymentHash ( Sha256 :: hash ( & payment_preimage_bytes) . into_inner ( ) ) ;
4649
+ ( payment_hash, PaymentSecret ( payment_secret_bytes) )
4575
4650
}
4576
4651
4577
4652
/// Gets a [`PaymentSecret`] for a given [`PaymentHash`], for which the payment preimage is
@@ -4593,18 +4668,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
4593
4668
/// in excess of the current time. This should roughly match the expiry time set in the invoice.
4594
4669
/// After this many seconds, we will remove the inbound payment, resulting in any attempts to
4595
4670
/// pay the invoice failing. The BOLT spec suggests 3,600 secs as a default validity time for
4596
- /// invoices when no timeout is set.
4597
- ///
4598
- /// Note that we use block header time to time-out pending inbound payments (with some margin
4599
- /// to compensate for the inaccuracy of block header timestamps). Thus, in practice we will
4671
+ /// invoices when no timeout is set. Note that we use block header time to time-out pending
4672
+ /// inbound payments (with some margin to compensate for the inaccuracy of block header
4673
+ /// timestamps). Thus, in practice we will
4600
4674
/// accept a payment and generate a [`PaymentReceived`] event for some time after the expiry.
4601
4675
/// If you need exact expiry semantics, you should enforce them upon receipt of
4602
4676
/// [`PaymentReceived`].
4603
4677
///
4604
- /// Pending inbound payments are stored in memory and in serialized versions of this
4605
- /// [`ChannelManager`]. If potentially unbounded numbers of inbound payments may exist and
4606
- /// space is limited, you may wish to rate-limit inbound payment creation.
4607
- ///
4608
4678
/// May panic if `invoice_expiry_delta_secs` is greater than one year.
4609
4679
///
4610
4680
/// Note that invoices generated for inbound payments should have their `min_final_cltv_expiry`
@@ -4613,7 +4683,48 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
4613
4683
/// [`create_inbound_payment`]: Self::create_inbound_payment
4614
4684
/// [`PaymentReceived`]: events::Event::PaymentReceived
4615
4685
pub fn create_inbound_payment_for_hash ( & self , payment_hash : PaymentHash , min_value_msat : Option < u64 > , invoice_expiry_delta_secs : u32 ) -> Result < PaymentSecret , APIError > {
4616
- self . set_payment_hash_secret_map ( payment_hash, None , min_value_msat, invoice_expiry_delta_secs)
4686
+ let mut min_amt_msat_bytes: [ u8 ; 8 ] = match min_value_msat {
4687
+ Some ( amt) => amt. to_be_bytes ( ) ,
4688
+ None => [ 0 ; 8 ] ,
4689
+ } ;
4690
+ // Flip the highest bit of the min_amt_msat field to indicate that this payment has a
4691
+ // user-generated PaymentHash.
4692
+ min_amt_msat_bytes[ 0 ] |= 1 << 7 ;
4693
+
4694
+ // We assume that highest_seen_timestamp is pretty close to the current time - its updated when
4695
+ // we receive a new block with the maximum time we've seen in a header. It should never be more
4696
+ // than two hours in the future. Thus, we add two hours here as a buffer to ensure we
4697
+ // absolutely never fail a payment too early.
4698
+ // Note that we assume that received blocks have reasonably up-to-date timestamps.
4699
+ let expiry_bytes = ( self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 + invoice_expiry_delta_secs as u64 + 7200 ) . to_be_bytes ( ) ;
4700
+
4701
+ let mut metadata_bytes: [ u8 ; 16 ] = [ 0 ; 16 ] ;
4702
+ {
4703
+ let ( min_amt_msat_slice, expiry_slice) = metadata_bytes. split_at_mut ( 8 ) ;
4704
+ min_amt_msat_slice. copy_from_slice ( & min_amt_msat_bytes) ;
4705
+ expiry_slice. copy_from_slice ( & expiry_bytes) ;
4706
+ }
4707
+
4708
+ let mut hmac = HmacEngine :: < Sha256 > :: new ( & self . our_network_key [ ..] ) ;
4709
+ hmac. input ( & metadata_bytes) ;
4710
+ hmac. input ( & payment_hash. 0 ) ;
4711
+ let hmac_bytes = Hmac :: from_engine ( hmac) . into_inner ( ) ;
4712
+ let iv_bytes = & hmac_bytes[ ..16 ] ;
4713
+
4714
+ let mut payment_secret_bytes: [ u8 ; 32 ] = [ 0 ; 32 ] ;
4715
+ {
4716
+ let ( iv_slice, encrypted_metadata_slice) = payment_secret_bytes. split_at_mut ( 16 ) ;
4717
+ iv_slice. copy_from_slice ( iv_bytes) ;
4718
+
4719
+ let mut chacha = ChaCha20 :: new ( & self . our_network_key [ ..] , & iv_bytes[ ..12 ] ) ;
4720
+ let mut chacha_bytes = [ 0 ; 16 ] ;
4721
+ chacha. process_in_place ( & mut chacha_bytes) ;
4722
+
4723
+ for i in 0 ..16 {
4724
+ encrypted_metadata_slice[ i] = chacha_bytes[ i] ^ metadata_bytes[ i] ;
4725
+ }
4726
+ }
4727
+ Ok ( PaymentSecret ( payment_secret_bytes) )
4617
4728
}
4618
4729
4619
4730
#[ cfg( any( test, feature = "fuzztarget" , feature = "_test_utils" ) ) ]
0 commit comments