Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clearly distinguish factored width from the tree width #183

Merged
merged 2 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rustfmt.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fn_call_width = 100
format_code_in_doc_comments = true
fn_single_line = true
format_macro_matchers = true
format_macro_bodues = true
format_macro_bodies = true
format_strings = true
merge_derives = false
overflow_delimited_expr = true
Expand Down
2 changes: 1 addition & 1 deletion commit_verify/doc/MPC.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions commit_verify/doc/Merklization.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
520 changes: 382 additions & 138 deletions commit_verify/doc/MPC.drawio → commit_verify/doc/Workflows.drawio

Large diffs are not rendered by default.

40 changes: 24 additions & 16 deletions commit_verify/src/mpc/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl From<&MerkleTree> for MerkleBlock {
fn from(tree: &MerkleTree) -> Self {
let map = &tree.map;

let iter = (0..tree.width()).map(|pos| {
let iter = (0..tree.width_limit()).map(|pos| {
map.get(&pos)
.map(|(protocol_id, message)| TreeNode::CommitmentLeaf {
protocol_id: *protocol_id,
Expand Down Expand Up @@ -242,23 +242,23 @@ impl MerkleBlock {
) -> Result<Self, InvalidProof> {
let path = proof.as_path();
let mut pos = proof.pos;
let mut width = proof.width();
let mut width_limit = proof.width_limit();

let expected = protocol_id_pos(protocol_id, proof.cofactor, width);
let expected = protocol_id_pos(protocol_id, proof.cofactor, proof.depth());
if expected != pos {
return Err(InvalidProof {
protocol_id,
expected,
actual: pos,
width,
width: width_limit,
});
}

let mut dir = Vec::with_capacity(path.len());
let mut rev = Vec::with_capacity(path.len());
for (depth, hash) in path.iter().enumerate() {
let list = if pos >= width / 2 {
pos -= width / 2;
let list = if pos >= width_limit / 2 {
pos -= width_limit / 2;
&mut dir
} else {
&mut rev
Expand All @@ -267,7 +267,7 @@ impl MerkleBlock {
depth: u5::with(depth as u8) + 1,
hash: *hash,
});
width /= 2;
width_limit /= 2;
}

let mut cross_section = Vec::with_capacity(path.len() + 1);
Expand Down Expand Up @@ -375,7 +375,7 @@ impl MerkleBlock {
offset += 2u32.pow(self.depth.to_u8() as u32 - depth1.to_u8() as u32);
} else {
self.cross_section[pos] =
TreeNode::with(hash1, hash2, depth, self.width());
TreeNode::with(hash1, hash2, depth, self.width_limit());
self.cross_section
.remove(pos + 1)
.expect("we allow 0 elements");
Expand Down Expand Up @@ -419,7 +419,7 @@ impl MerkleBlock {
if count == prev_count {
break;
}
debug_assert_eq!(offset, self.width());
debug_assert_eq!(offset, self.width_limit());
}

Ok(count)
Expand Down Expand Up @@ -533,7 +533,7 @@ impl MerkleBlock {
.map(|n| self.depth.to_u8() - n.depth_or(self.depth).to_u8())
.map(|height| 2u32.pow(height as u32))
.sum::<u32>(),
self.width(),
self.width_limit(),
"LNPBP-4 merge-reveal procedure is broken; please report the below data to the LNP/BP \
Standards Association
Original block: {orig:#?}
Expand Down Expand Up @@ -591,11 +591,15 @@ Changed commitment id: {}",

/// Computes position for a given `protocol_id` within the tree leaves.
pub fn protocol_id_pos(&self, protocol_id: ProtocolId) -> u32 {
protocol_id_pos(protocol_id, self.cofactor, self.width())
protocol_id_pos(protocol_id, self.cofactor, self.depth)
}

/// Computes the width of the merkle tree.
pub fn width(&self) -> u32 { 2u32.pow(self.depth.to_u8() as u32) }
/// Computes the maximum possible width of the merkle tree.
pub fn width_limit(&self) -> u32 { 2u32.pow(self.depth.to_u8() as u32) }

/// Computes the factored width of the merkle tree according to the formula
/// `2 ^ depth - cofactor`.
pub fn factored_width(&self) -> u32 { self.width_limit() - self.cofactor as u32 }

/// Constructs [`MessageMap`] for revealed protocols and messages.
pub fn to_known_message_map(&self) -> MessageMap {
Expand Down Expand Up @@ -670,10 +674,14 @@ impl Proof for MerkleProof {

impl MerkleProof {
/// Computes the depth of the merkle tree.
pub fn depth(&self) -> u8 { self.path.len() as u8 }
pub fn depth(&self) -> u5 { u5::with(self.path.len() as u8) }

/// Computes the maximum width of the merkle tree.
pub fn width_limit(&self) -> u32 { 2u32.pow(self.depth().to_u8() as u32) }

/// Computes the width of the merkle tree.
pub fn width(&self) -> u32 { 2u32.pow(self.depth() as u32) }
/// Computes the factored width of the merkle tree according to the formula
/// `2 ^ depth - cofactor`.
pub fn factored_width(&self) -> u32 { self.width_limit() - self.cofactor as u32 }

/// Converts the proof into inner merkle path representation
pub fn into_path(self) -> Confined<Vec<MerkleHash>, 0, 32> { self.path }
Expand Down
32 changes: 20 additions & 12 deletions commit_verify/src/mpc/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,14 @@ impl Proof for MerkleTree {

impl MerkleTree {
pub fn root(&self) -> MerkleHash {
let iter = (0..self.width()).map(|pos| {
let iter = (0..self.width_limit()).map(|pos| {
self.map
.get(&pos)
.map(|(protocol, msg)| Leaf::inhabited(*protocol, *msg))
.unwrap_or_else(|| Leaf::entropy(self.entropy, pos))
});
let leaves = LargeVec::try_from_iter(iter).expect("tree width has u32-bound size");
debug_assert_eq!(leaves.len_u32(), self.width());
debug_assert_eq!(leaves.len_u32(), self.width_limit());
MerkleHash::merklize(&leaves)
}
}
Expand Down Expand Up @@ -146,12 +146,12 @@ mod commit {
let mut depth = source.min_depth;
let mut prev_width = 1u32;
loop {
let width = 2u32.pow(depth.to_u8() as u32);
if width as usize >= msg_count {
let width_limit = 2u32.pow(depth.to_u8() as u32);
if width_limit as usize >= msg_count {
for cofactor in 0..=(prev_width.min(COFACTOR_ATTEMPTS as u32) as u16) {
map.clear();
if source.messages.iter().all(|(protocol, message)| {
let pos = protocol_id_pos(*protocol, cofactor, width);
let pos = protocol_id_pos(*protocol, cofactor, depth);
map.insert(pos, (*protocol, *message)).is_none()
}) {
return Ok(MerkleTree {
Expand All @@ -165,7 +165,7 @@ mod commit {
}
}

prev_width = width;
prev_width = width_limit;
depth = depth
.checked_add(1)
.ok_or(Error::CantFitInMaxSlots(msg_count))?;
Expand All @@ -174,7 +174,8 @@ mod commit {
}
}

pub(super) fn protocol_id_pos(protocol_id: ProtocolId, cofactor: u16, width: u32) -> u32 {
pub(super) fn protocol_id_pos(protocol_id: ProtocolId, cofactor: u16, depth: u5) -> u32 {
let width = 2u32.pow(depth.to_u8() as u32);
debug_assert_ne!(width, 0);
let rem = u256::from_le_bytes((*protocol_id).into_inner()) %
u256::from(width.saturating_sub(cofactor as u32).max(1) as u64);
Expand All @@ -184,14 +185,21 @@ pub(super) fn protocol_id_pos(protocol_id: ProtocolId, cofactor: u16, width: u32
impl MerkleTree {
/// Computes position for a given `protocol_id` within the tree leaves.
pub fn protocol_id_pos(&self, protocol_id: ProtocolId) -> u32 {
protocol_id_pos(protocol_id, self.cofactor, self.width())
protocol_id_pos(protocol_id, self.cofactor, self.depth)
}

/// Computes the width of the merkle tree.
pub fn width(&self) -> u32 { 2u32.pow(self.depth.to_u8() as u32) }
/// Computes the maximum possible width of the merkle tree, equal to `2 ^
/// depth`.
pub fn width_limit(&self) -> u32 { 2u32.pow(self.depth.to_u8() as u32) }

/// Computes the factored width of the merkle tree, equal to `2 ^ depth -
/// cofactor`.
pub fn factored_width(&self) -> u32 { self.width_limit() - self.cofactor as u32 }

pub fn depth(&self) -> u5 { self.depth }

pub fn cofactor(&self) -> u16 { self.cofactor }

pub fn entropy(&self) -> u64 { self.entropy }
}

Expand Down Expand Up @@ -307,7 +315,7 @@ mod test {
length {} bytes.\nTakes {} msecs to generate",
tree.depth,
tree.cofactor,
tree.width(),
tree.factored_width(),
counter.unconfine().count,
elapsed_gen.as_millis(),
);
Expand All @@ -323,7 +331,7 @@ mod test {
let msgs = make_random_messages(9);
let tree = make_random_tree(&msgs);
assert!(tree.depth() > u5::with(3));
assert!(tree.width() > 9);
assert!(tree.factored_width() > 9);
let mut set = BTreeSet::<u32>::new();
for (pid, msg) in msgs {
let pos = tree.protocol_id_pos(pid);
Expand Down
Loading