Rename "Level" -> "Altitude"
The FlyClient spec uses "Altitude" for this concept in Merkle mountain ranges, so I'm renaming for consistency.
This commit is contained in:
parent
d319262985
commit
aed785e896
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
|||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
||||
use super::{Hashable, Level, Recording, Tree};
|
||||
use super::{Altitude, Hashable, Recording, Tree};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[repr(transparent)]
|
||||
|
@ -19,18 +19,18 @@ impl Position {
|
|||
self.0 += 1
|
||||
}
|
||||
|
||||
fn max_level(&self) -> Level {
|
||||
Level(if self.0 == 0 {
|
||||
fn max_level(&self) -> Altitude {
|
||||
Altitude(if self.0 == 0 {
|
||||
0
|
||||
} else {
|
||||
63 - self.0.leading_zeros()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parent_levels(&self) -> impl Iterator<Item = Level> + '_ {
|
||||
pub fn parent_levels(&self) -> impl Iterator<Item = Altitude> + '_ {
|
||||
(0..=self.max_level().0).into_iter().filter_map(move |i| {
|
||||
if i != 0 && self.0 & (1 << i) != 0 {
|
||||
Some(Level(i))
|
||||
Some(Altitude(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -41,29 +41,29 @@ impl Position {
|
|||
self.levels_required().count()
|
||||
}
|
||||
|
||||
pub fn levels_required(&self) -> impl Iterator<Item = Level> + '_ {
|
||||
pub fn levels_required(&self) -> impl Iterator<Item = Altitude> + '_ {
|
||||
(0..=(self.max_level() + 1).0)
|
||||
.into_iter()
|
||||
.filter_map(move |i| {
|
||||
if self.0 == 0 || self.0 & (1 << i) == 0 {
|
||||
Some(Level(i))
|
||||
Some(Altitude(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn all_levels_required(&self) -> impl Iterator<Item = Level> + '_ {
|
||||
pub fn all_levels_required(&self) -> impl Iterator<Item = Altitude> + '_ {
|
||||
(0..64).into_iter().filter_map(move |i| {
|
||||
if self.0 == 0 || self.0 & (1 << i) == 0 {
|
||||
Some(Level(i))
|
||||
Some(Altitude(i))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_complete(&self, to_level: Level) -> bool {
|
||||
pub fn is_complete(&self, to_level: Altitude) -> bool {
|
||||
for i in 0..(to_level.0) {
|
||||
if self.0 & (1 << i) == 0 {
|
||||
return false;
|
||||
|
@ -72,7 +72,7 @@ impl Position {
|
|||
true
|
||||
}
|
||||
|
||||
pub fn has_observed(&self, level: Level, since: Position) -> bool {
|
||||
pub fn has_observed(&self, level: Altitude, since: Position) -> bool {
|
||||
let level_delta = 2usize.pow(level.0);
|
||||
self.0 - since.0 > level_delta
|
||||
}
|
||||
|
@ -120,9 +120,9 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
Leaf::Right(a, b) => {
|
||||
carry = Some((
|
||||
Parent {
|
||||
value: H::combine(Level::zero(), &a, &b),
|
||||
value: H::combine(Altitude::zero(), &a, &b),
|
||||
},
|
||||
Level::one(),
|
||||
Altitude::one(),
|
||||
));
|
||||
self.leaf = Leaf::Left(value);
|
||||
}
|
||||
|
@ -171,8 +171,8 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
|
||||
/// If the tree is full to the specified level, return the data
|
||||
/// required to witness a sibling at that level.
|
||||
pub fn witness(&self, sibling_level: Level) -> Option<H> {
|
||||
if sibling_level == Level::zero() {
|
||||
pub fn witness(&self, sibling_level: Altitude) -> Option<H> {
|
||||
if sibling_level == Altitude::zero() {
|
||||
match &self.leaf {
|
||||
Leaf::Left(_) => None,
|
||||
Leaf::Right(_, a) => Some(a.clone()),
|
||||
|
@ -193,13 +193,13 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
|
||||
/// If the tree is not full, generate the root of the incomplete subtree
|
||||
/// by hashing with empty branches
|
||||
pub fn witness_incomplete(&self, level: Level) -> Option<H> {
|
||||
pub fn witness_incomplete(&self, level: Altitude) -> Option<H> {
|
||||
if self.position.is_complete(level) {
|
||||
// if the tree is complete to this level, its hash should
|
||||
// have already been included in an auth fragment.
|
||||
None
|
||||
} else {
|
||||
Some(if level == Level::zero() {
|
||||
Some(if level == Altitude::zero() {
|
||||
H::empty_leaf()
|
||||
} else {
|
||||
Self::inner_root(
|
||||
|
@ -217,14 +217,14 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
position: Position,
|
||||
leaf: &Leaf<H>,
|
||||
parents: &[Parent<H>],
|
||||
result_lvl: Option<Level>,
|
||||
result_lvl: Option<Altitude>,
|
||||
) -> H {
|
||||
let mut digest = match leaf {
|
||||
Leaf::Left(a) => H::combine(Level::zero(), a, &H::empty_leaf()),
|
||||
Leaf::Right(a, b) => H::combine(Level::zero(), a, b),
|
||||
Leaf::Left(a) => H::combine(Altitude::zero(), a, &H::empty_leaf()),
|
||||
Leaf::Right(a, b) => H::combine(Altitude::zero(), a, b),
|
||||
};
|
||||
|
||||
let mut complete_lvl = Level::one();
|
||||
let mut complete_lvl = Altitude::one();
|
||||
for (parent, parent_lvl) in parents.iter().zip(position.parent_levels()) {
|
||||
// stop once we've reached the max level
|
||||
if result_lvl
|
||||
|
@ -264,8 +264,8 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn value_at(&self, lvl: Level) -> Option<H> {
|
||||
if lvl == Level::zero() {
|
||||
pub fn value_at(&self, lvl: Altitude) -> Option<H> {
|
||||
if lvl == Altitude::zero() {
|
||||
Some(self.leaf_value())
|
||||
} else {
|
||||
self.parents
|
||||
|
@ -276,7 +276,7 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn max_level(&self) -> Level {
|
||||
pub fn max_level(&self) -> Altitude {
|
||||
self.position.max_level()
|
||||
}
|
||||
|
||||
|
@ -289,14 +289,14 @@ impl<H: Hashable + Clone> NonEmptyFrontier<H> {
|
|||
/// full functionality of a Merkle bridge is not necessary.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Frontier<H> {
|
||||
max_level: Level,
|
||||
max_level: Altitude,
|
||||
frontier: Option<NonEmptyFrontier<H>>,
|
||||
}
|
||||
|
||||
impl<H> Frontier<H> {
|
||||
pub fn new(max_depth: usize) -> Self {
|
||||
Frontier {
|
||||
max_level: Level(max_depth as u32 - 1),
|
||||
max_level: Altitude(max_depth as u32 - 1),
|
||||
frontier: None,
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ impl<A> AuthFragment<A> {
|
|||
self.levels_observed >= self.position.levels_required_count()
|
||||
}
|
||||
|
||||
pub fn next_required_level(&self) -> Option<Level> {
|
||||
pub fn next_required_level(&self) -> Option<Altitude> {
|
||||
self.position
|
||||
.all_levels_required()
|
||||
.nth(self.levels_observed)
|
||||
|
@ -449,7 +449,7 @@ impl<H: Hashable + Clone + PartialEq> MerkleBridge<H> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn max_level(&self) -> Level {
|
||||
pub fn max_level(&self) -> Altitude {
|
||||
self.frontier.max_level()
|
||||
}
|
||||
|
||||
|
@ -518,7 +518,7 @@ pub struct BridgeTree<H: Hash + Eq> {
|
|||
/// Version value for the serialized form
|
||||
ser_version: u8,
|
||||
/// The depth of the Merkle tree
|
||||
max_level: Level,
|
||||
max_level: Altitude,
|
||||
/// The ordered list of Merkle bridges representing the history
|
||||
/// of the tree. There will be one bridge for each saved leaf, plus
|
||||
/// the current bridge to the tip of the tree.
|
||||
|
@ -550,7 +550,7 @@ impl<H: Hashable + Hash + Eq + Clone> BridgeTree<H> {
|
|||
pub fn new(max_depth: usize, max_checkpoints: usize) -> Self {
|
||||
BridgeTree {
|
||||
ser_version: 0,
|
||||
max_level: Level(max_depth as u32 - 1),
|
||||
max_level: Altitude(max_depth as u32 - 1),
|
||||
bridges: vec![],
|
||||
incomplete_from: 0,
|
||||
saved: HashMap::new(),
|
||||
|
@ -688,7 +688,7 @@ impl<H: Hashable + Hash + Eq + Clone> Tree<H> for BridgeTree<H> {
|
|||
result.push(
|
||||
auth_values
|
||||
.next()
|
||||
.unwrap_or_else(|| H::empty_root(Level(synth_lvl as u32))),
|
||||
.unwrap_or_else(|| H::empty_root(Altitude(synth_lvl as u32))),
|
||||
)
|
||||
}
|
||||
result.push(parent.value.clone());
|
||||
|
@ -698,7 +698,7 @@ impl<H: Hashable + Hash + Eq + Clone> Tree<H> for BridgeTree<H> {
|
|||
result.push(
|
||||
auth_values
|
||||
.next()
|
||||
.unwrap_or_else(|| H::empty_root(Level(synth_lvl as u32))),
|
||||
.unwrap_or_else(|| H::empty_root(Altitude(synth_lvl as u32))),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -815,7 +815,7 @@ impl<H: Hashable + Hash + Eq + Clone> Tree<H> for BridgeTree<H> {
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct BridgeRecording<H> {
|
||||
max_level: Level,
|
||||
max_level: Altitude,
|
||||
bridge: Option<MerkleBridge<H>>,
|
||||
}
|
||||
|
||||
|
@ -858,13 +858,13 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn position_levels() {
|
||||
assert_eq!(Position(0).max_level(), Level(0));
|
||||
assert_eq!(Position(1).max_level(), Level(0));
|
||||
assert_eq!(Position(2).max_level(), Level(1));
|
||||
assert_eq!(Position(3).max_level(), Level(1));
|
||||
assert_eq!(Position(4).max_level(), Level(2));
|
||||
assert_eq!(Position(7).max_level(), Level(2));
|
||||
assert_eq!(Position(8).max_level(), Level(3));
|
||||
assert_eq!(Position(0).max_level(), Altitude(0));
|
||||
assert_eq!(Position(1).max_level(), Altitude(0));
|
||||
assert_eq!(Position(2).max_level(), Altitude(1));
|
||||
assert_eq!(Position(3).max_level(), Altitude(1));
|
||||
assert_eq!(Position(4).max_level(), Altitude(2));
|
||||
assert_eq!(Position(7).max_level(), Altitude(2));
|
||||
assert_eq!(Position(8).max_level(), Altitude(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
76
src/lib.rs
76
src/lib.rs
|
@ -33,44 +33,44 @@ use std::ops::Sub;
|
|||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[repr(transparent)]
|
||||
pub struct Level(u32);
|
||||
pub struct Altitude(u32);
|
||||
|
||||
impl Level {
|
||||
impl Altitude {
|
||||
pub fn zero() -> Self {
|
||||
Level(0)
|
||||
Altitude(0)
|
||||
}
|
||||
|
||||
pub fn one() -> Self {
|
||||
Level(1)
|
||||
Altitude(1)
|
||||
}
|
||||
|
||||
pub fn iter_to(self, other: Level) -> impl Iterator<Item = Level> {
|
||||
(self.0..other.0).into_iter().map(Level)
|
||||
pub fn iter_to(self, other: Altitude) -> impl Iterator<Item = Altitude> {
|
||||
(self.0..other.0).into_iter().map(Altitude)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<u32> for Level {
|
||||
type Output = Level;
|
||||
impl Add<u32> for Altitude {
|
||||
type Output = Altitude;
|
||||
fn add(self, value: u32) -> Self {
|
||||
Level(self.0 + value)
|
||||
Altitude(self.0 + value)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub<u32> for Level {
|
||||
type Output = Level;
|
||||
impl Sub<u32> for Altitude {
|
||||
type Output = Altitude;
|
||||
fn sub(self, value: u32) -> Self {
|
||||
Level(self.0 - value)
|
||||
Altitude(self.0 - value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Level {
|
||||
impl From<u32> for Altitude {
|
||||
fn from(value: u32) -> Self {
|
||||
Level(value)
|
||||
Altitude(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Level> for usize {
|
||||
fn from(level: Level) -> usize {
|
||||
impl From<Altitude> for usize {
|
||||
fn from(level: Altitude) -> usize {
|
||||
level.0 as usize
|
||||
}
|
||||
}
|
||||
|
@ -80,10 +80,10 @@ impl From<Level> for usize {
|
|||
pub trait Hashable: Sized {
|
||||
fn empty_leaf() -> Self;
|
||||
|
||||
fn combine(level: Level, a: &Self, b: &Self) -> Self;
|
||||
fn combine(level: Altitude, a: &Self, b: &Self) -> Self;
|
||||
|
||||
fn empty_root(level: Level) -> Self {
|
||||
Level::zero()
|
||||
fn empty_root(level: Altitude) -> Self {
|
||||
Altitude::zero()
|
||||
.iter_to(level)
|
||||
.fold(Self::empty_leaf(), |v, lvl| Self::combine(lvl, &v, &v))
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ pub(crate) mod tests {
|
|||
|
||||
use super::bridgetree::{BridgeRecording, BridgeTree};
|
||||
use super::sample::{lazy_root, CompleteRecording, CompleteTree};
|
||||
use super::{Frontier, Hashable, Level, Recording, Tree};
|
||||
use super::{Altitude, Frontier, Hashable, Recording, Tree};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CombinedTree<H: Hashable + Hash + Eq> {
|
||||
|
@ -294,7 +294,7 @@ pub(crate) mod tests {
|
|||
SipHashable(0)
|
||||
}
|
||||
|
||||
fn combine(_level: Level, a: &Self, b: &Self) -> Self {
|
||||
fn combine(_level: Altitude, a: &Self, b: &Self) -> Self {
|
||||
let mut hasher = SipHasher::new();
|
||||
hasher.write_u64(a.0);
|
||||
hasher.write_u64(b.0);
|
||||
|
@ -307,7 +307,7 @@ pub(crate) mod tests {
|
|||
"_".to_string()
|
||||
}
|
||||
|
||||
fn combine(_: Level, a: &Self, b: &Self) -> Self {
|
||||
fn combine(_: Altitude, a: &Self, b: &Self) -> Self {
|
||||
a.to_string() + b
|
||||
}
|
||||
}
|
||||
|
@ -369,7 +369,7 @@ pub(crate) mod tests {
|
|||
path: &[H],
|
||||
) -> H {
|
||||
let mut cur = value;
|
||||
let mut lvl = Level::zero();
|
||||
let mut lvl = Altitude::zero();
|
||||
for (i, v) in path
|
||||
.iter()
|
||||
.enumerate()
|
||||
|
@ -388,16 +388,16 @@ pub(crate) mod tests {
|
|||
#[test]
|
||||
fn test_compute_root_from_auth_path() {
|
||||
let expected = SipHashable::combine(
|
||||
<Level>::from(2),
|
||||
<Altitude>::from(2),
|
||||
&SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
),
|
||||
&SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -407,11 +407,11 @@ pub(crate) mod tests {
|
|||
0,
|
||||
&[
|
||||
SipHashable(1),
|
||||
SipHashable::combine(Level::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
SipHashable::combine(Altitude::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(6), &SipHashable(7))
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(6), &SipHashable(7))
|
||||
)
|
||||
]
|
||||
),
|
||||
|
@ -424,11 +424,11 @@ pub(crate) mod tests {
|
|||
4,
|
||||
&[
|
||||
SipHashable(5),
|
||||
SipHashable::combine(Level::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
SipHashable::combine(Altitude::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(2), &SipHashable(3))
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(2), &SipHashable(3))
|
||||
)
|
||||
]
|
||||
),
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/// Sample implementation of the Tree interface.
|
||||
use super::{Frontier, Hashable, Level, Recording, Tree};
|
||||
use super::{Altitude, Frontier, Hashable, Recording, Tree};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CompleteTree<H: Hashable> {
|
||||
|
@ -214,7 +214,7 @@ impl<H: Hashable + Clone> Recording<H> for CompleteRecording<H> {
|
|||
|
||||
pub(crate) fn lazy_root<H: Hashable + Clone>(mut leaves: Vec<H>) -> H {
|
||||
//leaves are always at level zero, so we start there.
|
||||
let mut level = Level::zero();
|
||||
let mut level = Altitude::zero();
|
||||
while leaves.len() != 1 {
|
||||
leaves = leaves
|
||||
.iter()
|
||||
|
@ -239,7 +239,7 @@ pub(crate) fn lazy_root<H: Hashable + Clone>(mut leaves: Vec<H>) -> H {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::{compute_root_from_auth_path, SipHashable};
|
||||
use crate::{Frontier, Hashable, Level, Tree};
|
||||
use crate::{Altitude, Frontier, Hashable, Tree};
|
||||
|
||||
use super::CompleteTree;
|
||||
|
||||
|
@ -267,16 +267,16 @@ mod tests {
|
|||
assert!(!tree.append(&SipHashable(0)));
|
||||
|
||||
let expected = SipHashable::combine(
|
||||
<Level>::from(2),
|
||||
<Altitude>::from(2),
|
||||
&SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
),
|
||||
&SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -296,16 +296,16 @@ mod tests {
|
|||
assert!(!tree.append(&SipHashable(0)));
|
||||
|
||||
let expected = SipHashable::combine(
|
||||
<Level>::from(2),
|
||||
<Altitude>::from(2),
|
||||
&SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(0), &SipHashable(1)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(2), &SipHashable(3)),
|
||||
),
|
||||
&SipHashable::combine(
|
||||
Level::one(),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Level::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
Altitude::one(),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(4), &SipHashable(5)),
|
||||
&SipHashable::combine(Altitude::zero(), &SipHashable(6), &SipHashable(7)),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue