Skip to content

Commit

Permalink
mpc: clearly distinguish factored width from the tree width
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-orlovsky committed Aug 20, 2024
1 parent 8aaf1ba commit 4071666
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 29 deletions.
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
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

0 comments on commit 4071666

Please sign in to comment.