mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-25 12:06:02 +00:00
Correct when the decoys distribution lock is acquired
The existing design maintained a non-Send object across async contexts.
This commit is contained in:
parent
1caa6a9606
commit
1d4018c1ba
1 changed files with 23 additions and 16 deletions
|
@ -27,7 +27,6 @@ async fn select_n<R: RngCore + CryptoRng>(
|
||||||
rng: &mut R,
|
rng: &mut R,
|
||||||
rpc: &Rpc,
|
rpc: &Rpc,
|
||||||
height: usize,
|
height: usize,
|
||||||
distribution: &Vec<u64>,
|
|
||||||
high: u64,
|
high: u64,
|
||||||
per_second: f64,
|
per_second: f64,
|
||||||
used: &mut HashSet<u64>,
|
used: &mut HashSet<u64>,
|
||||||
|
@ -56,6 +55,7 @@ async fn select_n<R: RngCore + CryptoRng>(
|
||||||
|
|
||||||
let o = (age * per_second) as u64;
|
let o = (age * per_second) as u64;
|
||||||
if o < high {
|
if o < high {
|
||||||
|
let distribution = DISTRIBUTION.lock().unwrap();
|
||||||
let i = distribution.partition_point(|s| *s < (high - 1 - o));
|
let i = distribution.partition_point(|s| *s < (high - 1 - o));
|
||||||
let prev = i.saturating_sub(1);
|
let prev = i.saturating_sub(1);
|
||||||
let n = distribution[i] - distribution[prev];
|
let n = distribution[i] - distribution[prev];
|
||||||
|
@ -108,8 +108,6 @@ impl Decoys {
|
||||||
height: usize,
|
height: usize,
|
||||||
inputs: &[SpendableOutput]
|
inputs: &[SpendableOutput]
|
||||||
) -> Result<Vec<Decoys>, RpcError> {
|
) -> Result<Vec<Decoys>, RpcError> {
|
||||||
let mut distribution = DISTRIBUTION.lock().unwrap();
|
|
||||||
|
|
||||||
// Convert the inputs in question to the raw output data
|
// Convert the inputs in question to the raw output data
|
||||||
let mut outputs = Vec::with_capacity(inputs.len());
|
let mut outputs = Vec::with_capacity(inputs.len());
|
||||||
for input in inputs {
|
for input in inputs {
|
||||||
|
@ -119,20 +117,30 @@ impl Decoys {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if distribution.len() <= height {
|
let distribution_len = {
|
||||||
let from = distribution.len();
|
let distribution = DISTRIBUTION.lock().unwrap();
|
||||||
distribution.extend(rpc.get_output_distribution(from, height).await?);
|
distribution.len()
|
||||||
|
};
|
||||||
|
if distribution_len <= height {
|
||||||
|
let extension = rpc.get_output_distribution(distribution_len, height).await?;
|
||||||
|
DISTRIBUTION.lock().unwrap().extend(extension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let high;
|
||||||
|
let per_second;
|
||||||
|
{
|
||||||
|
let mut distribution = DISTRIBUTION.lock().unwrap();
|
||||||
// If asked to use an older height than previously asked, truncate to ensure accuracy
|
// If asked to use an older height than previously asked, truncate to ensure accuracy
|
||||||
// Should never happen, yet risks desyncing if it did
|
// Should never happen, yet risks desyncing if it did
|
||||||
distribution.truncate(height + 1); // height is inclusive, and 0 is a valid height
|
distribution.truncate(height + 1); // height is inclusive, and 0 is a valid height
|
||||||
|
|
||||||
let high = distribution[distribution.len() - 1];
|
high = distribution[distribution.len() - 1];
|
||||||
let per_second = {
|
per_second = {
|
||||||
let blocks = distribution.len().min(BLOCKS_PER_YEAR);
|
let blocks = distribution.len().min(BLOCKS_PER_YEAR);
|
||||||
let outputs = high - distribution[distribution.len().saturating_sub(blocks + 1)];
|
let outputs = high - distribution[distribution.len().saturating_sub(blocks + 1)];
|
||||||
(outputs as f64) / ((blocks * BLOCK_TIME) as f64)
|
(outputs as f64) / ((blocks * BLOCK_TIME) as f64)
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
let mut used = HashSet::<u64>::new();
|
let mut used = HashSet::<u64>::new();
|
||||||
for o in &outputs {
|
for o in &outputs {
|
||||||
|
@ -151,7 +159,6 @@ impl Decoys {
|
||||||
rng,
|
rng,
|
||||||
rpc,
|
rpc,
|
||||||
height,
|
height,
|
||||||
&distribution,
|
|
||||||
high,
|
high,
|
||||||
per_second,
|
per_second,
|
||||||
&mut used,
|
&mut used,
|
||||||
|
@ -192,7 +199,7 @@ impl Decoys {
|
||||||
|
|
||||||
// Select new outputs until we have a full sized ring again
|
// Select new outputs until we have a full sized ring again
|
||||||
ring.extend(
|
ring.extend(
|
||||||
select_n(rng, rpc, height, &distribution, high, per_second, &mut used, RING_LEN - ring.len()).await?
|
select_n(rng, rpc, height, high, per_second, &mut used, RING_LEN - ring.len()).await?
|
||||||
);
|
);
|
||||||
ring.sort_by(|a, b| a.0.cmp(&b.0));
|
ring.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue