Skip to content

Commit cd7b6bf

Browse files
committed
first working version
1 parent 33a84ab commit cd7b6bf

19 files changed

+377
-111
lines changed

gossip/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ lru = { workspace = true }
2525
num-traits = { workspace = true }
2626
pcap-file = "2.0.0"
2727
rand = { workspace = true }
28+
rand0-7 = { workspace = true }
2829
rand_chacha = { workspace = true }
2930
rayon = { workspace = true }
3031
serde = { workspace = true }
@@ -73,7 +74,7 @@ num_cpus = { workspace = true }
7374
rand0-7 = { workspace = true }
7475
rand_chacha0-2 = { workspace = true }
7576
serial_test = { workspace = true }
76-
solana-gossip = { workspace = true, features = ["dev-context-only-utils"] }
77+
solana-gossip = { path=".", features = ["dev-context-only-utils"] }
7778
solana-perf = { workspace = true, features = ["dev-context-only-utils"] }
7879
solana-runtime = { workspace = true, features = ["dev-context-only-utils"] }
7980
test-case = { workspace = true }

gossip/benches/crds.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use {
99
crds::{Crds, GossipRoute},
1010
crds_gossip_pull::{CrdsTimeouts, CRDS_GOSSIP_PULL_CRDS_TIMEOUT_MS},
1111
crds_value::CrdsValue,
12+
testing_fixtures::FormatValidation,
1213
},
1314
solana_pubkey::Pubkey,
1415
std::{collections::HashMap, time::Duration},

gossip/benches/crds_gossip_pull.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use {
99
crds::{Crds, GossipRoute},
1010
crds_gossip_pull::{CrdsFilter, CrdsGossipPull},
1111
crds_value::CrdsValue,
12+
testing_fixtures::FormatValidation,
1213
},
1314
solana_sdk::hash::Hash,
1415
std::sync::RwLock,

gossip/benches/crds_shards.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use {
88
crds::{Crds, GossipRoute, VersionedCrdsValue},
99
crds_shards::CrdsShards,
1010
crds_value::CrdsValue,
11+
testing_fixtures::FormatValidation,
1112
},
1213
solana_sdk::timing::timestamp,
1314
std::iter::repeat_with,

