No Pod IDs (#394)
- middleware:
- Add `Statement::Intro`
- Add `SignedBy` native predicate and operation. The signature is auxiliary data to the operation
- Rename `PodSigner` to `Signer` with a new API (just for signing `RawValue`)
- Removed `NewEntry` operation. Use `ContainsFromEntries` instead
- Remove `KEY_SIGNER` and `KEY_TYPE` which are no longer used
- Merge `RecursivePod` and `Pod` traits
- Change the `Pod::deserialize_data` method to use `Self` instead of `Box<dyn Pod>`
- Extend `Pod` trait with these methods:
- `is_main`: when the pod is Main, in a (recursive) verification its vk will be checked to exist in the vd_set but not if it's intro pod
- `is_mock`: skip some verifications in the recursive mock MainPod verification
- `verifier_data_hash`
- `pod_id` renamed to `statements_hash`
- AnchoredKeys are now a pair of dictionary root and key
- Entry statements are now defined as Contains with literal arguments
- Operations that take Entries now use Contains statements with literal arguments
- frontend:
- Rename `SignedPod` to `SignedDict` (which now contains the dict, public key and signature, and can still `verify(self)`ed)
- The `SignedDict` keeps the method `get_statement` for convenience but now it returns a `Contains` statement that proves the existence of the key in the dict
- The `MainPodBuilder` automatically inserts a `Contains` statement when an operation is added that uses an entry as argument that was not yet "opened".
- Removed the `literal` methods from the `MainPodBuilder` that were loading literals to anchored keys: that was no longer needed after we introduced literal arguments
- backend
- Only verify inclusion of the verifying key into the vd_set if the pod is MainPod. A pod is not MainPod if the first statement is Intro.
- Reject intro pods that have non-intro statements
- Empty pod now returns an intro statement
- Don't insert a type statement automatically in MainPod and MockMainPod. We get rid of the type entry.
- Implement `SignedBy` operation, which uses the muxed table to store signature verifications
- Rename `PodId` to `statements_hash` or `sts_hash` for short. Now this is only used as a hash of the statements for the circuits public inputs.
- Refactor normalization of `self` statements:
- Before: replace values that contain `SELF` by the given pod_id
- After: place the verifying key hash into the Intro predicates
This commit is contained in:
parent
122f9c3cac
commit
0e2f7b756e
39 changed files with 2127 additions and 3064 deletions
|
|
@ -9,14 +9,9 @@ use serde::{Deserialize, Serialize};
|
|||
use strum_macros::FromRepr;
|
||||
|
||||
use crate::middleware::{
|
||||
AnchoredKey, CustomPredicateRef, Error, Params, Result, ToFields, Value, F, VALUE_SIZE,
|
||||
self, AnchoredKey, CustomPredicateRef, Error, Params, Result, ToFields, Value, F, VALUE_SIZE,
|
||||
};
|
||||
|
||||
// TODO: Maybe store KEY_SIGNER and KEY_TYPE as Key with lazy_static
|
||||
// hash(KEY_SIGNER) = [2145458785152392366, 15113074911296146791, 15323228995597834291, 11804480340100333725]
|
||||
pub const KEY_SIGNER: &str = "_signer";
|
||||
// hash(KEY_TYPE) = [17948789436443445142, 12513915140657440811, 15878361618879468769, 938231894693848619]
|
||||
pub const KEY_TYPE: &str = "_type";
|
||||
pub const STATEMENT_ARG_F_LEN: usize = 8;
|
||||
|
||||
#[derive(Clone, Copy, Debug, FromRepr, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
|
|
@ -34,9 +29,10 @@ pub enum NativePredicate {
|
|||
MaxOf = 10,
|
||||
HashOf = 11,
|
||||
PublicKeyOf = 12,
|
||||
ContainerInsert = 13,
|
||||
ContainerUpdate = 14,
|
||||
ContainerDelete = 15,
|
||||
SignedBy = 13,
|
||||
ContainerInsert = 14,
|
||||
ContainerUpdate = 15,
|
||||
ContainerDelete = 16,
|
||||
|
||||
// Syntactic sugar predicates. These predicates are not supported by the backend. The
|
||||
// frontend compiler is responsible of translating these predicates into the predicates above.
|
||||
|
|
@ -73,6 +69,7 @@ impl Display for NativePredicate {
|
|||
NativePredicate::MaxOf => "MaxOf",
|
||||
NativePredicate::HashOf => "HashOf",
|
||||
NativePredicate::PublicKeyOf => "PublicKeyOf",
|
||||
NativePredicate::SignedBy => "SignedBy",
|
||||
NativePredicate::ContainerInsert => "ContainerInsert",
|
||||
NativePredicate::ContainerUpdate => "ContainerUpdate",
|
||||
NativePredicate::ContainerDelete => "ContainerDelete",
|
||||
|
|
@ -98,12 +95,20 @@ impl ToFields for NativePredicate {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct IntroPredicateRef {
|
||||
pub name: String,
|
||||
pub args_len: usize,
|
||||
pub verifier_data_hash: middleware::Hash,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(tag = "type", content = "value")]
|
||||
pub enum Predicate {
|
||||
Native(NativePredicate),
|
||||
BatchSelf(usize),
|
||||
Custom(CustomPredicateRef),
|
||||
Intro(IntroPredicateRef),
|
||||
}
|
||||
|
||||
impl From<NativePredicate> for Predicate {
|
||||
|
|
@ -117,6 +122,7 @@ pub enum PredicatePrefix {
|
|||
Native = 1,
|
||||
BatchSelf = 2,
|
||||
Custom = 3,
|
||||
Intro = 4,
|
||||
}
|
||||
|
||||
impl From<PredicatePrefix> for F {
|
||||
|
|
@ -133,6 +139,8 @@ impl ToFields for Predicate {
|
|||
// CustomPredicateRef(pb, i) as
|
||||
// (3, [hash of pb], i) -- pb hashes to 4 field elements
|
||||
// -- i: usize
|
||||
// IntroPredicateRef(vd_hash) as
|
||||
// (4, [vd_hash], 0)
|
||||
|
||||
// in every case: pad to (hash_size + 2) field elements
|
||||
let mut fields: Vec<F> = match self {
|
||||
|
|
@ -148,6 +156,11 @@ impl ToFields for Predicate {
|
|||
.chain(iter::once(F::from_canonical_usize(*index)))
|
||||
.collect()
|
||||
}
|
||||
Self::Intro(IntroPredicateRef {
|
||||
verifier_data_hash, ..
|
||||
}) => iter::once(F::from(PredicatePrefix::Intro))
|
||||
.chain(verifier_data_hash.0)
|
||||
.collect(),
|
||||
};
|
||||
fields.resize_with(Params::predicate_size(), || F::from_canonical_u64(0));
|
||||
fields
|
||||
|
|
@ -172,6 +185,7 @@ impl fmt::Display for Predicate {
|
|||
write!(f, "{}", batch.predicates()[*index].name)
|
||||
}
|
||||
}
|
||||
Self::Intro(IntroPredicateRef { name, .. }) => write!(f, "{}", name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -196,6 +210,7 @@ pub enum Statement {
|
|||
MaxOf(ValueRef, ValueRef, ValueRef),
|
||||
HashOf(ValueRef, ValueRef, ValueRef),
|
||||
PublicKeyOf(ValueRef, ValueRef),
|
||||
SignedBy(ValueRef, ValueRef),
|
||||
ContainerInsert(
|
||||
/* new_root */ ValueRef,
|
||||
/* old_root */ ValueRef,
|
||||
|
|
@ -214,6 +229,7 @@ pub enum Statement {
|
|||
/* key */ ValueRef,
|
||||
),
|
||||
Custom(CustomPredicateRef, Vec<Value>),
|
||||
Intro(IntroPredicateRef, Vec<Value>),
|
||||
}
|
||||
|
||||
macro_rules! statement_constructor {
|
||||
|
|
@ -258,6 +274,7 @@ impl Statement {
|
|||
statement_constructor!(max_of, MaxOf, 3);
|
||||
statement_constructor!(hash_of, HashOf, 3);
|
||||
statement_constructor!(public_key_of, PublicKeyOf, 2);
|
||||
statement_constructor!(signed_by, SignedBy, 2);
|
||||
statement_constructor!(insert, ContainerInsert, 4);
|
||||
statement_constructor!(update, ContainerUpdate, 4);
|
||||
statement_constructor!(delete, ContainerDelete, 3);
|
||||
|
|
@ -276,10 +293,12 @@ impl Statement {
|
|||
Self::MaxOf(_, _, _) => Native(NativePredicate::MaxOf),
|
||||
Self::HashOf(_, _, _) => Native(NativePredicate::HashOf),
|
||||
Self::PublicKeyOf(_, _) => Native(NativePredicate::PublicKeyOf),
|
||||
Self::SignedBy(_, _) => Native(NativePredicate::SignedBy),
|
||||
Self::ContainerInsert(_, _, _, _) => Native(NativePredicate::ContainerInsert),
|
||||
Self::ContainerUpdate(_, _, _, _) => Native(NativePredicate::ContainerUpdate),
|
||||
Self::ContainerDelete(_, _, _) => Native(NativePredicate::ContainerDelete),
|
||||
Self::Custom(cpr, _) => Custom(cpr.clone()),
|
||||
Self::Intro(ir, _) => Intro(ir.clone()),
|
||||
}
|
||||
}
|
||||
pub fn args(&self) -> Vec<StatementArg> {
|
||||
|
|
@ -297,6 +316,7 @@ impl Statement {
|
|||
Self::MaxOf(ak1, ak2, ak3) => vec![ak1.into(), ak2.into(), ak3.into()],
|
||||
Self::HashOf(ak1, ak2, ak3) => vec![ak1.into(), ak2.into(), ak3.into()],
|
||||
Self::PublicKeyOf(ak1, ak2) => vec![ak1.into(), ak2.into()],
|
||||
Self::SignedBy(ak1, ak2) => vec![ak1.into(), ak2.into()],
|
||||
Self::ContainerInsert(ak1, ak2, ak3, ak4) => {
|
||||
vec![ak1.into(), ak2.into(), ak3.into(), ak4.into()]
|
||||
}
|
||||
|
|
@ -305,6 +325,7 @@ impl Statement {
|
|||
}
|
||||
Self::ContainerDelete(ak1, ak2, ak3) => vec![ak1.into(), ak2.into(), ak3.into()],
|
||||
Self::Custom(_, args) => Vec::from_iter(args.into_iter().map(Literal)),
|
||||
Self::Intro(_, args) => Vec::from_iter(args.into_iter().map(Literal)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -351,6 +372,9 @@ impl Statement {
|
|||
(Native(NativePredicate::PublicKeyOf), &[a1, a2]) => {
|
||||
Self::PublicKeyOf(a1.try_into()?, a2.try_into()?)
|
||||
}
|
||||
(Native(NativePredicate::SignedBy), &[a1, a2]) => {
|
||||
Self::SignedBy(a1.try_into()?, a2.try_into()?)
|
||||
}
|
||||
(Native(NativePredicate::ContainerInsert), &[a1, a2, a3, a4]) => Self::ContainerInsert(
|
||||
a1.try_into()?,
|
||||
a2.try_into()?,
|
||||
|
|
@ -380,6 +404,16 @@ impl Statement {
|
|||
.collect();
|
||||
Self::Custom(cpr, v_args?)
|
||||
}
|
||||
(Intro(ir), _) => {
|
||||
let v_args: Result<Vec<Value>> = args
|
||||
.iter()
|
||||
.map(|x| match x {
|
||||
StatementArg::Literal(v) => Ok(v.clone()),
|
||||
_ => Err(Error::incorrect_statements_args()),
|
||||
})
|
||||
.collect();
|
||||
Self::Intro(ir, v_args?)
|
||||
}
|
||||
};
|
||||
Ok(st)
|
||||
}
|
||||
|
|
@ -453,7 +487,7 @@ impl ToFields for StatementArg {
|
|||
/// Encoding:
|
||||
/// - None => [0, 0, 0, 0, 0, 0, 0, 0]
|
||||
/// - Literal(v) => [[v], 0, 0, 0, 0]
|
||||
/// - Key(pod_id, key) => [[pod_id], [key]]
|
||||
/// - Key(root, key) => [[root], [key]]
|
||||
/// - WildcardLiteral(v) => [[v], 0, 0, 0, 0]
|
||||
fn to_fields(&self, params: &Params) -> Vec<F> {
|
||||
// NOTE for @ax0: I removed the old comment because may `to_fields` implementations do
|
||||
|
|
@ -467,7 +501,7 @@ impl ToFields for StatementArg {
|
|||
.chain(iter::repeat(F::ZERO).take(STATEMENT_ARG_F_LEN - VALUE_SIZE))
|
||||
.collect(),
|
||||
StatementArg::Key(ak) => {
|
||||
let mut fields = ak.pod_id.to_fields(params);
|
||||
let mut fields = ak.root.to_fields(params);
|
||||
fields.extend(ak.key.to_fields(params));
|
||||
fields
|
||||
}
|
||||
|
|
@ -528,17 +562,3 @@ where
|
|||
Self::Literal(value.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::middleware::hash_str;
|
||||
|
||||
#[test]
|
||||
fn test_print_special_keys() {
|
||||
let key = hash_str(KEY_SIGNER);
|
||||
println!("hash(KEY_SIGNER) = {:?}", key);
|
||||
let key = hash_str(KEY_TYPE);
|
||||
println!("hash(KEY_TYPE) = {:?}", key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue