Skip to content

Commit a75fdab

Browse files
authored
Merge pull request #3302 from TheBlueMatt/2024-09-atomic-cleanups
Simplify and fix AtomicCounter
2 parents 1059f5f + 1c2bd09 commit a75fdab

File tree

7 files changed

+61
-27
lines changed

7 files changed

+61
-27
lines changed

lightning/src/ln/functional_tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7670,8 +7670,8 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
76707670
assert_ne!(node_txn[0].input[0].previous_output, node_txn[2].input[0].previous_output);
76717671
assert_ne!(node_txn[1].input[0].previous_output, node_txn[2].input[0].previous_output);
76727672

7673-
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
7674-
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
7673+
assert_eq!(node_txn[1].input[0].previous_output, revoked_htlc_txn[1].input[0].previous_output);
7674+
assert_eq!(node_txn[0].input[0].previous_output, revoked_htlc_txn[0].input[0].previous_output);
76757675

76767676
// node_txn[3] spends the revoked outputs from the revoked_htlc_txn (which only have one
76777677
// output, checked above).

lightning/src/ln/interactivetxs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1328,7 +1328,7 @@ mod tests {
13281328
impl EntropySource for TestEntropySource {
13291329
fn get_secure_random_bytes(&self) -> [u8; 32] {
13301330
let mut res = [0u8; 32];
1331-
let increment = self.0.get_increment();
1331+
let increment = self.0.next();
13321332
for (i, byte) in res.iter_mut().enumerate() {
13331333
// Rotate the increment value by 'i' bits to the right, to avoid clashes
13341334
// when `generate_local_serial_id` does a parity flip on consecutive calls for the

lightning/src/ln/max_payment_path_len_tests.rs

+7
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ fn blinded_path_with_custom_tlv() {
255255
create_announced_chan_between_nodes(&nodes, 1, 2);
256256
let chan_upd_2_3 = create_announced_chan_between_nodes_with_value(&nodes, 2, 3, 1_000_000, 0).0.contents;
257257

258+
// Ensure all nodes are at the same height
259+
let node_max_height = nodes.iter().map(|node| node.blocks.lock().unwrap().len()).max().unwrap() as u32;
260+
connect_blocks(&nodes[0], node_max_height - nodes[0].best_block_info().1);
261+
connect_blocks(&nodes[1], node_max_height - nodes[1].best_block_info().1);
262+
connect_blocks(&nodes[2], node_max_height - nodes[2].best_block_info().1);
263+
connect_blocks(&nodes[3], node_max_height - nodes[3].best_block_info().1);
264+
258265
// Construct the route parameters for sending to nodes[3]'s blinded path.
259266
let amt_msat = 100_000;
260267
let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash(&nodes[3], Some(amt_msat), None);

lightning/src/ln/monitor_tests.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,10 @@ fn do_test_restored_packages_retry(check_old_monitor_retries_after_upgrade: bool
22512251

22522252
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
22532253

2254+
// Reset our RNG counters to mirror the RNG output from when this test was written.
2255+
nodes[0].keys_manager.backing.inner.entropy_source.set_counter(0x1_0000_0004);
2256+
nodes[1].keys_manager.backing.inner.entropy_source.set_counter(0x1_0000_0004);
2257+
22542258
// Open a channel, lock in an HTLC, and immediately broadcast the commitment transaction. This
22552259
// ensures that the HTLC timeout package is held until we reach its expiration height.
22562260
let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100_000, 50_000_000);

lightning/src/ln/peer_handler.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1055,7 +1055,7 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
10551055

10561056
fn get_ephemeral_key(&self) -> SecretKey {
10571057
let mut ephemeral_hash = self.ephemeral_key_midstate.clone();
1058-
let counter = self.peer_counter.get_increment();
1058+
let counter = self.peer_counter.next();
10591059
ephemeral_hash.input(&counter.to_le_bytes());
10601060
SecretKey::from_slice(&Sha256::from_engine(ephemeral_hash).to_byte_array()).expect("You broke SHA-256!")
10611061
}

lightning/src/sign/mod.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -1027,7 +1027,6 @@ pub trait ChangeDestinationSource {
10271027
///
10281028
/// This implementation performs no policy checks and is insufficient by itself as
10291029
/// a secure external signer.
1030-
#[derive(Debug)]
10311030
pub struct InMemorySigner {
10321031
/// Holder secret key in the 2-of-2 multisig script of a channel. This key also backs the
10331032
/// holder's anchor output in a commitment transaction, if one is present.
@@ -1854,6 +1853,9 @@ pub struct KeysManager {
18541853
channel_master_key: Xpriv,
18551854
channel_child_index: AtomicUsize,
18561855

1856+
#[cfg(test)]
1857+
pub(crate) entropy_source: RandomBytes,
1858+
#[cfg(not(test))]
18571859
entropy_source: RandomBytes,
18581860

18591861
seed: [u8; 32],
@@ -2310,6 +2312,9 @@ impl SignerProvider for KeysManager {
23102312
/// Switching between this struct and [`KeysManager`] will invalidate any previously issued
23112313
/// invoices and attempts to pay previous invoices will fail.
23122314
pub struct PhantomKeysManager {
2315+
#[cfg(test)]
2316+
pub(crate) inner: KeysManager,
2317+
#[cfg(not(test))]
23132318
inner: KeysManager,
23142319
inbound_payment_key: KeyMaterial,
23152320
phantom_secret: SecretKey,
@@ -2475,7 +2480,6 @@ impl PhantomKeysManager {
24752480
}
24762481

24772482
/// An implementation of [`EntropySource`] using ChaCha20.
2478-
#[derive(Debug)]
24792483
pub struct RandomBytes {
24802484
/// Seed from which all randomness produced is derived from.
24812485
seed: [u8; 32],
@@ -2489,11 +2493,18 @@ impl RandomBytes {
24892493
pub fn new(seed: [u8; 32]) -> Self {
24902494
Self { seed, index: AtomicCounter::new() }
24912495
}
2496+
2497+
#[cfg(test)]
2498+
/// Force the counter to a value to produce the same output again. Mostly useful in tests where
2499+
/// we need to maintain behavior with a previous version which didn't use as much RNG output.
2500+
pub(crate) fn set_counter(&self, count: u64) {
2501+
self.index.set_counter(count);
2502+
}
24922503
}
24932504

24942505
impl EntropySource for RandomBytes {
24952506
fn get_secure_random_bytes(&self) -> [u8; 32] {
2496-
let index = self.index.get_increment();
2507+
let index = self.index.next();
24972508
let mut nonce = [0u8; 16];
24982509
nonce[..8].copy_from_slice(&index.to_be_bytes());
24992510
ChaCha20::get_single_block(&self.seed, &nonce)

lightning/src/util/atomic_counter.rs

+32-20
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,44 @@
1-
//! A simple atomic counter that uses AtomicUsize to give a u64 counter.
1+
//! A simple atomic counter that uses mutexes if the platform doesn't support atomic u64s.
22
3-
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
4-
compile_error!("We need at least 32-bit pointers for atomic counter (and to have enough memory to run LDK)");
3+
#[cfg(target_has_atomic = "64")]
4+
use core::sync::atomic::{AtomicU64, Ordering};
5+
#[cfg(not(target_has_atomic = "64"))]
6+
use crate::sync::Mutex;
57

6-
use core::sync::atomic::{AtomicUsize, Ordering};
7-
8-
#[derive(Debug)]
98
pub(crate) struct AtomicCounter {
10-
// Usize needs to be at least 32 bits to avoid overflowing both low and high. If usize is 64
11-
// bits we will never realistically count into high:
12-
counter_low: AtomicUsize,
13-
counter_high: AtomicUsize,
9+
#[cfg(target_has_atomic = "64")]
10+
counter: AtomicU64,
11+
#[cfg(not(target_has_atomic = "64"))]
12+
counter: Mutex<u64>,
1413
}
1514

1615
impl AtomicCounter {
1716
pub(crate) fn new() -> Self {
1817
Self {
19-
counter_low: AtomicUsize::new(0),
20-
counter_high: AtomicUsize::new(0),
18+
#[cfg(target_has_atomic = "64")]
19+
counter: AtomicU64::new(0),
20+
#[cfg(not(target_has_atomic = "64"))]
21+
counter: Mutex::new(0),
22+
}
23+
}
24+
pub(crate) fn next(&self) -> u64 {
25+
#[cfg(target_has_atomic = "64")] {
26+
self.counter.fetch_add(1, Ordering::AcqRel)
27+
}
28+
#[cfg(not(target_has_atomic = "64"))] {
29+
let mut mtx = self.counter.lock().unwrap();
30+
*mtx += 1;
31+
*mtx - 1
2132
}
2233
}
23-
pub(crate) fn get_increment(&self) -> u64 {
24-
let low = self.counter_low.fetch_add(1, Ordering::AcqRel) as u64;
25-
let high = if low == 0 {
26-
self.counter_high.fetch_add(1, Ordering::AcqRel) as u64
27-
} else {
28-
self.counter_high.load(Ordering::Acquire) as u64
29-
};
30-
(high << 32) | low
34+
#[cfg(test)]
35+
pub(crate) fn set_counter(&self, count: u64) {
36+
#[cfg(target_has_atomic = "64")] {
37+
self.counter.store(count, Ordering::Release);
38+
}
39+
#[cfg(not(target_has_atomic = "64"))] {
40+
let mut mtx = self.counter.lock().unwrap();
41+
*mtx = count;
42+
}
3143
}
3244
}

0 commit comments

Comments
 (0)