Refactor frontend/middleware types (#194)
* unify fe/be NativeOp and NativePred * remove Origin in favour of PodId * Combine string and hash in Key * use middleware::AnchoredKey in frontend * merge frontend/middleware types * refactor custom predicates * clean up a bit * fix middleware custom tests * clean up * clean up 2 * add acronyms in typos list
This commit is contained in:
parent
9e860ef262
commit
c232c8dae5
33 changed files with 1985 additions and 2800 deletions
|
|
@ -4,10 +4,10 @@ use std::{collections::HashMap, fmt, iter::IntoIterator};
|
|||
|
||||
use anyhow::{anyhow, Result};
|
||||
use plonky2::field::types::Field;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
// use serde::{Deserialize, Serialize};
|
||||
pub use super::merkletree_circuit::*;
|
||||
use crate::backends::plonky2::basetypes::{hash_fields, Hash, Value, EMPTY_HASH, F};
|
||||
use crate::middleware::{hash_fields, Hash, RawValue, EMPTY_HASH, F};
|
||||
|
||||
/// Implements the MerkleTree specified at
|
||||
/// https://0xparc.github.io/pod2/merkletree.html
|
||||
|
|
@ -19,7 +19,7 @@ pub struct MerkleTree {
|
|||
|
||||
impl MerkleTree {
|
||||
/// builds a new `MerkleTree` where the leaves contain the given key-values
|
||||
pub fn new(max_depth: usize, kvs: &HashMap<Value, Value>) -> Result<Self> {
|
||||
pub fn new(max_depth: usize, kvs: &HashMap<RawValue, RawValue>) -> Result<Self> {
|
||||
// Construct leaves.
|
||||
let mut leaves: Vec<_> = kvs
|
||||
.iter()
|
||||
|
|
@ -50,7 +50,7 @@ impl MerkleTree {
|
|||
}
|
||||
|
||||
/// returns the value at the given key
|
||||
pub fn get(&self, key: &Value) -> Result<Value> {
|
||||
pub fn get(&self, key: &RawValue) -> Result<RawValue> {
|
||||
let path = keypath(self.max_depth, *key)?;
|
||||
let key_resolution = self.root.down(0, self.max_depth, path, None)?;
|
||||
match key_resolution {
|
||||
|
|
@ -60,7 +60,7 @@ impl MerkleTree {
|
|||
}
|
||||
|
||||
/// returns a boolean indicating whether the key exists in the tree
|
||||
pub fn contains(&self, key: &Value) -> Result<bool> {
|
||||
pub fn contains(&self, key: &RawValue) -> Result<bool> {
|
||||
let path = keypath(self.max_depth, *key)?;
|
||||
match self.root.down(0, self.max_depth, path, None) {
|
||||
Ok(Some((k, _))) => {
|
||||
|
|
@ -77,7 +77,7 @@ impl MerkleTree {
|
|||
/// returns a proof of existence, which proves that the given key exists in
|
||||
/// the tree. It returns the `value` of the leaf at the given `key`, and the
|
||||
/// `MerkleProof`.
|
||||
pub fn prove(&self, key: &Value) -> Result<(Value, MerkleProof)> {
|
||||
pub fn prove(&self, key: &RawValue) -> Result<(RawValue, MerkleProof)> {
|
||||
let path = keypath(self.max_depth, *key)?;
|
||||
|
||||
let mut siblings: Vec<Hash> = Vec::new();
|
||||
|
|
@ -102,7 +102,7 @@ impl MerkleTree {
|
|||
/// `key` does not exist in the tree. The return value specifies
|
||||
/// the key-value pair in the leaf reached as a result of
|
||||
/// resolving `key` as well as a `MerkleProof`.
|
||||
pub fn prove_nonexistence(&self, key: &Value) -> Result<MerkleProof> {
|
||||
pub fn prove_nonexistence(&self, key: &RawValue) -> Result<MerkleProof> {
|
||||
let path = keypath(self.max_depth, *key)?;
|
||||
|
||||
let mut siblings: Vec<Hash> = Vec::new();
|
||||
|
|
@ -134,8 +134,8 @@ impl MerkleTree {
|
|||
max_depth: usize,
|
||||
root: Hash,
|
||||
proof: &MerkleProof,
|
||||
key: &Value,
|
||||
value: &Value,
|
||||
key: &RawValue,
|
||||
value: &RawValue,
|
||||
) -> Result<()> {
|
||||
let h = proof.compute_root_from_leaf(max_depth, key, Some(*value))?;
|
||||
|
||||
|
|
@ -152,13 +152,13 @@ impl MerkleTree {
|
|||
max_depth: usize,
|
||||
root: Hash,
|
||||
proof: &MerkleProof,
|
||||
key: &Value,
|
||||
key: &RawValue,
|
||||
) -> Result<()> {
|
||||
match proof.other_leaf {
|
||||
Some((k, _v)) if &k == key => Err(anyhow!("Invalid non-existence proof.")),
|
||||
_ => {
|
||||
let k = proof.other_leaf.map(|(k, _)| k).unwrap_or(*key);
|
||||
let v: Option<Value> = proof.other_leaf.map(|(_, v)| v);
|
||||
let v: Option<RawValue> = proof.other_leaf.map(|(_, v)| v);
|
||||
let h = proof.compute_root_from_leaf(max_depth, &k, v)?;
|
||||
|
||||
if h != root {
|
||||
|
|
@ -180,14 +180,14 @@ impl MerkleTree {
|
|||
|
||||
/// Hash function for key-value pairs. Different branch pair hashes to
|
||||
/// mitigate fake proofs.
|
||||
pub fn kv_hash(key: &Value, value: Option<Value>) -> Hash {
|
||||
pub fn kv_hash(key: &RawValue, value: Option<RawValue>) -> Hash {
|
||||
value
|
||||
.map(|v| hash_fields(&[key.0.to_vec(), v.0.to_vec(), vec![F::ONE]].concat()))
|
||||
.unwrap_or(EMPTY_HASH)
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a MerkleTree {
|
||||
type Item = (&'a Value, &'a Value);
|
||||
type Item = (&'a RawValue, &'a RawValue);
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
|
@ -208,7 +208,7 @@ impl fmt::Display for MerkleTree {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MerkleProof {
|
||||
// note: currently we don't use the `_existence` field, we would use if we merge the methods
|
||||
// `verify` and `verify_nonexistence` into a single one
|
||||
|
|
@ -216,7 +216,7 @@ pub struct MerkleProof {
|
|||
pub(crate) existence: bool,
|
||||
pub(crate) siblings: Vec<Hash>,
|
||||
// other_leaf is used for non-existence proofs
|
||||
pub(crate) other_leaf: Option<(Value, Value)>,
|
||||
pub(crate) other_leaf: Option<(RawValue, RawValue)>,
|
||||
}
|
||||
|
||||
impl fmt::Display for MerkleProof {
|
||||
|
|
@ -238,8 +238,8 @@ impl MerkleProof {
|
|||
fn compute_root_from_leaf(
|
||||
&self,
|
||||
max_depth: usize,
|
||||
key: &Value,
|
||||
value: Option<Value>,
|
||||
key: &RawValue,
|
||||
value: Option<RawValue>,
|
||||
) -> Result<Hash> {
|
||||
if self.siblings.len() >= max_depth {
|
||||
return Err(anyhow!("max depth reached"));
|
||||
|
|
@ -335,7 +335,7 @@ impl Node {
|
|||
max_depth: usize,
|
||||
path: Vec<bool>,
|
||||
mut siblings: Option<&mut Vec<Hash>>,
|
||||
) -> Result<Option<(Value, Value)>> {
|
||||
) -> Result<Option<(RawValue, RawValue)>> {
|
||||
if lvl >= max_depth {
|
||||
return Err(anyhow!("max depth reached"));
|
||||
}
|
||||
|
|
@ -494,11 +494,11 @@ impl Intermediate {
|
|||
struct Leaf {
|
||||
hash: Option<Hash>,
|
||||
path: Vec<bool>,
|
||||
key: Value,
|
||||
value: Value,
|
||||
key: RawValue,
|
||||
value: RawValue,
|
||||
}
|
||||
impl Leaf {
|
||||
fn new(max_depth: usize, key: Value, value: Value) -> Result<Self> {
|
||||
fn new(max_depth: usize, key: RawValue, value: RawValue) -> Result<Self> {
|
||||
Ok(Self {
|
||||
hash: None,
|
||||
path: keypath(max_depth, key)?,
|
||||
|
|
@ -523,7 +523,7 @@ impl Leaf {
|
|||
// max-depth? ie, what happens when two keys share the same path for more bits
|
||||
// than the max_depth?
|
||||
/// returns the path of the given key
|
||||
pub(crate) fn keypath(max_depth: usize, k: Value) -> Result<Vec<bool>> {
|
||||
pub(crate) fn keypath(max_depth: usize, k: RawValue) -> Result<Vec<bool>> {
|
||||
let bytes = k.to_bytes();
|
||||
if max_depth > 8 * bytes.len() {
|
||||
// note that our current keys are of Value type, which are 4 Goldilocks
|
||||
|
|
@ -545,7 +545,7 @@ pub struct Iter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = (&'a Value, &'a Value);
|
||||
type Item = (&'a RawValue, &'a RawValue);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let node = self.state.pop();
|
||||
|
|
@ -586,10 +586,10 @@ pub mod tests {
|
|||
if i == 1 {
|
||||
continue;
|
||||
}
|
||||
kvs.insert(Value::from(i), Value::from(1000 + i));
|
||||
kvs.insert(RawValue::from(i), RawValue::from(1000 + i));
|
||||
}
|
||||
let key = Value::from(13);
|
||||
let value = Value::from(1013);
|
||||
let key = RawValue::from(13);
|
||||
let value = RawValue::from(1013);
|
||||
kvs.insert(key, value);
|
||||
|
||||
let tree = MerkleTree::new(32, &kvs)?;
|
||||
|
|
@ -598,25 +598,25 @@ pub mod tests {
|
|||
println!("{}", tree);
|
||||
|
||||
// Inclusion checks
|
||||
let (v, proof) = tree.prove(&Value::from(13))?;
|
||||
assert_eq!(v, Value::from(1013));
|
||||
let (v, proof) = tree.prove(&RawValue::from(13))?;
|
||||
assert_eq!(v, RawValue::from(1013));
|
||||
println!("{}", proof);
|
||||
|
||||
MerkleTree::verify(32, tree.root(), &proof, &key, &value)?;
|
||||
|
||||
// Exclusion checks
|
||||
let key = Value::from(12);
|
||||
let key = RawValue::from(12);
|
||||
let proof = tree.prove_nonexistence(&key)?;
|
||||
assert_eq!(
|
||||
proof.other_leaf.unwrap(),
|
||||
(Value::from(4), Value::from(1004))
|
||||
(RawValue::from(4), RawValue::from(1004))
|
||||
);
|
||||
println!("{}", proof);
|
||||
|
||||
MerkleTree::verify_nonexistence(32, tree.root(), &proof, &key)?;
|
||||
|
||||
let key = Value::from(1);
|
||||
let proof = tree.prove_nonexistence(&Value::from(1))?;
|
||||
let key = RawValue::from(1);
|
||||
let proof = tree.prove_nonexistence(&RawValue::from(1))?;
|
||||
assert_eq!(proof.other_leaf, None);
|
||||
println!("{}", proof);
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,13 @@ use plonky2::{
|
|||
plonk::circuit_builder::CircuitBuilder,
|
||||
};
|
||||
|
||||
use crate::backends::plonky2::{
|
||||
basetypes::{Hash, Value, D, EMPTY_HASH, EMPTY_VALUE, F, HASH_SIZE},
|
||||
circuits::common::{CircuitBuilderPod, ValueTarget},
|
||||
primitives::merkletree::MerkleProof,
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
basetypes::D,
|
||||
circuits::common::{CircuitBuilderPod, ValueTarget},
|
||||
primitives::merkletree::MerkleProof,
|
||||
},
|
||||
middleware::{Hash, RawValue, EMPTY_HASH, EMPTY_VALUE, F, HASH_SIZE},
|
||||
};
|
||||
|
||||
/// `MerkleProofGadget` allows to verify both proofs of existence and proofs
|
||||
|
|
@ -163,8 +166,8 @@ impl MerkleClaimAndProofTarget {
|
|||
existence: bool,
|
||||
root: Hash,
|
||||
proof: MerkleProof,
|
||||
key: Value,
|
||||
value: Value,
|
||||
key: RawValue,
|
||||
value: RawValue,
|
||||
) -> Result<()> {
|
||||
pw.set_bool_target(self.enabled, enabled)?;
|
||||
pw.set_hash_target(self.root, HashOut::from_vec(root.0.to_vec()))?;
|
||||
|
|
@ -268,8 +271,8 @@ impl MerkleProofExistenceTarget {
|
|||
enabled: bool,
|
||||
root: Hash,
|
||||
proof: MerkleProof,
|
||||
key: Value,
|
||||
value: Value,
|
||||
key: RawValue,
|
||||
value: RawValue,
|
||||
) -> Result<()> {
|
||||
assert!(proof.existence); // sanity check
|
||||
|
||||
|
|
@ -405,9 +408,9 @@ pub mod tests {
|
|||
use plonky2::plonk::{circuit_builder::CircuitBuilder, circuit_data::CircuitConfig};
|
||||
|
||||
use super::*;
|
||||
use crate::backends::plonky2::{
|
||||
basetypes::{hash_value, C},
|
||||
primitives::merkletree::*,
|
||||
use crate::{
|
||||
backends::plonky2::{basetypes::C, primitives::merkletree::*},
|
||||
middleware::{hash_value, RawValue},
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
|
@ -424,7 +427,7 @@ pub mod tests {
|
|||
let mut builder = CircuitBuilder::<F, D>::new(config);
|
||||
let mut pw = PartialWitness::<F>::new();
|
||||
|
||||
let key = Value::from(hash_value(&Value::from(i)));
|
||||
let key = RawValue::from(hash_value(&RawValue::from(i)));
|
||||
let expected_path = keypath(max_depth, key)?;
|
||||
|
||||
// small circuit logic to check
|
||||
|
|
@ -455,8 +458,8 @@ pub mod tests {
|
|||
#[test]
|
||||
fn test_kv_hash() -> Result<()> {
|
||||
for i in 0..10 {
|
||||
let key = Value::from(hash_value(&Value::from(i)));
|
||||
let value = Value::from(1000 + i);
|
||||
let key = RawValue::from(hash_value(&RawValue::from(i)));
|
||||
let value = RawValue::from(1000 + i);
|
||||
let h = kv_hash(&key, Some(value));
|
||||
|
||||
// circuit
|
||||
|
|
@ -502,20 +505,23 @@ pub mod tests {
|
|||
|
||||
// test logic to be reused both by the existence & nonexistence tests
|
||||
fn test_merkleproof_verify_opt(max_depth: usize, existence: bool) -> Result<()> {
|
||||
let mut kvs: HashMap<Value, Value> = HashMap::new();
|
||||
let mut kvs: HashMap<RawValue, RawValue> = HashMap::new();
|
||||
for i in 0..10 {
|
||||
kvs.insert(Value::from(hash_value(&Value::from(i))), Value::from(i));
|
||||
kvs.insert(
|
||||
RawValue::from(hash_value(&RawValue::from(i))),
|
||||
RawValue::from(i),
|
||||
);
|
||||
}
|
||||
|
||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
||||
|
||||
let (key, value, proof) = if existence {
|
||||
let key = Value::from(hash_value(&Value::from(5)));
|
||||
let key = RawValue::from(hash_value(&RawValue::from(5)));
|
||||
let (value, proof) = tree.prove(&key)?;
|
||||
assert_eq!(value, Value::from(5));
|
||||
assert_eq!(value, RawValue::from(5));
|
||||
(key, value, proof)
|
||||
} else {
|
||||
let key = Value::from(hash_value(&Value::from(200)));
|
||||
let key = RawValue::from(hash_value(&RawValue::from(200)));
|
||||
(key, EMPTY_VALUE, tree.prove_nonexistence(&key)?)
|
||||
};
|
||||
assert_eq!(proof.existence, existence);
|
||||
|
|
@ -559,16 +565,19 @@ pub mod tests {
|
|||
}
|
||||
|
||||
fn test_merkleproof_only_existence_verify_opt(max_depth: usize) -> Result<()> {
|
||||
let mut kvs: HashMap<Value, Value> = HashMap::new();
|
||||
let mut kvs: HashMap<RawValue, RawValue> = HashMap::new();
|
||||
for i in 0..10 {
|
||||
kvs.insert(Value::from(hash_value(&Value::from(i))), Value::from(i));
|
||||
kvs.insert(
|
||||
RawValue::from(hash_value(&RawValue::from(i))),
|
||||
RawValue::from(i),
|
||||
);
|
||||
}
|
||||
|
||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
||||
|
||||
let key = Value::from(hash_value(&Value::from(5)));
|
||||
let key = RawValue::from(hash_value(&RawValue::from(5)));
|
||||
let (value, proof) = tree.prove(&key)?;
|
||||
assert_eq!(value, Value::from(5));
|
||||
assert_eq!(value, RawValue::from(5));
|
||||
assert_eq!(proof.existence, true);
|
||||
|
||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
||||
|
|
@ -604,24 +613,28 @@ pub mod tests {
|
|||
// 5 13
|
||||
|
||||
let mut kvs = HashMap::new();
|
||||
kvs.insert(Value::from(0), Value::from(1000));
|
||||
kvs.insert(Value::from(2), Value::from(1002));
|
||||
kvs.insert(Value::from(5), Value::from(1005));
|
||||
kvs.insert(Value::from(13), Value::from(1013));
|
||||
kvs.insert(RawValue::from(0), RawValue::from(1000));
|
||||
kvs.insert(RawValue::from(2), RawValue::from(1002));
|
||||
kvs.insert(RawValue::from(5), RawValue::from(1005));
|
||||
kvs.insert(RawValue::from(13), RawValue::from(1013));
|
||||
|
||||
let max_depth = 5;
|
||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
||||
// existence
|
||||
test_merkletree_edgecase_opt(max_depth, &tree, Value::from(5))?;
|
||||
test_merkletree_edgecase_opt(max_depth, &tree, RawValue::from(5))?;
|
||||
// non-existence case i) expected leaf does not exist
|
||||
test_merkletree_edgecase_opt(max_depth, &tree, Value::from(1))?;
|
||||
test_merkletree_edgecase_opt(max_depth, &tree, RawValue::from(1))?;
|
||||
// non-existence case ii) expected leaf does exist but it has a different 'key'
|
||||
test_merkletree_edgecase_opt(max_depth, &tree, Value::from(21))?;
|
||||
test_merkletree_edgecase_opt(max_depth, &tree, RawValue::from(21))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn test_merkletree_edgecase_opt(max_depth: usize, tree: &MerkleTree, key: Value) -> Result<()> {
|
||||
fn test_merkletree_edgecase_opt(
|
||||
max_depth: usize,
|
||||
tree: &MerkleTree,
|
||||
key: RawValue,
|
||||
) -> Result<()> {
|
||||
let contains = tree.contains(&key)?;
|
||||
// generate merkleproof
|
||||
let (value, proof) = if contains {
|
||||
|
|
@ -666,19 +679,19 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_wrong_witness() -> Result<()> {
|
||||
let mut kvs: HashMap<Value, Value> = HashMap::new();
|
||||
let mut kvs: HashMap<RawValue, RawValue> = HashMap::new();
|
||||
for i in 0..10 {
|
||||
kvs.insert(Value::from(i), Value::from(i));
|
||||
kvs.insert(RawValue::from(i), RawValue::from(i));
|
||||
}
|
||||
let max_depth = 16;
|
||||
let tree = MerkleTree::new(max_depth, &kvs)?;
|
||||
|
||||
let key = Value::from(3);
|
||||
let key = RawValue::from(3);
|
||||
let (value, proof) = tree.prove(&key)?;
|
||||
|
||||
// build another tree with an extra key-value, so that it has a
|
||||
// different root
|
||||
kvs.insert(Value::from(100), Value::from(100));
|
||||
kvs.insert(RawValue::from(100), RawValue::from(100));
|
||||
let tree2 = MerkleTree::new(max_depth, &kvs)?;
|
||||
|
||||
MerkleTree::verify(max_depth, tree.root(), &proof, &key, &value)?;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,10 @@ use plonky2::{
|
|||
};
|
||||
|
||||
pub use super::signature_circuit::*;
|
||||
use crate::backends::plonky2::basetypes::{Proof, Value, C, D, F, VALUE_SIZE};
|
||||
use crate::{
|
||||
backends::plonky2::basetypes::{Proof, C, D},
|
||||
middleware::{RawValue, F, VALUE_SIZE},
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
/// Signature prover parameters
|
||||
|
|
@ -45,10 +48,10 @@ pub struct ProverParams {
|
|||
pub struct VerifierParams(pub(crate) VerifierCircuitData<F, C, D>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SecretKey(pub(crate) Value);
|
||||
pub struct SecretKey(pub(crate) RawValue);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PublicKey(pub(crate) Value);
|
||||
pub struct PublicKey(pub(crate) RawValue);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Signature(pub(crate) Proof);
|
||||
|
|
@ -57,16 +60,16 @@ pub struct Signature(pub(crate) Proof);
|
|||
impl SecretKey {
|
||||
pub fn new_rand() -> Self {
|
||||
// note: the `F::rand()` internally uses `rand::rngs::OsRng`
|
||||
Self(Value(std::array::from_fn(|_| F::rand())))
|
||||
Self(RawValue(std::array::from_fn(|_| F::rand())))
|
||||
}
|
||||
|
||||
pub fn public_key(&self) -> PublicKey {
|
||||
PublicKey(Value(PoseidonHash::hash_no_pad(&self.0 .0).elements))
|
||||
PublicKey(RawValue(PoseidonHash::hash_no_pad(&self.0 .0).elements))
|
||||
}
|
||||
|
||||
pub fn sign(&self, msg: Value) -> Result<Signature> {
|
||||
pub fn sign(&self, msg: RawValue) -> Result<Signature> {
|
||||
let pk = self.public_key();
|
||||
let s = Value(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
let s = RawValue(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
|
||||
let mut pw = PartialWitness::<F>::new();
|
||||
PP.circuit.set_targets(&mut pw, self.clone(), pk, msg, s)?;
|
||||
|
|
@ -108,9 +111,9 @@ impl Signature {
|
|||
Ok((builder, circuit))
|
||||
}
|
||||
|
||||
pub fn verify(&self, pk: &PublicKey, msg: Value) -> Result<()> {
|
||||
pub fn verify(&self, pk: &PublicKey, msg: RawValue) -> Result<()> {
|
||||
// prepare public inputs as [pk, msg, s]
|
||||
let s = Value(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
let s = RawValue(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
let public_inputs: Vec<F> = [pk.0 .0, msg.0, s.0].concat();
|
||||
|
||||
// verify plonky2 proof
|
||||
|
|
@ -122,16 +125,16 @@ impl Signature {
|
|||
}
|
||||
|
||||
fn dummy_public_inputs() -> Result<Vec<F>> {
|
||||
let sk = SecretKey(Value::from(0));
|
||||
let sk = SecretKey(RawValue::from(0));
|
||||
let pk = sk.public_key();
|
||||
let msg = Value::from(0);
|
||||
let s = Value(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
let msg = RawValue::from(0);
|
||||
let s = RawValue(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
Ok([pk.0 .0, msg.0, s.0].concat())
|
||||
}
|
||||
|
||||
fn dummy_signature() -> Result<Signature> {
|
||||
let sk = SecretKey(Value::from(0));
|
||||
let msg = Value::from(0);
|
||||
let sk = SecretKey(RawValue::from(0));
|
||||
let msg = RawValue::from(0);
|
||||
sk.sign(msg)
|
||||
}
|
||||
|
||||
|
|
@ -186,8 +189,8 @@ impl SignatureInternalCircuit {
|
|||
pw: &mut PartialWitness<F>,
|
||||
sk: SecretKey,
|
||||
pk: PublicKey,
|
||||
msg: Value,
|
||||
s: Value,
|
||||
msg: RawValue,
|
||||
s: RawValue,
|
||||
) -> Result<()> {
|
||||
pw.set_target_arr(&self.sk_targ, sk.0 .0.as_ref())?;
|
||||
pw.set_hash_target(self.pk_targ, HashOut::<F>::from_vec(pk.0 .0.to_vec()))?;
|
||||
|
|
@ -201,23 +204,23 @@ impl SignatureInternalCircuit {
|
|||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::backends::plonky2::basetypes::Hash;
|
||||
use crate::middleware::hash_str;
|
||||
|
||||
#[test]
|
||||
fn test_signature() -> Result<()> {
|
||||
let sk = SecretKey::new_rand();
|
||||
let pk = sk.public_key();
|
||||
|
||||
let msg = Value::from(42);
|
||||
let msg = RawValue::from(42);
|
||||
let sig = sk.sign(msg)?;
|
||||
sig.verify(&pk, msg)?;
|
||||
|
||||
// expect the signature verification to fail when using a different msg
|
||||
let v = sig.verify(&pk, Value::from(24));
|
||||
let v = sig.verify(&pk, RawValue::from(24));
|
||||
assert!(v.is_err(), "should fail to verify");
|
||||
|
||||
// perform a 2nd signature over another msg and verify it
|
||||
let msg_2 = Value::from(Hash::from("message"));
|
||||
let msg_2 = RawValue::from(hash_str("message"));
|
||||
let sig2 = sk.sign(msg_2)?;
|
||||
sig2.verify(&pk, msg_2)?;
|
||||
|
||||
|
|
@ -226,9 +229,9 @@ pub mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_dummy_signature() -> Result<()> {
|
||||
let sk = SecretKey(Value::from(0));
|
||||
let sk = SecretKey(RawValue::from(0));
|
||||
let pk = sk.public_key();
|
||||
let msg = Value::from(0);
|
||||
let msg = RawValue::from(0);
|
||||
DUMMY_SIGNATURE.clone().verify(&pk, msg)?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -22,12 +22,15 @@ use plonky2::{
|
|||
},
|
||||
};
|
||||
|
||||
use crate::backends::plonky2::{
|
||||
basetypes::{Hash, Proof, Value, C, D, EMPTY_HASH, EMPTY_VALUE, F, VALUE_SIZE},
|
||||
circuits::common::{CircuitBuilderPod, ValueTarget},
|
||||
primitives::signature::{
|
||||
PublicKey, SecretKey, Signature, DUMMY_PUBLIC_INPUTS, DUMMY_SIGNATURE,
|
||||
use crate::{
|
||||
backends::plonky2::{
|
||||
basetypes::{Proof, C, D},
|
||||
circuits::common::{CircuitBuilderPod, ValueTarget},
|
||||
primitives::signature::{
|
||||
PublicKey, SecretKey, Signature, DUMMY_PUBLIC_INPUTS, DUMMY_SIGNATURE,
|
||||
},
|
||||
},
|
||||
middleware::{Hash, RawValue, EMPTY_HASH, EMPTY_VALUE, F, VALUE_SIZE},
|
||||
};
|
||||
|
||||
lazy_static! {
|
||||
|
|
@ -81,12 +84,12 @@ impl SignatureVerifyGadget {
|
|||
let dummy_pi = DUMMY_PUBLIC_INPUTS.clone();
|
||||
|
||||
let pk_targ_dummy =
|
||||
builder.constant_value(Value(dummy_pi[..VALUE_SIZE].try_into().unwrap()));
|
||||
let msg_targ_dummy = builder.constant_value(Value(
|
||||
builder.constant_value(RawValue(dummy_pi[..VALUE_SIZE].try_into().unwrap()));
|
||||
let msg_targ_dummy = builder.constant_value(RawValue(
|
||||
dummy_pi[VALUE_SIZE..VALUE_SIZE * 2].try_into().unwrap(),
|
||||
));
|
||||
let s_targ_dummy =
|
||||
builder.constant_value(Value(dummy_pi[VALUE_SIZE * 2..].try_into().unwrap()));
|
||||
builder.constant_value(RawValue(dummy_pi[VALUE_SIZE * 2..].try_into().unwrap()));
|
||||
|
||||
// connect the {pk, msg, s} with the proof_targ.public_inputs conditionally
|
||||
let pk_targ_connect = builder.select_value(enabled, pk_targ, pk_targ_dummy);
|
||||
|
|
@ -129,7 +132,7 @@ impl SignatureVerifyTarget {
|
|||
pw: &mut PartialWitness<F>,
|
||||
enabled: bool,
|
||||
pk: PublicKey,
|
||||
msg: Value,
|
||||
msg: RawValue,
|
||||
signature: Signature,
|
||||
) -> Result<()> {
|
||||
pw.set_bool_target(self.enabled, enabled)?;
|
||||
|
|
@ -137,7 +140,7 @@ impl SignatureVerifyTarget {
|
|||
pw.set_target_arr(&self.msg.elements, &msg.0)?;
|
||||
|
||||
// note that this hash is checked again in-circuit at the `SignatureInternalCircuit`
|
||||
let s = Value(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
let s = RawValue(PoseidonHash::hash_no_pad(&[pk.0 .0, msg.0].concat()).elements);
|
||||
let public_inputs: Vec<F> = [pk.0 .0, msg.0, s.0].concat();
|
||||
|
||||
if enabled {
|
||||
|
|
@ -170,14 +173,14 @@ impl SignatureVerifyTarget {
|
|||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
use crate::backends::plonky2::{basetypes::Hash, primitives::signature::SecretKey};
|
||||
use crate::{backends::plonky2::primitives::signature::SecretKey, middleware::Hash};
|
||||
|
||||
#[test]
|
||||
fn test_signature_gadget() -> Result<()> {
|
||||
// generate a valid signature
|
||||
let sk = SecretKey::new_rand();
|
||||
let pk = sk.public_key();
|
||||
let msg = Value::from(42);
|
||||
let msg = RawValue::from(42);
|
||||
let sig = sk.sign(msg)?;
|
||||
sig.verify(&pk, msg)?;
|
||||
|
||||
|
|
@ -208,15 +211,15 @@ pub mod tests {
|
|||
// generate a valid signature
|
||||
let sk = SecretKey::new_rand();
|
||||
let pk = sk.public_key();
|
||||
let msg = Value::from(42);
|
||||
let msg = RawValue::from(42);
|
||||
let sig = sk.sign(msg)?;
|
||||
// verification should pass
|
||||
sig.verify(&pk, msg)?;
|
||||
|
||||
// replace the message, so that verifications should fail
|
||||
let msg = Value::from(24);
|
||||
let msg = RawValue::from(24);
|
||||
// expect signature native verification to fail
|
||||
let v = sig.verify(&pk, Value::from(24));
|
||||
let v = sig.verify(&pk, RawValue::from(24));
|
||||
assert!(v.is_err(), "should fail to verify");
|
||||
|
||||
// circuit
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue