Skip to content

Commit fa8c546

Browse files
isolated no handshake
1 parent 48d56a9 commit fa8c546

File tree

11 files changed

+191
-98
lines changed

11 files changed

+191
-98
lines changed

node/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. The format
1414
### Added
1515
* Add `BinaryPort` interface along with the relevant config entries.
1616
* Added chainspec settings `finders_fee`, `finality_signature_proportion` and `signature_rewards_max_delay` to control behavior of the new seigniorage model.
17+
* Isolated sync handling, which comes online with only local data and rejects peers. Useful for testing, auditing, and similar scenarios.
1718

1819
### Changed
1920
* All SSE events are emitted via the `<IP:Port>/events` endpoint. None of the previous ones (`/events/main`, `/events/deploys`, and `/events/sigs`) is available any longer.

node/src/components/network.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ where
248248
registry: &Registry,
249249
chain_info_source: C,
250250
validator_matrix: ValidatorMatrix,
251+
allow_handshake: bool,
251252
) -> Result<Network<REv, P>> {
252253
let net_metrics = Arc::new(Metrics::new(registry)?);
253254

@@ -285,6 +286,7 @@ where
285286
node_key_pair.map(NodeKeyPair::new),
286287
chain_info_source.into(),
287288
&net_metrics,
289+
allow_handshake,
288290
));
289291

290292
let component = Network {
@@ -662,6 +664,7 @@ where
662664
| ConnectionError::TlsHandshake(_)
663665
| ConnectionError::HandshakeSend(_)
664666
| ConnectionError::HandshakeRecv(_)
667+
| ConnectionError::HandshakeNotAllowed
665668
| ConnectionError::IncompatibleVersion(_) => None,
666669

667670
// These errors are potential bugs on our side.
@@ -1121,6 +1124,10 @@ where
11211124
{
11221125
type Event = Event<P>;
11231126

1127+
fn name(&self) -> &str {
1128+
COMPONENT_NAME
1129+
}
1130+
11241131
fn handle_event(
11251132
&mut self,
11261133
effect_builder: EffectBuilder<REv>,
@@ -1281,10 +1288,6 @@ where
12811288
},
12821289
}
12831290
}
1284-
1285-
fn name(&self) -> &str {
1286-
COMPONENT_NAME
1287-
}
12881291
}
12891292

12901293
impl<REv, P> InitializedComponent<REv> for Network<REv, P>

node/src/components/network/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,9 @@ pub enum ConnectionError {
196196
/// This is usually a bug.
197197
#[error("handshake sink/stream could not be reunited")]
198198
FailedToReuniteHandshakeSinkAndStream,
199+
/// Handshake not allowed (Isolated mode)
200+
#[error("handshake not allowed (Isolated mode)")]
201+
HandshakeNotAllowed,
199202
}
200203

201204
/// IO operation that can time out or close.

node/src/components/network/tasks.rs

+12
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ where
236236
max_in_flight_demands: usize,
237237
/// Flag indicating whether this node is syncing.
238238
is_syncing: AtomicBool,
239+
/// If false, will not allow handshake.
240+
allow_handshake: bool,
239241
}
240242

