Struct bridgetree::BridgeTree

source ·
pub struct BridgeTree<H, const DEPTH: u8> { /* private fields */ }
Expand description

A sparse representation of a Merkle tree with linear appending of leaves that contains enough information to produce a witness for any marked leaf.

Implementations§

Construct an empty BridgeTree value with the specified maximum number of checkpoints.

Returns the prior bridges that make up this tree

Returns the current bridge at the tip of this tree

Returns the map from leaf positions that have been marked to the index of the bridge whose tip is at that position in this tree’s list of bridges.

Returns the checkpoints to which this tree may be rewound.

Returns the maximum number of checkpoints that will be maintained by the data structure. When this number of checkpoints is exceeded, the oldest checkpoints are discarded when creating new checkpoints.

Returns the bridge’s frontier.

Construct a new BridgeTree that will start recording changes from the state of the specified frontier.

Construct a new BridgeTree from its constituent parts, checking for internal consistency.

Appends a new value to the tree at the next available slot. Returns true if successful and false if the tree would exceed the maximum allowed depth.

Obtains the root of the Merkle tree at the specified checkpoint depth by hashing against empty nodes up to the maximum height of the tree. Returns None if there are not enough checkpoints available to reach the requested checkpoint depth.

Examples found in repository?
src/lib.rs (line 1093)
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
    fn witness_inner(&self, position: Position, as_of_root: &H) -> Result<Vec<H>, WitnessingError> {
        #[derive(Debug)]
        enum AuthBase<'a> {
            Current,
            Checkpoint(usize, &'a Checkpoint),
            NotFound,
        }

        let max_alt = Level::from(DEPTH);

        // Find the earliest checkpoint having a matching root, or the current
        // root if it matches and there is no earlier matching checkpoint.
        let auth_base = self
            .checkpoints
            .iter()
            .enumerate()
            .rev()
            .take_while(|(_, c)| c.position(&self.prior_bridges) >= Some(position))
            .filter(|(_, c)| &c.root(&self.prior_bridges, max_alt) == as_of_root)
            .last()
            .map(|(i, c)| AuthBase::Checkpoint(i, c))
            .unwrap_or_else(|| {
                if self.root(0).as_ref() == Some(as_of_root) {
                    AuthBase::Current
                } else {
                    AuthBase::NotFound
                }
            });

        let saved_idx = self
            .saved
            .get(&position)
            .or_else(|| {
                if let AuthBase::Checkpoint(i, _) = auth_base {
                    // The saved position might have been forgotten since the checkpoint,
                    // so look for it in each of the subsequent checkpoints' forgotten
                    // items.
                    self.checkpoints[i..].iter().find_map(|c| {
                        // restore the forgotten position, if that position was not also marked
                        // in the same checkpoint
                        c.forgotten
                            .get(&position)
                            .filter(|_| !c.marked.contains(&position))
                    })
                } else {
                    None
                }
            })
            .ok_or(WitnessingError::PositionNotMarked(position))?;

        let prior_frontier = &self.prior_bridges[*saved_idx].frontier;

        // Fuse the following bridges to obtain a bridge that has all
        // of the data to the right of the selected value in the tree,
        // up to the specified checkpoint depth.
        let fuse_from = saved_idx + 1;
        let successor = match auth_base {
            AuthBase::Current => {
                // fuse all the way up to the current tip
                MerkleBridge::fuse_all(
                    self.prior_bridges[fuse_from..]
                        .iter()
                        .chain(&self.current_bridge),
                )
                .map(|fused| fused.unwrap()) // safe as the iterator being fused is nonempty
                .map_err(WitnessingError::BridgeFusionError)
            }
            AuthBase::Checkpoint(_, checkpoint) if fuse_from < checkpoint.bridges_len => {
                // fuse from the provided checkpoint
                MerkleBridge::fuse_all(self.prior_bridges[fuse_from..checkpoint.bridges_len].iter())
                    .map(|fused| fused.unwrap()) // safe as the iterator being fused is nonempty
                    .map_err(WitnessingError::BridgeFusionError)
            }
            AuthBase::Checkpoint(_, checkpoint) if fuse_from == checkpoint.bridges_len => {
                // The successor bridge should just be the empty successor to the
                // checkpointed bridge.
                if checkpoint.bridges_len > 0 {
                    Ok(self.prior_bridges[checkpoint.bridges_len - 1].successor(false))
                } else {
                    Err(WitnessingError::CheckpointInvalid)
                }
            }
            AuthBase::Checkpoint(_, checkpoint) => {
                // if the saved index is after the checkpoint, we can't generate
                // an auth path
                Err(WitnessingError::CheckpointTooDeep(
                    fuse_from - checkpoint.bridges_len,
                ))
            }
            AuthBase::NotFound => {
                // we didn't find any suitable auth base
                Err(WitnessingError::AuthBaseNotFound)
            }
        }?;

        successor.witness(DEPTH, prior_frontier)
    }

