@@ -774,22 +774,39 @@ pub struct UpdateAddHTLC {
774774 /// Note that this field is [`experimental`] so should not be used for forwarding decisions.
775775 ///
776776 /// [`experimental`]: https://github.com/lightning/blips/blob/master/blip-0004.md
777- pub accountable : ExperimentalAccountable ,
777+ pub accountable : Option < bool > ,
778778}
779779
780- /// Represents the value sent on the wire to signal experimental accountability. For historical
781- /// reasons the least significant three bits are used to represent the accountable signal's value,
782- /// though it is now only interpreted as a binary value.
783- pub type ExperimentalAccountable = Option < u8 > ;
780+ struct AccountableBool < T > ( T ) ;
784781
785- /// Converts a boolean accountable signal to its wire representation.
786- pub fn accountable_from_bool ( value : bool ) -> ExperimentalAccountable {
787- Some ( if value { 7 } else { 0 } )
782+ impl Writeable for AccountableBool < bool > {
783+ #[ inline]
784+ fn write < W : Writer > ( & self , writer : & mut W ) -> Result < ( ) , io:: Error > {
785+ let wire_value = if self . 0 { 7u8 } else { 0u8 } ;
786+ writer. write_all ( & [ wire_value] )
787+ }
788+ }
789+
790+ impl Readable for AccountableBool < bool > {
791+ #[ inline]
792+ fn read < R : Read > ( reader : & mut R ) -> Result < AccountableBool < bool > , DecodeError > {
793+ let mut buf = [ 0u8 ; 1 ] ;
794+ reader. read_exact ( & mut buf) ?;
795+ let bool_value = buf[ 0 ] == 7 ;
796+ Ok ( AccountableBool ( bool_value) )
797+ }
788798}
789799
790- /// Converts the accountable signal on the wire to a boolean signal.
791- pub fn accountable_into_bool ( accountable : ExperimentalAccountable ) -> bool {
792- accountable. is_some_and ( |v| v == 7 )
800+ impl From < bool > for AccountableBool < bool > {
801+ fn from ( val : bool ) -> Self {
802+ Self ( val)
803+ }
804+ }
805+
806+ impl From < AccountableBool < bool > > for bool {
807+ fn from ( val : AccountableBool < bool > ) -> Self {
808+ val. 0
809+ }
793810}
794811
795812/// An [`onion message`] to be sent to or received from a peer.
@@ -3395,7 +3412,7 @@ impl_writeable_msg!(UpdateAddHTLC, {
33953412 // TODO: currently we may fail to read the `ChannelManager` if we write a new even TLV in this message
33963413 // and then downgrade. Once this is fixed, update the type here to match BOLTs PR 989.
33973414 ( 75537 , hold_htlc, option) ,
3398- ( 106823 , accountable, option) ,
3415+ ( 106823 , accountable, ( option, encoding : ( bool , AccountableBool ) ) ) ,
33993416} ) ;
34003417
34013418impl LengthReadable for OnionMessage {
@@ -4395,7 +4412,7 @@ mod tests {
43954412 } ;
43964413 use crate :: types:: payment:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
43974414 use crate :: util:: ser:: { BigSize , Hostname , LengthReadable , Readable , ReadableArgs , Writeable } ;
4398- use crate :: util:: test_utils;
4415+ use crate :: util:: test_utils:: { self , pubkey } ;
43994416 use bitcoin:: hex:: DisplayHex ;
44004417 use bitcoin:: { Amount , ScriptBuf , Sequence , Transaction , TxIn , TxOut , Witness } ;
44014418
@@ -6786,4 +6803,71 @@ mod tests {
67866803 . to_socket_addrs( )
67876804 . is_err( ) ) ;
67886805 }
6806+
6807+ fn test_update_add_htlc ( ) -> msgs:: UpdateAddHTLC {
6808+ msgs:: UpdateAddHTLC {
6809+ channel_id : ChannelId :: from_bytes ( [ 2 ; 32 ] ) ,
6810+ htlc_id : 42 ,
6811+ amount_msat : 1000 ,
6812+ payment_hash : PaymentHash ( [ 1 ; 32 ] ) ,
6813+ cltv_expiry : 500000 ,
6814+ skimmed_fee_msat : None ,
6815+ onion_routing_packet : msgs:: OnionPacket {
6816+ version : 0 ,
6817+ public_key : Ok ( pubkey ( 42 ) ) ,
6818+ hop_data : [ 1 ; 20 * 65 ] ,
6819+ hmac : [ 2 ; 32 ] ,
6820+ } ,
6821+ blinding_point : None ,
6822+ hold_htlc : None ,
6823+ accountable : None ,
6824+ }
6825+ }
6826+
6827+ #[ test]
6828+ fn test_update_add_htlc_accountable_encoding ( ) {
6829+ // Tests that accountable boolean values are written to the wire with correct u8 values.
6830+ for ( bool_signal, wire_value) in [ ( Some ( false ) , 0u8 ) , ( Some ( true ) , 7u8 ) ] {
6831+ let mut base_msg = test_update_add_htlc ( ) ;
6832+ base_msg. accountable = bool_signal;
6833+ let encoded = base_msg. encode ( ) ;
6834+ assert_eq ! (
6835+ * encoded. last( ) . unwrap( ) ,
6836+ wire_value,
6837+ "wrong wire value for accountable={:?}" ,
6838+ bool_signal
6839+ ) ;
6840+ }
6841+ }
6842+
6843+ fn do_test_htlc_accountable_from_u8 ( accountable_override : Option < u8 > , expected : Option < bool > ) {
6844+ // Tests custom encoding conversion of u8 wire values to appropriate boolean, manually
6845+ // writing to support values that we wouldn't encode ourselves but should be able to read.
6846+ let base_msg = test_update_add_htlc ( ) ;
6847+ let mut encoded = base_msg. encode ( ) ;
6848+ if let Some ( value) = accountable_override {
6849+ encoded. extend_from_slice ( & [ 0xfe , 0x00 , 0x01 , 0xa1 , 0x47 ] ) ;
6850+ encoded. push ( 1 ) ;
6851+ encoded. push ( value) ;
6852+ }
6853+
6854+ let decoded: msgs:: UpdateAddHTLC =
6855+ LengthReadable :: read_from_fixed_length_buffer ( & mut & encoded[ ..] ) . unwrap ( ) ;
6856+
6857+ assert_eq ! (
6858+ decoded. accountable, expected,
6859+ "accountable={:?} with override={:?} not eq to expected={:?}" ,
6860+ decoded. accountable, accountable_override, expected
6861+ ) ;
6862+ }
6863+
6864+ #[ test]
6865+ fn update_add_htlc_accountable_from_u8 ( ) {
6866+ // Tests that accountable signals encoded as a u8 are properly translated to a bool.
6867+ do_test_htlc_accountable_from_u8 ( None , None ) ;
6868+ do_test_htlc_accountable_from_u8 ( Some ( 8 ) , Some ( false ) ) ; // 8 is an invalid value
6869+ do_test_htlc_accountable_from_u8 ( Some ( 7 ) , Some ( true ) ) ;
6870+ do_test_htlc_accountable_from_u8 ( Some ( 3 ) , Some ( false ) ) ;
6871+ do_test_htlc_accountable_from_u8 ( Some ( 0 ) , Some ( false ) ) ;
6872+ }
67896873}
0 commit comments