use super::*;
impl<N: Network> Transition<N> {
pub fn to_root(&self) -> Result<Field<N>> {
Ok(*self.to_tree()?.root())
}
pub fn to_path(&self, leaf: &TransitionLeaf<N>) -> Result<TransitionPath<N>> {
self.to_tree()?.prove(leaf.index() as usize, &leaf.to_bits_le())
}
pub fn to_leaf(&self, id: &Field<N>, is_input: bool) -> Result<TransitionLeaf<N>> {
match is_input {
true => {
for (index, input) in self.inputs.iter().enumerate() {
if id == input.id() {
return Ok(input.to_transition_leaf(u8::try_from(index)?));
}
}
bail!("Input ID not found in transition")
}
false => {
for (index, output) in self.outputs.iter().enumerate() {
if id == output.id() {
return Ok(output.to_transition_leaf(u8::try_from(self.inputs.len() + index)?));
}
}
bail!("Output ID not found in transition")
}
}
}
pub fn to_tree(&self) -> Result<TransitionTree<N>> {
Self::function_tree(&self.inputs, &self.outputs)
}
pub(super) fn function_tree(inputs: &[Input<N>], outputs: &[Output<N>]) -> Result<TransitionTree<N>> {
ensure!(
inputs.len() <= N::MAX_INPUTS,
"Transition cannot exceed {} inputs, found {} inputs",
N::MAX_INPUTS,
inputs.len()
);
ensure!(
outputs.len() <= N::MAX_OUTPUTS,
"Transition cannot exceed {} outputs, found {} outputs",
N::MAX_OUTPUTS,
outputs.len()
);
let input_leaves = inputs
.iter()
.enumerate()
.map(|(index, input)| Ok::<_, Error>(input.to_transition_leaf(u8::try_from(index)?).to_bits_le()));
let output_leaves = outputs
.iter()
.enumerate()
.map(|(index, output)| Ok(output.to_transition_leaf(u8::try_from(inputs.len() + index)?).to_bits_le()));
N::merkle_tree_bhp::<TRANSITION_DEPTH>(&input_leaves.chain(output_leaves).collect::<Result<Vec<_>, _>>()?)
}
}
#[cfg(test)]
mod tests {
use super::*;
use console::network::MainnetV0;
type CurrentNetwork = MainnetV0;
#[test]
fn test_transition_depth() {
assert_eq!(2usize.pow(TRANSITION_DEPTH as u32), CurrentNetwork::MAX_INPUTS + CurrentNetwork::MAX_OUTPUTS);
}
}