Skip to content

Commit a0c7f33

Browse files
committed
fix: custom sample qty
1 parent e0a1a4c commit a0c7f33

File tree

5 files changed

+77
-68
lines changed

5 files changed

+77
-68
lines changed

scripts/test-cli.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ slot_number=$(echo $slot | cut -d':' -f 2 | xargs | sed 's/\x1B\[[0-9;]\{1,\}[A-
2828
sleep 1
2929
tinydancer verify --slot "$slot_number"
3030

31+
tinydancer verify --slot "$slot_number" --sample-qty 20
32+
3133
echo "Continue? (y/n)"
3234
read cont
3335
if [ "$cont" != "y" ]; then

tinydancer/src/main.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub enum Commands {
7777

7878
/// Amount of shreds you want to sample per slot
7979
#[clap(long, short, default_value_t = 10)]
80-
sample_qty: u64,
80+
sample_qty: usize,
8181
/// Rocks db path for storing shreds
8282
#[clap(required = false)]
8383
archive_path: Option<String>,
@@ -90,6 +90,9 @@ pub enum Commands {
9090
Verify {
9191
#[clap(long, required = false, default_value = "0")]
9292
slot: usize,
93+
94+
#[clap(long, required = false, default_value = "10")]
95+
sample_qty: usize,
9396
},
9497
/// Stream the client logs to your terminal
9598
Logs {
@@ -151,10 +154,14 @@ async fn main() -> Result<()> {
151154
tui_monitor,
152155
log_path: config_file.log_path,
153156
archive_config: {
154-
archive_path.map(|path| Ok(ArchiveConfig {
155-
shred_archive_duration,
156-
archive_path: path,
157-
})).unwrap_or(Err(anyhow!("shred path not provided...")))?
157+
archive_path
158+
.map(|path| {
159+
Ok(ArchiveConfig {
160+
shred_archive_duration,
161+
archive_path: path,
162+
})
163+
})
164+
.unwrap_or(Err(anyhow!("shred path not provided...")))?
158165
},
159166
};
160167

@@ -267,7 +274,7 @@ async fn main() -> Result<()> {
267274
}
268275
}
269276
},
270-
Commands::Verify { slot } => {
277+
Commands::Verify { slot, sample_qty } => {
271278
let _spinner = Spinner::new(
272279
spinners::Dots,
273280
format!("Verifying Shreds for Slot {}", slot),
@@ -276,7 +283,8 @@ async fn main() -> Result<()> {
276283

277284
let config_file =
278285
get_config_file().map_err(|_| anyhow!("tinydancer config not set"))?;
279-
let is_verified = pull_and_verify_shreds(slot, get_endpoint(config_file.cluster)).await;
286+
let is_verified =
287+
pull_and_verify_shreds(slot, get_endpoint(config_file.cluster), sample_qty).await;
280288

281289
if is_verified {
282290
println!(

tinydancer/src/rpc_wrapper/bridge.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,12 @@ impl LiteRpcServer for LiteBridge {
261261

262262
info!("glb {blockhash} {slot} {block_height}");
263263

264-
let sampled =
265-
pull_and_verify_shreds(slot as usize, String::from("http://0.0.0.0:8899")).await;
264+
let sampled = pull_and_verify_shreds(
265+
slot as usize,
266+
String::from("http://0.0.0.0:8899"),
267+
10 as usize,
268+
)
269+
.await;
266270

267271
Ok(LiteResponse {
268272
context: LiteRpcResponseContext {
@@ -341,8 +345,12 @@ impl LiteRpcServer for LiteBridge {
341345
.get_latest_block_info(CommitmentConfig::finalized())
342346
.await
343347
.slot;
344-
let sampled =
345-
pull_and_verify_shreds(slot as usize, String::from("http://0.0.0.0:8899")).await;
348+
let sampled = pull_and_verify_shreds(
349+
slot as usize,
350+
String::from("http://0.0.0.0:8899"),
351+
10 as usize,
352+
)
353+
.await;
346354
Ok(LiteResponse {
347355
context: LiteRpcResponseContext {
348356
slot,

tinydancer/src/sampler.rs

Lines changed: 43 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::tinydancer::{endpoint, ClientService, ClientStatus, Cluster};
22
use crate::{convert_to_websocket, send_rpc_call, try_coerce_shred};
3+
use anyhow::anyhow;
34
use async_trait::async_trait;
45
use crossbeam::channel::{Receiver, Sender};
56
use futures::Sink;
@@ -43,7 +44,6 @@ use tokio::{
4344
};
4445
use tungstenite::{connect, Message};
4546
use url::Url;
46-
use anyhow::anyhow;
4747

4848
pub const SHRED_CF: &str = "archived_shreds";
4949

@@ -57,6 +57,7 @@ pub struct SampleServiceConfig {
5757
pub archive_config: ArchiveConfig,
5858
pub instance: Arc<rocksdb::DB>,
5959
pub status_sampler: Arc<Mutex<ClientStatus>>,
60+
pub sample_qty: usize,
6061
}
6162

6263
#[derive(Clone, Debug)]
@@ -96,6 +97,7 @@ impl ClientService<SampleServiceConfig> for SampleService {
9697
rpc_url,
9798
shred_tx,
9899
status_arc,
100+
config.sample_qty,
99101
)));
100102

101103
// verify shreds + store in db in shred_archiver
@@ -137,16 +139,16 @@ pub async fn request_shreds(
137139
endpoint: String,
138140
) -> Result<GetShredResponse, serde_json::Error> {
139141
let request = serde_json::json!({
140-
"jsonrpc": "2.0",
141-
"id": 1,
142-
"method": "getShreds",
143-
"params":[
144-
slot,
145-
indices,
146-
{ "commitment": "confirmed" }
147-
]
148-
}) // getting one shred just to get max shreds per slot, can maybe randomize the selection here
149-
.to_string();
142+
"jsonrpc": "2.0",
143+
"id": 1,
144+
"method": "getShreds",
145+
"params":[
146+
slot,
147+
indices,
148+
{ "commitment": "confirmed" }
149+
]
150+
}) // getting one shred just to get max shreds per slot, can maybe randomize the selection here
151+
.to_string();
150152

151153
let res = send_rpc_call!(endpoint, request);
152154
// info!("{:?}", res);
@@ -165,9 +167,9 @@ async fn slot_update_loop(
165167
*status = ClientStatus::Crashed(String::from("Client can't connect to socket"));
166168
None
167169
}
168-
};
169-
170-
if result.is_none() {
170+
};
171+
172+
if result.is_none() {
171173
return Err(anyhow!(""));
172174
}
173175
let (mut socket, _response) = result.unwrap();
@@ -179,8 +181,7 @@ async fn slot_update_loop(
179181
loop {
180182
match socket.read_message() {
181183
Ok(msg) => {
182-
let res =
183-
serde_json::from_str::<SlotSubscribeResponse>(msg.to_string().as_str());
184+
let res = serde_json::from_str::<SlotSubscribeResponse>(msg.to_string().as_str());
184185

185186
// info!("res: {:?}", msg.to_string().as_str());
186187
if let Ok(res) = res {
@@ -189,10 +190,7 @@ async fn slot_update_loop(
189190
info!("slot updated: {:?}", res.params.result.root);
190191
}
191192
Err(e) => {
192-
info!(
193-
"error here: {:?} {:?}",
194-
e, res.params.result.root as u64
195-
);
193+
info!("error here: {:?} {:?}", e, res.params.result.root as u64);
196194
continue; // @TODO: we should add retries here incase send fails for some reason
197195
}
198196
}
@@ -205,57 +203,57 @@ async fn slot_update_loop(
205203

206204
macro_rules! unwrap_or_return {
207205
(Result $var:ident) => {
208-
if let Err(e) = $var {
206+
if let Err(e) = $var {
209207
return Err(e.into());
210-
} else {
208+
} else {
211209
$var.unwrap()
212210
}
213211
};
214212
(Option $var:ident $err:expr) => {
215-
if $var.is_none() {
213+
if $var.is_none() {
216214
return Err(anyhow!($err));
217-
} else {
215+
} else {
218216
$var.unwrap()
219217
}
220218
};
221219
(OptionRef $var:ident $err:expr) => {
222-
if $var.is_none() {
220+
if $var.is_none() {
223221
return Err(anyhow!($err));
224-
} else {
222+
} else {
225223
$var.as_ref().unwrap()
226224
}
227225
};
228226
}
229227

230228
async fn get_shreds_and_leader_for_slot(
231229
slot: u64,
232-
endpoint: &String
233-
) -> anyhow::Result<(Vec<Option<Shred>>, Pubkey)> {
234-
230+
endpoint: &String,
231+
sample_qty: usize,
232+
) -> anyhow::Result<(Vec<Option<Shred>>, Pubkey)> {
235233
// get shred length (max_shreds_per_slot)
236234
let first_shred = request_shreds(slot as usize, vec![0], endpoint.clone()).await;
237235
let first_shred = unwrap_or_return!(Result first_shred);
238236

239-
let first_shred = &first_shred.result.shreds[1];
237+
let first_shred = &first_shred.result.shreds[1];
240238
let first_shred = unwrap_or_return!(OptionRef first_shred "first shred not found");
241239

242240
let max_shreds_per_slot = {
243-
if let Some(data_shred) = &first_shred.shred_data {
241+
if let Some(data_shred) = &first_shred.shred_data {
244242
Shred::ShredData(data_shred.clone())
245243
.num_data_shreds()
246244
.expect("num data shreds error")
247-
} else if let Some(code_shred) = &first_shred.shred_code {
245+
} else if let Some(code_shred) = &first_shred.shred_code {
248246
Shred::ShredCode(code_shred.clone())
249-
.num_coding_shreds()
250-
.expect("num code shreds error")
247+
.num_coding_shreds()
248+
.expect("num code shreds error")
251249
} else {
252250
// todo
253251
return Err(anyhow!("shred isnt either data or code type"));
254252
}
255253
};
256254

257255
// get a random sample of shreds
258-
let mut shred_indices_for_slot = gen_random_indices(max_shreds_per_slot as usize, 10); // unwrap only temporary
256+
let mut shred_indices_for_slot = gen_random_indices(max_shreds_per_slot as usize, sample_qty); // unwrap only temporary
259257
shred_indices_for_slot.push(0_usize);
260258
info!("indices of: {:?} {:?}", shred_indices_for_slot, slot);
261259

@@ -276,9 +274,7 @@ async fn get_shreds_and_leader_for_slot(
276274
.collect();
277275

278276
// info!("before leader");
279-
let leader = solana_ledger::shred::Pubkey::from_str(
280-
shreds_for_slot.result.leader.as_str(),
281-
)?;
277+
let leader = solana_ledger::shred::Pubkey::from_str(shreds_for_slot.result.leader.as_str())?;
282278

283279
// info!("leader {:?}", leader);
284280
let mut fullfill_count = AtomicU32::new(0u32);
@@ -311,8 +307,7 @@ async fn get_shreds_and_leader_for_slot(
311307
}
312308
});
313309

314-
if (fullfill_count.get_mut().to_owned() as usize) < shred_indices_for_slot.len()
315-
{
310+
if (fullfill_count.get_mut().to_owned() as usize) < shred_indices_for_slot.len() {
316311
info!("Received incomplete number of shreds, requested {:?} shreds for slot {:?} and received {:?}", shred_indices_for_slot.len(),slot, fullfill_count);
317312
}
318313

@@ -324,11 +319,12 @@ async fn shred_update_loop(
324319
endpoint: String,
325320
shred_tx: Sender<(Vec<Option<Shred>>, solana_ledger::shred::Pubkey)>,
326321
status_sampler: Arc<Mutex<ClientStatus>>,
322+
sample_qty: usize,
327323
) -> anyhow::Result<()> {
328324
loop {
329325
{
330326
let mut status = status_sampler.lock().unwrap();
331-
if let ClientStatus::Crashed(_) = &*status {
327+
if let ClientStatus::Crashed(_) = &*status {
332328
return Err(anyhow!("Client crashed"));
333329
} else {
334330
*status = ClientStatus::Active(String::from(
@@ -338,8 +334,8 @@ async fn shred_update_loop(
338334
}
339335

340336
if let Ok(slot) = slot_update_rx.recv() {
341-
let shreds = get_shreds_and_leader_for_slot(slot, &endpoint).await;
342-
if let Err(e) = shreds {
337+
let shreds = get_shreds_and_leader_for_slot(slot, &endpoint, sample_qty).await;
338+
if let Err(e) = shreds {
343339
info!("{}", e);
344340
continue;
345341
}
@@ -354,7 +350,7 @@ async fn shred_update_loop(
354350

355351
// use solana_ledger::shred::dispatch;
356352

357-
// verifies the merkle proof of the shread
353+
// verifies the merkle proof of the shread
358354
pub fn verify_sample(shred: &Shred, leader: solana_ledger::shred::Pubkey) -> bool {
359355
// @TODO fix error handling here
360356
let verify_merkle_root = match shred {
@@ -412,7 +408,6 @@ pub async fn shred_verify_loop(
412408
}
413409
}
414410

415-
416411
// store verified shreds in db
417412
pub async fn shred_archiver(
418413
verified_shred_rx: Receiver<(Shred, solana_ledger::shred::Pubkey)>,
@@ -455,10 +450,9 @@ pub async fn shred_archiver(
455450
}
456451
}
457452

458-
459-
pub async fn pull_and_verify_shreds(slot: usize, endpoint: String) -> bool {
460-
let shreds = get_shreds_and_leader_for_slot(slot as u64, &endpoint).await;
461-
if let Err(e) = shreds {
453+
pub async fn pull_and_verify_shreds(slot: usize, endpoint: String, sample_qty: usize) -> bool {
454+
let shreds = get_shreds_and_leader_for_slot(slot as u64, &endpoint, sample_qty).await;
455+
if let Err(e) = shreds {
462456
info!("{}", e);
463457
return false;
464458
}

tinydancer/src/tinydancer.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ pub struct TinyDancer {
4444
#[derive(Clone)]
4545
pub struct TinyDancerConfig {
4646
pub rpc_endpoint: Cluster,
47-
pub sample_qty: u64,
47+
pub sample_qty: usize,
4848
pub enable_ui_service: bool,
4949
pub archive_config: ArchiveConfig,
5050
pub tui_monitor: bool,
@@ -82,19 +82,16 @@ impl TinyDancer {
8282
opts.create_missing_column_families(true);
8383

8484
// setup db
85-
let db = rocksdb::DB::open_cf(
86-
&opts,
87-
archive_config.clone().archive_path,
88-
vec![SHRED_CF],
89-
)
90-
.unwrap();
85+
let db = rocksdb::DB::open_cf(&opts, archive_config.clone().archive_path, vec![SHRED_CF])
86+
.unwrap();
9187
let db = Arc::new(db);
9288

9389
let sample_service_config = SampleServiceConfig {
9490
cluster: rpc_endpoint.clone(),
9591
archive_config,
9692
instance: db.clone(),
9793
status_sampler,
94+
sample_qty,
9895
};
9996
let sample_service = SampleService::new(sample_service_config);
10097

@@ -111,7 +108,7 @@ impl TinyDancer {
111108
}))
112109
} else {
113110
None
114-
};
111+
};
115112

116113
// run
117114
sample_service

0 commit comments

Comments
 (0)