mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-09 12:49:23 +00:00
Add a TributaryReader which doesn't require a borrow to operate
Reduces lock contention. Additionally changes block_key to include the genesis. While not technically needed, the lack of genesis introduced a side effect where any Tributary on the the database could return the block of any other Tributary. While that wasn't a security issue, returning it suggested it was on-chain when it wasn't. This may have been usable to create issues.
This commit is contained in:
@@ -117,6 +117,7 @@ pub async fn wait_for_tx_inclusion(
|
||||
mut last_checked: [u8; 32],
|
||||
hash: [u8; 32],
|
||||
) -> [u8; 32] {
|
||||
let reader = tributary.reader();
|
||||
loop {
|
||||
let tip = tributary.tip().await;
|
||||
if tip == last_checked {
|
||||
@@ -124,14 +125,14 @@ pub async fn wait_for_tx_inclusion(
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut queue = vec![tributary.block(&tip).unwrap()];
|
||||
let mut queue = vec![reader.block(&tip).unwrap()];
|
||||
let mut block = None;
|
||||
while {
|
||||
let parent = queue.last().unwrap().parent();
|
||||
if parent == tributary.genesis() {
|
||||
false
|
||||
} else {
|
||||
block = Some(tributary.block(&parent).unwrap());
|
||||
block = Some(reader.block(&parent).unwrap());
|
||||
block.as_ref().unwrap().hash() != last_checked
|
||||
}
|
||||
} {
|
||||
|
||||
@@ -81,7 +81,7 @@ async fn dkg_test() {
|
||||
) -> (TributaryDb<MemDb>, MemProcessor) {
|
||||
let mut scanner_db = TributaryDb(MemDb::new());
|
||||
let mut processor = MemProcessor::new();
|
||||
handle_new_blocks(&mut scanner_db, key, &mut processor, spec, tributary).await;
|
||||
handle_new_blocks(&mut scanner_db, key, &mut processor, spec, &tributary.reader()).await;
|
||||
(scanner_db, processor)
|
||||
}
|
||||
|
||||
@@ -96,7 +96,8 @@ async fn dkg_test() {
|
||||
sleep(Duration::from_secs(Tributary::<MemDb, Transaction, LocalP2p>::block_time().into())).await;
|
||||
|
||||
// Verify the scanner emits a KeyGen::Commitments message
|
||||
handle_new_blocks(&mut scanner_db, &keys[0], &mut processor, &spec, &tributaries[0].1).await;
|
||||
handle_new_blocks(&mut scanner_db, &keys[0], &mut processor, &spec, &tributaries[0].1.reader())
|
||||
.await;
|
||||
{
|
||||
let mut msgs = processor.0.write().await;
|
||||
assert_eq!(msgs.pop_front().unwrap(), expected_commitments);
|
||||
@@ -137,7 +138,8 @@ async fn dkg_test() {
|
||||
}
|
||||
|
||||
// With just 4 sets of shares, nothing should happen yet
|
||||
handle_new_blocks(&mut scanner_db, &keys[0], &mut processor, &spec, &tributaries[0].1).await;
|
||||
handle_new_blocks(&mut scanner_db, &keys[0], &mut processor, &spec, &tributaries[0].1.reader())
|
||||
.await;
|
||||
assert!(processor.0.write().await.is_empty());
|
||||
|
||||
// Publish the final set of shares
|
||||
@@ -168,7 +170,8 @@ async fn dkg_test() {
|
||||
};
|
||||
|
||||
// Any scanner which has handled the prior blocks should only emit the new event
|
||||
handle_new_blocks(&mut scanner_db, &keys[0], &mut processor, &spec, &tributaries[0].1).await;
|
||||
handle_new_blocks(&mut scanner_db, &keys[0], &mut processor, &spec, &tributaries[0].1.reader())
|
||||
.await;
|
||||
{
|
||||
let mut msgs = processor.0.write().await;
|
||||
assert_eq!(msgs.pop_front().unwrap(), shares_for(0));
|
||||
|
||||
@@ -50,7 +50,7 @@ async fn handle_p2p_test() {
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
// Make sure every tributary has it
|
||||
for tributary in &tributaries {
|
||||
assert!(tributary.read().await.block(&tip).is_some());
|
||||
assert!(tributary.read().await.reader().block(&tip).is_some());
|
||||
}
|
||||
|
||||
// Then after another block of time, we should have yet another new block
|
||||
@@ -59,6 +59,6 @@ async fn handle_p2p_test() {
|
||||
assert!(new_tip != tip);
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
for tributary in tributaries {
|
||||
assert!(tributary.read().await.block(&new_tip).is_some());
|
||||
assert!(tributary.read().await.reader().block(&new_tip).is_some());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ async fn sync_test() {
|
||||
sleep(Duration::from_secs(1)).await;
|
||||
// Make sure every tributary has it
|
||||
for tributary in &tributaries {
|
||||
assert!(tributary.read().await.block(&tip).is_some());
|
||||
assert!(tributary.read().await.reader().block(&tip).is_some());
|
||||
}
|
||||
|
||||
// Now that we've confirmed the other tributaries formed a net without issue, drop the syncer's
|
||||
@@ -100,7 +100,9 @@ async fn sync_test() {
|
||||
let tip = tributary.tip().await;
|
||||
let syncer_tip = syncer_tributary.tip().await;
|
||||
// Allow a one block tolerance in case of race conditions
|
||||
assert!(HashSet::from([tip, tributary.block(&tip).unwrap().parent()]).contains(&syncer_tip));
|
||||
assert!(
|
||||
HashSet::from([tip, tributary.reader().block(&tip).unwrap().parent()]).contains(&syncer_tip)
|
||||
);
|
||||
syncer_tip
|
||||
};
|
||||
|
||||
@@ -115,6 +117,7 @@ async fn sync_test() {
|
||||
for _ in 0 .. 10 {
|
||||
let syncer_tributary = syncer_tributary.read().await;
|
||||
if syncer_tributary
|
||||
.reader()
|
||||
.parsed_commit(&syncer_tributary.tip().await)
|
||||
.unwrap()
|
||||
.validators
|
||||
|
||||
@@ -46,7 +46,7 @@ async fn tx_test() {
|
||||
|
||||
// All tributaries should have acknowledged this transaction in a block
|
||||
for (_, tributary) in tributaries {
|
||||
let block = tributary.block(&included_in).unwrap();
|
||||
let block = tributary.reader().block(&included_in).unwrap();
|
||||
assert_eq!(block.transactions, vec![tx.clone()]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user