mod bytes;
mod serialize;
mod string;
mod to_bits;
use snarkvm_console_network::prelude::*;
use snarkvm_console_types::Field;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum LeafVersion {
Static = 1,
Dynamic = 2,
}
impl TryFrom<u8> for LeafVersion {
type Error = Error;
fn try_from(value: u8) -> Result<Self> {
match value {
1 => Ok(Self::Static),
2 => Ok(Self::Dynamic),
_ => bail!("Invalid transition leaf version: {value}"),
}
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct TransitionLeaf<N: Network> {
version: u8,
index: u8,
variant: u8,
id: Field<N>,
}
impl<N: Network> TransitionLeaf<N> {
pub const fn new(index: u8, variant: u8, id: Field<N>) -> Self {
Self { version: LeafVersion::Static as u8, index, variant, id }
}
pub const fn new_record_with_dynamic_id(index: u8, id: Field<N>) -> Self {
Self { version: LeafVersion::Dynamic as u8, index, variant: 3, id }
}
pub const fn new_external_record_with_dynamic_id(index: u8, id: Field<N>) -> Self {
Self { version: LeafVersion::Dynamic as u8, index, variant: 4, id }
}
pub fn from(version: u8, index: u8, variant: u8, id: Field<N>) -> Result<Self> {
let leaf_version = LeafVersion::try_from(version)?;
if matches!(leaf_version, LeafVersion::Dynamic) && variant != 3 && variant != 4 {
bail!("Dynamic transition leaf variant must be 3 (Record) or 4 (ExternalRecord), found {variant}");
}
Ok(Self { version, index, variant, id })
}
pub const fn version(&self) -> u8 {
self.version
}
pub const fn index(&self) -> u8 {
self.index
}
pub const fn variant(&self) -> u8 {
self.variant
}
pub const fn id(&self) -> Field<N> {
self.id
}
}
#[cfg(test)]
mod test_helpers {
use super::*;
use snarkvm_console_network::MainnetV0;
type CurrentNetwork = MainnetV0;
pub(super) fn sample_leaf(rng: &mut TestRng) -> TransitionLeaf<CurrentNetwork> {
TransitionLeaf::new(rng.r#gen(), rng.r#gen(), Uniform::rand(rng))
}
pub(super) fn sample_dynamic_leaf(rng: &mut TestRng) -> TransitionLeaf<CurrentNetwork> {
if rng.r#gen() {
TransitionLeaf::new_record_with_dynamic_id(rng.r#gen(), Uniform::rand(rng))
} else {
TransitionLeaf::new_external_record_with_dynamic_id(rng.r#gen(), Uniform::rand(rng))
}
}
}