2019-09-09 04:33:49 -07:00
|
|
|
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
|
2019-09-07 03:52:19 -07:00
|
|
|
|
2020-03-03 17:11:44 -08:00
|
|
|
use crate::{EntryKind, EntryLink, Error, NodeData, MAX_NODE_DATA_SIZE};
|
2019-09-07 04:04:51 -07:00
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Max serialized length of entry data.
|
2019-09-07 04:04:51 -07:00
|
|
|
pub const MAX_ENTRY_SIZE: usize = MAX_NODE_DATA_SIZE + 9;
|
2019-09-07 03:52:19 -07:00
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// MMR Entry.
|
2019-09-07 03:52:19 -07:00
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Entry {
|
|
|
|
pub(crate) kind: EntryKind,
|
|
|
|
pub(crate) data: NodeData,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Entry {
|
2019-09-25 00:50:59 -07:00
|
|
|
/// New entry of type node.
|
|
|
|
pub fn new(data: NodeData, left: EntryLink, right: EntryLink) -> Self {
|
|
|
|
Entry {
|
|
|
|
kind: EntryKind::Node(left, right),
|
|
|
|
data,
|
|
|
|
}
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Returns if is this node complete (has total of 2^N leaves)
|
2019-09-07 03:52:19 -07:00
|
|
|
pub fn complete(&self) -> bool {
|
|
|
|
let leaves = self.leaf_count();
|
|
|
|
leaves & (leaves - 1) == 0
|
|
|
|
}
|
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Number of leaves under this node.
|
2019-09-07 03:52:19 -07:00
|
|
|
pub fn leaf_count(&self) -> u64 {
|
2019-10-10 22:00:07 -07:00
|
|
|
self.data.end_height - (self.data.start_height - 1)
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Is this node a leaf.
|
2019-09-25 00:53:06 -07:00
|
|
|
pub fn leaf(&self) -> bool {
|
2020-03-03 17:11:44 -08:00
|
|
|
if let EntryKind::Leaf = self.kind {
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Left child
|
2019-09-07 03:52:19 -07:00
|
|
|
pub fn left(&self) -> Result<EntryLink, Error> {
|
|
|
|
match self.kind {
|
2020-03-03 17:11:44 -08:00
|
|
|
EntryKind::Leaf => Err(Error::node_expected()),
|
|
|
|
EntryKind::Node(left, _) => Ok(left),
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Right child.
|
2019-09-07 03:52:19 -07:00
|
|
|
pub fn right(&self) -> Result<EntryLink, Error> {
|
|
|
|
match self.kind {
|
2020-03-03 17:11:44 -08:00
|
|
|
EntryKind::Leaf => Err(Error::node_expected()),
|
|
|
|
EntryKind::Node(_, right) => Ok(right),
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-07 04:00:34 -07:00
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Read from byte representation.
|
2019-09-07 04:10:08 -07:00
|
|
|
pub fn read<R: std::io::Read>(consensus_branch_id: u32, r: &mut R) -> std::io::Result<Self> {
|
2019-09-07 04:00:34 -07:00
|
|
|
let kind = {
|
|
|
|
match r.read_u8()? {
|
|
|
|
0 => {
|
|
|
|
let left = r.read_u32::<LittleEndian>()?;
|
|
|
|
let right = r.read_u32::<LittleEndian>()?;
|
|
|
|
EntryKind::Node(EntryLink::Stored(left), EntryLink::Stored(right))
|
2020-03-03 17:11:44 -08:00
|
|
|
}
|
|
|
|
1 => EntryKind::Leaf,
|
|
|
|
_ => return Err(std::io::Error::from(std::io::ErrorKind::InvalidData)),
|
2019-09-07 04:00:34 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
let data = NodeData::read(consensus_branch_id, r)?;
|
|
|
|
|
2020-03-03 17:11:44 -08:00
|
|
|
Ok(Entry { kind, data })
|
2019-09-07 04:00:34 -07:00
|
|
|
}
|
2019-09-07 04:10:08 -07:00
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Write to byte representation.
|
2019-09-09 04:33:49 -07:00
|
|
|
pub fn write<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
|
|
|
match self.kind {
|
|
|
|
EntryKind::Node(EntryLink::Stored(left), EntryLink::Stored(right)) => {
|
|
|
|
w.write_u8(0)?;
|
|
|
|
w.write_u32::<LittleEndian>(left)?;
|
|
|
|
w.write_u32::<LittleEndian>(right)?;
|
2020-03-03 17:11:44 -08:00
|
|
|
}
|
2019-09-09 04:33:49 -07:00
|
|
|
EntryKind::Leaf => {
|
|
|
|
w.write_u8(1)?;
|
2020-03-03 17:11:44 -08:00
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
return Err(std::io::Error::from(std::io::ErrorKind::InvalidData));
|
|
|
|
}
|
2019-09-09 04:33:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
self.data.write(w)?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2019-09-24 03:45:23 -07:00
|
|
|
/// Convert from byte representation.
|
2019-09-07 23:32:47 -07:00
|
|
|
pub fn from_bytes<T: AsRef<[u8]>>(consensus_branch_id: u32, buf: T) -> std::io::Result<Self> {
|
2019-09-07 04:10:08 -07:00
|
|
|
let mut cursor = std::io::Cursor::new(buf);
|
|
|
|
Self::read(consensus_branch_id, &mut cursor)
|
|
|
|
}
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From<NodeData> for Entry {
|
|
|
|
fn from(s: NodeData) -> Self {
|
2020-03-03 17:11:44 -08:00
|
|
|
Entry {
|
|
|
|
kind: EntryKind::Leaf,
|
|
|
|
data: s,
|
|
|
|
}
|
2019-09-07 03:52:19 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-25 00:50:59 -07:00
|
|
|
|
|
|
|
impl std::fmt::Display for Entry {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self.kind {
|
|
|
|
EntryKind::Node(l, r) => write!(f, "node({}, {}, ..)", l, r),
|
|
|
|
EntryKind::Leaf => write!(f, "leaf(..)"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|