|
2 | 2 |
|
3 | 3 | use std::time::Duration; |
4 | 4 |
|
5 | | -use smite::bolt::{Init, InitTlvs, Message}; |
| 5 | +use smite::bolt::{FeatureBit, Features, Init, InitTlvs, Message}; |
6 | 6 | use smite::noise::NoiseConnection; |
7 | 7 | use smite::scenarios::ScenarioError; |
8 | 8 |
|
@@ -30,49 +30,34 @@ pub trait SnapshotSetup<T: Target> { |
30 | 30 | fn setup(target: &T) -> Result<(NoiseConnection, ProgramContext), ScenarioError>; |
31 | 31 | } |
32 | 32 |
|
33 | | -/// Clears a feature bit from a feature vector. |
34 | | -/// |
35 | | -/// Feature vectors are encoded as big-endian byte arrays where bit N lives in |
36 | | -/// byte `features[len - 1 - N/8]` at position `N % 8`. |
37 | | -fn clear_feature_bit(features: &mut [u8], bit: usize) { |
38 | | - let byte_index = features.len().checked_sub(1 + bit / 8); |
39 | | - if let Some(i) = byte_index { |
40 | | - features[i] &= !(1 << (bit % 8)); |
41 | | - } |
42 | | -} |
43 | | - |
44 | | -/// Gossip-related feature bits (BOLT 9): `gossip_queries` (6/7), |
45 | | -/// `gossip_queries_ex` (10/11). Stripped so the target doesn't send |
46 | | -/// `gossip_timestamp_filter` or other gossip noise during execution. |
47 | | -const GOSSIP_FEATURE_BITS: &[usize] = &[6, 7, 10, 11]; |
48 | | - |
49 | | -/// Feature bits that force a dual-funded flow when both peers support them: |
50 | | -/// `option_dual_fund` (28/29). Eclair in particular will not allow |
51 | | -/// single-funded flows if either of these feature bits is set, so we strip them |
52 | | -/// when fuzzing the single-funded flow. |
53 | | -const DUAL_FUNDING_FEATURE_BITS: &[usize] = &[28, 29]; |
54 | | - |
55 | | -/// Peer storage feature bits: `option_provide_storage` (42/43). When enabled, |
56 | | -/// peers may send `peer_storage` and `peer_storage_retrieval` messages at |
57 | | -/// arbitrary times. Disabling these bits eliminates peer storage noise. |
58 | | -const PEER_STORAGE_FEATURE_BITS: &[usize] = &[42, 43]; |
| 33 | +/// Features stripped from our echoed `init` so the target stays on the single |
| 34 | +/// funded flow and doesn't emit unrelated noise: |
| 35 | +/// - `gossip_queries` (6/7), `gossip_queries_ex` (10/11): Stripped so the |
| 36 | +/// target doesn't send `gossip_timestamp_filter` or other gossip noise during |
| 37 | +/// execution. |
| 38 | +/// - `option_dual_fund` (28/29): Eclair in particular will not allow |
| 39 | +/// single-funded flows if either of these feature bits is set. |
| 40 | +/// - `option_provide_storage` (42/43): When enabled, peers may send |
| 41 | +/// `peer_storage` and `peer_storage_retrieval` messages at arbitrary times. |
| 42 | +const STRIPPED_FEATURES: &[FeatureBit] = &[ |
| 43 | + Features::GOSSIP_QUERIES, |
| 44 | + Features::GOSSIP_QUERIES_EX, |
| 45 | + Features::OPTION_DUAL_FUND, |
| 46 | + Features::OPTION_PROVIDE_STORAGE, |
| 47 | +]; |
59 | 48 |
|
60 | 49 | /// Creates an `init` that echoes the received features with bits stripped that |
61 | 50 | /// would steer the target away from the single-funded `open_channel` flow. |
62 | 51 | fn init_for_single_funded(received: &Init) -> Init { |
63 | | - let mut globalfeatures = received.globalfeatures.clone(); |
64 | | - let mut features = received.features.clone(); |
65 | | - for &bit in GOSSIP_FEATURE_BITS |
66 | | - .iter() |
67 | | - .chain(DUAL_FUNDING_FEATURE_BITS) |
68 | | - .chain(PEER_STORAGE_FEATURE_BITS) |
69 | | - { |
70 | | - clear_feature_bit(&mut globalfeatures, bit); |
71 | | - clear_feature_bit(&mut features, bit); |
| 52 | + let mut globalfeatures = Features::from(received.globalfeatures.clone()); |
| 53 | + let mut features = Features::from(received.features.clone()); |
| 54 | + for &bit in STRIPPED_FEATURES { |
| 55 | + globalfeatures.clear_feature(bit); |
| 56 | + features.clear_feature(bit); |
72 | 57 | } |
73 | 58 | Init { |
74 | | - globalfeatures, |
75 | | - features, |
| 59 | + globalfeatures: globalfeatures.into_bytes(), |
| 60 | + features: features.into_bytes(), |
76 | 61 | tlvs: InitTlvs::default(), |
77 | 62 | } |
78 | 63 | } |
|
0 commit comments