witness filled
This commit is contained in:
parent
9283e9940b
commit
260a4c0145
273
src/builder.rs
273
src/builder.rs
|
@ -8,7 +8,7 @@ trait Builder<T, C> {
|
||||||
fn collect(&mut self, commitments: &[Node], context: &C) -> usize;
|
fn collect(&mut self, commitments: &[Node], context: &C) -> usize;
|
||||||
fn up(&mut self);
|
fn up(&mut self);
|
||||||
fn finished(&self) -> bool;
|
fn finished(&self) -> bool;
|
||||||
fn finalize(self) -> T;
|
fn finalize(self, context: &C) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CTreeBuilder {
|
struct CTreeBuilder {
|
||||||
|
@ -39,11 +39,11 @@ impl Builder<CTree, ()> for CTreeBuilder {
|
||||||
|
|
||||||
let n = if self.depth == 0 {
|
let n = if self.depth == 0 {
|
||||||
if m % 2 == 0 {
|
if m % 2 == 0 {
|
||||||
self.next_tree.left = Some(Self::get(commitments, m - 2, offset));
|
self.next_tree.left = Some(*Self::get(commitments, m - 2, &offset));
|
||||||
self.next_tree.right = Some(Self::get(commitments, m - 1, offset));
|
self.next_tree.right = Some(*Self::get(commitments, m - 1, &offset));
|
||||||
m - 2
|
m - 2
|
||||||
} else {
|
} else {
|
||||||
self.next_tree.left = Some(Self::get(commitments, m - 1, offset));
|
self.next_tree.left = Some(*Self::get(commitments, m - 1, &offset));
|
||||||
self.next_tree.right = None;
|
self.next_tree.right = None;
|
||||||
m - 1
|
m - 1
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,8 @@ impl Builder<CTree, ()> for CTreeBuilder {
|
||||||
self.next_tree.parents.push(None);
|
self.next_tree.parents.push(None);
|
||||||
m
|
m
|
||||||
} else {
|
} else {
|
||||||
let last_node = Self::get(commitments, m - 1, offset);
|
let last_node = Self::get(commitments, m - 1, &offset);
|
||||||
self.next_tree.parents.push(Some(last_node));
|
self.next_tree.parents.push(Some(*last_node));
|
||||||
m - 1
|
m - 1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -65,7 +65,11 @@ impl Builder<CTree, ()> for CTreeBuilder {
|
||||||
|
|
||||||
fn up(&mut self) {
|
fn up(&mut self) {
|
||||||
let h = if self.left.is_some() && self.right.is_some() {
|
let h = if self.left.is_some() && self.right.is_some() {
|
||||||
Some(Node::combine(self.depth, &self.left.unwrap(), &self.right.unwrap()))
|
Some(Node::combine(
|
||||||
|
self.depth,
|
||||||
|
&self.left.unwrap(),
|
||||||
|
&self.right.unwrap(),
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -88,7 +92,7 @@ impl Builder<CTree, ()> for CTreeBuilder {
|
||||||
self.depth >= self.prev_tree.parents.len() && self.left.is_none() && self.right.is_none()
|
self.depth >= self.prev_tree.parents.len() && self.left.is_none() && self.right.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(self) -> CTree {
|
fn finalize(self, _context: &()) -> CTree {
|
||||||
self.next_tree
|
self.next_tree
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,18 +112,50 @@ impl CTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn get(commitments: &[Node], index: usize, offset: Option<Node>) -> Node {
|
fn get_opt<'a>(
|
||||||
match offset {
|
commitments: &'a [Node],
|
||||||
Some(offset) => {
|
index: usize,
|
||||||
if index > 0 {
|
offset: &'a Option<Node>,
|
||||||
commitments[index - 1]
|
) -> Option<&'a Node> {
|
||||||
} else {
|
if offset.is_some() {
|
||||||
offset
|
if index > 0 {
|
||||||
}
|
commitments.get(index - 1)
|
||||||
|
} else {
|
||||||
|
offset.as_ref()
|
||||||
}
|
}
|
||||||
None => commitments[index],
|
} else {
|
||||||
|
commitments.get(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn get<'a>(commitments: &'a [Node], index: usize, offset: &'a Option<Node>) -> &'a Node {
|
||||||
|
Self::get_opt(commitments, index, offset).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adjusted_start(&self) -> usize {
|
||||||
|
if self.offset.is_some() {
|
||||||
|
self.start - 1
|
||||||
|
} else {
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adjusted_end(&self, commitments: &[Node]) -> usize {
|
||||||
|
self.start + commitments.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clone_trimmed(&self, mut depth: usize) -> CTree {
|
||||||
|
if depth == 0 {
|
||||||
|
return CTree::new()
|
||||||
|
}
|
||||||
|
let mut tree = self.next_tree.clone();
|
||||||
|
while depth > 0 && depth <= tree.parents.len() && tree.parents[depth - 1].is_none() {
|
||||||
|
depth -= 1;
|
||||||
|
}
|
||||||
|
tree.parents.truncate(depth);
|
||||||
|
tree
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn combine_level(commitments: &mut [Node], offset: Option<Node>, n: usize, depth: usize) -> usize {
|
fn combine_level(commitments: &mut [Node], offset: Option<Node>, n: usize, depth: usize) -> usize {
|
||||||
|
@ -131,8 +167,8 @@ fn combine_level(commitments: &mut [Node], offset: Option<Node>, n: usize, depth
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
Node::combine(
|
Node::combine(
|
||||||
depth,
|
depth,
|
||||||
&CTreeBuilder::get(commitments, 2 * i, offset),
|
CTreeBuilder::get(commitments, 2 * i, &offset),
|
||||||
&CTreeBuilder::get(commitments, 2 * i + 1, offset),
|
CTreeBuilder::get(commitments, 2 * i + 1, &offset),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -163,30 +199,52 @@ impl Builder<Witness, CTreeBuilder> for WitnessBuilder {
|
||||||
let offset = context.offset;
|
let offset = context.offset;
|
||||||
let depth = context.depth;
|
let depth = context.depth;
|
||||||
|
|
||||||
|
if depth == 1 {
|
||||||
|
context.offset.map(|c| println!("{}", hex::encode(c.repr)));
|
||||||
|
for c in commitments.iter() {
|
||||||
|
println!("{}", hex::encode(c.repr));
|
||||||
|
}
|
||||||
|
println!("===");
|
||||||
|
}
|
||||||
|
|
||||||
|
let tree = &mut self.witness.tree;
|
||||||
|
|
||||||
if self.inside {
|
if self.inside {
|
||||||
let rp = self.p - context.start;
|
let rp = self.p - context.adjusted_start();
|
||||||
if depth == 0 {
|
if depth == 0 {
|
||||||
if self.p % 2 == 1 {
|
if self.p % 2 == 1 {
|
||||||
self.witness.tree.left = Some(CTreeBuilder::get(commitments, rp - 1, offset));
|
tree.left = Some(*CTreeBuilder::get(commitments, rp - 1, &offset));
|
||||||
self.witness.tree.right = Some(CTreeBuilder::get(commitments, rp, offset));
|
tree.right = Some(*CTreeBuilder::get(commitments, rp, &offset));
|
||||||
|
} else {
|
||||||
|
tree.left = Some(*CTreeBuilder::get(commitments, rp, &offset));
|
||||||
|
tree.right = None;
|
||||||
}
|
}
|
||||||
else {
|
} else {
|
||||||
self.witness.tree.left = Some(CTreeBuilder::get(commitments, rp, offset));
|
|
||||||
self.witness.tree.right = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if self.p % 2 == 1 {
|
if self.p % 2 == 1 {
|
||||||
self.witness.tree.parents.push(Some(CTreeBuilder::get(commitments, rp, offset)));
|
tree.parents
|
||||||
}
|
.push(Some(*CTreeBuilder::get(commitments, rp - 1, &offset)));
|
||||||
else {
|
} else if self.p != 0 {
|
||||||
self.witness.tree.parents.push(None);
|
tree.parents.push(None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: update filled
|
let p1 = self.p + 1;
|
||||||
|
let has_p1 = p1 >= context.adjusted_start() && p1 < context.adjusted_end(commitments);
|
||||||
|
// println!("D{}: {} {} {} {}", depth, p1, context.start, context.start + commitments.len(), context.offset.is_some());
|
||||||
|
if has_p1 {
|
||||||
|
let p1 = CTreeBuilder::get(commitments, p1 - context.adjusted_start(), &offset);
|
||||||
|
println!("P1 {} {}", depth, hex::encode(p1.repr));
|
||||||
|
if depth == 0 {
|
||||||
|
if tree.right.is_none() {
|
||||||
|
self.witness.filled.push(*p1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if depth - 1 >= tree.parents.len() || tree.parents[depth - 1].is_none() {
|
||||||
|
self.witness.filled.push(*p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,20 +256,48 @@ impl Builder<Witness, CTreeBuilder> for WitnessBuilder {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(self) -> Witness {
|
fn finalize(mut self, context: &CTreeBuilder) -> Witness {
|
||||||
|
let tree = &self.witness.tree;
|
||||||
|
let mut num_filled = self.witness.filled.len();
|
||||||
|
|
||||||
|
let mut depth = 0;
|
||||||
|
loop {
|
||||||
|
let is_none = if depth == 0 { // check if this level is occupied
|
||||||
|
tree.right.is_none()
|
||||||
|
} else {
|
||||||
|
depth > tree.parents.len() || tree.parents[depth - 1].is_none()
|
||||||
|
};
|
||||||
|
if is_none {
|
||||||
|
if num_filled > 0 {
|
||||||
|
num_filled -= 1; // we filled it
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
depth += 1;
|
||||||
|
// loop terminates because we are eventually going to run out of ancestors and filled
|
||||||
|
}
|
||||||
|
|
||||||
|
self.witness.cursor = context.clone_trimmed(depth - 1);
|
||||||
self.witness
|
self.witness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn advance_tree(prev_tree: CTree, prev_witnesses: &[Witness], mut commitments: &mut [Node]) -> (CTree, Vec<Witness>) {
|
fn advance_tree(
|
||||||
|
prev_tree: CTree,
|
||||||
|
prev_witnesses: &[Witness],
|
||||||
|
mut commitments: &mut [Node],
|
||||||
|
) -> (CTree, Vec<Witness>) {
|
||||||
if commitments.is_empty() {
|
if commitments.is_empty() {
|
||||||
return (prev_tree, prev_witnesses.to_vec());
|
return (prev_tree, prev_witnesses.to_vec());
|
||||||
}
|
}
|
||||||
let mut builder = CTreeBuilder::new(prev_tree);
|
let mut builder = CTreeBuilder::new(prev_tree);
|
||||||
let mut witness_builders: Vec<_> = prev_witnesses.iter().map(|witness| {
|
let mut witness_builders: Vec<_> = prev_witnesses
|
||||||
WitnessBuilder::new(&builder, witness.clone(), commitments.len())
|
.iter()
|
||||||
}).collect();
|
.map(|witness| WitnessBuilder::new(&builder, witness.clone(), commitments.len()))
|
||||||
|
.collect();
|
||||||
while !commitments.is_empty() || !builder.finished() {
|
while !commitments.is_empty() || !builder.finished() {
|
||||||
let n = builder.collect(commitments, &());
|
let n = builder.collect(commitments, &());
|
||||||
for b in witness_builders.iter_mut() {
|
for b in witness_builders.iter_mut() {
|
||||||
|
@ -225,49 +311,61 @@ fn advance_tree(prev_tree: CTree, prev_witnesses: &[Witness], mut commitments: &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let tree = builder.finalize();
|
let witnesses = witness_builders
|
||||||
let witnesses = witness_builders.into_iter().map(|b| b.finalize()).collect();
|
.into_iter()
|
||||||
|
.map(|b| b.finalize(&builder))
|
||||||
|
.collect();
|
||||||
|
let tree = builder.finalize(&());
|
||||||
(tree, witnesses)
|
(tree, witnesses)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(unused_imports)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::builder::{advance_tree, WitnessBuilder};
|
use crate::builder::advance_tree;
|
||||||
use crate::commitment::{CTree, Witness};
|
use crate::commitment::{CTree, Witness};
|
||||||
use zcash_primitives::sapling::Node;
|
use crate::print::{print_tree, print_witness};
|
||||||
use zcash_primitives::merkle_tree::{CommitmentTree, IncrementalWitness};
|
use zcash_primitives::merkle_tree::{CommitmentTree, IncrementalWitness};
|
||||||
use crate::print::{print_witness, print_tree};
|
use zcash_primitives::sapling::Node;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_advance_tree() {
|
fn test_advance_tree() {
|
||||||
const NUM_NODES: usize = 10;
|
const NUM_NODES: usize = 10;
|
||||||
const NUM_CHUNKS: usize = 10;
|
const NUM_CHUNKS: usize = 5;
|
||||||
|
const WITNESS_PERCENT: f64 = 100.0; // percentage of notes that are ours
|
||||||
|
const DEBUG_PRINT: bool = true;
|
||||||
|
let witness_freq = (100.0 / WITNESS_PERCENT) as usize;
|
||||||
|
|
||||||
let mut tree1: CommitmentTree<Node> = CommitmentTree::empty();
|
let mut tree1: CommitmentTree<Node> = CommitmentTree::empty();
|
||||||
let mut tree2 = CTree::new();
|
let mut tree2 = CTree::new();
|
||||||
let mut ws: Vec<IncrementalWitness<Node>> = vec![];
|
let mut ws: Vec<IncrementalWitness<Node>> = vec![];
|
||||||
let mut ws2: Vec<Witness> = vec![];
|
let mut ws2: Vec<Witness> = vec![];
|
||||||
for i in 0..NUM_CHUNKS {
|
for i in 0..NUM_CHUNKS {
|
||||||
let mut nodes: Vec<_> = (0..NUM_NODES).map(|k| {
|
let mut nodes: Vec<_> = vec![];
|
||||||
|
for j in 0..NUM_NODES {
|
||||||
let mut bb = [0u8; 32];
|
let mut bb = [0u8; 32];
|
||||||
let v = i*NUM_NODES + k;
|
let v = i * NUM_NODES + j;
|
||||||
bb[0..8].copy_from_slice(&v.to_be_bytes());
|
bb[0..8].copy_from_slice(&v.to_be_bytes());
|
||||||
let node = Node::new(bb);
|
let node = Node::new(bb);
|
||||||
tree1.append(node).unwrap();
|
tree1.append(node).unwrap();
|
||||||
for w in ws.iter_mut() {
|
for w in ws.iter_mut() {
|
||||||
w.append(node).unwrap();
|
w.append(node).unwrap();
|
||||||
}
|
}
|
||||||
if v == 55 {
|
// if v % witness_freq == 0 {
|
||||||
|
if v == 37 {
|
||||||
let w = IncrementalWitness::from_tree(&tree1);
|
let w = IncrementalWitness::from_tree(&tree1);
|
||||||
ws.push(w);
|
ws.push(w);
|
||||||
ws2.push(Witness::new(v));
|
ws2.push(Witness::new(v));
|
||||||
}
|
}
|
||||||
node
|
nodes.push(node);
|
||||||
}).collect();
|
}
|
||||||
|
|
||||||
let (new_tree, new_witnesses) = advance_tree(tree2, &ws2, &mut nodes);
|
let (new_tree, new_witnesses) = advance_tree(tree2, &ws2, &mut nodes);
|
||||||
tree2 = new_tree;
|
tree2 = new_tree;
|
||||||
ws2 = new_witnesses;
|
ws2 = new_witnesses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check final state
|
||||||
let mut bb1: Vec<u8> = vec![];
|
let mut bb1: Vec<u8> = vec![];
|
||||||
tree1.write(&mut bb1).unwrap();
|
tree1.write(&mut bb1).unwrap();
|
||||||
|
|
||||||
|
@ -276,25 +374,64 @@ mod tests {
|
||||||
|
|
||||||
let equal = bb1.as_slice() == bb2.as_slice();
|
let equal = bb1.as_slice() == bb2.as_slice();
|
||||||
|
|
||||||
print_tree(&ws[0].tree);
|
println!("# witnesses = {}", ws.len());
|
||||||
println!("-----");
|
|
||||||
|
|
||||||
let tree2 = &ws2[0].tree;
|
// check witnesses
|
||||||
|
let mut failed_index: Option<usize> = None;
|
||||||
|
for (i, (w1, w2)) in ws.iter().zip(&ws2).enumerate() {
|
||||||
|
let mut bb1: Vec<u8> = vec![];
|
||||||
|
w1.write(&mut bb1).unwrap();
|
||||||
|
|
||||||
// println!("{:?}", tree1.left.map(|n| hex::encode(n.repr)));
|
let mut bb2: Vec<u8> = vec![];
|
||||||
// println!("{:?}", tree1.right.map(|n| hex::encode(n.repr)));
|
w2.write(&mut bb2).unwrap();
|
||||||
// for p in tree1.parents.iter() {
|
|
||||||
// println!("{:?}", p.map(|n| hex::encode(n.repr)));
|
if bb1.as_slice() != bb2.as_slice() {
|
||||||
// }
|
failed_index = Some(i);
|
||||||
// println!("-----");
|
}
|
||||||
//
|
}
|
||||||
println!("{:?}", tree2.left.map(|n| hex::encode(n.repr)));
|
|
||||||
println!("{:?}", tree2.right.map(|n| hex::encode(n.repr)));
|
if DEBUG_PRINT && (failed_index.is_some() || !equal) {
|
||||||
for p in tree2.parents.iter() {
|
let i = failed_index.unwrap();
|
||||||
println!("{:?}", p.map(|n| hex::encode(n.repr)));
|
println!("FAILED AT {}", i);
|
||||||
|
print_witness(&ws[i]);
|
||||||
|
|
||||||
|
// println!("-----");
|
||||||
|
// println!("Final-----");
|
||||||
|
//
|
||||||
|
// println!("{:?}", tree2.left.map(|n| hex::encode(n.repr)));
|
||||||
|
// println!("{:?}", tree2.right.map(|n| hex::encode(n.repr)));
|
||||||
|
// for p in tree2.parents.iter() {
|
||||||
|
// println!("{:?}", p.map(|n| hex::encode(n.repr)));
|
||||||
|
// }
|
||||||
|
// println!("-----");
|
||||||
|
|
||||||
|
// println!("{:?}", tree1.left.map(|n| hex::encode(n.repr)));
|
||||||
|
// println!("{:?}", tree1.right.map(|n| hex::encode(n.repr)));
|
||||||
|
// for p in tree1.parents.iter() {
|
||||||
|
// println!("{:?}", p.map(|n| hex::encode(n.repr)));
|
||||||
|
// }
|
||||||
|
println!("----- {}", ws2[i].position);
|
||||||
|
let tree2 = &ws2[i].tree;
|
||||||
|
println!("{:?}", tree2.left.map(|n| hex::encode(n.repr)));
|
||||||
|
println!("{:?}", tree2.right.map(|n| hex::encode(n.repr)));
|
||||||
|
for p in tree2.parents.iter() {
|
||||||
|
println!("{:?}", p.map(|n| hex::encode(n.repr)));
|
||||||
|
}
|
||||||
|
println!("-----");
|
||||||
|
let filled2 = &ws2[i].filled;
|
||||||
|
println!("Filled");
|
||||||
|
for f in filled2.iter() {
|
||||||
|
println!("{:?}", hex::encode(f.repr));
|
||||||
|
}
|
||||||
|
println!("Cursor");
|
||||||
|
let cursor2 = &ws2[i].cursor;
|
||||||
|
println!("{:?}", cursor2.left.map(|n| hex::encode(n.repr)));
|
||||||
|
println!("{:?}", cursor2.right.map(|n| hex::encode(n.repr)));
|
||||||
|
for p in cursor2.parents.iter() {
|
||||||
|
println!("{:?}", p.map(|n| hex::encode(n.repr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(false);
|
||||||
}
|
}
|
||||||
println!("-----");
|
|
||||||
//
|
|
||||||
// assert!(equal, "not equal");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,10 +77,10 @@ gets pushed into `filled`.
|
||||||
*/
|
*/
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Witness {
|
pub struct Witness {
|
||||||
pub(crate) position: usize,
|
pub position: usize,
|
||||||
pub(crate) tree: CTree, // commitment tree at the moment the witness is created: immutable
|
pub tree: CTree, // commitment tree at the moment the witness is created: immutable
|
||||||
filled: Vec<Node>, // as more nodes are added, levels get filled up: won't change anymore
|
pub filled: Vec<Node>, // as more nodes are added, levels get filled up: won't change anymore
|
||||||
cursor: CTree, // partial tree which still updates when nodes are added
|
pub cursor: CTree, // partial tree which still updates when nodes are added
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Witness {
|
impl Witness {
|
||||||
|
@ -299,6 +299,10 @@ impl CTree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.left.is_none() && self.right.is_none()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
|
pub(crate) fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
|
||||||
Optional::write(&mut writer, &self.left, |w, n| n.write(w))?;
|
Optional::write(&mut writer, &self.left, |w, n| n.write(w))?;
|
||||||
Optional::write(&mut writer, &self.right, |w, n| n.write(w))?;
|
Optional::write(&mut writer, &self.right, |w, n| n.write(w))?;
|
||||||
|
@ -391,7 +395,7 @@ mod tests {
|
||||||
|
|
||||||
println!("# witnesses = {}", all_positions.len());
|
println!("# witnesses = {}", all_positions.len());
|
||||||
|
|
||||||
for (i, (w, p)) in witnesses.iter().zip(&all_positions).enumerate() {
|
for (_i, (w, p)) in witnesses.iter().zip(&all_positions).enumerate() {
|
||||||
let mut bb1: Vec<u8> = vec![];
|
let mut bb1: Vec<u8> = vec![];
|
||||||
w.write(&mut bb1).unwrap();
|
w.write(&mut bb1).unwrap();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue