From f01a8657419462990ae25be90e909bf4ec6cad99 Mon Sep 17 00:00:00 2001 From: DarkingLee Date: Mon, 10 Jul 2023 19:45:38 +0800 Subject: [PATCH] Merged kzg and kzg_data --- primitives/src/kzg.rs | 214 ++++++++++++++++++++++++++++++++++++- primitives/src/kzg_data.rs | 209 ------------------------------------ primitives/src/lib.rs | 3 +- 3 files changed, 210 insertions(+), 216 deletions(-) delete mode 100644 primitives/src/kzg_data.rs diff --git a/primitives/src/kzg.rs b/primitives/src/kzg.rs index 64e5e40..857b283 100644 --- a/primitives/src/kzg.rs +++ b/primitives/src/kzg.rs @@ -13,11 +13,15 @@ // limitations under the License. extern crate alloc; -use super::kzg_data::{Blob, BlsScalar, KZGCommitment, KZGProof}; - -use alloc::string::String; -use alloc::vec::Vec; -use kzg::{FFTSettings, KZGSettings}; +use alloc::{ + string::{String, ToString}, + vec::Vec, +}; +use core::hash::{Hash, Hasher}; +use core::mem; +use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into}; +use kzg::{FFTSettings, Fr, KZGSettings, G1}; +use parity_scale_codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen}; use rust_kzg_blst::{ eip_4844::{ compute_blob_kzg_proof_rust, load_trusted_setup_filename_rust, @@ -27,6 +31,206 @@ use rust_kzg_blst::{ fft_settings::FsFFTSettings, fr::FsFr, g1::FsG1, kzg_settings::FsKZGSettings, poly::FsPoly, }, }; +use scale_info::{Type, TypeInfo}; + +macro_rules! kzg_type_with_size { + ($name:ident, $type:ty, $size:expr) => { + #[derive( + Debug, Default, Copy, Clone, PartialEq, Eq, Into, From, AsRef, AsMut, Deref, DerefMut, + )] + #[repr(transparent)] + pub struct $name(pub $type); + impl $name { + #[warn(dead_code)] + const SIZE: usize = $size; + + #[inline] + pub fn to_bytes(&self) -> [u8; $size] { + self.0.to_bytes() + } + + #[inline] + pub fn try_from_bytes(bytes: &[u8; $size]) -> Result { + Ok($name(<$type>::from_bytes(bytes)?)) + } + } + + impl Hash for $name { + fn hash(&self, state: &mut H) { + self.to_bytes().hash(state); + } + } + + impl From<$name> for [u8; $size] { + #[inline] + fn from(kzd_data: $name) -> Self { + kzd_data.to_bytes() + } + } + + impl From<&$name> for [u8; $size] { + #[inline] + fn from(kzd_data: &$name) -> Self { + kzd_data.to_bytes() + } + } + + impl TryFrom<&[u8; $size]> for $name { + type Error = String; + + #[inline] + fn try_from(bytes: &[u8; $size]) -> Result { + Self::try_from_bytes(bytes) + } + } + + impl TryFrom<[u8; $size]> for $name { + type Error = String; + + #[inline] + fn try_from(bytes: [u8; $size]) -> Result { + Self::try_from(&bytes) + } + } + + impl Encode for $name { + #[inline] + fn size_hint(&self) -> usize { + Self::SIZE + } + + fn using_encoded R>(&self, f: F) -> R { + f(&self.to_bytes()) + } + + #[inline] + fn encoded_size(&self) -> usize { + Self::SIZE + } + } + + impl EncodeLike for $name {} + + impl MaxEncodedLen for $name { + #[inline] + fn max_encoded_len() -> usize { + Self::SIZE + } + } + + impl Decode for $name { + fn decode(input: &mut I) -> Result { + Self::try_from_bytes(&Decode::decode(input)?).map_err(|error| { + parity_scale_codec::Error::from("Failed to decode from bytes") + .chain(alloc::format!("{error:?}")) + }) + } + + #[inline] + fn encoded_fixed_size() -> Option { + Some(Self::SIZE) + } + } + + impl TypeInfo for $name { + type Identity = Self; + + fn type_info() -> Type { + Type::builder() + .path(scale_info::Path::new(stringify!($name), module_path!())) + .docs(&["Commitment to polynomial"]) + .composite(scale_info::build::Fields::named().field(|f| { + f.ty::<[u8; $size]>().name(stringify!(inner)).type_name("G1Affine") + })) + } + } + }; +} + +// TODO: Automatic size reading +kzg_type_with_size!(KZGCommitment, FsG1, 48); +kzg_type_with_size!(KZGProof, FsG1, 48); +kzg_type_with_size!(BlsScalar, FsFr, 32); + +pub const BYTES_PER_BLOB: usize = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB; +pub const BYTES_PER_FIELD_ELEMENT: usize = 32; +pub const FIELD_ELEMENTS_PER_BLOB: usize = 4; + +macro_rules! repr_convertible { + ($name:ident, $type:ty) => { + impl $name { + pub fn slice_to_repr(value: &[Self]) -> &[$type] { + unsafe { mem::transmute(value) } + } + + pub fn vec_to_repr(value: Vec) -> Vec<$type> { + unsafe { + let mut value = mem::ManuallyDrop::new(value); + Vec::from_raw_parts( + value.as_mut_ptr() as *mut $type, + value.len(), + value.capacity(), + ) + } + } + } + }; +} + +#[derive(Debug, Default, Clone, PartialEq, Eq, From, AsRef, AsMut, Deref, DerefMut)] +#[repr(transparent)] +pub struct Blob(pub Vec); +// TODO: Change to automatic implementation +repr_convertible!(Blob, Vec); +repr_convertible!(KZGCommitment, FsG1); +repr_convertible!(KZGProof, FsG1); +repr_convertible!(BlsScalar, FsFr); + +impl Blob { + #[inline] + pub fn try_from_bytes(bytes: &[u8]) -> Result { + if bytes.len() != BYTES_PER_BLOB { + return Err(format!( + "Invalid byte length. Expected {} got {}", + BYTES_PER_BLOB, + bytes.len(), + )); + } + + Self::from_bytes(bytes).map(Self) + } + + #[inline] + pub fn try_from_bytes_pad(bytes: &[u8]) -> Result { + if bytes.len() > BYTES_PER_BLOB { + return Err(format!( + "Invalid byte length. Expected maximum {} got {}", + BYTES_PER_BLOB, + bytes.len(), + )); + } + Self::from_bytes(bytes).map(|mut data| { + if data.len() == FIELD_ELEMENTS_PER_BLOB { + Self(data) + } else { + data.resize(FIELD_ELEMENTS_PER_BLOB, FsFr::zero()); + Self(data) + } + }) + } + + fn from_bytes(bytes: &[u8]) -> Result, String> { + bytes + .chunks(BYTES_PER_FIELD_ELEMENT) + .map(|chunk| { + chunk + .try_into() + .map_err(|_| "Chunked into incorrect number of bytes".to_string()) + .and_then(FsFr::from_bytes) + }) + .collect() + } +} const TRUSTED_SETUP_FILENAME: &str = "eth-public-parameters.bin"; diff --git a/primitives/src/kzg_data.rs b/primitives/src/kzg_data.rs deleted file mode 100644 index 0aaaee5..0000000 --- a/primitives/src/kzg_data.rs +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2023 ZeroDAO -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this filepub(crate) except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -extern crate alloc; - -use alloc::{ - string::{String, ToString}, - vec::Vec, -}; -use core::hash::{Hash, Hasher}; -use core::mem; -use derive_more::{AsMut, AsRef, Deref, DerefMut, From, Into}; -use kzg::{Fr, G1}; -use parity_scale_codec::{Decode, Encode, EncodeLike, Input, MaxEncodedLen}; -use rust_kzg_blst::types::{fr::FsFr, g1::FsG1}; -use scale_info::{Type, TypeInfo}; - -macro_rules! kzg_type_with_size { - ($name:ident, $type:ty, $size:expr) => { - #[derive( - Debug, Default, Copy, Clone, PartialEq, Eq, Into, From, AsRef, AsMut, Deref, DerefMut, - )] - #[repr(transparent)] - pub struct $name(pub $type); - impl $name { - #[warn(dead_code)] - const SIZE: usize = $size; - - #[inline] - pub fn to_bytes(&self) -> [u8; $size] { - self.0.to_bytes() - } - - #[inline] - pub fn try_from_bytes(bytes: &[u8; $size]) -> Result { - Ok($name(<$type>::from_bytes(bytes)?)) - } - } - - impl Hash for $name { - fn hash(&self, state: &mut H) { - self.to_bytes().hash(state); - } - } - - impl From<$name> for [u8; $size] { - #[inline] - fn from(kzd_data: $name) -> Self { - kzd_data.to_bytes() - } - } - - impl From<&$name> for [u8; $size] { - #[inline] - fn from(kzd_data: &$name) -> Self { - kzd_data.to_bytes() - } - } - - impl TryFrom<&[u8; $size]> for $name { - type Error = String; - - #[inline] - fn try_from(bytes: &[u8; $size]) -> Result { - Self::try_from_bytes(bytes) - } - } - - impl TryFrom<[u8; $size]> for $name { - type Error = String; - - #[inline] - fn try_from(bytes: [u8; $size]) -> Result { - Self::try_from(&bytes) - } - } - - impl Encode for $name { - #[inline] - fn size_hint(&self) -> usize { - Self::SIZE - } - - fn using_encoded R>(&self, f: F) -> R { - f(&self.to_bytes()) - } - - #[inline] - fn encoded_size(&self) -> usize { - Self::SIZE - } - } - - impl EncodeLike for $name {} - - impl MaxEncodedLen for $name { - #[inline] - fn max_encoded_len() -> usize { - Self::SIZE - } - } - - impl Decode for $name { - fn decode(input: &mut I) -> Result { - Self::try_from_bytes(&Decode::decode(input)?).map_err(|error| { - parity_scale_codec::Error::from("Failed to decode from bytes") - .chain(alloc::format!("{error:?}")) - }) - } - - #[inline] - fn encoded_fixed_size() -> Option { - Some(Self::SIZE) - } - } - - impl TypeInfo for $name { - type Identity = Self; - - fn type_info() -> Type { - Type::builder() - .path(scale_info::Path::new(stringify!($name), module_path!())) - .docs(&["Commitment to polynomial"]) - .composite(scale_info::build::Fields::named().field(|f| { - f.ty::<[u8; $size]>().name(stringify!(inner)).type_name("G1Affine") - })) - } - } - }; -} - -// TODO: Automatic size reading -kzg_type_with_size!(KZGCommitment, FsG1, 48); -kzg_type_with_size!(KZGProof, FsG1, 48); -kzg_type_with_size!(BlsScalar, FsFr, 32); - -pub const BYTES_PER_BLOB: usize = BYTES_PER_FIELD_ELEMENT * FIELD_ELEMENTS_PER_BLOB; -pub const BYTES_PER_FIELD_ELEMENT: usize = 32; -pub const FIELD_ELEMENTS_PER_BLOB: usize = 4; - -macro_rules! repr_convertible { - ($name:ident, $type:ty) => { - impl $name { - pub fn slice_to_repr(value: &[Self]) -> &[$type] { - unsafe { mem::transmute(value) } - } - - pub fn vec_to_repr(value: Vec) -> Vec<$type> { - unsafe { - let mut value = mem::ManuallyDrop::new(value); - Vec::from_raw_parts(value.as_mut_ptr() as *mut $type, value.len(), value.capacity()) - } - } - } - }; -} - -#[derive( - Debug, Default, Clone, PartialEq, Eq, From, AsRef, AsMut, Deref, DerefMut, -)] -#[repr(transparent)] -pub struct Blob(pub Vec); -// TODO: Change to automatic implementation -repr_convertible!(Blob, Vec); -repr_convertible!(KZGCommitment, FsG1); -repr_convertible!(KZGProof, FsG1); -repr_convertible!(BlsScalar, FsFr); - -impl Blob { - #[inline] - pub fn try_from_bytes(bytes: &[u8]) -> Result { - if bytes.len() > BYTES_PER_BLOB { - return Err(format!( - "Invalid byte length. Expected maximum {} got {}", - BYTES_PER_BLOB, - bytes.len(), - )); - } - let data_result: Result, String> = bytes - .chunks(BYTES_PER_FIELD_ELEMENT) - .map(|chunk| { - chunk - .try_into() - .map_err(|_| "Chunked into incorrect number of bytes".to_string()) - .and_then(FsFr::from_bytes) - }) - .collect(); - - data_result.map(|mut data| { - if data.len() == FIELD_ELEMENTS_PER_BLOB { - Self(data) - } else { - data.resize(FIELD_ELEMENTS_PER_BLOB, FsFr::zero()); - Self(data) - } - }) - } -} diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 931bc5d..bc42bdc 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -12,5 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub mod kzg; -pub mod kzg_data; \ No newline at end of file +pub mod kzg; \ No newline at end of file