gossip/src/cluster_info.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3126,6 +3126,7 @@ mod tests {
31263126
duplicate_shred::tests::new_rand_shred,
31273127
protocol::tests::new_rand_remote_node,
31283128
socketaddr,
3129+
testing_fixtures::{new_insecure_keypair, FormatValidation},
31293130
},
31303131
bincode::serialize,
31313132
itertools::izip,
@@ -3796,7 +3797,8 @@ mod tests {
37963797
#[test]
37973798
fn test_append_entrypoint_to_pulls() {
37983799
let thread_pool = ThreadPoolBuilder::new().build().unwrap();
3799-
let node_keypair = Arc::new(Keypair::new());
3800+
let mut rng = rand::thread_rng();
3801+
let node_keypair = Arc::new(new_insecure_keypair(&mut rng));
38003802
let cluster_info = ClusterInfo::new(
38013803
ContactInfo::new_localhost(&node_keypair.pubkey(), timestamp()),
38023804
node_keypair,

gossip/src/crds.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,10 @@ fn should_report_message_signature(signature: &Signature) -> bool {
781781
mod tests {
782782
use {
783783
super::*,
784-
crate::crds_data::{new_rand_timestamp, AccountsHashes, NodeInstance},
784+
crate::{
785+
crds_data::{AccountsHashes, NodeInstance},
786+
testing_fixtures::*,
787+
},
785788
rand::{thread_rng, Rng, SeedableRng},
786789
rand_chacha::ChaChaRng,
787790
rayon::ThreadPoolBuilder,
@@ -1250,7 +1253,9 @@ mod tests {
12501253
#[test]
12511254
fn test_crds_value_indices() {
12521255
let mut rng = thread_rng();
1253-
let keypairs: Vec<_> = repeat_with(Keypair::new).take(128).collect();
1256+
let keypairs: Vec<_> = repeat_with(|| new_insecure_keypair(&mut rng))
1257+
.take(128)
1258+
.collect();
12541259
let mut crds = Crds::default();
12551260
let mut num_inserts = 0;
12561261
for k in 0..4096 {
@@ -1301,7 +1306,9 @@ mod tests {
13011306
}
13021307
}
13031308
let mut rng = thread_rng();
1304-
let keypairs: Vec<_> = repeat_with(Keypair::new).take(128).collect();
1309+
let keypairs: Vec<_> = repeat_with(|| new_insecure_keypair(&mut rng))
1310+
.take(128)
1311+
.collect();
13051312
let mut crds = Crds::default();
13061313
for k in 0..4096 {
13071314
let keypair = &keypairs[rng.gen_range(0..keypairs.len())];
@@ -1400,7 +1407,9 @@ mod tests {
14001407
.len()
14011408
}
14021409
let mut rng = thread_rng();
1403-
let keypairs: Vec<_> = repeat_with(Keypair::new).take(64).collect();
1410+
let keypairs: Vec<_> = repeat_with(|| new_insecure_keypair(&mut rng))
1411+
.take(64)
1412+
.collect();
14041413
let stakes = keypairs
14051414
.iter()
14061415
.map(|k| (k.pubkey(), rng.gen_range(0..1000)))

gossip/src/crds_data.rs

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
#[cfg(feature = "dev-context-only-utils")]
2+
use {
3+
crate::testing_fixtures::{new_rand_timestamp, new_random_pubkey, FormatValidation},
4+
rand::Rng,
5+
std::hint::black_box,
6+
};
17
use {
28
crate::{
39
contact_info::ContactInfo,
@@ -9,20 +15,11 @@ use {
915
},
1016
serde::de::{Deserialize, Deserializer},
1117
solana_sanitize::{Sanitize, SanitizeError},
12-
solana_sdk::{
13-
clock::Slot,
14-
hash::Hash,
15-
pubkey::{self, Pubkey},
16-
timing::timestamp,
17-
transaction::Transaction,
18-
},
18+
solana_sdk::{clock::Slot, hash::Hash, pubkey::Pubkey, transaction::Transaction},
1919
solana_vote::vote_parser,
2020
std::{cmp::Ordering, collections::BTreeSet},
2121
};
2222

23-
#[cfg(feature = "dev-context-only-utils")]
24-
use {crate::format_validation::FormatValidation, rand::Rng, std::hint::black_box};
25-
2623
pub(crate) const MAX_WALLCLOCK: u64 = 1_000_000_000_000_000;
2724
pub(crate) const MAX_SLOT: u64 = 1_000_000_000_000_000;
2825
/// Maximum number of hashes in AccountsHashes a node publishes
@@ -109,21 +106,16 @@ impl Sanitize for CrdsData {
109106
}
110107
}
111108

112-
/// Random timestamp for tests and benchmarks.
113-
pub(crate) fn new_rand_timestamp<R: Rng>(rng: &mut R) -> u64 {
114-
const DELAY: u64 = 10 * 60 * 1000; // 10 minutes
115-
timestamp() - DELAY + rng.gen_range(0..2 * DELAY)
116-
}
117-
118-
impl CrdsData {
109+
#[cfg(feature = "dev-context-only-utils")]
110+
impl crate::testing_fixtures::FormatValidation<Pubkey> for CrdsData {
119111
/// New random CrdsData for tests and benchmarks.
120-
pub(crate) fn new_rand<R: Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> CrdsData {
112+
fn new_rand<R: Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> CrdsData {
121113
let kind = rng.gen_range(0..8);
122114
// TODO: Implement other kinds of CrdsData here.
123115
// TODO: Assign ranges to each arm proportional to their frequency in
124116
// the mainnet crds table.
125117
match kind {
126-
0 => CrdsData::from(ContactInfo::new_rand(rng, pubkey)),
118+
0 => CrdsData::ContactInfo(ContactInfo::new_rand(rng, pubkey)),
127119
// Index for LowestSlot is deprecated and should be zero.
128120
1 => CrdsData::LowestSlot(0, LowestSlot::new_rand(rng, pubkey)),
129121
2 => CrdsData::LegacySnapshotHashes(LegacySnapshotHashes::new_rand(rng, pubkey)),
@@ -139,7 +131,9 @@ impl CrdsData {
139131
),
140132
}
141133
}
134+
}
142135

136+
impl CrdsData {
143137
pub(crate) fn wallclock(&self) -> u64 {
144138
match self {
145139
CrdsData::LegacyContactInfo(contact_info) => contact_info.wallclock(),
@@ -226,6 +220,9 @@ pub(crate) struct AccountsHashes {
226220
impl Sanitize for AccountsHashes {
227221
fn sanitize(&self) -> Result<(), SanitizeError> {
228222
sanitize_wallclock(self.wallclock)?;
223+
if self.hashes.len() > MAX_ACCOUNTS_HASHES {
224+
return Err(SanitizeError::IndexOutOfBounds);
225+
}
229226
for (slot, _) in &self.hashes {
230227
if *slot >= MAX_SLOT {
231228
return Err(SanitizeError::ValueOutOfBounds);
@@ -247,14 +244,14 @@ impl FormatValidation for AccountsHashes {
247244
.take(num_hashes)
248245
.collect();
249246
Self {
250-
from: pubkey.unwrap_or_else(pubkey::new_rand),
247+
from: pubkey.unwrap_or_else(|| new_random_pubkey(rng)),
251248
hashes,
252249
wallclock: new_rand_timestamp(rng),
253250
}
254251
}
255252

256253
fn exercise(&self) -> anyhow::Result<()> {
257-
FormatValidation::exercise(&self)?;
254+
self.sanitize()?;
258255
let s: u64 = self.hashes.iter().map(|v| v.0).sum();
259256
black_box(s);
260257
Ok(())
@@ -318,7 +315,7 @@ impl LowestSlot {
318315
impl FormatValidation for LowestSlot {
319316
fn new_rand<R: Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> Self {
320317
Self {
321-
from: pubkey.unwrap_or_else(pubkey::new_rand),
318+
from: pubkey.unwrap_or_else(|| new_random_pubkey(rng)),
322319
root: rng.gen(),
323320
lowest: rng.gen(),
324321
slots: BTreeSet::default(),
@@ -365,6 +362,19 @@ impl Sanitize for Vote {
365362
}
366363
}
367364

365+
#[cfg(feature = "dev-context-only-utils")]
366+
impl FormatValidation for Vote {
367+
/// New random Vote for tests and benchmarks.
368+
fn new_rand<R: Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> Self {
369+
Self {
370+
from: pubkey.unwrap_or_else(|| new_random_pubkey(rng)),
371+
transaction: Transaction::default(),
372+
wallclock: new_rand_timestamp(rng),
373+
slot: None,
374+
}
375+
}
376+
}
377+
368378
impl Vote {
369379
// Returns None if cannot parse transaction into a vote.
370380
pub fn new(from: Pubkey, transaction: Transaction, wallclock: u64) -> Option<Self> {
@@ -376,16 +386,6 @@ impl Vote {
376386
})
377387
}
378388

379-
/// New random Vote for tests and benchmarks.
380-
fn new_rand<R: Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> Self {
381-
Self {
382-
from: pubkey.unwrap_or_else(pubkey::new_rand),
383-
transaction: Transaction::default(),
384-
wallclock: new_rand_timestamp(rng),
385-
slot: None,
386-
}
387-
}
388-
389389
pub(crate) fn transaction(&self) -> &Transaction {
390390
&self.transaction
391391
}

gossip/src/crds_entry.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ mod tests {
6565
super::*,
6666
crate::{
6767
crds::{Crds, GossipRoute},
68-
crds_data::new_rand_timestamp,
68+
testing_fixtures::*,
6969
},
7070
rand::seq::SliceRandom,
7171
solana_sdk::signature::Keypair,

gossip/src/crds_gossip_pull.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl solana_sanitize::Sanitize for CrdsFilter {
8282
}
8383

8484
impl CrdsFilter {
85-
#[cfg(test)]
85+
#[cfg(feature = "dev-context-only-utils")]
8686
pub(crate) fn new_rand(num_items: usize, max_bytes: usize) -> Self {
8787
let max_bits = (max_bytes * 8) as f64;
8888
let max_items = Self::max_items(max_bits, FALSE_RATE, KEYS);
@@ -666,6 +666,7 @@ pub(crate) mod tests {
666666
crds_data::{CrdsData, Vote},
667667
legacy_contact_info::LegacyContactInfo,
668668
protocol::Protocol,
669+
testing_fixtures::*,
669670
},
670671
itertools::Itertools,
671672
rand::{seq::SliceRandom, SeedableRng},

gossip/src/crds_shards.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ mod test {
137137
crate::{
138138
crds::{Crds, GossipRoute},
139139
crds_value::CrdsValue,
140+
testing_fixtures::*,
140141
},
141142
rand::{thread_rng, Rng},
142143
solana_sdk::timing::timestamp,

gossip/src/crds_value.rs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
#[cfg(feature = "dev-context-only-utils")]
2+
use {
3+
crate::testing_fixtures::{new_insecure_keypair, FormatValidation},
4+
rand::Rng,
5+
};
16
use {
27
crate::{
38
contact_info::ContactInfo,
@@ -6,7 +11,6 @@ use {
611
epoch_slots::EpochSlots,
712
},
813
bincode::serialize,
9-
rand::Rng,
1014
serde::de::{Deserialize, Deserializer},
1115
solana_sanitize::{Sanitize, SanitizeError},
1216
solana_sdk::{
@@ -17,7 +21,8 @@ use {
1721
std::borrow::{Borrow, Cow},
1822
};
1923

20-
/// CrdsValue that is replicated across the cluster
24+
/// CrdsValue is a wrapper around CrdsData that is replicated across the cluster
25+
/// CrdsValue's purpose is to add signature to verify the origin of the CrdsData
2126
#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
2227
#[derive(Serialize, Clone, Debug, PartialEq, Eq)]
2328
pub struct CrdsValue {
@@ -98,6 +103,24 @@ impl CrdsValueLabel {
98103
}
99104
}
100105

106+
#[cfg(feature = "dev-context-only-utils")]
107+
impl FormatValidation<&Keypair> for CrdsValue {
108+
fn new_rand<R: Rng>(rng: &mut R, keypair: Option<&Keypair>) -> Self {
109+
let mut random_keypair: Option<Keypair> = None;
110+
let keypair = keypair
111+
.unwrap_or_else(|| random_keypair.get_or_insert_with(|| new_insecure_keypair(rng)));
112+
let data = CrdsData::new_rand(rng, Some(keypair.pubkey()));
113+
Self::new(data, keypair)
114+
}
115+
116+
fn exercise(&self) -> anyhow::Result<()> {
117+
self.sanitize()?;
118+
if !self.verify() {
119+
anyhow::bail!("sigverify");
120+
};
121+
self.data().exercise()
122+
}
123+
}
101124
impl CrdsValue {
102125
pub fn new(data: CrdsData, keypair: &Keypair) -> Self {
103126
let bincode_serialized_data = bincode::serialize(&data).unwrap();
@@ -122,21 +145,6 @@ impl CrdsValue {
122145
}
123146
}
124147

125-
/// New random CrdsValue for tests and benchmarks.
126-
pub fn new_rand<R: Rng>(rng: &mut R, keypair: Option<&Keypair>) -> CrdsValue {
127-
match keypair {
128-
None => {
129-
let keypair = Keypair::new();
130-
let data = CrdsData::new_rand(rng, Some(keypair.pubkey()));
131-
Self::new(data, &keypair)
132-
}
133-
Some(keypair) => {
134-
let data = CrdsData::new_rand(rng, Some(keypair.pubkey()));
135-
Self::new(data, keypair)
136-
}
137-
}
138-
}
139-
140148
#[inline]
141149
pub(crate) fn signature(&self) -> &Signature {
142150
&self.signature

gossip/src/epoch_slots.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
#[cfg(feature = "dev-context-only-utils")]
2+
use crate::testing_fixtures::*;
13
use {
24
crate::{
3-
crds_data::{self, MAX_SLOT, MAX_WALLCLOCK},
5+
crds_data::{MAX_SLOT, MAX_WALLCLOCK},
46
protocol::MAX_CRDS_OBJECT_SIZE,
57
},
68
bincode::serialized_size,
@@ -341,10 +343,12 @@ impl EpochSlots {
341343
.filter_map(move |s| s.to_slots(min_slot).ok())
342344
.flatten()
343345
}
346+
}
344347

345-
/// New random EpochSlots for tests and simulations.
346-
pub(crate) fn new_rand<R: rand::Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> Self {
347-
let now = crds_data::new_rand_timestamp(rng);
348+
#[cfg(feature = "dev-context-only-utils")]
349+
impl FormatValidation<Pubkey> for EpochSlots {
350+
fn new_rand<R: rand::Rng>(rng: &mut R, pubkey: Option<Pubkey>) -> Self {
351+
let now = new_rand_timestamp(rng);
348352
let pubkey = pubkey.unwrap_or_else(solana_pubkey::new_rand);
349353
let mut epoch_slots = Self::new(pubkey, now);
350354
let num_slots = rng.gen_range(0..20);
@@ -354,6 +358,13 @@ impl EpochSlots {
354358
epoch_slots.add(&slots);
355359
epoch_slots
356360
}
361+
362+
fn exercise(&self) -> anyhow::Result<()> {
363+
self.sanitize()?;
364+
let s: Slot = self.to_slots(0).sum();
365+
std::hint::black_box(s);
366+
Ok(())
367+
}
357368
}
358369

359370
#[cfg(test)]

gossip/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,4 @@ extern crate solana_frozen_abi_macro;
4848
extern crate solana_metrics;
4949

5050
#[cfg(feature = "dev-context-only-utils")]
51-
pub mod format_validation;
51+
pub mod testing_fixtures;

0 commit comments

Comments
 (0)