Skip to content

Commit

Permalink
Merge pull request #124 from ralexstokes/more-gi
Browse files Browse the repository at this point in the history
More work on generalized indices
  • Loading branch information
ralexstokes authored Feb 19, 2024
2 parents 2d706b6 + 9d7cb0e commit e671bd5
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 20 deletions.
2 changes: 1 addition & 1 deletion ssz-rs-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ fn derive_indexed_impl(data: &Data, name: &Ident, generics: &Generics) -> TokenS
quote! {
#selector => {
let chunk_position = #i;
let child = parent + get_power_of_two_ceil(Self::chunk_count()) + chunk_position;
let child = parent * get_power_of_two_ceil(Self::chunk_count()) + chunk_position;
<#field_ty as ssz_rs::Indexed>::compute_generalized_index(child, path)
}
}
Expand Down
21 changes: 7 additions & 14 deletions ssz-rs/examples/generalized_indices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,32 @@ struct Qux {
}

fn main() {
let path = &[PathElement::Index(2)];
let index = get_generalized_index::<Vector<u8, 16>>(path).unwrap();
let path = &[2.into()];
let index = Vector::<u8, 16>::generalized_index(path).unwrap();
dbg!(index);

let path = &[PathElement::Index(2)];
let path = &[2.into()];
let index = get_generalized_index::<List<u8, 256>>(path).unwrap();
dbg!(index);
let path = &[PathElement::Length];
let index = List::<u8, 256>::generalized_index(path).unwrap();
dbg!(index);

// containers
let path = &[PathElement::Field("c".into())];
let path = &["c".into()];
let index = Bar::generalized_index(path).unwrap();
dbg!(index);

// nested access
let path = &[PathElement::Field("a".into()), PathElement::Index(2)];
let path = &["a".into(), 2.into()];
let index = Bar::generalized_index(path).unwrap();
dbg!(index);

let path = &[
PathElement::Field("f".into()),
PathElement::Field("y".into()),
PathElement::Index(2),
PathElement::Field("a".into()),
PathElement::Index(3),
];
let path = &["f".into(), "y".into(), 2.into(), "a".into(), 3.into()];
let index = Bar::generalized_index(path).unwrap();
dbg!(index);

let path =
&[PathElement::Field("f".into()), PathElement::Field("y".into()), PathElement::Length];
let path = &["f".into(), "y".into(), PathElement::Length];
let index = Bar::generalized_index(path).unwrap();
dbg!(index);
}
12 changes: 11 additions & 1 deletion ssz-rs/src/bitlist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use crate::{
error::{Error, InstanceError},
lib::*,
merkleization::{
merkleize, mix_in_length, pack_bytes, MerkleizationError, Merkleized, Node, BITS_PER_CHUNK,
merkleize, mix_in_length, multiproofs::*, pack_bytes, MerkleizationError, Merkleized, Node,
BITS_PER_CHUNK,
},
ser::{Serialize, SerializeError},
Serializable, SimpleSerialize,
Expand Down Expand Up @@ -182,6 +183,15 @@ impl<const N: usize> Merkleized for Bitlist<N> {
}
}

impl<const N: usize> Indexed for Bitlist<N> {
fn generalized_index(_path: Path) -> Result<GeneralizedIndex, MerkleizationError>
where
Self: Sized,
{
unimplemented!()
}
}

impl<const N: usize> SimpleSerialize for Bitlist<N> {}

impl<const N: usize> TryFrom<&[u8]> for Bitlist<N> {
Expand Down
13 changes: 12 additions & 1 deletion ssz-rs/src/bitvector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use crate::{
de::{Deserialize, DeserializeError},
error::{Error, InstanceError, TypeError},
lib::*,
merkleization::{merkleize, pack_bytes, MerkleizationError, Merkleized, Node, BITS_PER_CHUNK},
merkleization::{
merkleize, multiproofs::*, pack_bytes, MerkleizationError, Merkleized, Node, BITS_PER_CHUNK,
},
ser::{Serialize, SerializeError},
Serializable, SimpleSerialize,
};
Expand Down Expand Up @@ -169,6 +171,15 @@ impl<const N: usize> Merkleized for Bitvector<N> {
}
}

