fix frontend::Operation::new_entry + doc improvements (#370)
This commit is contained in:
parent
4fa285d9fb
commit
7f120f026d
5 changed files with 206 additions and 222 deletions
|
|
@ -8,9 +8,9 @@ use serde::{Deserialize, Serialize};
|
|||
pub use serialization::{SerializedMainPod, SerializedSignedPod};
|
||||
|
||||
use crate::middleware::{
|
||||
self, check_st_tmpl, hash_op, hash_str, max_op, prod_op, sum_op, AnchoredKey, Key,
|
||||
MainPodInputs, NativeOperation, OperationAux, OperationType, Params, PodId, PodProver,
|
||||
PodSigner, Statement, StatementArg, VDSet, Value, ValueRef, KEY_TYPE, SELF,
|
||||
self, check_custom_pred, check_st_tmpl, hash_op, hash_str, max_op, prod_op, sum_op,
|
||||
AnchoredKey, Key, MainPodInputs, NativeOperation, OperationAux, OperationType, Params, PodId,
|
||||
PodProver, PodSigner, Statement, StatementArg, VDSet, Value, ValueRef, KEY_TYPE, SELF,
|
||||
};
|
||||
|
||||
mod custom;
|
||||
|
|
@ -285,190 +285,138 @@ impl MainPodBuilder {
|
|||
|
||||
fn op_statement(&mut self, op: Operation) -> Result<Statement> {
|
||||
use NativeOperation::*;
|
||||
let arg_error = |s: &str| Error::op_invalid_args(s.to_string());
|
||||
let st = match op.0 {
|
||||
OperationType::Native(o) => match (o, &op.1.as_slice()) {
|
||||
(None, &[]) => Statement::None,
|
||||
(NewEntry, &[OperationArg::Entry(k, v)]) => {
|
||||
Statement::equal(AnchoredKey::from((SELF, k.as_str())), v.clone())
|
||||
}
|
||||
(EqualFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("equal-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("equal-from-entries"))?;
|
||||
if v1 == v2 {
|
||||
Statement::equal(r1, r2)
|
||||
} else {
|
||||
return Err(arg_error("equal-from-entries"));
|
||||
OperationType::Native(o) => {
|
||||
let native_arg_error = move || Error::op_invalid_args(format!("{o:?}"));
|
||||
match (o, &op.1.as_slice()) {
|
||||
(None, &[]) => Statement::None,
|
||||
(NewEntry, &[OperationArg::Entry(k, v)]) => {
|
||||
Statement::equal(AnchoredKey::from((SELF, k.as_str())), v.clone())
|
||||
}
|
||||
(EqualFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 == v2 {
|
||||
Statement::equal(r1, r2)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(NotEqualFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 != v2 {
|
||||
Statement::not_equal(r1, r2)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(LtFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 < v2 {
|
||||
Statement::lt(r1, r2)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(LtEqFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 <= v2 {
|
||||
Statement::not_equal(r1, r2)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(CopyStatement, &[OperationArg::Statement(s)]) => s.clone(),
|
||||
(
|
||||
TransitiveEqualFromStatements,
|
||||
&[OperationArg::Statement(Statement::Equal(r1, r2)), OperationArg::Statement(Statement::Equal(r3, r4))],
|
||||
) => {
|
||||
if r2 == r3 {
|
||||
Statement::Equal(r1.clone(), r4.clone())
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(LtToNotEqual, &[OperationArg::Statement(Statement::Lt(r1, r2))]) => {
|
||||
Statement::NotEqual(r1.clone(), r2.clone())
|
||||
}
|
||||
(SumOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if middleware::Operation::check_int_fn(v1, v2, v3, sum_op)? {
|
||||
Statement::SumOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(ProductOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if middleware::Operation::check_int_fn(v1, v2, v3, prod_op)? {
|
||||
Statement::ProductOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(MaxOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if middleware::Operation::check_int_fn(v1, v2, v3, max_op)? {
|
||||
Statement::MaxOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(HashOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if v1 == &hash_op(v2.clone(), v3.clone()) {
|
||||
Statement::HashOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(ContainsFromEntries, &[a1, a2, a3]) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r3, _v3) = a3.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
// TODO: validate proof
|
||||
Statement::Contains(r1, r2, r3)
|
||||
}
|
||||
(NotContainsFromEntries, &[a1, a2]) => {
|
||||
let (r1, _v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, _v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
// TODO: validate proof
|
||||
Statement::NotContains(r1, r2)
|
||||
}
|
||||
(PublicKeyOf, &[a1, a2]) => {
|
||||
let (r1, v1) = a1.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
let (r2, v2) = a2.value_and_ref().ok_or_else(native_arg_error)?;
|
||||
if middleware::Operation::check_public_key(v1, v2)? {
|
||||
Statement::PublicKeyOf(r1, r2)
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
(t, _) => {
|
||||
if t.is_syntactic_sugar() {
|
||||
return Err(Error::custom(format!(
|
||||
"Unexpected syntactic sugar: {:?}",
|
||||
t
|
||||
)));
|
||||
} else {
|
||||
return Err(native_arg_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
(NotEqualFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("not-equal-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("not-equal-from-entries"))?;
|
||||
if v1 != v2 {
|
||||
Statement::not_equal(r1, r2)
|
||||
} else {
|
||||
return Err(arg_error("not-equal-from-entries"));
|
||||
}
|
||||
}
|
||||
(LtFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("lt-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("lt-from-entries"))?;
|
||||
if v1 < v2 {
|
||||
Statement::lt(r1, r2)
|
||||
} else {
|
||||
return Err(arg_error("lt-from-entries"));
|
||||
}
|
||||
}
|
||||
(LtEqFromEntries, &[a1, a2]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("lt-eq-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("lt-eq-from-entries"))?;
|
||||
if v1 <= v2 {
|
||||
Statement::not_equal(r1, r2)
|
||||
} else {
|
||||
return Err(arg_error("lt-eq-from-entries"));
|
||||
}
|
||||
}
|
||||
(CopyStatement, &[OperationArg::Statement(s)]) => s.clone(),
|
||||
(
|
||||
TransitiveEqualFromStatements,
|
||||
&[OperationArg::Statement(Statement::Equal(r1, r2)), OperationArg::Statement(Statement::Equal(r3, r4))],
|
||||
) => {
|
||||
if r2 == r3 {
|
||||
Statement::Equal(r1.clone(), r4.clone())
|
||||
} else {
|
||||
return Err(arg_error("transitive-eq"));
|
||||
}
|
||||
}
|
||||
(LtToNotEqual, &[OperationArg::Statement(Statement::Lt(r1, r2))]) => {
|
||||
Statement::NotEqual(r1.clone(), r2.clone())
|
||||
}
|
||||
(SumOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("sum-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("sum-from-entries"))?;
|
||||
let (r3, v3) = a3
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("sum-from-entries"))?;
|
||||
if middleware::Operation::check_int_fn(v1, v2, v3, sum_op)? {
|
||||
Statement::SumOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(arg_error("sum-from-entries"));
|
||||
}
|
||||
}
|
||||
(ProductOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("prod-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("prod-from-entries"))?;
|
||||
let (r3, v3) = a3
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("prod-from-entries"))?;
|
||||
if middleware::Operation::check_int_fn(v1, v2, v3, prod_op)? {
|
||||
Statement::ProductOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(arg_error("prod-from-entries"));
|
||||
}
|
||||
}
|
||||
(MaxOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("max-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("max-from-entries"))?;
|
||||
let (r3, v3) = a3
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("max-from-entries"))?;
|
||||
if middleware::Operation::check_int_fn(v1, v2, v3, max_op)? {
|
||||
Statement::MaxOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(arg_error("max-from-entries"));
|
||||
}
|
||||
}
|
||||
(HashOf, &[a1, a2, a3]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("hash-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("hash-from-entries"))?;
|
||||
let (r3, v3) = a3
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("hash-from-entries"))?;
|
||||
if v1 == &hash_op(v2.clone(), v3.clone()) {
|
||||
Statement::HashOf(r1, r2, r3)
|
||||
} else {
|
||||
return Err(arg_error("hash-from-entries"));
|
||||
}
|
||||
}
|
||||
(ContainsFromEntries, &[a1, a2, a3]) => {
|
||||
let (r1, _v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("contains-from-entries"))?;
|
||||
let (r2, _v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("contains-from-entries"))?;
|
||||
let (r3, _v3) = a3
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("contains-from-entries"))?;
|
||||
// TODO: validate proof
|
||||
Statement::Contains(r1, r2, r3)
|
||||
}
|
||||
(NotContainsFromEntries, &[a1, a2]) => {
|
||||
let (r1, _v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("contains-from-entries"))?;
|
||||
let (r2, _v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("contains-from-entries"))?;
|
||||
// TODO: validate proof
|
||||
Statement::NotContains(r1, r2)
|
||||
}
|
||||
(PublicKeyOf, &[a1, a2]) => {
|
||||
let (r1, v1) = a1
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("public-key-from-entries"))?;
|
||||
let (r2, v2) = a2
|
||||
.value_and_ref()
|
||||
.ok_or_else(|| arg_error("public-key-from-entries"))?;
|
||||
if middleware::Operation::check_public_key(v1, v2)? {
|
||||
Statement::PublicKeyOf(r1, r2)
|
||||
} else {
|
||||
return Err(arg_error("public-key-from-entries"));
|
||||
}
|
||||
}
|
||||
(t, _) => {
|
||||
if t.is_syntactic_sugar() {
|
||||
return Err(Error::custom(format!(
|
||||
"Unexpected syntactic sugar: {:?}",
|
||||
t
|
||||
)));
|
||||
} else {
|
||||
return Err(arg_error("malformed operation"));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
OperationType::Custom(cpr) => {
|
||||
let pred = &cpr.batch.predicates()[cpr.index];
|
||||
if pred.statements.len() != op.1.len() {
|
||||
|
|
@ -509,6 +457,7 @@ impl MainPodBuilder {
|
|||
.take(pred.args_len)
|
||||
.map(|v| v.unwrap_or_else(|| v_default.clone()))
|
||||
.collect();
|
||||
check_custom_pred(&self.params, &cpr, &args, &st_args)?;
|
||||
Statement::Custom(cpr, st_args)
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -164,10 +164,10 @@ macro_rules! op_impl_st {
|
|||
}
|
||||
|
||||
impl Operation {
|
||||
pub fn new_entry(a1: impl Into<OperationArg>, a2: impl Into<Value>) -> Self {
|
||||
pub fn new_entry(a1: impl Into<String>, a2: impl Into<Value>) -> Self {
|
||||
Self(
|
||||
OperationType::Native(NativeOperation::NewEntry),
|
||||
vec![a1.into(), a2.into().into()],
|
||||
vec![OperationArg::Entry(a1.into(), a2.into())],
|
||||
OperationAux::None,
|
||||
)
|
||||
}
|
||||
|
|
@ -180,6 +180,12 @@ impl Operation {
|
|||
op_impl_oa!(sum_of, SumOf, 3);
|
||||
op_impl_oa!(product_of, ProductOf, 3);
|
||||
op_impl_oa!(max_of, MaxOf, 3);
|
||||
/// Creates a custom operation.
|
||||
///
|
||||
/// `args` should contain the statements that are needed to prove the
|
||||
/// custom statement. It should have the same length as
|
||||
/// `cpr.predicate().statements()`. If `cpr` refers to an `or` predicate,
|
||||
/// then all but one of the statements should be `Statement::None`.
|
||||
pub fn custom(cpr: CustomPredicateRef, args: Vec<OperationArg>) -> Self {
|
||||
Self(OperationType::Custom(cpr), args, OperationAux::None)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue