ironfish_primitives/
merkle_tree.rs

1//! Implementation of a Merkle tree of commitments used to prove the existence of notes.
2
3use byteorder::{LittleEndian, ReadBytesExt};
4use incrementalmerkletree::{
5    self,
6    bridgetree::{self, Leaf},
7    Altitude,
8};
9use std::collections::VecDeque;
10use std::convert::TryFrom;
11use std::io::{self, Read, Write};
12use std::iter::repeat;
13use zcash_encoding::{Optional, Vector};
14
15use crate::sapling::SAPLING_COMMITMENT_TREE_DEPTH;
16
17pub mod incremental;
18
19/// A hashable node within a Merkle tree.
20pub trait Hashable: Clone + Copy {
21    /// Parses a node from the given byte source.
22    fn read<R: Read>(reader: R) -> io::Result<Self>;
23
24    /// Serializes this node.
25    fn write<W: Write>(&self, writer: W) -> io::Result<()>;
26
27    /// Returns the parent node within the tree of the two given nodes.
28    fn combine(_: usize, _: &Self, _: &Self) -> Self;
29
30    /// Returns a blank leaf node.
31    fn blank() -> Self;
32
33    /// Returns the empty root for the given depth.
34    fn empty_root(_: usize) -> Self;
35}
36
37/// A hashable node within a Merkle tree.
38pub trait HashSer {
39    /// Parses a node from the given byte source.
40    fn read<R: Read>(reader: R) -> io::Result<Self>
41    where
42        Self: Sized;
43
44    /// Serializes this node.
45    fn write<W: Write>(&self, writer: W) -> io::Result<()>;
46}
47
48impl<T> Hashable for T
49where
50    T: incrementalmerkletree::Hashable + HashSer + Copy,
51{
52    /// Parses a node from the given byte source.
53    fn read<R: Read>(reader: R) -> io::Result<Self> {
54        <Self as HashSer>::read(reader)
55    }
56
57    /// Serializes this node.
58    fn write<W: Write>(&self, writer: W) -> io::Result<()> {
59        <Self as HashSer>::write(self, writer)
60    }
61
62    /// Returns the parent node within the tree of the two given nodes.
63    fn combine(alt: usize, lhs: &Self, rhs: &Self) -> Self {
64        <Self as incrementalmerkletree::Hashable>::combine(
65            Altitude::from(
66                u8::try_from(alt).expect("Tree heights greater than 255 are unsupported."),
67            ),
68            lhs,
69            rhs,
70        )
71    }
72
73    /// Returns a blank leaf node.
74    fn blank() -> Self {
75        <Self as incrementalmerkletree::Hashable>::empty_leaf()
76    }
77
78    /// Returns the empty root for the given depth.
79    fn empty_root(alt: usize) -> Self {
80        <Self as incrementalmerkletree::Hashable>::empty_root(Altitude::from(
81            u8::try_from(alt).expect("Tree heights greater than 255 are unsupported."),
82        ))
83    }
84}
85
86struct PathFiller<Node: Hashable> {
87    queue: VecDeque<Node>,
88}
89
90impl<Node: Hashable> PathFiller<Node> {
91    fn empty() -> Self {
92        PathFiller {
93            queue: VecDeque::new(),
94        }
95    }
96
97    fn next(&mut self, depth: usize) -> Node {
98        self.queue
99            .pop_front()
100            .unwrap_or_else(|| Node::empty_root(depth))
101    }
102}
103
104/// A Merkle tree of note commitments.
105///
106/// The depth of the Merkle tree is fixed at 32, equal to the depth of the Sapling
107/// commitment tree.
108#[derive(Clone, Debug, PartialEq, Eq)]
109pub struct CommitmentTree<Node> {
110    pub(crate) left: Option<Node>,
111    pub(crate) right: Option<Node>,
112    pub(crate) parents: Vec<Option<Node>>,
113}
114
115impl<Node> CommitmentTree<Node> {
116    /// Creates an empty tree.
117    pub fn empty() -> Self {
118        CommitmentTree {
119            left: None,
120            right: None,
121            parents: vec![],
122        }
123    }
124
125    pub fn from_frontier<const DEPTH: u8>(frontier: &bridgetree::Frontier<Node, DEPTH>) -> Self
126    where
127        Node: Clone,
128    {
129        frontier.value().map_or_else(Self::empty, |f| {
130            let (left, right) = match f.leaf() {
131                Leaf::Left(v) => (Some(v.clone()), None),
132                Leaf::Right(l, r) => (Some(l.clone()), Some(r.clone())),
133            };
134            let mut ommers_iter = f.ommers().iter().cloned();
135            let upos: usize = f.position().into();
136            Self {
137                left,
138                right,
139                parents: (1..DEPTH)
140                    .into_iter()
141                    .map(|i| {
142                        if upos & (1 << i) == 0 {
143                            None
144                        } else {
145                            ommers_iter.next()
146                        }
147                    })
148                    .collect(),
149            }
150        })
151    }
152
153    pub fn to_frontier<const DEPTH: u8>(&self) -> bridgetree::Frontier<Node, DEPTH>
154    where
155        Node: incrementalmerkletree::Hashable + Clone,
156    {
157        if self.size() == 0 {
158            bridgetree::Frontier::empty()
159        } else {
160            let leaf = match (self.left.as_ref(), self.right.as_ref()) {
161                (Some(a), None) => bridgetree::Leaf::Left(a.clone()),
162                (Some(a), Some(b)) => bridgetree::Leaf::Right(a.clone(), b.clone()),
163                _ => unreachable!(),
164            };
165
166            let ommers = self
167                .parents
168                .iter()
169                .filter_map(|v| v.as_ref())
170                .cloned()
171                .collect();
172
173            // If a frontier cannot be successfully constructed from the
174            // parts of a commitment tree, it is a programming error.
175            bridgetree::Frontier::from_parts((self.size() - 1).into(), leaf, ommers)
176                .expect("Frontier should be constructable from CommitmentTree.")
177        }
178    }
179
180    /// Returns the number of leaf nodes in the tree.
181    pub fn size(&self) -> usize {
182        self.parents.iter().enumerate().fold(
183            match (self.left.as_ref(), self.right.as_ref()) {
184                (None, None) => 0,
185                (Some(_), None) => 1,
186                (Some(_), Some(_)) => 2,
187                (None, Some(_)) => unreachable!(),
188            },
189            |acc, (i, p)| {
190                // Treat occupation of parents array as a binary number
191                // (right-shifted by 1)
192                acc + if p.is_some() { 1 << (i + 1) } else { 0 }
193            },
194        )
195    }
196
197    fn is_complete(&self, depth: usize) -> bool {
198        if depth == 0 {
199            self.left.is_some() && self.right.is_none() && self.parents.is_empty()
200        } else {
201            self.left.is_some()
202                && self.right.is_some()
203                && self
204                    .parents
205                    .iter()
206                    .chain(repeat(&None))
207                    .take(depth - 1)
208                    .all(|p| p.is_some())
209        }
210    }
211}
212
213impl<Node: Hashable> CommitmentTree<Node> {
214    /// Reads a `CommitmentTree` from its serialized form.
215    pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
216        let left = Optional::read(&mut reader, Node::read)?;
217        let right = Optional::read(&mut reader, Node::read)?;
218        let parents = Vector::read(&mut reader, |r| Optional::read(r, Node::read))?;
219
220        Ok(CommitmentTree {
221            left,
222            right,
223            parents,
224        })
225    }
226
227    /// Serializes this tree as an array of bytes.
228    pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
229        Optional::write(&mut writer, self.left, |w, n| n.write(w))?;
230        Optional::write(&mut writer, self.right, |w, n| n.write(w))?;
231        Vector::write(&mut writer, &self.parents, |w, e| {
232            Optional::write(w, *e, |w, n| n.write(w))
233        })
234    }
235
236    /// Adds a leaf node to the tree.
237    ///
238    /// Returns an error if the tree is full.
239    pub fn append(&mut self, node: Node) -> Result<(), ()> {
240        self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH)
241    }
242
243    fn append_inner(&mut self, node: Node, depth: usize) -> Result<(), ()> {
244        if self.is_complete(depth) {
245            // Tree is full
246            return Err(());
247        }
248
249        match (self.left, self.right) {
250            (None, _) => self.left = Some(node),
251            (_, None) => self.right = Some(node),
252            (Some(l), Some(r)) => {
253                let mut combined = Node::combine(0, &l, &r);
254                self.left = Some(node);
255                self.right = None;
256
257                for i in 0..depth {
258                    if i < self.parents.len() {
259                        if let Some(p) = self.parents[i] {
260                            combined = Node::combine(i + 1, &p, &combined);
261                            self.parents[i] = None;
262                        } else {
263                            self.parents[i] = Some(combined);
264                            break;
265                        }
266                    } else {
267                        self.parents.push(Some(combined));
268                        break;
269                    }
270                }
271            }
272        }
273
274        Ok(())
275    }
276
277    /// Returns the current root of the tree.
278    pub fn root(&self) -> Node {
279        self.root_inner(SAPLING_COMMITMENT_TREE_DEPTH, PathFiller::empty())
280    }
281
282    fn root_inner(&self, depth: usize, mut filler: PathFiller<Node>) -> Node {
283        assert!(depth > 0);
284
285        // 1) Hash left and right leaves together.
286        //    - Empty leaves are used as needed.
287        let leaf_root = Node::combine(
288            0,
289            &self.left.unwrap_or_else(|| filler.next(0)),
290            &self.right.unwrap_or_else(|| filler.next(0)),
291        );
292
293        // 2) Extend the parents to the desired depth with None values, then hash from leaf to
294        //    root. Roots of the empty subtrees are used as needed.
295        self.parents
296            .iter()
297            .chain(repeat(&None))
298            .take(depth - 1)
299            .enumerate()
300            .fold(leaf_root, |root, (i, p)| match p {
301                Some(node) => Node::combine(i + 1, node, &root),
302                None => Node::combine(i + 1, &root, &filler.next(i + 1)),
303            })
304    }
305}
306
307/// An updatable witness to a path from a position in a particular [`CommitmentTree`].
308///
309/// Appending the same commitments in the same order to both the original
310/// [`CommitmentTree`] and this `IncrementalWitness` will result in a witness to the path
311/// from the target position to the root of the updated tree.
312///
313/// # Examples
314///
315/// ```
316/// use ff::{Field, PrimeField};
317/// use rand_core::OsRng;
318/// use ironfish_primitives::{
319///     merkle_tree::{CommitmentTree, IncrementalWitness},
320///     sapling::Node,
321/// };
322///
323/// let mut rng = OsRng;
324///
325/// let mut tree = CommitmentTree::<Node>::empty();
326///
327/// tree.append(Node::new(blstrs::Scalar::random(&mut rng).to_repr()));
328/// tree.append(Node::new(blstrs::Scalar::random(&mut rng).to_repr()));
329/// let mut witness = IncrementalWitness::from_tree(&tree);
330/// assert_eq!(witness.position(), 1);
331/// assert_eq!(tree.root(), witness.root());
332///
333/// let cmu = Node::new(blstrs::Scalar::random(&mut rng).to_repr());
334/// tree.append(cmu);
335/// witness.append(cmu);
336/// assert_eq!(tree.root(), witness.root());
337/// ```
338#[derive(Clone)]
339pub struct IncrementalWitness<Node: Hashable> {
340    tree: CommitmentTree<Node>,
341    filled: Vec<Node>,
342    cursor_depth: usize,
343    cursor: Option<CommitmentTree<Node>>,
344}
345
346impl<Node: Hashable> IncrementalWitness<Node> {
347    /// Creates an `IncrementalWitness` for the most recent commitment added to the given
348    /// [`CommitmentTree`].
349    pub fn from_tree(tree: &CommitmentTree<Node>) -> IncrementalWitness<Node> {
350        IncrementalWitness {
351            tree: tree.clone(),
352            filled: vec![],
353            cursor_depth: 0,
354            cursor: None,
355        }
356    }
357
358    /// Reads an `IncrementalWitness` from its serialized form.
359    #[allow(clippy::redundant_closure)]
360    pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
361        let tree = CommitmentTree::read(&mut reader)?;
362        let filled = Vector::read(&mut reader, |r| Node::read(r))?;
363        let cursor = Optional::read(&mut reader, CommitmentTree::read)?;
364
365        let mut witness = IncrementalWitness {
366            tree,
367            filled,
368            cursor_depth: 0,
369            cursor,
370        };
371
372        witness.cursor_depth = witness.next_depth();
373
374        Ok(witness)
375    }
376
377    /// Serializes this `IncrementalWitness` as an array of bytes.
378    pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
379        self.tree.write(&mut writer)?;
380        Vector::write(&mut writer, &self.filled, |w, n| n.write(w))?;
381        Optional::write(&mut writer, self.cursor.as_ref(), |w, t| t.write(w))
382    }
383
384    /// Returns the position of the witnessed leaf node in the commitment tree.
385    pub fn position(&self) -> usize {
386        self.tree.size() - 1
387    }
388
389    fn filler(&self) -> PathFiller<Node> {
390        let cursor_root = self
391            .cursor
392            .as_ref()
393            .map(|c| c.root_inner(self.cursor_depth, PathFiller::empty()));
394
395        PathFiller {
396            queue: self.filled.iter().cloned().chain(cursor_root).collect(),
397        }
398    }
399
400    /// Finds the next "depth" of an unfilled subtree.
401    fn next_depth(&self) -> usize {
402        let mut skip = self.filled.len();
403
404        if self.tree.left.is_none() {
405            if skip > 0 {
406                skip -= 1;
407            } else {
408                return 0;
409            }
410        }
411
412        if self.tree.right.is_none() {
413            if skip > 0 {
414                skip -= 1;
415            } else {
416                return 0;
417            }
418        }
419
420        let mut d = 1;
421        for p in &self.tree.parents {
422            if p.is_none() {
423                if skip > 0 {
424                    skip -= 1;
425                } else {
426                    return d;
427                }
428            }
429            d += 1;
430        }
431
432        d + skip
433    }
434
435    /// Tracks a leaf node that has been added to the underlying tree.
436    ///
437    /// Returns an error if the tree is full.
438    pub fn append(&mut self, node: Node) -> Result<(), ()> {
439        self.append_inner(node, SAPLING_COMMITMENT_TREE_DEPTH)
440    }
441
442    fn append_inner(&mut self, node: Node, depth: usize) -> Result<(), ()> {
443        if let Some(mut cursor) = self.cursor.take() {
444            cursor
445                .append_inner(node, depth)
446                .expect("cursor should not be full");
447            if cursor.is_complete(self.cursor_depth) {
448                self.filled
449                    .push(cursor.root_inner(self.cursor_depth, PathFiller::empty()));
450            } else {
451                self.cursor = Some(cursor);
452            }
453        } else {
454            self.cursor_depth = self.next_depth();
455            if self.cursor_depth >= depth {
456                // Tree is full
457                return Err(());
458            }
459
460            if self.cursor_depth == 0 {
461                self.filled.push(node);
462            } else {
463                let mut cursor = CommitmentTree::empty();
464                cursor
465                    .append_inner(node, depth)
466                    .expect("cursor should not be full");
467                self.cursor = Some(cursor);
468            }
469        }
470
471        Ok(())
472    }
473
474    /// Returns the current root of the tree corresponding to the witness.
475    pub fn root(&self) -> Node {
476        self.root_inner(SAPLING_COMMITMENT_TREE_DEPTH)
477    }
478
479    fn root_inner(&self, depth: usize) -> Node {
480        self.tree.root_inner(depth, self.filler())
481    }
482
483    /// Returns the current witness, or None if the tree is empty.
484    pub fn path(&self) -> Option<MerklePath<Node>> {
485        self.path_inner(SAPLING_COMMITMENT_TREE_DEPTH)
486    }
487
488    fn path_inner(&self, depth: usize) -> Option<MerklePath<Node>> {
489        let mut filler = self.filler();
490        let mut auth_path = Vec::new();
491
492        if let Some(node) = self.tree.left {
493            if self.tree.right.is_some() {
494                auth_path.push((node, true));
495            } else {
496                auth_path.push((filler.next(0), false));
497            }
498        } else {
499            // Can't create an authentication path for the beginning of the tree
500            return None;
501        }
502
503        for (i, p) in self
504            .tree
505            .parents
506            .iter()
507            .chain(repeat(&None))
508            .take(depth - 1)
509            .enumerate()
510        {
511            auth_path.push(match p {
512                Some(node) => (*node, true),
513                None => (filler.next(i + 1), false),
514            });
515        }
516
517        assert_eq!(auth_path.len(), depth);
518
519        Some(MerklePath::from_path(auth_path, self.position() as u64))
520    }
521}
522
523/// A path from a position in a particular commitment tree to the root of that tree.
524#[derive(Clone, Debug, PartialEq)]
525pub struct MerklePath<Node: Hashable> {
526    pub auth_path: Vec<(Node, bool)>,
527    pub position: u64,
528}
529
530impl<Node: Hashable> MerklePath<Node> {
531    /// Constructs a Merkle path directly from a path and position.
532    pub fn from_path(auth_path: Vec<(Node, bool)>, position: u64) -> Self {
533        MerklePath {
534            auth_path,
535            position,
536        }
537    }
538
539    /// Reads a Merkle path from its serialized form.
540    pub fn from_slice(witness: &[u8]) -> Result<Self, ()> {
541        Self::from_slice_with_depth(witness, SAPLING_COMMITMENT_TREE_DEPTH)
542    }
543
544    fn from_slice_with_depth(mut witness: &[u8], depth: usize) -> Result<Self, ()> {
545        // Skip the first byte, which should be "depth" to signify the length of
546        // the following vector of Pedersen hashes.
547        if witness[0] != depth as u8 {
548            return Err(());
549        }
550        witness = &witness[1..];
551
552        // Begin to construct the authentication path
553        let iter = witness.chunks_exact(33);
554        witness = iter.remainder();
555
556        // The vector works in reverse
557        let mut auth_path = iter
558            .rev()
559            .map(|bytes| {
560                // Length of inner vector should be the length of a Pedersen hash
561                if bytes[0] == 32 {
562                    // Sibling node should be an element of Fr
563                    Node::read(&bytes[1..])
564                        .map(|sibling| {
565                            // Set the value in the auth path; we put false here
566                            // for now (signifying the position bit) which we'll
567                            // fill in later.
568                            (sibling, false)
569                        })
570                        .map_err(|_| ())
571                } else {
572                    Err(())
573                }
574            })
575            .collect::<Result<Vec<_>, _>>()?;
576        if auth_path.len() != depth {
577            return Err(());
578        }
579
580        // Read the position from the witness
581        let position = witness.read_u64::<LittleEndian>().map_err(|_| ())?;
582
583        // Given the position, let's finish constructing the authentication
584        // path
585        let mut tmp = position;
586        for entry in auth_path.iter_mut() {
587            entry.1 = (tmp & 1) == 1;
588            tmp >>= 1;
589        }
590
591        // The witness should be empty now; if it wasn't, the caller would
592        // have provided more information than they should have, indicating
593        // a bug downstream
594        if witness.is_empty() {
595            Ok(MerklePath {
596                auth_path,
597                position,
598            })
599        } else {
600            Err(())
601        }
602    }
603
604    /// Returns the root of the tree corresponding to this path applied to `leaf`.
605    pub fn root(&self, leaf: Node) -> Node {
606        self.auth_path
607            .iter()
608            .enumerate()
609            .fold(
610                leaf,
611                |root, (i, (p, leaf_is_on_right))| match leaf_is_on_right {
612                    false => Node::combine(i, &root, p),
613                    true => Node::combine(i, p, &root),
614                },
615            )
616    }
617}
618
619#[cfg(test)]
620mod tests {
621    use incrementalmerkletree::bridgetree::Frontier;
622    use proptest::prelude::*;
623    use std::convert::TryInto;
624    use std::io::{self, Read, Write};
625
626    use crate::sapling::{testing::arb_node, Node};
627
628    use super::{
629        testing::{arb_commitment_tree, TestNode},
630        CommitmentTree, Hashable, IncrementalWitness, MerklePath, PathFiller,
631    };
632
633    const HEX_EMPTY_ROOTS: [&str; 33] = [
634        "0100000000000000000000000000000000000000000000000000000000000000",
635        "817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca155",
636        "ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e34",
637        "d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c",
638        "e110de65c907b9dea4ae0bd83a4b0a51bea175646a64c12b4c9f931b2cb31b49",
639        "912d82b2c2bca231f71efcf61737fbf0a08befa0416215aeef53e8bb6d23390a",
640        "8ac9cf9c391e3fd42891d27238a81a8a5c1d3a72b1bcbea8cf44a58ce7389613",
641        "d6c639ac24b46bd19341c91b13fdcab31581ddaf7f1411336a271f3d0aa52813",
642        "7b99abdc3730991cc9274727d7d82d28cb794edbc7034b4f0053ff7c4b680444",
643        "43ff5457f13b926b61df552d4e402ee6dc1463f99a535f9a713439264d5b616b",
644        "ba49b659fbd0b7334211ea6a9d9df185c757e70aa81da562fb912b84f49bce72",
645        "4777c8776a3b1e69b73a62fa701fa4f7a6282d9aee2c7a6b82e7937d7081c23c",
646        "ec677114c27206f5debc1c1ed66f95e2b1885da5b7be3d736b1de98579473048",
647        "1b77dac4d24fb7258c3c528704c59430b630718bec486421837021cf75dab651",
648        "bd74b25aacb92378a871bf27d225cfc26baca344a1ea35fdd94510f3d157082c",
649        "d6acdedf95f608e09fa53fb43dcd0990475726c5131210c9e5caeab97f0e642f",
650        "1ea6675f9551eeb9dfaaa9247bc9858270d3d3a4c5afa7177a984d5ed1be2451",
651        "6edb16d01907b759977d7650dad7e3ec049af1a3d875380b697c862c9ec5d51c",
652        "cd1c8dbf6e3acc7a80439bc4962cf25b9dce7c896f3a5bd70803fc5a0e33cf00",
653        "6aca8448d8263e547d5ff2950e2ed3839e998d31cbc6ac9fd57bc6002b159216",
654        "8d5fa43e5a10d11605ac7430ba1f5d81fb1b68d29a640405767749e841527673",
655        "08eeab0c13abd6069e6310197bf80f9c1ea6de78fd19cbae24d4a520e6cf3023",
656        "0769557bc682b1bf308646fd0b22e648e8b9e98f57e29f5af40f6edb833e2c49",
657        "4c6937d78f42685f84b43ad3b7b00f81285662f85c6a68ef11d62ad1a3ee0850",
658        "fee0e52802cb0c46b1eb4d376c62697f4759f6c8917fa352571202fd778fd712",
659        "16d6252968971a83da8521d65382e61f0176646d771c91528e3276ee45383e4a",
660        "d2e1642c9a462229289e5b0e3b7f9008e0301cbb93385ee0e21da2545073cb58",
661        "a5122c08ff9c161d9ca6fc462073396c7d7d38e8ee48cdb3bea7e2230134ed6a",
662        "28e7b841dcbc47cceb69d7cb8d94245fb7cb2ba3a7a6bc18f13f945f7dbd6e2a",
663        "e1f34b034d4a3cd28557e2907ebf990c918f64ecb50a94f01d6fda5ca5c7ef72",
664        "12935f14b676509b81eb49ef25f39269ed72309238b4c145803544b646dca62d",
665        "b2eed031d4d6a4f02a097f80b54cc1541d4163c6b6f5971f88b6e41d35c53814",
666        "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e",
667    ];
668
669    const TESTING_DEPTH: usize = 4;
670
671    struct TestCommitmentTree(CommitmentTree<Node>);
672
673    impl TestCommitmentTree {
674        fn new() -> Self {
675            TestCommitmentTree(CommitmentTree::empty())
676        }
677
678        pub fn read<R: Read>(reader: R) -> io::Result<Self> {
679            let tree = CommitmentTree::read(reader)?;
680            Ok(TestCommitmentTree(tree))
681        }
682
683        pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
684            self.0.write(writer)
685        }
686
687        fn size(&self) -> usize {
688            self.0.size()
689        }
690
691        fn append(&mut self, node: Node) -> Result<(), ()> {
692            self.0.append_inner(node, TESTING_DEPTH)
693        }
694
695        fn root(&self) -> Node {
696            self.0.root_inner(TESTING_DEPTH, PathFiller::empty())
697        }
698    }
699
700    struct TestIncrementalWitness(IncrementalWitness<Node>);
701
702    impl TestIncrementalWitness {
703        fn from_tree(tree: &TestCommitmentTree) -> Self {
704            TestIncrementalWitness(IncrementalWitness::from_tree(&tree.0))
705        }
706
707        pub fn read<R: Read>(reader: R) -> io::Result<Self> {
708            let witness = IncrementalWitness::read(reader)?;
709            Ok(TestIncrementalWitness(witness))
710        }
711
712        pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
713            self.0.write(writer)
714        }
715
716        fn append(&mut self, node: Node) -> Result<(), ()> {
717            self.0.append_inner(node, TESTING_DEPTH)
718        }
719
720        fn root(&self) -> Node {
721            self.0.root_inner(TESTING_DEPTH)
722        }
723
724        fn path(&self) -> Option<MerklePath<Node>> {
725            self.0.path_inner(TESTING_DEPTH)
726        }
727    }
728
729    #[test]
730    fn empty_root_test_vectors() {
731        let mut tmp = [0u8; 32];
732        for (i, &expected) in HEX_EMPTY_ROOTS.iter().enumerate() {
733            Node::empty_root(i)
734                .write(&mut tmp[..])
735                .expect("length is 32 bytes");
736            assert_eq!(hex::encode(tmp), expected);
737        }
738    }
739
740    #[test]
741    fn sapling_empty_root() {
742        let mut tmp = [0u8; 32];
743        CommitmentTree::<Node>::empty()
744            .root()
745            .write(&mut tmp[..])
746            .expect("length is 32 bytes");
747        assert_eq!(
748            hex::encode(tmp),
749            "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e"
750        );
751    }
752
753    #[test]
754    fn empty_commitment_tree_roots() {
755        let tree = CommitmentTree::<Node>::empty();
756        let mut tmp = [0u8; 32];
757        for (i, &expected) in HEX_EMPTY_ROOTS.iter().enumerate().skip(1) {
758            tree.root_inner(i, PathFiller::empty())
759                .write(&mut tmp[..])
760                .expect("length is 32 bytes");
761            assert_eq!(hex::encode(tmp), expected);
762        }
763    }
764
765    #[test]
766    fn test_sapling_tree() {
767        // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_commitments_sapling.json
768        // Byte-reversed because the original test vectors are loaded using uint256S()
769        let commitments = [
770            "b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55",
771            "225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458",
772            "7c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c",
773            "50421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030",
774            "aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12",
775            "f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02",
776            "bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e",
777            "da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a511",
778            "3a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f77446",
779            "c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008",
780            "f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702",
781            "e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c608",
782            "8cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e826",
783            "22fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03",
784            "f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c",
785            "3a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac15",
786        ];
787
788        // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_roots_sapling.json
789        let roots = [
790            "8c3daa300c9710bf24d2595536e7c80ff8d147faca726636d28e8683a0c27703",
791            "8611f17378eb55e8c3c3f0a5f002e2b0a7ca39442fc928322b8072d1079c213d",
792            "3db73b998d536be0e1c2ec124df8e0f383ae7b602968ff6a5276ca0695023c46",
793            "7ac2e6442fec5970e116dfa4f2ee606f395366cafb1fa7dfd6c3de3ce18c4363",
794            "6a8f11ab2a11c262e39ed4ea3825ae6c94739ccf94479cb69402c5722b034532",
795            "149595eed0b54a7e694cc8a68372525b9ae2c7b102514f527460db91eb690565",
796            "8c0432f1994a2381a7a4b5fda770336011f9e0b30784f9a5597901619c797045",
797            "e780c48d70420601f3313ff8488d7766b70c059c53aa3cda2ff1ef57ff62383c",
798            "f919f03caaed8a2c60f58c0d43838f83e670dc7e8ccd25daa04a13f3e8f45541",
799            "74f32b36629724038e71cbd6823b5a666440205a7d1a9242e95870b53d81f34a",
800            "a4af205a4e1ee02102866b23a68930ac33efda9235832f49b17fcc4939be4525",
801            "a946a42f1636045a16e65b2308e036d9da70089686c87c692e45912bd1cab772",
802            "a1db2dbac055364c1cb43cbeb49c7e2815bff855122602a2ad0fb981a91e0e39",
803            "16329b3ba4f0640f4d306532d9ea6ba0fbf0e70e44ed57d27b4277ed9cda6849",
804            "7b6523b2d9b23f72fec6234aa6a1f8fae3dba1c6a266023ea8b1826feba7a25c",
805            "5c0bea7e17bde5bee4eb795c2eec3d389a68da587b36dd687b134826ecc09308",
806        ];
807
808        // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_serialization_sapling.json
809        let tree_ser = [
810            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550000",
811            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145800",
812            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666",
813            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666",
814            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564",
815            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564",
816            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564",
817            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564",
818            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
819            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
820            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
821            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
822            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
823            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
824            "01f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0003015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
825            "01f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c013a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac1503015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d",
826        ];
827
828        // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_path_sapling.json
829        let paths = [
830            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
831            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342037b3a0921a4047e617bde62b8958f86c010e6af6cc650959b9f50af8c7e8392620225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
832            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342037b3a0921a4047e617bde62b8958f86c010e6af6cc650959b9f50af8c7e8392620b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
833            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
834            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
835            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
836            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f1740220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
837            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f1740220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
838            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f174022062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
839            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2031d39685384e4ea322594d99a15aa8bdd8cc5cd6724410fa385b8d5447f174022062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
840            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c157320f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
841            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c157320f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
842            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c15732062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
843            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20f0321eea8e13c2f3a567f894c9738759d9d01e64ec259caf2cecca61374c15732062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
844            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
845            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d32220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
846            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d32220f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
847            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d3222062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
848            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c2082c424de0185a63f6ce0aa65d3d55890748af44bb4bb5822a9a21df34546d3222062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
849            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564206ab2e08286c36f6fe4374baebdc28b97e2f1f4ea3544fafd8a6489f42824bf0e20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
850            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564206ab2e08286c36f6fe4374baebdc28b97e2f1f4ea3544fafd8a6489f42824bf0e20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
851            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
852            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
853            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
854            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
855            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
856            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
857            "0420d8283386ef2ef07ebdbb4383c12a739a953a4d6e0d6fb1139a4036d693bfbb6c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
858            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
859            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
860            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
861            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d5573120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
862            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
863            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
864            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
865            "0420109713c6c346ab0b17904ae18d101d92a98a612116a3f787043c802b55d55731201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
866            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
867            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
868            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
869            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af54220130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
870            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
871            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
872            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
873            "0420bced38e720c8eab9b3b8b2959e5a8b8dda2b2537f6ea71c8e2aea8834a9af542201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
874            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca15520c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
875            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
876            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
877            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
878            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
879            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
880            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
881            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
882            "042094d3061a43d999e95bab82684aeb53d0a381b40e33a80abfc5c05e25b0a91d0f201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
883            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342076bd791f7708c0b6f5a348d574032e07ce3b1929daae19530346f5de955d543c20c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
884            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e342076bd791f7708c0b6f5a348d574032e07ce3b1929daae19530346f5de955d543c203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000",
885            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
886            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
887            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
888            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
889            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
890            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
891            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
892            "042061ae87cb694e8237accda801c8271a8a9d4ffc2581aebf923f5227f24c6bb92a201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
893            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
894            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000",
895            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20ffe9fc03f18b176c998806439ff0bb8ad193afdb27b2ccbc88856916dd804e3420cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000",
896            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
897            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
898            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
899            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e1820130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
900            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
901            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
902            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
903            "04208850438b439403c52a62aa6c81280ce5ea92bc5ff899ada6933c6afddc882e18201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
904            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
905            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000",
906            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000",
907            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20130266c8ace013b416e56be57600a9da16e136df92231a964613e2885cce756620cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000",
908            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
909            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
910            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
911            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac7120130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
912            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
913            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
914            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
915            "0420c9cd5269cd697706cb0745d57f66e5ba4a5051fb910127318d283f751910ac71201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
916            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
917            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000",
918            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000",
919            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20c2b786e4ab72ae4f01c7241bc056817b19d42bc85107f42c3fd3a9b9e98f156420cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000",
920            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c20817de36ab2d57feb077634bca77819c8e0bd298c04f6fed0e6a83cc1356ca1552022fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030c00000000000000",
921            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
922            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
923            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
924            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
925            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
926            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
927            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
928            "04203cf9ea50bea2cebf829213d91c098813d11dbe5c6696cdaefab3249dbf892f5e201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
929            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
930            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000",
931            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000",
932            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20cd6db4bcd77d6ca695b9579f9ec5791d106f83b69118bb3a2a2a99f63779e06720cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000",
933            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c2045d573e80606a552974215e13b5d3e7b4dd8675c77b8d612d293475ee139b9472022fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030c00000000000000",
934            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c2045d573e80606a552974215e13b5d3e7b4dd8675c77b8d612d293475ee139b947208cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260d00000000000000",
935            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580000000000000000",
936            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2420f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826420b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f550100000000000000",
937            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6662050421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300200000000000000",
938            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c20130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f242062324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666207c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0300000000000000",
939            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020400000000000000",
940            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c20aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120500000000000000",
941            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110600000000000000",
942            "04201d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c201fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656420eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd72420bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0700000000000000",
943            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614420c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080800000000000000",
944            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144203a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460900000000000000",
945            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080a00000000000000",
946            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394020cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173220f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020b00000000000000",
947            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c20afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a5322022fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030c00000000000000",
948            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c20afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a532208cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260d00000000000000",
949            "04200d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d20002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c205991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349203a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac150e00000000000000",
950        ];
951
952        // From https://github.com/zcash/zcash/blob/master/src/test/data/merkle_witness_serialization_sapling.json
953        let witness_ser = [
954            "00000001b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5500",
955            "00000002b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145800",
956            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000001225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145800",
957            "00000002b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145801017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0000",
958            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000001225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b1145801017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0000",
959            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458000001017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0000",
960            "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826400",
961            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826400",
962            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a826400",
963            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a03000",
964            "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000",
965            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000",
966            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000",
967            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000",
968            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666000101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc120000",
969            "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200",
970            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200",
971            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200",
972            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200",
973            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666000101aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200",
974            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a0200",
975            "00000003b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724",
976            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000002225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724",
977            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580001f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a82640101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724",
978            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a0300101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724",
979            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e666000101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000101eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724",
980            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0000",
981            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e0000",
982            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400",
983            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400",
984            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400",
985            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400",
986            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2400",
987            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c00",
988            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c00",
989            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51100",
990            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
991            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
992            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
993            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
994            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
995            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
996            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
997            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
998            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f774460000",
999            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1000            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1001            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1002            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1003            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1004            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1005            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1006            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1007            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1008            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f16300800",
1009            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1010            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1011            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1012            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1013            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1014            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1015            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1016            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1017            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1018            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f1630080101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020000",
1019            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d000101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c37020000",
1020            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1021            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1022            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1023            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1024            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1025            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1026            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1027            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1028            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef31732",
1029            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614400",
1030            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614400",
1031            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c60800",
1032            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1033            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1034            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1035            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1036            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1037            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1038            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1039            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1040            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1041            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000",
1042            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000",
1043            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c60801018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000",
1044            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260000",
1045            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1046            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1047            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1048            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1049            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f2401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1050            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1051            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c01018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1052            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a51101018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1053            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f6551865640001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03020001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1054            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300",
1055            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b614401018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300",
1056            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c60801018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300",
1057            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0001018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300",
1058            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c0300",
1059            "00000004b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1060            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000003225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1061            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580002f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1062            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660250421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1063            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66601130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f240101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1064            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1065            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c0101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1066            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656401da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1067            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564000101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0002015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c",
1068            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b61440101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349",
1069            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b61440101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349",
1070            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349",
1071            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d000101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0001015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c349",
1072            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c030101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0000",
1073            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d000101f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0000",
1074            "00000005b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1075            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f55000004225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b11458f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1076            "01b02310f2e087e55bfd07ef5e242e3b87ee5d00c9ab52f61e6bd42542f93a6f5501225747f3b5d5dab4e5a424f81f85c904ff43286e0f3fd07ef0b8c6a627b114580003f2c6ff34520c4ed63159b5ad4e99712fe64e3b4add73c66218e9797ac15a8264130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1077            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c00010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e6660350421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1078            "017c3ea01a6e3a3d90cf59cd789e467044b5cd78eb2c84cc6816f960746d0e036c0150421d6c2c94571dfaaa135a4ff15bf916681ebd62c0e43e69e3b90684d0a030010162324ff2c329e99193a74d28a585a3c167a93bf41a255135529c913bd9b1e66602130adab3afe0931c42f058efb1381c2dce6cc768ad7964330146bf88b2b34f241d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1079            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc12000200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656403f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a02d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c1d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1080            "01aaec63863aaa0b2e3b8009429bdddd455e59be6f40ccab887a32eb98723efc1201f76748d40d5ee5f9a608512e7954dd515f86e8f6d009141c89163de1cf351a020200011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402d0c26e22b78df58552b4fd61e8883a70f9011556b2e14b80ff23c591db7dbc4c1d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1081            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e000201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f65518656402da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5111d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1082            "01bc8a5ec71647415c380203b681f7717366f3501661512225b6dc3e121efc0b2e01da1adda2ccde9381e11151686c121e7f52d19a990439161c7eb5a9f94be5a5110201eb97b35d826f55a65e23ea7febf38fadea8517312ca79346c129a277260fd724011fb189b02ad2f7c6b0d09bd5691c4896c28269da3d4ba768b1b446f655186564011d73ff8e39cff60ff0d6402cc752a3351f1b434dccfa1941da3b1e422b73a33c00",
1083            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744600030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d03c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000",
1084            "013a27fed5dbbc475d3880360e38638c882fd9b273b618fc433106896083f7744601c7ca8f7df8fd997931d33985d935ee2d696856cc09cc516d419ea6365f163008030000010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02635c0b1b8035705127dc3f672191b4958ad331f9134117e3ba7d721f712b6144076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000",
1085            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c3702000301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d02e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c608076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000",
1086            "01f0fa37e8063b139d342246142fc48e7c0c50d0a62c97768589e06466742c370201e6d4d7685894d01b32f7e081ab188930be6c2b9f76d6847b7f382e3dddd7c6080301cca46d2249e0d79669b8ad2e8c3fc5e67a8501112aa4e572fe03a1868ef3173200010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01076795f3651049c8895a7d127eb9bb4a17698da400430b33fdd06b1d8160394000",
1087            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e82600030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d0222fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a53200",
1088            "018cebb73be883466d18d3b0c06990520e80b936440a2c9fd184d92a1f06c4e8260122fab8bcdb88154dbf5877ad1e2d7f1b541bc8a5ec1b52266095381339c27c03030001002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d01afa80a9a1bb8b6aad144cfb53e0bab004dd541c8b72025ae694bb60d6050a53200",
1089            "01f43e3aac61e5a753062d4d0508c26ceaf5e4c0c58ba3c956e104b5d2cf67c41c0003015991131c5c25911b35fcea2a8343e2dfd7a4d5b45493390e0cb184394d91c34901002df68503da9247dfde6585cb8c9fa94897cf21735f8fc1b32116ef474de05c010d6b42350c11df4fcc17987c13d8492ba4e8b3f31eb9baff9be5d8890cfa512d013a3661bc12b72646c94bc6c92796e81953985ee62d80a9ec3645a9a95740ac1500",
1090        ];
1091
1092        fn assert_root_eq(root: Node, expected: &str) {
1093            let mut tmp = [0u8; 32];
1094            root.write(&mut tmp[..]).expect("length is 32 bytes");
1095            assert_eq!(hex::encode(tmp), expected);
1096        }
1097
1098        fn assert_tree_ser_eq(tree: &TestCommitmentTree, expected: &str) {
1099            // Check that the tree matches its encoding
1100            let mut tmp = Vec::new();
1101            tree.write(&mut tmp).unwrap();
1102            assert_eq!(hex::encode(&tmp[..]), expected);
1103
1104            // Check round-trip encoding
1105            let decoded = TestCommitmentTree::read(&hex::decode(expected).unwrap()[..]).unwrap();
1106            tmp.clear();
1107            decoded.write(&mut tmp).unwrap();
1108            assert_eq!(hex::encode(tmp), expected);
1109        }
1110
1111        fn assert_witness_ser_eq(witness: &TestIncrementalWitness, expected: &str) {
1112            // Check that the witness matches its encoding
1113            let mut tmp = Vec::new();
1114            witness.write(&mut tmp).unwrap();
1115            assert_eq!(hex::encode(&tmp[..]), expected);
1116
1117            // Check round-trip encoding
1118            let decoded =
1119                TestIncrementalWitness::read(&hex::decode(expected).unwrap()[..]).unwrap();
1120            tmp.clear();
1121            decoded.write(&mut tmp).unwrap();
1122            assert_eq!(hex::encode(tmp), expected);
1123        }
1124
1125        let mut tree = TestCommitmentTree::new();
1126        assert_eq!(tree.size(), 0);
1127
1128        let mut witnesses = vec![];
1129        let mut last_cmu = None;
1130        let mut paths_i = 0;
1131        let mut witness_ser_i = 0;
1132        for i in 0..16 {
1133            let cmu = hex::decode(commitments[i]).unwrap();
1134
1135            let cmu = Node::new(cmu[..].try_into().unwrap());
1136
1137            // Witness here
1138            witnesses.push((TestIncrementalWitness::from_tree(&tree), last_cmu));
1139
1140            // Now append a commitment to the tree
1141            assert!(tree.append(cmu).is_ok());
1142
1143            // Size incremented by one.
1144            assert_eq!(tree.size(), i + 1);
1145
1146            // Check tree root consistency
1147            assert_root_eq(tree.root(), roots[i]);
1148
1149            // Check serialization of tree
1150            assert_tree_ser_eq(&tree, tree_ser[i]);
1151
1152            for (witness, leaf) in witnesses.as_mut_slice() {
1153                // Append the same commitment to all the witnesses
1154                assert!(witness.append(cmu).is_ok());
1155
1156                if let Some(leaf) = leaf {
1157                    let path = witness.path().expect("should be able to create a path");
1158                    let expected = MerklePath::from_slice_with_depth(
1159                        &hex::decode(paths[paths_i]).unwrap(),
1160                        TESTING_DEPTH,
1161                    )
1162                    .unwrap();
1163                    assert_eq!(path, expected);
1164                    assert_eq!(path.root(*leaf), witness.root());
1165                    paths_i += 1;
1166                } else {
1167                    // The first witness can never form a path
1168                    assert!(witness.path().is_none());
1169                }
1170
1171                // Check witness serialization
1172                assert_witness_ser_eq(witness, witness_ser[witness_ser_i]);
1173                witness_ser_i += 1;
1174
1175                assert_eq!(witness.root(), tree.root());
1176            }
1177
1178            last_cmu = Some(cmu);
1179        }
1180
1181        // Tree should be full now
1182        let node = Node::blank();
1183        assert!(tree.append(node).is_err());
1184        for (witness, _) in witnesses.as_mut_slice() {
1185            assert!(witness.append(node).is_err());
1186        }
1187    }
1188
1189    proptest! {
1190        #[test]
1191        fn prop_commitment_tree_roundtrip(ct in arb_commitment_tree(32, arb_node(), 8)) {
1192            let frontier: Frontier<Node, 8> = ct.to_frontier();
1193            let ct0 = CommitmentTree::from_frontier(&frontier);
1194            assert_eq!(ct, ct0);
1195            let frontier0: Frontier<Node, 8> = ct0.to_frontier();
1196            assert_eq!(frontier, frontier0);
1197        }
1198    }
1199
1200    #[test]
1201    fn test_commitment_tree_complete() {
1202        let mut t: CommitmentTree<TestNode> = CommitmentTree::empty();
1203        for n in 1u64..=32 {
1204            t.append(TestNode(n)).unwrap();
1205            // every tree of a power-of-two height is complete
1206            let is_complete = n.count_ones() == 1;
1207            let level = 63 - n.leading_zeros(); //log2
1208            assert_eq!(
1209                is_complete,
1210                t.is_complete(level.try_into().unwrap()),
1211                "Tree {:?} {} complete at height {}",
1212                t,
1213                if is_complete {
1214                    "should be"
1215                } else {
1216                    "should not be"
1217                },
1218                n
1219            );
1220        }
1221    }
1222}
1223
1224#[cfg(any(test, feature = "test-dependencies"))]
1225pub mod testing {
1226    use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
1227    use core::fmt::Debug;
1228    use proptest::collection::vec;
1229    use proptest::prelude::*;
1230    use std::collections::hash_map::DefaultHasher;
1231    use std::hash::Hasher;
1232    use std::io::{self, Read, Write};
1233
1234    use super::{CommitmentTree, Hashable};
1235
1236    pub fn arb_commitment_tree<Node: Hashable + Debug, T: Strategy<Value = Node>>(
1237        min_size: usize,
1238        arb_node: T,
1239        depth: u8,
1240    ) -> impl Strategy<Value = CommitmentTree<Node>> {
1241        assert!((1 << depth) >= min_size + 100);
1242        vec(arb_node, min_size..(min_size + 100)).prop_map(move |v| {
1243            let mut tree = CommitmentTree::empty();
1244            for node in v.into_iter() {
1245                tree.append(node).unwrap();
1246            }
1247            tree.parents.resize_with((depth - 1).into(), || None);
1248            tree
1249        })
1250    }
1251
1252    #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
1253    pub(crate) struct TestNode(pub(crate) u64);
1254
1255    impl Hashable for TestNode {
1256        fn read<R: Read>(mut reader: R) -> io::Result<TestNode> {
1257            reader.read_u64::<LittleEndian>().map(TestNode)
1258        }
1259
1260        fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
1261            writer.write_u64::<LittleEndian>(self.0)
1262        }
1263
1264        fn combine(_: usize, a: &TestNode, b: &TestNode) -> TestNode {
1265            let mut hasher = DefaultHasher::new();
1266            hasher.write_u64(a.0);
1267            hasher.write_u64(b.0);
1268            TestNode(hasher.finish())
1269        }
1270
1271        fn blank() -> TestNode {
1272            TestNode(0)
1273        }
1274
1275        fn empty_root(alt: usize) -> TestNode {
1276            (0..alt).fold(Self::blank(), |v, lvl| Self::combine(lvl, &v, &v))
1277        }
1278    }
1279}