Skip to content

Commit 669410c

Browse files
committed
f use custom encoding to read/write accountable signal as u8
1 parent 50175d5 commit 669410c

File tree

1 file changed

+97
-13
lines changed

1 file changed

+97
-13
lines changed

lightning/src/ln/msgs.rs

Lines changed: 97 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

34013418
impl 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

Comments
 (0)