Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a form of serialize and deserialize for Opening #55

Closed
moCello opened this issue Jun 9, 2023 · 1 comment · Fixed by #57
Closed

Implement a form of serialize and deserialize for Opening #55

moCello opened this issue Jun 9, 2023 · 1 comment · Fixed by #57

Comments

@moCello
Copy link
Member

moCello commented Jun 9, 2023

Summary

We need a way to serialize the Opening so that we can send it to the proof generator.

Possible solution design or implementation

Implement dusk-bytes::Serializable

@moCello
Copy link
Member Author

moCello commented Jun 14, 2023

Why we didn't implement Serializable:

The current implementation of Serializable is only possible via a macro for Opening<T, H, A>. This is most notably due to the fact that in order to implement the trait, we need to know the size of the opening and for that we need to know the size of T. The only solution here is to implement Serializable<Opening<T, H, A>::SIZE> over different T::SIZE.
The following macro does the trick, in 'src/opening.rs':

// This macro is necessary due to the fact that `generic_const_exprs`, is still
// unstable. It should remain here until this is completed:
// https://github.com/rust-lang/rust/issues/76560
macro_rules! impl_serializable_opening {
    ( $( $size_t:literal, $height:literal, $arity:literal ),+ ) => {
        $(impl<T> Serializable<{ $size_t + $size_t * $arity * $height + (u32::BITS as usize / 8) * $height }> for Opening<T, $height, $arity>
            where
                T: Aggregate<$arity> + Serializable<$size_t>,
                dusk_bytes::Error: From<<T as Serializable<$size_t>>::Error>,
                <T as Serializable<$size_t>>::Error: dusk_bytes::BadLength,
            {
                type Error = dusk_bytes::Error;

                fn from_bytes(buf: &[u8; { $size_t + $size_t * $arity * $height + (u32::BITS as usize / 8) * $height }]) -> Result<Self, Self::Error>
                    where Self: Sized,
                {
                    let mut bytes = &buf[..];

                    // deserialize root
                    let root = T::from_reader(&mut bytes)?;

                    // deserialize branch
                    let mut branch: [[T; $arity]; $height] = init_array(|_| init_array(|_| T::EMPTY_SUBTREE));
                    for level in branch.iter_mut() {
                        for item in level.iter_mut() {
                            *item = T::from_reader(&mut bytes)?;
                        }
                    }

                    // deserialize positions
                    let mut positions = [0usize; $height];
                    for pos in positions.iter_mut() {
                        *pos = u32::from_reader(&mut bytes)? as usize;
                    }

                    Ok(Self {root, branch, positions })
                }

                fn to_bytes(&self) -> [u8; { $size_t + $size_t * $arity * $height + (u32::BITS as usize / 8) * $height }] {
                    const SIZE_U32: usize = u32::BITS as usize / 8;
                    let mut buf = [0u8; { $size_t + $size_t * $arity * $height + SIZE_U32 * $height }];

                    // serialize root
                    buf[0..T::SIZE]
                        .copy_from_slice(&self.root.to_bytes());

                    // serialize branch
                    const SIZE_LEVEL: usize = $arity * $size_t;
                    let start = T::SIZE;
                    for (h, level) in self.branch.iter().enumerate() {
                        for (a, item) in level.iter().enumerate() {
                            buf[start + h * SIZE_LEVEL + a * $size_t..start + h * SIZE_LEVEL + (a + 1) * $size_t]
                                .copy_from_slice(&item.to_bytes());
                        }
                    }

                    // serialize positions
                    let start = start + $height * $arity * $size_t;
                    for (h, pos) in self.positions.iter().enumerate() {
                        buf[start + h * SIZE_U32..start + (h + 1) * SIZE_U32]
                            .copy_from_slice(&(*pos as u32).to_bytes());
                    }

                    buf
                }
            })+
    };
}

impl_serializable_opening!(50, 17, 4);

With this solution however we need to implement the multiple T::SIZE which results in a lot of unused code.

What we will do instead

To avoid that we opted for an alternative until the new implementation of Serializable is available.

Instead of the Serializable trait we will add the methods:

pub fn to_var_bytes(&self) -> Vec<u8> {...}

and

pub fn from_slice(buf: &[u8]) -> Result<Self, BytesError> {...}

@moCello moCello changed the title Implement dusk-bytes::Serializable for Opening Implement serialize and deserialize for Opening Jun 14, 2023
@moCello moCello changed the title Implement serialize and deserialize for Opening Implement a form of serialize and deserialize for Opening Jun 14, 2023
moCello added a commit that referenced this issue Jun 14, 2023
moCello added a commit that referenced this issue Jun 15, 2023
moCello added a commit that referenced this issue Jun 15, 2023
moCello added a commit that referenced this issue Jun 15, 2023
moCello added a commit that referenced this issue Jun 15, 2023
moCello added a commit that referenced this issue Jun 15, 2023
moCello added a commit that referenced this issue Jun 15, 2023
moCello added a commit that referenced this issue Jun 15, 2023
This was referenced Jun 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant