#![cfg_attr(not(feature = "std"), no_std)]
pub use pallet::*;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
mod traits;
mod types;
pub use traits::Plonk;
pub use types::*;
use frame_support::dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo};
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_std::vec::Vec;
#[frame_support::pallet]
pub mod pallet {
use super::*;
#[pallet::config]
pub trait Config: frame_system::Config {
type CustomCircuit: Circuit;
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
#[pallet::storage]
#[pallet::getter(fn public_parameter)]
pub type PublicParameter<T: Config> = StorageValue<_, PublicParameters>;
#[pallet::event]
#[pallet::metadata(u32 = "Metadata")]
pub enum Event<T: Config> {
TrustedSetup(PublicParameters),
}
#[pallet::error]
pub enum Error<T> {
NoneValue,
StorageOverflow,
}
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {}
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::weight(10_000)]
pub fn trusted_setup(
origin: OriginFor<T>,
val: u32,
rng: FullcodecRng,
) -> DispatchResultWithPostInfo {
let transactor = ensure_signed(origin)?;
<Self as Plonk<_>>::trusted_setup(&transactor, val, rng)?;
Ok(().into())
}
#[pallet::weight(10_000)]
pub fn verify(
origin: OriginFor<T>,
vd: VerifierData,
proof: Proof,
public_inputs: Vec<PublicInputValue>,
transcript_init: Transcript,
) -> DispatchResultWithPostInfo {
let transactor = ensure_signed(origin)?;
<Self as Plonk<_>>::verify(&transactor, vd, proof, public_inputs, transcript_init)?;
Ok(().into())
}
}
}
impl<T: Config> Pallet<T> {
pub fn get_public_parameters() -> Option<PublicParameters> {
PublicParameter::<T>::get()
}
}
impl<T: Config> Plonk<T::AccountId> for Pallet<T> {
type CustomCircuit = T::CustomCircuit;
fn trusted_setup(
_who: &T::AccountId,
val: u32,
mut rng: FullcodecRng,
) -> DispatchResultWithPostInfo {
match Self::public_parameter() {
Some(_) => {
return Err(DispatchErrorWithPostInfo {
post_info: PostDispatchInfo::from(()),
error: DispatchError::Other("already setup"),
})
}
None => {
let pp = PublicParameters::setup(1 << val, &mut rng).unwrap();
PublicParameter::<T>::put(&pp);
Event::<T>::TrustedSetup(pp);
return Ok(().into());
}
}
}
fn verify(
_who: &T::AccountId,
vd: VerifierData,
proof: Proof,
public_inputs: Vec<PublicInputValue>,
transcript_init: Transcript,
) -> DispatchResultWithPostInfo {
match Self::public_parameter() {
Some(pp) => {
match T::CustomCircuit::verify(&pp, &vd, &proof, &public_inputs, transcript_init.0)
{
Ok(_) => return Ok(().into()),
Err(_) => {
return Err(DispatchErrorWithPostInfo {
post_info: PostDispatchInfo::from(()),
error: DispatchError::Other("invalid proof"),
})
}
}
}
None => {
return Err(DispatchErrorWithPostInfo {
post_info: PostDispatchInfo::from(()),
error: DispatchError::Other("setup not yet"),
})
}
}
}
}