Returns the most recently appended leaf value.

Returns the most recently appended leaf value.

Marks the current leaf as one for which we’re interested in producing a witness. Returns an optional value containing the current position if successful or if the current value was already marked, or None if the tree is empty.

Examples found in repository?
src/lib.rs (line 1054)
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
    pub fn rewind(&mut self) -> bool {
        match self.checkpoints.pop() {
            Some(mut c) => {
                // drop marked values at and above the checkpoint height;
                // we will re-mark if necessary.
                self.saved.append(&mut c.forgotten);
                self.saved.retain(|_, i| *i + 1 < c.bridges_len);
                self.prior_bridges.truncate(c.bridges_len);
                self.current_bridge = self.prior_bridges.last().map(|b| b.successor(c.is_marked));
                if c.is_marked {
                    self.mark();
                }
                true
            }
            None => false,
        }
    }

Return a set of all the positions for which we have marked.

Returns the leaf at the specified position if the tree can produce a witness for it.

Examples found in repository?
src/lib.rs (line 1012)
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
    pub fn checkpoint(&mut self) {
        match self.current_bridge.take() {
            Some(cur_b) => {
                let is_marked = self.get_marked_leaf(cur_b.position()).is_some();

                // Do not create a duplicate bridge
                if self
                    .prior_bridges
                    .last()
                    .map_or(false, |pb| pb.position() == cur_b.position())
                {
                    self.current_bridge = Some(cur_b);
                } else {
                    self.current_bridge = Some(cur_b.successor(false));
                    self.prior_bridges.push(cur_b);
                }

                self.checkpoints
                    .push(Checkpoint::at_length(self.prior_bridges.len(), is_marked));
            }
            None => {
                self.checkpoints.push(Checkpoint::at_length(0, false));
            }
        }

        if self.checkpoints.len() > self.max_checkpoints {
            self.drop_oldest_checkpoint();
        }
    }

Marks the value at the specified position as a value we’re no longer interested in maintaining a mark for. Returns true if successful and false if we were already not maintaining a mark at this position.

Creates a new checkpoint for the current tree state. It is valid to have multiple checkpoints for the same tree state, and each rewind call will remove a single checkpoint.

Rewinds the tree state to the previous checkpoint, and then removes that checkpoint record. If there are multiple checkpoints at a given tree state, the tree state will not be altered until all checkpoints at that tree state have been removed using rewind. This function return false and leave the tree unmodified if no checkpoints exist.

Obtains a witness to the value at the specified position, as of the tree state corresponding to the given root. Returns None if there is no available witness to that position or if the root does not correspond to a checkpointed root of the tree.

Remove state from the tree that no longer needs to be maintained because it is associated with checkpoints or marks that have been removed from the tree at positions deeper than those reachable by calls to rewind.

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Deserialize this value from the given Serde deserializer. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.