mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-10 21:04:40 +00:00
Bound decoy selection to prevent it from infinite looping
This commit is contained in:
parent
e1831ee5af
commit
1ef528bf8c
1 changed files with 10 additions and 3 deletions
|
@ -33,11 +33,18 @@ async fn select_n<R: RngCore + CryptoRng>(
|
||||||
used: &mut HashSet<u64>,
|
used: &mut HashSet<u64>,
|
||||||
count: usize
|
count: usize
|
||||||
) -> Result<Vec<(u64, [EdwardsPoint; 2])>, RpcError> {
|
) -> Result<Vec<(u64, [EdwardsPoint; 2])>, RpcError> {
|
||||||
|
let mut iters = 0;
|
||||||
let mut confirmed = Vec::with_capacity(count);
|
let mut confirmed = Vec::with_capacity(count);
|
||||||
while confirmed.len() != count {
|
while confirmed.len() != count {
|
||||||
let remaining = count - confirmed.len();
|
let remaining = count - confirmed.len();
|
||||||
let mut candidates = Vec::with_capacity(remaining);
|
let mut candidates = Vec::with_capacity(remaining);
|
||||||
while candidates.len() != remaining {
|
while candidates.len() != remaining {
|
||||||
|
iters += 1;
|
||||||
|
// This is cheap and on fresh chains, thousands of rounds may be needed
|
||||||
|
if iters == 10000 {
|
||||||
|
Err(RpcError::InternalError("not enough decoy candidates".to_string()))?;
|
||||||
|
}
|
||||||
|
|
||||||
// Use a gamma distribution
|
// Use a gamma distribution
|
||||||
let mut age = GAMMA.sample(rng).exp();
|
let mut age = GAMMA.sample(rng).exp();
|
||||||
if age > TIP_APPLICATION {
|
if age > TIP_APPLICATION {
|
||||||
|
@ -126,7 +133,7 @@ impl Decoys {
|
||||||
// Panic if not enough decoys are available
|
// Panic if not enough decoys are available
|
||||||
// TODO: Simply create a TX with less than the target amount, or at least return an error
|
// TODO: Simply create a TX with less than the target amount, or at least return an error
|
||||||
if (high - MATURITY) < u64::try_from(inputs.len() * RING_LEN).unwrap() {
|
if (high - MATURITY) < u64::try_from(inputs.len() * RING_LEN).unwrap() {
|
||||||
panic!("Not enough decoys available");
|
Err(RpcError::InternalError("not enough decoy candidates".to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select all decoys for this transaction, assuming we generate a sane transaction
|
// Select all decoys for this transaction, assuming we generate a sane transaction
|
||||||
|
@ -161,8 +168,8 @@ impl Decoys {
|
||||||
if high > 500 {
|
if high > 500 {
|
||||||
// Make sure the TX passes the sanity check that the median output is within the last 40%
|
// Make sure the TX passes the sanity check that the median output is within the last 40%
|
||||||
// This actually checks the median is within the last third, a slightly more aggressive
|
// This actually checks the median is within the last third, a slightly more aggressive
|
||||||
// boundary, as the height used in this calculation will be slightly under the height this is
|
// boundary, as the height used in this calculation will be slightly under the height this
|
||||||
// sanity checked against
|
// is sanity checked against
|
||||||
let target_median = high * 2 / 3;
|
let target_median = high * 2 / 3;
|
||||||
while ring[RING_LEN / 2].0 < target_median {
|
while ring[RING_LEN / 2].0 < target_median {
|
||||||
// If it's not, update the bottom half with new values to ensure the median only moves up
|
// If it's not, update the bottom half with new values to ensure the median only moves up
|
||||||
|
|
Loading…
Reference in a new issue