Fix an error in dominance calculation.
This commit is contained in:
parent
6fa0b46d8e
commit
6db4355fc4
|
@ -1,7 +1,7 @@
|
||||||
use rusqlite::{self, named_params, types::Value, OptionalExtension};
|
use rusqlite::{self, named_params, types::Value, OptionalExtension};
|
||||||
use std::cmp::{max, min, Ordering};
|
use std::cmp::{max, min, Ordering};
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::ops::Range;
|
use std::ops::{Not, Range};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use zcash_client_backend::data_api::scanning::{ScanPriority, ScanRange};
|
use zcash_client_backend::data_api::scanning::{ScanPriority, ScanRange};
|
||||||
|
|
||||||
|
@ -15,13 +15,39 @@ use crate::{PRUNING_DEPTH, VALIDATION_DEPTH};
|
||||||
|
|
||||||
use super::block_height_extrema;
|
use super::block_height_extrema;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
enum Insert {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Not for Insert {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn not(self) -> Self::Output {
|
||||||
|
match self {
|
||||||
|
Insert::Left => Insert::Right,
|
||||||
|
Insert::Right => Insert::Left,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
enum Dominance {
|
enum Dominance {
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
Equal,
|
Equal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Insert> for Dominance {
|
||||||
|
fn from(value: Insert) -> Self {
|
||||||
|
match value {
|
||||||
|
Insert::Left => Dominance::Left,
|
||||||
|
Insert::Right => Dominance::Right,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_priority_code(code: i64) -> Option<ScanPriority> {
|
pub(crate) fn parse_priority_code(code: i64) -> Option<ScanPriority> {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
match code {
|
match code {
|
||||||
|
@ -91,14 +117,14 @@ fn update_priority(current: ScanPriority, inserted: ScanPriority) -> ScanPriorit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dominance(current: &ScanPriority, inserted: &ScanPriority) -> Dominance {
|
fn dominance(current: &ScanPriority, inserted: &ScanPriority, insert: Insert) -> Dominance {
|
||||||
match (current, inserted) {
|
match (current, inserted) {
|
||||||
(_, ScanPriority::Verify) | (_, ScanPriority::Scanned) => Dominance::Right,
|
(_, ScanPriority::Verify | ScanPriority::Scanned) => Dominance::from(insert),
|
||||||
(ScanPriority::Scanned, _) => Dominance::Left,
|
(ScanPriority::Scanned, _) => Dominance::from(!insert),
|
||||||
(a, b) => match a.cmp(b) {
|
(a, b) => match a.cmp(b) {
|
||||||
Ordering::Less => Dominance::Right,
|
Ordering::Less => Dominance::from(insert),
|
||||||
Ordering::Equal => Dominance::Equal,
|
Ordering::Equal => Dominance::Equal,
|
||||||
Ordering::Greater => Dominance::Left,
|
Ordering::Greater => Dominance::from(!insert),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,11 +209,6 @@ fn join_nonoverlapping(left: ScanRange, right: ScanRange) -> Joined {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert(current: ScanRange, to_insert: ScanRange) -> Joined {
|
fn insert(current: ScanRange, to_insert: ScanRange) -> Joined {
|
||||||
enum Insert {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn join_overlapping(left: ScanRange, right: ScanRange, insert: Insert) -> Joined {
|
fn join_overlapping(left: ScanRange, right: ScanRange, insert: Insert) -> Joined {
|
||||||
assert!(
|
assert!(
|
||||||
left.block_range().start <= right.block_range().start
|
left.block_range().start <= right.block_range().start
|
||||||
|
@ -196,8 +217,8 @@ fn insert(current: ScanRange, to_insert: ScanRange) -> Joined {
|
||||||
|
|
||||||
// recompute the range dominance based upon the queue entry priorities
|
// recompute the range dominance based upon the queue entry priorities
|
||||||
let dominance = match insert {
|
let dominance = match insert {
|
||||||
Insert::Left => dominance(&right.priority(), &left.priority()),
|
Insert::Left => dominance(&right.priority(), &left.priority(), insert),
|
||||||
Insert::Right => dominance(&left.priority(), &right.priority()),
|
Insert::Right => dominance(&left.priority(), &right.priority(), insert),
|
||||||
};
|
};
|
||||||
|
|
||||||
match dominance {
|
match dominance {
|
||||||
|
@ -535,13 +556,15 @@ pub(crate) fn replace_queue_entries(
|
||||||
|
|
||||||
// Update the tree that we read from the database, or if we didn't find any ranges
|
// Update the tree that we read from the database, or if we didn't find any ranges
|
||||||
// start with the scanned range.
|
// start with the scanned range.
|
||||||
let mut to_create = match existing_ranges {
|
let mut to_create = match (existing_ranges, entries.next()) {
|
||||||
Some(cur) => entries.next().map(|entry| cur.insert(entry)),
|
(Some(cur), Some(entry)) => Some(cur.insert(entry)),
|
||||||
None => entries.next().map(SpanningTree::Leaf),
|
(None, Some(entry)) => Some(SpanningTree::Leaf(entry)),
|
||||||
|
(Some(cur), None) => Some(cur),
|
||||||
|
(None, None) => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
to_create = to_create.map(|cur| cur.insert(entry))
|
to_create = to_create.map(|cur| cur.insert(entry));
|
||||||
}
|
}
|
||||||
|
|
||||||
(to_create, to_delete_ends)
|
(to_create, to_delete_ends)
|
||||||
|
@ -841,7 +864,6 @@ mod tests {
|
||||||
use ScanPriority::*;
|
use ScanPriority::*;
|
||||||
|
|
||||||
let t = spanning_tree(&[(0..3, Verify), (2..8, Scanned), (6..10, Verify)]).unwrap();
|
let t = spanning_tree(&[(0..3, Verify), (2..8, Scanned), (6..10, Verify)]).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
t.into_vec(),
|
t.into_vec(),
|
||||||
vec![
|
vec![
|
||||||
|
@ -852,7 +874,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let t = spanning_tree(&[(0..3, Verify), (2..8, Historic), (6..10, Verify)]).unwrap();
|
let t = spanning_tree(&[(0..3, Verify), (2..8, Historic), (6..10, Verify)]).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
t.into_vec(),
|
t.into_vec(),
|
||||||
vec![
|
vec![
|
||||||
|
@ -863,7 +884,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let t = spanning_tree(&[(0..3, Scanned), (2..8, Verify), (6..10, Scanned)]).unwrap();
|
let t = spanning_tree(&[(0..3, Scanned), (2..8, Verify), (6..10, Scanned)]).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
t.into_vec(),
|
t.into_vec(),
|
||||||
vec![
|
vec![
|
||||||
|
@ -874,7 +894,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
|
|
||||||
let t = spanning_tree(&[(0..3, Scanned), (2..8, Historic), (6..10, Scanned)]).unwrap();
|
let t = spanning_tree(&[(0..3, Scanned), (2..8, Historic), (6..10, Scanned)]).unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
t.into_vec(),
|
t.into_vec(),
|
||||||
vec![
|
vec![
|
||||||
|
@ -883,6 +902,37 @@ mod tests {
|
||||||
scan_range(6..10, Scanned),
|
scan_range(6..10, Scanned),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// a `ChainTip` insertion should not overwrite a scanned range.
|
||||||
|
let mut t = spanning_tree(&[(0..3, ChainTip), (3..5, Scanned), (5..7, ChainTip)]).unwrap();
|
||||||
|
t = t.insert(scan_range(0..7, ChainTip));
|
||||||
|
assert_eq!(
|
||||||
|
t.into_vec(),
|
||||||
|
vec![
|
||||||
|
scan_range(0..3, ChainTip),
|
||||||
|
scan_range(3..5, Scanned),
|
||||||
|
scan_range(5..7, ChainTip),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut t =
|
||||||
|
spanning_tree(&[(280300..280310, FoundNote), (280310..280320, Scanned)]).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
t.clone().into_vec(),
|
||||||
|
vec![
|
||||||
|
scan_range(280300..280310, FoundNote),
|
||||||
|
scan_range(280310..280320, Scanned)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
t = t.insert(scan_range(280300..280340, ChainTip));
|
||||||
|
assert_eq!(
|
||||||
|
t.into_vec(),
|
||||||
|
vec![
|
||||||
|
scan_range(280300..280310, ChainTip),
|
||||||
|
scan_range(280310..280320, Scanned),
|
||||||
|
scan_range(280320..280340, ChainTip)
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in New Issue