Allow literals in statement templates (#287)

This PR is a continuation of the work done in #276 
- Fix PodType in MainPod (we were using `MockMain` instead of `Main`)
- Update anchored keys in statement template arguments to only support wildcards in the origin and literal keys as the key.
  - Update the pest grammar accordingly
  - Update the parser accordingly
- Rewrite the eth_dos example in a recursive manner so that we use one recursive pod for every distance increment of 1.
  - I've also used the podlang to define the eth_dos custom predicates.  Currently all predicates are in a single batch (previously `eth_friend` was in a different batch).  With #286 we could define `eth_friend` in a different batch again.
    - I was feeling a bit creative and used a format macro to pass `Value`s from rust to the podlang code.
  - The eth_dos is now written using literals.  This resolves https://github.com/0xPARC/pod2/issues/255
- Remove `StatementArg::WildcardValue` in favor of `StatementArg::Literal`.  The `WildcardValue` was just a way to have some kind of typing for values that would be used as arguments in custom predicates.  Now that we can have literals in any statement this value can be anything, so I just removed the `WildcardValue` and use `Literal` instead.  On the backend it was already the case that both cases were treated the same way (after all, `WildcardValue` and `Literal` were 4 fields in the backend).
  - Added a new type for Value: `PodId` so that we can use it for custom predicates that take a pod id to be used in a wildcard
- Add a mock vd_set that is empty for tests that don't use plonky2; this allows running those tests individually without paying for the expensive work of calculating the vd for various circuits.
- rename StatementTmplArg::WildcardValue to StatementTmplArg::Wildcard
This commit is contained in:
Eduard S. 2025-06-16 16:38:38 +02:00 committed by GitHub
parent 7d0d3ad769
commit 3c6930dfe6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 659 additions and 1111 deletions

View file

@ -206,6 +206,7 @@ impl Ord for Hash {
}
}
// TODO: In alternate mode, don't shorten the hash
impl fmt::Display for Hash {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let v0 = self.0[0].to_canonical_u64();

View file

@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use crate::middleware::{
hash_fields, Error, Hash, Key, NativePredicate, Params, Predicate, Result, ToFields, Value,
EMPTY_HASH, F, HASH_SIZE, VALUE_SIZE,
EMPTY_HASH, F, VALUE_SIZE,
};
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
@ -37,75 +37,14 @@ impl ToFields for Wildcard {
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", content = "value")]
pub enum KeyOrWildcard {
Key(Key),
Wildcard(Wildcard),
}
impl fmt::Display for KeyOrWildcard {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Key(k) => k.fmt(f),
Self::Wildcard(wc) => wc.fmt(f),
}
}
}
impl ToFields for KeyOrWildcard {
// Encoding:
// - Key(k) => [[k]]
// - Wildcard(index) => [[index + 1], 0, 0, 0]
fn to_fields(&self, params: &Params) -> Vec<F> {
match self {
KeyOrWildcard::Key(k) => k.hash().to_fields(params),
KeyOrWildcard::Wildcard(wc) => iter::once(F::from_canonical_u64(wc.index as u64 + 1))
.chain(iter::repeat(F::ZERO))
.take(HASH_SIZE)
.collect(),
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", content = "value")]
pub enum SelfOrWildcard {
SELF,
Wildcard(Wildcard),
}
impl fmt::Display for SelfOrWildcard {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::SELF => write!(f, "SELF"),
Self::Wildcard(wc) => wc.fmt(f),
}
}
}
impl ToFields for SelfOrWildcard {
// Encoding:
// - Self => [0]
// - Wildcard(index) => [index+1]
fn to_fields(&self, _params: &Params) -> Vec<F> {
match self {
SelfOrWildcard::SELF => vec![F::ZERO],
SelfOrWildcard::Wildcard(wc) => vec![F::from_canonical_u64(wc.index as u64 + 1)],
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", content = "value")]
pub enum StatementTmplArg {
None,
Literal(Value),
// AnchoredKey
AnchoredKey(SelfOrWildcard, KeyOrWildcard),
// TODO: This naming is a bit confusing: a WildcardLiteral that contains a Wildcard...
// Could we merge WildcardValue and Value and allow wildcard value apart from pod_id and key?
WildcardLiteral(Wildcard),
// AnchoredKey where the origin is a wildcard
AnchoredKey(Wildcard, Key),
Wildcard(Wildcard),
}
#[derive(Clone, Copy)]
@ -154,7 +93,7 @@ impl ToFields for StatementTmplArg {
.collect();
fields
}
StatementTmplArg::WildcardLiteral(wc) => {
StatementTmplArg::Wildcard(wc) => {
let fields: Vec<F> = iter::once(F::from(StatementTmplArgPrefix::WildcardLiteral))
.chain(wc.to_fields(params))
.chain(iter::repeat(F::ZERO))
@ -177,7 +116,7 @@ impl fmt::Display for StatementTmplArg {
key.fmt(f)?;
write!(f, "]")
}
Self::WildcardLiteral(v) => v.fmt(f),
Self::Wildcard(v) => v.fmt(f),
}
}
}
@ -208,7 +147,7 @@ impl fmt::Display for StatementTmpl {
}
arg.fmt(f)?;
}
writeln!(f)
write!(f, ")")
}
}
@ -451,6 +390,15 @@ impl CustomPredicateBatch {
pub fn predicates(&self) -> &[CustomPredicate] {
&self.predicates
}
pub fn predicate_ref_by_name(
self: &Arc<CustomPredicateBatch>,
name: &str,
) -> Option<CustomPredicateRef> {
self.predicates
.iter()
.enumerate()
.find_map(|(i, cp)| (cp.name == name).then(|| CustomPredicateRef::new(self.clone(), i)))
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
@ -473,26 +421,19 @@ impl CustomPredicateRef {
#[cfg(test)]
mod tests {
use std::array;
use plonky2::field::goldilocks_field::GoldilocksField;
use super::*;
use crate::middleware::{
AnchoredKey, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, Hash,
KeyOrWildcard, NativePredicate, Operation, Params, PodId, PodType, Predicate, Statement,
StatementTmpl, StatementTmplArg, WildcardValue, SELF,
AnchoredKey, CustomPredicate, CustomPredicateBatch, CustomPredicateRef, Key,
NativePredicate, Operation, Params, PodType, Predicate, Statement, StatementTmpl,
StatementTmplArg, SELF,
};
fn st(p: Predicate, args: Vec<StatementTmplArg>) -> StatementTmpl {
StatementTmpl { pred: p, args }
}
fn kow_wc(i: usize) -> KOW {
KOW::Wildcard(wc(i))
}
fn sow_wc(i: usize) -> SOW {
SOW::Wildcard(wc(i))
fn key(name: &str) -> Key {
Key::from(name)
}
fn wc(i: usize) -> Wildcard {
Wildcard {
@ -505,8 +446,6 @@ mod tests {
}
type STA = StatementTmplArg;
type KOW = KeyOrWildcard;
type SOW = SelfOrWildcard;
type P = Predicate;
type NP = NativePredicate;
@ -528,41 +467,35 @@ mod tests {
vec![
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(4), kow_wc(5)),
STA::Literal(2.into()),
],
vec![STA::AnchoredKey(wc(1), key("c")), STA::Literal(2.into())],
),
st(
P::Native(NP::ProductOf),
vec![
STA::AnchoredKey(sow_wc(0), kow_wc(1)),
STA::AnchoredKey(sow_wc(4), kow_wc(5)),
STA::AnchoredKey(sow_wc(2), kow_wc(3)),
STA::AnchoredKey(wc(0), key("a")),
STA::AnchoredKey(wc(1), key("b")),
STA::Literal(Value::from(3)),
],
),
],
2,
names(&["1", "2", "3", "4", "5"]),
1,
names(&["0", "1", "2"]),
)?],
);
let custom_statement = Statement::Custom(
CustomPredicateRef::new(cust_pred_batch.clone(), 0),
vec![
WildcardValue::PodId(SELF),
WildcardValue::Key(Key::from("Some value")),
],
vec![Value::from(SELF)],
);
let custom_deduction = Operation::Custom(
CustomPredicateRef::new(cust_pred_batch, 0),
vec![
Statement::equal(AnchoredKey::from((SELF, "Some constant")), 2),
Statement::equal(AnchoredKey::from((SELF, "c")), 2),
Statement::product_of(
AnchoredKey::from((SELF, "Some value")),
AnchoredKey::from((SELF, "Some constant")),
AnchoredKey::from((SELF, "Some other value")),
AnchoredKey::from((SELF, "a")),
AnchoredKey::from((SELF, "b")),
Value::from(3),
),
],
);
@ -580,38 +513,38 @@ mod tests {
..Default::default()
};
let eth_friend_cp = CustomPredicate::and(
let eth_friend = CustomPredicate::and(
&params,
"eth_friend_cp".into(),
"eth_friend".into(),
vec![
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(4), KeyOrWildcard::Key("type".into())),
STA::AnchoredKey(wc(2), Key::from("_type")),
STA::Literal(PodType::Signed.into()),
],
),
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(4), KeyOrWildcard::Key("signer".into())),
STA::AnchoredKey(sow_wc(0), kow_wc(1)),
STA::AnchoredKey(wc(2), Key::from("_signer")),
STA::Wildcard(wc(0)),
],
),
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(4), KeyOrWildcard::Key("attestation".into())),
STA::AnchoredKey(sow_wc(2), kow_wc(3)),
STA::AnchoredKey(wc(2), Key::from("attestation")),
STA::Wildcard(wc(1)),
],
),
],
4,
names(&["1", "2", "3", "4"]),
2,
names(&["0", "1", "2"]),
)?;
let eth_friend_batch =
CustomPredicateBatch::new(&params, "eth_friend".to_string(), vec![eth_friend_cp]);
CustomPredicateBatch::new(&params, "eth_friend".to_string(), vec![eth_friend]);
// 0
let eth_dos_base = CustomPredicate::and(
@ -620,21 +553,15 @@ mod tests {
vec![
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(0), kow_wc(1)),
STA::AnchoredKey(sow_wc(2), kow_wc(3)),
],
vec![STA::Wildcard(wc(0)), STA::Wildcard(wc(1))],
),
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(4), kow_wc(5)),
STA::Literal(0.into()),
],
vec![STA::Wildcard(wc(2)), STA::Literal(0.into())],
),
],
6,
names(&["0", "1", "2", "3", "4", "5"]),
3,
names(&["0", "1", "2"]),
)?;
// 1
@ -645,98 +572,64 @@ mod tests {
st(
P::BatchSelf(2),
vec![
STA::WildcardLiteral(wc(0)),
STA::WildcardLiteral(wc(1)),
STA::WildcardLiteral(wc(10)),
STA::WildcardLiteral(wc(11)),
STA::WildcardLiteral(wc(8)),
STA::WildcardLiteral(wc(9)),
],
),
st(
P::Native(NP::Equal),
vec![
STA::AnchoredKey(sow_wc(6), kow_wc(7)),
STA::Literal(1.into()),
STA::Wildcard(wc(0)),
STA::Wildcard(wc(4)),
STA::Wildcard(wc(3)),
],
),
st(
P::Native(NP::SumOf),
vec![
STA::AnchoredKey(sow_wc(4), kow_wc(5)),
STA::AnchoredKey(sow_wc(8), kow_wc(9)),
STA::AnchoredKey(sow_wc(6), kow_wc(7)),
STA::Wildcard(wc(2)),
STA::Wildcard(wc(3)),
STA::Literal(Value::from(1)),
],
),
st(
P::Custom(CustomPredicateRef::new(eth_friend_batch.clone(), 0)),
vec![
STA::WildcardLiteral(wc(10)),
STA::WildcardLiteral(wc(11)),
STA::WildcardLiteral(wc(2)),
STA::WildcardLiteral(wc(3)),
],
vec![STA::Wildcard(wc(4)), STA::Wildcard(wc(1))],
),
],
6,
names(&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"]),
3,
names(&["0", "1", "2", "3", "4"]),
)?;
// 2
let eth_dos_distance_either = CustomPredicate::or(
let eth_dos = CustomPredicate::or(
&params,
"eth_dos_distance_either".into(),
"eth_dos".into(),
vec![
st(
P::BatchSelf(0),
vec![
STA::WildcardLiteral(wc(0)),
STA::WildcardLiteral(wc(1)),
STA::WildcardLiteral(wc(2)),
STA::WildcardLiteral(wc(3)),
STA::WildcardLiteral(wc(4)),
STA::WildcardLiteral(wc(5)),
STA::Wildcard(wc(0)),
STA::Wildcard(wc(1)),
STA::Wildcard(wc(2)),
],
),
st(
P::BatchSelf(1),
vec![
STA::WildcardLiteral(wc(0)),
STA::WildcardLiteral(wc(1)),
STA::WildcardLiteral(wc(2)),
STA::WildcardLiteral(wc(3)),
STA::WildcardLiteral(wc(4)),
STA::WildcardLiteral(wc(5)),
STA::Wildcard(wc(0)),
STA::Wildcard(wc(1)),
STA::Wildcard(wc(2)),
],
),
],
6,
names(&["0", "1", "2", "3", "4", "5"]),
3,
names(&["0", "1", "2"]),
)?;
let eth_dos_distance_batch = CustomPredicateBatch::new(
&params,
"ETHDoS_distance".to_string(),
vec![eth_dos_base, eth_dos_ind, eth_dos_distance_either],
vec![eth_dos_base, eth_dos_ind, eth_dos],
);
// Some POD IDs
let pod_id1 = PodId(Hash(array::from_fn(|i| GoldilocksField(i as u64))));
let pod_id2 = PodId(Hash(array::from_fn(|i| GoldilocksField((i * i) as u64))));
let pod_id3 = PodId(Hash(array::from_fn(|i| GoldilocksField((2 * i) as u64))));
let pod_id4 = PodId(Hash(array::from_fn(|i| GoldilocksField((2 * i) as u64))));
// Example statement
let ethdos_example = Statement::Custom(
CustomPredicateRef::new(eth_dos_distance_batch.clone(), 2),
vec![
WildcardValue::PodId(pod_id1),
WildcardValue::Key(Key::from("Alice")),
WildcardValue::PodId(pod_id2),
WildcardValue::Key(Key::from("Bob")),
WildcardValue::PodId(SELF),
WildcardValue::Key(Key::from("Seven")),
],
vec![Value::from("Alice"), Value::from("Bob"), Value::from(7)],
);
// Copies should work.
@ -745,14 +638,7 @@ mod tests {
// This could arise as the inductive step.
let ethdos_ind_example = Statement::Custom(
CustomPredicateRef::new(eth_dos_distance_batch.clone(), 1),
vec![
WildcardValue::PodId(pod_id1),
WildcardValue::Key(Key::from("Alice")),
WildcardValue::PodId(pod_id2),
WildcardValue::Key(Key::from("Bob")),
WildcardValue::PodId(SELF),
WildcardValue::Key(Key::from("Seven")),
],
vec![Value::from("Alice"), Value::from("Bob"), Value::from(7)],
);
assert!(Operation::Custom(
@ -767,29 +653,12 @@ mod tests {
let ethdos_facts = vec![
Statement::Custom(
CustomPredicateRef::new(eth_dos_distance_batch.clone(), 2),
vec![
WildcardValue::PodId(pod_id1),
WildcardValue::Key(Key::from("Alice")),
WildcardValue::PodId(pod_id3),
WildcardValue::Key(Key::from("Charlie")),
WildcardValue::PodId(pod_id4),
WildcardValue::Key(Key::from("Six")),
],
),
Statement::equal(AnchoredKey::from((SELF, "One")), 1),
Statement::sum_of(
AnchoredKey::from((SELF, "Seven")),
AnchoredKey::from((pod_id4, "Six")),
AnchoredKey::from((SELF, "One")),
vec![Value::from("Alice"), Value::from("Charlie"), Value::from(6)],
),
Statement::sum_of(Value::from(7), Value::from(6), Value::from(1)),
Statement::Custom(
CustomPredicateRef::new(eth_friend_batch.clone(), 0),
vec![
WildcardValue::PodId(pod_id3),
WildcardValue::Key(Key::from("Charlie")),
WildcardValue::PodId(pod_id2),
WildcardValue::Key(Key::from("Bob")),
],
vec![Value::from("Charlie"), Value::from("Bob")],
),
];

View file

@ -64,6 +64,7 @@ pub enum TypedValue {
Raw(RawValue),
// Public key variant
PublicKey(PublicKey),
PodId(PodId),
// UNTAGGED TYPES:
#[serde(untagged)]
Array(Array),
@ -109,6 +110,12 @@ impl From<PublicKey> for TypedValue {
}
}
impl From<PodId> for TypedValue {
fn from(id: PodId) -> Self {
TypedValue::PodId(id)
}
}
impl From<Set> for TypedValue {
fn from(s: Set) -> Self {
TypedValue::Set(s)
@ -174,6 +181,7 @@ impl fmt::Display for TypedValue {
TypedValue::Array(a) => write!(f, "arr:{}", a.commitment()),
TypedValue::Raw(v) => write!(f, "{}", v),
TypedValue::PublicKey(p) => write!(f, "ecGFp5_pt:({},{})", p.x, p.u),
TypedValue::PodId(id) => write!(f, "pod_id:{}", id),
}
}
}
@ -189,6 +197,7 @@ impl From<&TypedValue> for RawValue {
TypedValue::Array(a) => RawValue::from(a.commitment()),
TypedValue::Raw(v) => *v,
TypedValue::PublicKey(p) => RawValue::from(hash_fields(&p.as_fields())),
TypedValue::PodId(id) => RawValue::from(id.0),
}
}
}
@ -677,7 +686,7 @@ impl Default for Params {
max_custom_predicate_verifications: 5,
max_custom_predicate_arity: 5,
max_custom_predicate_wildcards: 10,
max_custom_batch_size: 5,
max_custom_batch_size: 5, // TODO: Move down to 4?
max_merkle_proofs_containers: 5,
max_depth_mt_containers: 32,
max_depth_mt_vds: 6, // up to 64 (2^6) different pod circuits

View file

@ -7,9 +7,9 @@ use serde::{Deserialize, Serialize};
use crate::{
backends::plonky2::primitives::merkletree::MerkleProof,
middleware::{
custom::KeyOrWildcard, hash_values, AnchoredKey, CustomPredicate, CustomPredicateRef,
Error, NativePredicate, Params, Predicate, Result, SelfOrWildcard, Statement, StatementArg,
StatementTmplArg, ToFields, Value, ValueRef, Wildcard, WildcardValue, F, SELF,
hash_values, AnchoredKey, CustomPredicate, CustomPredicateRef, Error, NativePredicate,
Params, Predicate, Result, Statement, StatementArg, StatementTmplArg, ToFields, Value,
ValueRef, Wildcard, F, SELF,
},
};
@ -369,14 +369,10 @@ pub fn check_st_tmpl(
st_tmpl_arg: &StatementTmplArg,
st_arg: &StatementArg,
// Map from wildcards to values that we have seen so far.
wildcard_map: &mut [Option<WildcardValue>],
wildcard_map: &mut [Option<Value>],
) -> bool {
// Check that the value `v` at wildcard `wc` exists in the map or set it.
fn check_or_set(
v: WildcardValue,
wc: &Wildcard,
wildcard_map: &mut [Option<WildcardValue>],
) -> bool {
fn check_or_set(v: Value, wc: &Wildcard, wildcard_map: &mut [Option<Value>]) -> bool {
if let Some(prev) = &wildcard_map[wc.index] {
if *prev != v {
// TODO: Return nice error
@ -392,27 +388,19 @@ pub fn check_st_tmpl(
(StatementTmplArg::None, StatementArg::None) => true,
(StatementTmplArg::Literal(lhs), StatementArg::Literal(rhs)) if lhs == rhs => true,
(
StatementTmplArg::AnchoredKey(self_or_wc, key_or_wc),
StatementTmplArg::AnchoredKey(pod_id_wc, key_tmpl),
StatementArg::Key(AnchoredKey { pod_id, key }),
) => {
let pod_id_ok = match self_or_wc {
SelfOrWildcard::SELF => SELF == *pod_id,
SelfOrWildcard::Wildcard(pod_id_wc) => {
check_or_set(WildcardValue::PodId(*pod_id), pod_id_wc, wildcard_map)
}
};
let key_ok = match key_or_wc {
KeyOrWildcard::Key(tmpl_key) => tmpl_key == key,
KeyOrWildcard::Wildcard(key_wc) => {
check_or_set(WildcardValue::Key(key.clone()), key_wc, wildcard_map)
}
};
pod_id_ok && key_ok
let pod_id_ok = check_or_set(Value::from(*pod_id), pod_id_wc, wildcard_map);
pod_id_ok && (key_tmpl == key)
}
(StatementTmplArg::WildcardLiteral(wc), StatementArg::WildcardLiteral(v)) => {
(StatementTmplArg::Wildcard(wc), StatementArg::Literal(v)) => {
check_or_set(v.clone(), wc, wildcard_map)
}
_ => false,
_ => {
println!("DBG {:?} {:?}", st_tmpl_arg, st_arg);
false
}
}
}
@ -420,7 +408,7 @@ pub fn resolve_wildcard_values(
params: &Params,
pred: &CustomPredicate,
args: &[Statement],
) -> Option<Vec<WildcardValue>> {
) -> Option<Vec<Value>> {
// Check that all wildcard have consistent values as assigned in the statements while storing a
// map of their values.
// NOTE: We assume the statements have the same order as defined in the custom predicate. For
@ -444,7 +432,7 @@ pub fn resolve_wildcard_values(
Some(
wildcard_map
.into_iter()
.map(|opt| opt.unwrap_or(WildcardValue::None))
.map(|opt| opt.unwrap_or(Value::from(0)))
.collect(),
)
}
@ -453,7 +441,7 @@ fn check_custom_pred(
params: &Params,
custom_pred_ref: &CustomPredicateRef,
args: &[Statement],
s_args: &[WildcardValue],
s_args: &[Value],
) -> Result<bool> {
let pred = custom_pred_ref.predicate();
if pred.statements.len() != args.len() {

View file

@ -6,8 +6,7 @@ use serde::{Deserialize, Serialize};
use strum_macros::FromRepr;
use crate::middleware::{
AnchoredKey, CustomPredicateRef, Error, Key, Params, PodId, RawValue, Result, ToFields, Value,
EMPTY_VALUE, F, VALUE_SIZE,
AnchoredKey, CustomPredicateRef, Error, Params, Result, ToFields, Value, F, VALUE_SIZE,
};
// TODO: Maybe store KEY_SIGNER and KEY_TYPE as Key with lazy_static
@ -51,39 +50,6 @@ impl ToFields for NativePredicate {
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub enum WildcardValue {
None,
PodId(PodId),
Key(Key),
}
impl WildcardValue {
pub fn raw(&self) -> RawValue {
match self {
WildcardValue::None => EMPTY_VALUE,
WildcardValue::PodId(pod_id) => RawValue::from(pod_id.0),
WildcardValue::Key(key) => key.raw(),
}
}
}
impl fmt::Display for WildcardValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
WildcardValue::None => write!(f, "none"),
WildcardValue::PodId(pod_id) => pod_id.fmt(f),
WildcardValue::Key(key) => key.fmt(f),
}
}
}
impl ToFields for WildcardValue {
fn to_fields(&self, params: &Params) -> Vec<F> {
self.raw().to_fields(params)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "type", content = "value")]
pub enum Predicate {
@ -181,7 +147,7 @@ pub enum Statement {
ProductOf(ValueRef, ValueRef, ValueRef),
MaxOf(ValueRef, ValueRef, ValueRef),
HashOf(ValueRef, ValueRef, ValueRef),
Custom(CustomPredicateRef, Vec<WildcardValue>),
Custom(CustomPredicateRef, Vec<Value>),
}
macro_rules! statement_constructor {
@ -246,7 +212,7 @@ impl Statement {
Self::ProductOf(ak1, ak2, ak3) => vec![ak1.into(), ak2.into(), ak3.into()],
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::Custom(_, args) => Vec::from_iter(args.into_iter().map(WildcardLiteral)),
Self::Custom(_, args) => Vec::from_iter(args.into_iter().map(Literal)),
}
}
@ -296,10 +262,10 @@ impl Statement {
}
(BatchSelf(_), _) => unreachable!(),
(Custom(cpr), _) => {
let v_args: Result<Vec<WildcardValue>> = args
let v_args: Result<Vec<Value>> = args
.iter()
.map(|x| match x {
StatementArg::WildcardLiteral(v) => Ok(v.clone()),
StatementArg::Literal(v) => Ok(v.clone()),
_ => Err(Error::incorrect_statements_args()),
})
.collect();
@ -338,7 +304,6 @@ pub enum StatementArg {
None,
Literal(Value),
Key(AnchoredKey),
WildcardLiteral(WildcardValue),
}
impl fmt::Display for StatementArg {
@ -347,7 +312,6 @@ impl fmt::Display for StatementArg {
StatementArg::None => write!(f, "none"),
StatementArg::Literal(v) => v.fmt(f),
StatementArg::Key(r) => r.fmt(f),
StatementArg::WildcardLiteral(v) => v.fmt(f),
}
}
}
@ -398,12 +362,6 @@ impl ToFields for StatementArg {
fields.extend(ak.key.to_fields(params));
fields
}
StatementArg::WildcardLiteral(v) => v
.raw()
.0
.into_iter()
.chain(iter::repeat(F::ZERO).take(STATEMENT_ARG_F_LEN - VALUE_SIZE))
.collect(),
};
assert_eq!(f.len(), STATEMENT_ARG_F_LEN); // sanity check
f