241243
impl<REv> NetworkContext<REv> {
@@ -245,6 +247,7 @@ impl<REv> NetworkContext<REv> {
245247
node_key_pair: Option<NodeKeyPair>,
246248
chain_info: ChainInfo,
247249
net_metrics: &Arc<Metrics>,
250+
allow_handshake: bool,
248251
) -> Self {
249252
// Set the demand max from configuration, regarding `0` as "unlimited".
250253
let max_in_flight_demands = if cfg.max_in_flight_demands == 0 {
@@ -277,6 +280,7 @@ impl<REv> NetworkContext<REv> {
277280
tarpit_chance: cfg.tarpit_chance,
278281
max_in_flight_demands,
279282
is_syncing: AtomicBool::new(false),
283+
allow_handshake,
280284
}
281285
}
282286

@@ -363,6 +367,14 @@ where
363367
peer_consensus_public_key,
364368
is_peer_syncing: _,
365369
}) => {
370+
if !context.allow_handshake {
371+
return IncomingConnection::Failed {
372+
peer_addr,
373+
peer_id,
374+
error: ConnectionError::HandshakeNotAllowed,
375+
};
376+
}
377+
366378
if let Some(ref public_key) = peer_consensus_public_key {
367379
Span::current().record("consensus_key", &field::display(public_key));
368380
}

node/src/components/network/tests.rs

+71-68
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ use tracing::{debug, info};
2121
use casper_types::{Chainspec, ChainspecRawBytes, SecretKey};
2222

2323
use super::{
24-
chain_info::ChainInfo, Config, Event as NetworkEvent, FromIncoming, GossipedAddress, Identity,
24+
chain_info::ChainInfo, Event as NetworkEvent, FromIncoming, GossipedAddress, Identity,
2525
MessageKind, Network, Payload,
2626
};
2727
use crate::{
2828
components::{
2929
gossiper::{self, GossipItem, Gossiper},
30-
Component, InitializedComponent,
30+
network, Component, InitializedComponent,
3131
},
3232
effect::{
3333
announcements::{ControlAnnouncement, GossiperAnnouncement, PeerBehaviorAnnouncement},
@@ -39,13 +39,13 @@ use crate::{
3939
EffectBuilder, Effects,
4040
},
4141
protocol,
42-
reactor::{self, EventQueueHandle, Finalize, Reactor, Runner},
42+
reactor::{self, main_reactor::Config, EventQueueHandle, Finalize, Reactor, Runner},
4343
testing::{
4444
self, init_logging,
4545
network::{NetworkedReactor, Nodes, TestingNetwork},
4646
ConditionCheckReactor,
4747
},
48-
types::{NodeId, ValidatorMatrix},
48+
types::{NodeId, SyncHandling, ValidatorMatrix},
4949
NodeRng,
5050
};
5151

@@ -182,43 +182,6 @@ impl Reactor for TestReactor {
182182
type Config = Config;
183183
type Error = anyhow::Error;
184184

185-
fn new(
186-
cfg: Self::Config,
187-
_chainspec: Arc<Chainspec>,
188-
_chainspec_raw_bytes: Arc<ChainspecRawBytes>,
189-
our_identity: Identity,
190-
registry: &Registry,
191-
_event_queue: EventQueueHandle<Self::Event>,
192-
rng: &mut NodeRng,
193-
) -> anyhow::Result<(Self, Effects<Self::Event>)> {
194-
let secret_key = SecretKey::random(rng);
195-
let mut net = Network::new(
196-
cfg,
197-
our_identity,
198-
None,
199-
registry,
200-
ChainInfo::create_for_testing(),
201-
ValidatorMatrix::new_with_validator(Arc::new(secret_key)),
202-
)?;
203-
let gossiper_config = gossiper::Config::new_with_small_timeouts();
204-
let address_gossiper = Gossiper::<{ GossipedAddress::ID_IS_COMPLETE_ITEM }, _>::new(
205-
"address_gossiper",
206-
gossiper_config,
207-
registry,
208-
)?;
209-
210-
net.start_initialization();
211-
let effects = smallvec![async { smallvec![Event::Net(NetworkEvent::Initialize)] }.boxed()];
212-
213-
Ok((
214-
TestReactor {
215-
net,
216-
address_gossiper,
217-
},
218-
effects,
219-
))
220-
}
221-
222185
fn dispatch_event(
223186
&mut self,
224187
effect_builder: EffectBuilder<Self::Event>,
@@ -277,6 +240,45 @@ impl Reactor for TestReactor {
277240
Event::BlocklistAnnouncement(_announcement) => Effects::new(),
278241
}
279242
}
243+
244+
fn new(
245+
cfg: Self::Config,
246+
_chainspec: Arc<Chainspec>,
247+
_chainspec_raw_bytes: Arc<ChainspecRawBytes>,
248+
our_identity: Identity,
249+
registry: &Registry,
250+
_event_queue: EventQueueHandle<Self::Event>,
251+
rng: &mut NodeRng,
252+
) -> anyhow::Result<(Self, Effects<Self::Event>)> {
253+
let secret_key = SecretKey::random(rng);
254+
let allow_handshake = cfg.node.sync_handling != SyncHandling::Isolated;
255+
let mut net = Network::new(
256+
cfg.network.clone(),
257+
our_identity,
258+
None,
259+
registry,
260+
ChainInfo::create_for_testing(),
261+
ValidatorMatrix::new_with_validator(Arc::new(secret_key)),
262+
allow_handshake,
263+
)?;
264+
let gossiper_config = gossiper::Config::new_with_small_timeouts();
265+
let address_gossiper = Gossiper::<{ GossipedAddress::ID_IS_COMPLETE_ITEM }, _>::new(
266+
"address_gossiper",
267+
gossiper_config,
268+
registry,
269+
)?;
270+
271+
net.start_initialization();
272+
let effects = smallvec![async { smallvec![Event::Net(NetworkEvent::Initialize)] }.boxed()];
273+
274+
Ok((
275+
TestReactor {
276+
net,
277+
address_gossiper,
278+
},
279+
effects,
280+
))
281+
}
280282
}
281283

282284
impl NetworkedReactor for TestReactor {
@@ -351,13 +353,15 @@ async fn run_two_node_network_five_times() {
351353
let mut net = TestingNetwork::new();
352354

353355
let start = Instant::now();
354-
net.add_node_with_config(
355-
Config::default_local_net_first_node(first_node_port),
356-
&mut rng,
357-
)
358-
.await
359-
.unwrap();
360-
net.add_node_with_config(Config::default_local_net(first_node_port), &mut rng)
356+
357+
let cfg = Config::default().with_network_config(
358+
network::Config::default_local_net_first_node(first_node_port),
359+
);
360+
net.add_node_with_config(cfg, &mut rng).await.unwrap();
361+
362+
let cfg = Config::default()
363+
.with_network_config(network::Config::default_local_net(first_node_port));
364+
net.add_node_with_config(cfg.clone(), &mut rng)
361365
.await
362366
.unwrap();
363367
let end = Instant::now();
@@ -417,12 +421,11 @@ async fn bind_to_real_network_interface() {
417421
.ip();
418422
let port = testing::unused_port_on_localhost();
419423

420-
let local_net_config = Config::new((local_addr, port).into());
424+
let cfg =
425+
Config::default().with_network_config(network::Config::new((local_addr, port).into()));
421426

422427
let mut net = TestingNetwork::<TestReactor>::new();
423-
net.add_node_with_config(local_net_config, &mut rng)
424-
.await
425-
.unwrap();
428+
net.add_node_with_config(cfg, &mut rng).await.unwrap();
426429

427430
// The network should be fully connected.
428431
let timeout = Duration::from_secs(2);
@@ -452,17 +455,16 @@ async fn check_varying_size_network_connects() {
452455

453456
// Pick a random port in the higher ranges that is likely to be unused.
454457
let first_node_port = testing::unused_port_on_localhost();
458+
let cfg = Config::default().with_network_config(
459+
network::Config::default_local_net_first_node(first_node_port),
460+
);
455461

456-
let _ = net
457-
.add_node_with_config(
458-
Config::default_local_net_first_node(first_node_port),
459-
&mut rng,
460-
)
461-
.await
462-
.unwrap();
462+
let _ = net.add_node_with_config(cfg, &mut rng).await.unwrap();
463+
let cfg = Config::default()
464+
.with_network_config(network::Config::default_local_net(first_node_port));
463465

464466
for _ in 1..number_of_nodes {
465-
net.add_node_with_config(Config::default_local_net(first_node_port), &mut rng)
467+
net.add_node_with_config(cfg.clone(), &mut rng)
466468
.await
467469
.unwrap();
468470
}
@@ -506,16 +508,17 @@ async fn ensure_peers_metric_is_correct() {
506508
// Pick a random port in the higher ranges that is likely to be unused.
507509
let first_node_port = testing::unused_port_on_localhost();
508510

509-
let _ = net
510-
.add_node_with_config(
511-
Config::default_local_net_first_node(first_node_port),
512-
&mut rng,
513-
)
514-
.await
515-
.unwrap();
511+
let cfg = Config::default().with_network_config(
512+
network::Config::default_local_net_first_node(first_node_port),
513+
);
514+
515+
let _ = net.add_node_with_config(cfg, &mut rng).await.unwrap();
516+
517+
let cfg = Config::default()
518+
.with_network_config(network::Config::default_local_net(first_node_port));
516519

517520
for _ in 1..number_of_nodes {
518-
net.add_node_with_config(Config::default_local_net(first_node_port), &mut rng)
521+
net.add_node_with_config(cfg.clone(), &mut rng)
519522
.await
520523
.unwrap();
521524
}

node/src/reactor/main_reactor.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1130,13 +1130,16 @@ impl reactor::Reactor for MainReactor {
11301130
registry,
11311131
)?;
11321132

1133+
let allow_handshake = config.node.sync_handling != SyncHandling::Isolated;
1134+
11331135
let network = Network::new(
11341136
config.network.clone(),
11351137
network_identity,
11361138
Some((our_secret_key, our_public_key)),
11371139
registry,
11381140
chainspec.as_ref(),
11391141
validator_matrix.clone(),
1142+
allow_handshake,
11401143
)?;
11411144

11421145
let address_gossiper = Gossiper::<{ GossipedAddress::ID_IS_COMPLETE_ITEM }, _>::new(

node/src/reactor/main_reactor/config.rs

+7
Original file line numberDiff line numberDiff line change
@@ -72,4 +72,11 @@ impl Config {
7272
chainspec.transaction_config.max_timestamp_leeway;
7373
}
7474
}
75+
76+
/// Set network config.
77+
#[cfg(test)]
78+
pub(crate) fn with_network_config(mut self, network_config: NetworkConfig) -> Self {
79+
self.network = network_config;
80+
self
81+
}
7582
}

0 commit comments

Comments
 (0)