impl<const N: usize> Indexed for Bitvector<N> {
fn generalized_index(_path: Path) -> Result<GeneralizedIndex, MerkleizationError>
where
Self: Sized,
{
unimplemented!()
}
}

impl<const N: usize> SimpleSerialize for Bitvector<N> {}

impl<const N: usize> TryFrom<&[u8]> for Bitvector<N> {
Expand Down
2 changes: 1 addition & 1 deletion ssz-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ mod lib {
};

#[cfg(not(feature = "std"))]
pub use alloc::{format, string::String, vec, vec::Vec};
pub use alloc::{format, string::String, string::ToString, vec, vec::Vec};

#[cfg(feature = "std")]
pub use std::vec::Vec;
Expand Down
72 changes: 72 additions & 0 deletions ssz-rs/src/merkleization/multiproofs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@ pub enum PathElement {
Length,
}

impl From<&str> for PathElement {
fn from(value: &str) -> Self {
PathElement::Field(value.to_string())
}
}

impl From<usize> for PathElement {
fn from(value: usize) -> Self {
PathElement::Index(value)
}
}

pub type Path<'a> = &'a [PathElement];

pub trait Indexed {
Expand Down Expand Up @@ -194,3 +206,63 @@ pub fn verify_merkle_multiproof(
Err(Error::InvalidProof)
}
}

#[cfg(test)]
mod tests {
use crate::prelude::*;

#[derive(Default, Debug, SimpleSerialize, Indexed)]
struct Bar {
c: u8,
f: Foo,
a: List<u8, 25>,
}

#[derive(Default, Debug, SimpleSerialize, Indexed)]
struct Foo {
x: Vector<u8, 32>,
y: List<Qux, 256>,
}

#[derive(Default, Debug, SimpleSerialize, Indexed)]
struct Qux {
a: Vector<u16, 8>,
}

#[test]
fn test_basic_generalized_index_computation() {
let mut indices = vec![];

let path = &[2.into()];
let index = Vector::<u8, 16>::generalized_index(path).unwrap();
indices.push(index);

let path = &[2.into()];
let index = get_generalized_index::<List<u8, 256>>(path).unwrap();
indices.push(index);

let path = &[PathElement::Length];
let index = List::<u8, 256>::generalized_index(path).unwrap();
indices.push(index);

// containers
let path = &["c".into()];
let index = Bar::generalized_index(path).unwrap();
indices.push(index);

// nested access
let path = &["a".into(), 2.into()];
let index = Bar::generalized_index(path).unwrap();
indices.push(index);

let path = &["f".into(), "y".into(), 2.into(), "a".into(), 3.into()];
let index = Bar::generalized_index(path).unwrap();
indices.push(index);

let path = &["f".into(), "y".into(), PathElement::Length];
let index = Bar::generalized_index(path).unwrap();
indices.push(index);

assert_eq!(indices, [1, 16, 3, 4, 12, 5634, 23])
}
}
2 changes: 1 addition & 1 deletion ssz-rs/src/merkleization/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
};

/// A node in a merkle tree.
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, SimpleSerialize)]
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, SimpleSerialize, Indexed)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Node(
#[cfg_attr(feature = "serde", serde(with = "crate::serde::as_hex"))] [u8; BYTES_PER_CHUNK],
Expand Down
2 changes: 1 addition & 1 deletion ssz-rs/tests/test_utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ssz_rs::prelude::*;
use std::{convert::TryInto, fs::File, io::Read, path::PathBuf};
use std::{fs::File, io::Read, path::PathBuf};

pub fn root_from_hex(hex_str: &str) -> Node {
let hex_str = hex_str.trim_start_matches("0x");
Expand Down

0 comments on commit e671bd5

Please sign in to comment.