diff --git a/Cargo.lock b/Cargo.lock index 6fb7f48f..7f28475f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10049,6 +10049,7 @@ dependencies = [ "proof-of-sql", "proof-of-sql-commitment-map", "proof-of-sql-static-setups", + "proof-of-sql-unchecked-deserialize", "scale-info", "snafu 0.8.5", "sp-api", @@ -13281,6 +13282,16 @@ dependencies = [ "url", ] +[[package]] +name = "proof-of-sql-unchecked-deserialize" +version = "0.1.0" +dependencies = [ + "ark-serialize 0.5.0", + "derive_more 0.99.19", + "proof-of-sql", + "serde", +] + [[package]] name = "proof-of-sql-unversioned" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index b35fac54..02dd46c6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ "proof-of-sql/on-chain-table", "proof-of-sql/commitment-sql", "proof-of-sql/static-setups", + "proof-of-sql/unchecked-deserialize", "proof-of-sql/unversioned", "native", "native-api", @@ -96,6 +97,7 @@ proof-of-sql-commitment-map = { path = "./proof-of-sql/commitment-map/", default commitment-column-mapping = { path = "./proof-of-sql/commitment-column-mapping/", default-features = false } proof-of-sql-static-setups = { path = "./proof-of-sql/static-setups/", default-features = false } proof-of-sql-unversioned = { path = "./proof-of-sql/unversioned/", default-features = false } +proof-of-sql-unchecked-deserialize = { path = "./proof-of-sql/unchecked-deserialize/", default-features = false } rand = { version = "0.8.5", default-features = false } rand_chacha = { version = "0.3.1", default-features = false } rayon = { version = "1.10.0" } @@ -235,6 +237,7 @@ prometheus = "0.14.0" proptest = { version = "1.7.0", default-features = false } proptest-derive = { version = "0.6.0", default-features = false } blake3 = { version = "1.6.1", default-features = false } +derive_more = { version = "0.99" } [workspace.lints] rust.missing_docs = "warn" diff --git a/pallets/commitments/Cargo.toml b/pallets/commitments/Cargo.toml index 1a3412ea..4d100993 100644 --- a/pallets/commitments/Cargo.toml +++ b/pallets/commitments/Cargo.toml @@ -29,6 +29,7 @@ on-chain-table.workspace = true proof-of-sql.workspace = true proof-of-sql-commitment-map = { workspace = true, features = ["substrate"] } proof-of-sql-static-setups = { workspace = true, features = ["baked"] } +proof-of-sql-unchecked-deserialize.workspace = true sp-core.workspace = true sp-api.workspace = true sqlparser.workspace = true diff --git a/pallets/commitments/src/lib.rs b/pallets/commitments/src/lib.rs index 2b814bd5..40b347e7 100644 --- a/pallets/commitments/src/lib.rs +++ b/pallets/commitments/src/lib.rs @@ -347,9 +347,28 @@ pub mod pallet { let commitments_bytes = commitments_bytes.data; - let commitments = commitments_bytes - .try_into() + let PerCommitmentScheme { + hyper_kzg: maybe_hyper_kzg_commitment_bytes, + dynamic_dory: maybe_dynamic_dory_commitment_bytes, + } = commitments_bytes; + let maybe_hyper_kzg_commitment = maybe_hyper_kzg_commitment_bytes + .map(|hyper_kzg_commitment_bytes| (&hyper_kzg_commitment_bytes).try_into()) + .transpose() .map_err(|_| Error::DeserializeCommitment)?; + let maybe_dynamic_dory_commitment = maybe_dynamic_dory_commitment_bytes + .map(|dynamic_dory_commitment_bytes| (&dynamic_dory_commitment_bytes).try_into()) + .transpose() + .map_err(|_| Error::DeserializeCommitment)? + .map(|unchecked_dynamic_dory_commitment| { + proof_of_sql_unchecked_deserialize::map_table_commitment( + &unchecked_dynamic_dory_commitment, + Into::into, + ) + }); + let commitments = PerCommitmentScheme { + hyper_kzg: maybe_hyper_kzg_commitment, + dynamic_dory: maybe_dynamic_dory_commitment, + }; let insert_with_meta_columns = insert_with_meta_columns_bytes .try_into() diff --git a/proof-of-sql/unchecked-deserialize/Cargo.toml b/proof-of-sql/unchecked-deserialize/Cargo.toml new file mode 100644 index 00000000..0c01bc3c --- /dev/null +++ b/proof-of-sql/unchecked-deserialize/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "proof-of-sql-unchecked-deserialize" +version = "0.1.0" +license.workspace = true +authors.workspace = true +homepage.workspace = true +repository.workspace = true +edition.workspace = true + +[dependencies] +proof-of-sql.workspace = true +ark-serialize.workspace = true +derive_more.workspace = true +serde.workspace = true + +[lints] +workspace = true + + + diff --git a/proof-of-sql/unchecked-deserialize/README.md b/proof-of-sql/unchecked-deserialize/README.md new file mode 100644 index 00000000..a350c23d --- /dev/null +++ b/proof-of-sql/unchecked-deserialize/README.md @@ -0,0 +1,2 @@ +# `proof-of-sql-unchecked-deserialize` +Utility for proof-of-sql that enables efficient deserialization (using no validation). \ No newline at end of file diff --git a/proof-of-sql/unchecked-deserialize/src/lib.rs b/proof-of-sql/unchecked-deserialize/src/lib.rs new file mode 100644 index 00000000..111f359c --- /dev/null +++ b/proof-of-sql/unchecked-deserialize/src/lib.rs @@ -0,0 +1,6 @@ +//! This crate enables unchecked deserialization for certain types, in particular `TableCommitment``. + +mod unchecked_dynamic_dory_commitment; +pub use crate::unchecked_dynamic_dory_commitment::UncheckedDynamicDoryCommitment; +mod table_commitment_util; +pub use crate::table_commitment_util::map_table_commitment; diff --git a/proof-of-sql/unchecked-deserialize/src/table_commitment_util.rs b/proof-of-sql/unchecked-deserialize/src/table_commitment_util.rs new file mode 100644 index 00000000..d061fc8a --- /dev/null +++ b/proof-of-sql/unchecked-deserialize/src/table_commitment_util.rs @@ -0,0 +1,19 @@ +//! Module containing utility functions `TableCommitment`s. + +use proof_of_sql::base::commitment::{Commitment, TableCommitment}; + +/// Map a `TableCommitment` to a `TableCommitment` by applying `f` to each column commitment. +pub fn map_table_commitment<'a, A: Commitment, B: Commitment, F: Fn(&'a A) -> B>( + table_commitment: &'a TableCommitment, + f: F, +) -> TableCommitment { + TableCommitment::try_new( + table_commitment + .column_commitments() + .iter() + .map(|(i, m, c)| (i.clone(), *m, f(c))) + .collect(), + table_commitment.range().clone(), + ) + .expect("range was cloned from existing commitment, so valid") +} diff --git a/proof-of-sql/unchecked-deserialize/src/unchecked_dynamic_dory_commitment.rs b/proof-of-sql/unchecked-deserialize/src/unchecked_dynamic_dory_commitment.rs new file mode 100644 index 00000000..d800f54e --- /dev/null +++ b/proof-of-sql/unchecked-deserialize/src/unchecked_dynamic_dory_commitment.rs @@ -0,0 +1,83 @@ +//! This module provides `UncheckedDynamicDoryCommitment`, a wrapper around `DynamicDoryCommitment` that allows for unchecked deserialization. + +use core::ops::Mul; + +use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; +use derive_more::{AddAssign, Neg, Sub, SubAssign}; +use proof_of_sql::base::commitment::{Commitment, CommittableColumn}; +use proof_of_sql::proof_primitive::dory::{DoryScalar, DynamicDoryCommitment}; + +#[derive( + Debug, + Sub, + Eq, + PartialEq, + Neg, + Copy, + Clone, + AddAssign, + SubAssign, + CanonicalSerialize, + CanonicalDeserialize, + Default, +)] + +/// A wrapper around `DynamicDoryCommitment` with unchecked deserialization. +/// Note: while it implements the `Commitment` trait, it does not actually implement its methods. +/// This should `only` be used for unchecked deserialization, and then converted to `DynamicDoryCommitment`. +pub struct UncheckedDynamicDoryCommitment(DynamicDoryCommitment); + +impl From for DynamicDoryCommitment { + fn from(value: UncheckedDynamicDoryCommitment) -> Self { + value.0 + } +} +impl From<&UncheckedDynamicDoryCommitment> for DynamicDoryCommitment { + fn from(value: &UncheckedDynamicDoryCommitment) -> Self { + value.0 + } +} + +impl serde::Serialize for UncheckedDynamicDoryCommitment { + fn serialize(&self, serializer: S) -> Result { + let mut bytes = Vec::with_capacity(CanonicalSerialize::compressed_size(self)); + CanonicalSerialize::serialize_compressed(self, &mut bytes) + .map_err(serde::ser::Error::custom)?; + bytes.serialize(serializer) + } +} +impl<'de> serde::Deserialize<'de> for UncheckedDynamicDoryCommitment { + fn deserialize>(deserializer: D) -> Result { + CanonicalDeserialize::deserialize_compressed_unchecked( + Vec::deserialize(deserializer)?.as_slice(), + ) + .map_err(serde::de::Error::custom) + } +} +impl Mul for DoryScalar { + type Output = UncheckedDynamicDoryCommitment; + fn mul(self, _rhs: UncheckedDynamicDoryCommitment) -> Self::Output { + unimplemented!() + } +} +impl Mul<&UncheckedDynamicDoryCommitment> for DoryScalar { + type Output = UncheckedDynamicDoryCommitment; + fn mul(self, _rhs: &UncheckedDynamicDoryCommitment) -> Self::Output { + unimplemented!() + } +} +impl Commitment for UncheckedDynamicDoryCommitment { + type Scalar = DoryScalar; + type PublicSetup<'a> = (); + fn compute_commitments( + _committable_columns: &[CommittableColumn], + _offset: usize, + _setup: &Self::PublicSetup<'_>, + ) -> Vec { + unimplemented!() + } + + fn to_transcript_bytes(&self) -> Vec { + unimplemented!() + } +}