implement SignedPod (non-mock) using proof-based signatures (#160)
This commit is contained in:
parent
30f26a94ef
commit
d6033b7090
9 changed files with 259 additions and 60 deletions
|
|
@ -16,6 +16,7 @@ anyhow = "1.0.56"
|
|||
dyn-clone = "1.0.18"
|
||||
log = "0.4"
|
||||
env_logger = "0.11"
|
||||
lazy_static = "1.5.0"
|
||||
# enabled by features:
|
||||
plonky2 = { git = "https://github.com/0xPolygonZero/plonky2", optional = true }
|
||||
serde = "1.0.219"
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ pub fn hash_statements(statements: &[Statement], _params: &Params) -> middleware
|
|||
}
|
||||
|
||||
impl Pod for MockMainPod {
|
||||
fn verify(&self) -> bool {
|
||||
fn verify(&self) -> Result<()> {
|
||||
// 1. TODO: Verify input pods
|
||||
|
||||
let input_statement_offset = self.offset_input_statements();
|
||||
|
|
@ -451,18 +451,20 @@ impl Pod for MockMainPod {
|
|||
.collect::<Result<Vec<_>>>()
|
||||
.unwrap();
|
||||
if !ids_match {
|
||||
error!("Verification failed: POD ID is incorrect.");
|
||||
return Err(anyhow!("Verification failed: POD ID is incorrect."));
|
||||
}
|
||||
if !has_type_statement {
|
||||
error!("Verification failed: POD does not have type statement.");
|
||||
return Err(anyhow!(
|
||||
"Verification failed: POD does not have type statement."
|
||||
));
|
||||
}
|
||||
if !value_ofs_unique {
|
||||
error!("Verification failed: Repeated ValueOf");
|
||||
return Err(anyhow!("Verification failed: Repeated ValueOf"));
|
||||
}
|
||||
if !statement_check.iter().all(|b| *b) {
|
||||
error!("Verification failed: Statement did not check.")
|
||||
return Err(anyhow!("Verification failed: Statement did not check."));
|
||||
}
|
||||
ids_match && has_type_statement && value_ofs_unique & statement_check.into_iter().all(|b| b)
|
||||
Ok(())
|
||||
}
|
||||
fn id(&self) -> PodId {
|
||||
self.id
|
||||
|
|
@ -539,9 +541,9 @@ pub mod tests {
|
|||
|
||||
println!("{:#}", pod);
|
||||
|
||||
assert!(pod.verify()); // TODO
|
||||
// println!("id: {}", pod.id());
|
||||
// println!("pub_statements: {:?}", pod.pub_statements());
|
||||
pod.verify()?; // TODO
|
||||
// println!("id: {}", pod.id());
|
||||
// println!("pub_statements: {:?}", pod.pub_statements());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -560,7 +562,7 @@ pub mod tests {
|
|||
|
||||
println!("{}", pod);
|
||||
|
||||
assert!(pod.verify());
|
||||
pod.verify()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -574,7 +576,7 @@ pub mod tests {
|
|||
let pod = proof_pod.pod.into_any().downcast::<MockMainPod>().unwrap();
|
||||
|
||||
println!("{}", pod);
|
||||
assert!(pod.verify());
|
||||
pod.verify()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Result;
|
||||
use anyhow::{anyhow, Result};
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
|
@ -55,44 +55,47 @@ impl MockSignedPod {
|
|||
}
|
||||
|
||||
impl Pod for MockSignedPod {
|
||||
fn verify(&self) -> bool {
|
||||
fn verify(&self) -> Result<()> {
|
||||
// 1. Verify type
|
||||
let value_at_type = match self.dict.get(&hash_str(KEY_TYPE).into()) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let value_at_type = self.dict.get(&hash_str(KEY_TYPE).into())?;
|
||||
if Value::from(PodType::MockSigned) != value_at_type {
|
||||
return false;
|
||||
return Err(anyhow!(
|
||||
"type does not match, expected MockSigned ({}), found {}",
|
||||
PodType::MockSigned,
|
||||
value_at_type
|
||||
));
|
||||
}
|
||||
|
||||
// 2. Verify id
|
||||
let mt = match MerkleTree::new(
|
||||
let mt = MerkleTree::new(
|
||||
MAX_DEPTH,
|
||||
&self
|
||||
.dict
|
||||
.iter()
|
||||
.map(|(&k, &v)| (k, v))
|
||||
.collect::<HashMap<Value, Value>>(),
|
||||
) {
|
||||
Ok(mt) => mt,
|
||||
Err(_) => return false,
|
||||
};
|
||||
)?;
|
||||
let id = PodId(mt.root());
|
||||
if id != self.id {
|
||||
return false;
|
||||
return Err(anyhow!(
|
||||
"id does not match, expected {}, computed {}",
|
||||
self.id,
|
||||
id
|
||||
));
|
||||
}
|
||||
|
||||
// 3. Verify signature
|
||||
let pk_hash = match self.dict.get(&hash_str(KEY_SIGNER).into()) {
|
||||
Ok(v) => v,
|
||||
Err(_) => return false,
|
||||
};
|
||||
let pk_hash = self.dict.get(&hash_str(KEY_SIGNER).into())?;
|
||||
let signature = format!("{}_signed_by_{}", id, pk_hash);
|
||||
if signature != self.signature {
|
||||
return false;
|
||||
return Err(anyhow!(
|
||||
"signature does not match, expected {}, computed {}",
|
||||
self.id,
|
||||
id
|
||||
));
|
||||
}
|
||||
|
||||
true
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn id(&self) -> PodId {
|
||||
|
|
@ -138,17 +141,17 @@ pub mod tests {
|
|||
let pod = pod.sign(&mut signer).unwrap();
|
||||
let pod = pod.pod.into_any().downcast::<MockSignedPod>().unwrap();
|
||||
|
||||
assert!(pod.verify());
|
||||
pod.verify()?;
|
||||
println!("id: {}", pod.id());
|
||||
println!("kvs: {:?}", pod.kvs());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
bad_pod.signature = "".into();
|
||||
assert!(!bad_pod.verify());
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
bad_pod.id.0 .0[0] = F::ZERO;
|
||||
assert!(!bad_pod.verify());
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
let bad_kv = (hash_str(KEY_SIGNER).into(), Value(PodId(EMPTY_HASH).0 .0));
|
||||
|
|
@ -160,7 +163,7 @@ pub mod tests {
|
|||
.collect::<HashMap<Value, Value>>();
|
||||
let bad_mt = MerkleTree::new(MAX_DEPTH, bad_kvs_mt)?;
|
||||
bad_pod.dict.mt = bad_mt;
|
||||
assert!(!bad_pod.verify());
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
let bad_kv = (hash_str(KEY_TYPE).into(), Value::from(0));
|
||||
|
|
@ -172,7 +175,7 @@ pub mod tests {
|
|||
.collect::<HashMap<Value, Value>>();
|
||||
let bad_mt = MerkleTree::new(MAX_DEPTH, bad_kvs_mt)?;
|
||||
bad_pod.dict.mt = bad_mt;
|
||||
assert!(!bad_pod.verify());
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@ pub mod basetypes;
|
|||
pub mod circuits;
|
||||
pub mod mock;
|
||||
pub mod primitives;
|
||||
pub mod signedpod;
|
||||
|
|
|
|||
|
|
@ -21,22 +21,29 @@ use plonky2::{
|
|||
|
||||
use crate::backends::plonky2::basetypes::{Proof, Value, C, D, F, VALUE_SIZE};
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
static ref PP: ProverParams = Signature::prover_params().unwrap();
|
||||
static ref VP: VerifierParams = Signature::verifier_params().unwrap();
|
||||
}
|
||||
|
||||
pub struct ProverParams {
|
||||
prover: ProverCircuitData<F, C, D>,
|
||||
circuit: SignatureCircuit,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VerifierParams(VerifierCircuitData<F, C, D>);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SecretKey(Value);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PublicKey(Value);
|
||||
pub struct PublicKey(pub(crate) Value);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Signature(Proof);
|
||||
pub struct Signature(pub(crate) Proof);
|
||||
|
||||
/// Implements the key generation and the computation of proof-based signatures.
|
||||
impl SecretKey {
|
||||
|
|
@ -49,14 +56,14 @@ impl SecretKey {
|
|||
PublicKey(Value(PoseidonHash::hash_no_pad(&self.0 .0).elements))
|
||||
}
|
||||
|
||||
pub fn sign(&self, pp: &ProverParams, msg: Value) -> Result<Signature> {
|
||||
pub fn sign(&self, msg: Value) -> Result<Signature> {
|
||||
let pk = self.public_key();
|
||||
let s = Value(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)?;
|
||||
PP.circuit.set_targets(&mut pw, self.clone(), pk, msg, s)?;
|
||||
|
||||
let proof = pp.prover.prove(pw)?;
|
||||
let proof = PP.prover.prove(pw)?;
|
||||
|
||||
Ok(Signature(proof.proof))
|
||||
}
|
||||
|
|
@ -65,15 +72,22 @@ impl SecretKey {
|
|||
/// Implements the parameters generation and the verification of proof-based
|
||||
/// signatures.
|
||||
impl Signature {
|
||||
pub fn params() -> Result<(ProverParams, VerifierParams)> {
|
||||
pub fn prover_params() -> Result<ProverParams> {
|
||||
let (builder, circuit) = Self::builder()?;
|
||||
let prover = builder.build_prover::<C>();
|
||||
|
||||
Ok(ProverParams { prover, circuit })
|
||||
}
|
||||
pub fn verifier_params() -> Result<VerifierParams> {
|
||||
let (builder, _) = Self::builder()?;
|
||||
let circuit_data = builder.build::<C>();
|
||||
let vp = circuit_data.verifier_data();
|
||||
|
||||
Ok((ProverParams { prover, circuit }, VerifierParams(vp)))
|
||||
Ok(VerifierParams(vp))
|
||||
}
|
||||
pub fn params() -> Result<(ProverParams, VerifierParams)> {
|
||||
let pp = Self::prover_params()?;
|
||||
let vp = Self::verifier_params()?;
|
||||
Ok((pp, vp))
|
||||
}
|
||||
|
||||
fn builder() -> Result<(CircuitBuilder<F, D>, SignatureCircuit)> {
|
||||
|
|
@ -86,13 +100,13 @@ impl Signature {
|
|||
Ok((builder, circuit))
|
||||
}
|
||||
|
||||
pub fn verify(&self, vp: &VerifierParams, pk: &PublicKey, msg: Value) -> Result<()> {
|
||||
pub fn verify(&self, pk: &PublicKey, msg: Value) -> Result<()> {
|
||||
// prepare public inputs as [pk, msg, s]
|
||||
let s = Value(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
|
||||
vp.0.verify(ProofWithPublicInputs {
|
||||
VP.0.verify(ProofWithPublicInputs {
|
||||
proof: self.0.clone(),
|
||||
public_inputs,
|
||||
})
|
||||
|
|
@ -171,23 +185,21 @@ pub mod tests {
|
|||
// Note: this test must be run with the `--release` flag.
|
||||
#[test]
|
||||
fn test_signature() -> Result<()> {
|
||||
let (pp, vp) = Signature::params()?;
|
||||
|
||||
let sk = SecretKey::new();
|
||||
let pk = sk.public_key();
|
||||
|
||||
let msg = Value::from(42);
|
||||
let sig = sk.sign(&pp, msg)?;
|
||||
sig.verify(&vp, &pk, msg)?;
|
||||
let sig = sk.sign(msg)?;
|
||||
sig.verify(&pk, msg)?;
|
||||
|
||||
// expect the signature verification to fail when using a different msg
|
||||
let v = sig.verify(&vp, &pk, Value::from(24));
|
||||
let v = sig.verify(&pk, Value::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 sig2 = sk.sign(&pp, msg_2)?;
|
||||
sig2.verify(&vp, &pk, msg_2)?;
|
||||
let sig2 = sk.sign(msg_2)?;
|
||||
sig2.verify(&pk, msg_2)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
165
src/backends/plonky2/signedpod.rs
Normal file
165
src/backends/plonky2/signedpod.rs
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use super::primitives::merkletree::MerkleTree;
|
||||
use crate::constants::MAX_DEPTH;
|
||||
use crate::middleware::{
|
||||
containers::Dictionary, hash_str, AnchoredKey, Hash, Params, Pod, PodId, PodSigner, PodType,
|
||||
Statement, Value, KEY_SIGNER, KEY_TYPE,
|
||||
};
|
||||
|
||||
use super::primitives::signature::{PublicKey, SecretKey, Signature};
|
||||
|
||||
pub struct Signer(SecretKey);
|
||||
|
||||
impl PodSigner for Signer {
|
||||
fn sign(&mut self, _params: &Params, kvs: &HashMap<Hash, Value>) -> Result<Box<dyn Pod>> {
|
||||
let mut kvs = kvs.clone();
|
||||
let pubkey = self.0.public_key();
|
||||
kvs.insert(hash_str(KEY_SIGNER), pubkey.0);
|
||||
kvs.insert(hash_str(KEY_TYPE), Value::from(PodType::Signed));
|
||||
|
||||
let dict = Dictionary::new(&kvs)?;
|
||||
let id = Value::from(dict.commitment()); // PodId as Value
|
||||
|
||||
let signature: Signature = self.0.sign(id)?;
|
||||
Ok(Box::new(SignedPod {
|
||||
id: PodId(Hash::from(id)),
|
||||
signature,
|
||||
dict,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SignedPod {
|
||||
id: PodId,
|
||||
signature: Signature,
|
||||
dict: Dictionary,
|
||||
}
|
||||
|
||||
impl Pod for SignedPod {
|
||||
fn verify(&self) -> Result<()> {
|
||||
// 1. Verify type
|
||||
let value_at_type = self.dict.get(&hash_str(KEY_TYPE).into())?;
|
||||
if Value::from(PodType::Signed) != value_at_type {
|
||||
return Err(anyhow!(
|
||||
"type does not match, expected Signed ({}), found {}",
|
||||
PodType::Signed,
|
||||
value_at_type
|
||||
));
|
||||
}
|
||||
|
||||
// 2. Verify id
|
||||
let mt = MerkleTree::new(
|
||||
MAX_DEPTH,
|
||||
&self
|
||||
.dict
|
||||
.iter()
|
||||
.map(|(&k, &v)| (k, v))
|
||||
.collect::<HashMap<Value, Value>>(),
|
||||
)?;
|
||||
let id = PodId(mt.root());
|
||||
if id != self.id {
|
||||
return Err(anyhow!(
|
||||
"id does not match, expected {}, computed {}",
|
||||
self.id,
|
||||
id
|
||||
));
|
||||
}
|
||||
|
||||
// 3. Verify signature
|
||||
let pk_value = self.dict.get(&hash_str(KEY_SIGNER).into())?;
|
||||
let pk = PublicKey(pk_value);
|
||||
self.signature.verify(&pk, Value::from(id.0))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn id(&self) -> PodId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn pub_statements(&self) -> Vec<Statement> {
|
||||
let id = self.id();
|
||||
self.dict
|
||||
.iter()
|
||||
.map(|(k, v)| Statement::ValueOf(AnchoredKey(id, Hash(k.0)), *v))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
|
||||
fn serialized_proof(&self) -> String {
|
||||
let mut buffer = Vec::new();
|
||||
use plonky2::util::serialization::Write;
|
||||
buffer.write_proof(&self.signature.0).unwrap();
|
||||
hex::encode(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use plonky2::field::types::Field;
|
||||
use std::iter;
|
||||
|
||||
use super::*;
|
||||
use crate::constants::MAX_DEPTH;
|
||||
use crate::frontend;
|
||||
use crate::middleware::{self, EMPTY_HASH, F};
|
||||
|
||||
#[test]
|
||||
fn test_signed_0() -> Result<()> {
|
||||
let params = middleware::Params::default();
|
||||
let mut pod = frontend::SignedPodBuilder::new(¶ms);
|
||||
pod.insert("idNumber", "4242424242");
|
||||
pod.insert("dateOfBirth", 1169909384);
|
||||
pod.insert("socialSecurityNumber", "G2121210");
|
||||
|
||||
let sk = SecretKey::new();
|
||||
let mut signer = Signer(sk);
|
||||
let pod = pod.sign(&mut signer).unwrap();
|
||||
let pod = pod.pod.into_any().downcast::<SignedPod>().unwrap();
|
||||
|
||||
pod.verify()?;
|
||||
println!("id: {}", pod.id());
|
||||
println!("kvs: {:?}", pod.kvs());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
bad_pod.signature = signer.0.sign(Value::from(42_i64))?;
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
bad_pod.id.0 .0[0] = F::ZERO;
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
let bad_kv = (hash_str(KEY_SIGNER).into(), Value(PodId(EMPTY_HASH).0 .0));
|
||||
let bad_kvs_mt = &bad_pod
|
||||
.kvs()
|
||||
.into_iter()
|
||||
.map(|(AnchoredKey(_, k), v)| (Value(k.0), v))
|
||||
.chain(iter::once(bad_kv))
|
||||
.collect::<HashMap<Value, Value>>();
|
||||
let bad_mt = MerkleTree::new(MAX_DEPTH, bad_kvs_mt)?;
|
||||
bad_pod.dict.mt = bad_mt;
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
let mut bad_pod = pod.clone();
|
||||
let bad_kv = (hash_str(KEY_TYPE).into(), Value::from(0));
|
||||
let bad_kvs_mt = &bad_pod
|
||||
.kvs()
|
||||
.into_iter()
|
||||
.map(|(AnchoredKey(_, k), v)| (Value(k.0), v))
|
||||
.chain(iter::once(bad_kv))
|
||||
.collect::<HashMap<Value, Value>>();
|
||||
let bad_mt = MerkleTree::new(MAX_DEPTH, bad_kvs_mt)?;
|
||||
bad_pod.dict.mt = bad_mt;
|
||||
assert!(bad_pod.verify().is_err());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
@ -249,7 +249,7 @@ impl SignedPod {
|
|||
pub fn origin(&self) -> Origin {
|
||||
Origin::new(PodClass::Signed, self.id())
|
||||
}
|
||||
pub fn verify(&self) -> bool {
|
||||
pub fn verify(&self) -> Result<()> {
|
||||
self.pod.verify()
|
||||
}
|
||||
pub fn kvs(&self) -> HashMap<Hash, middleware::Value> {
|
||||
|
|
@ -808,7 +808,7 @@ pub struct MainPod {
|
|||
impl fmt::Display for MainPod {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "MainPod: {}", self.pod.id())?;
|
||||
writeln!(f, " valid? {}", self.pod.verify())?;
|
||||
writeln!(f, " valid? {}", self.pod.verify().is_ok())?;
|
||||
writeln!(f, " statements:")?;
|
||||
for st in &self.pod.pub_statements() {
|
||||
writeln!(f, " - {}", st)?;
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ mod tests {
|
|||
|
||||
assert_eq!(pod.kvs, deserialized.kvs);
|
||||
assert_eq!(pod.origin(), deserialized.origin());
|
||||
assert_eq!(pod.verify(), deserialized.verify());
|
||||
assert_eq!(pod.verify().is_ok(), deserialized.verify().is_ok());
|
||||
assert_eq!(pod.id(), deserialized.id())
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +289,9 @@ mod tests {
|
|||
|
||||
assert_eq!(kyc_pod.public_statements, deserialized.public_statements);
|
||||
assert_eq!(kyc_pod.pod.id(), deserialized.pod.id());
|
||||
assert_eq!(kyc_pod.pod.verify(), deserialized.pod.verify());
|
||||
assert_eq!(
|
||||
kyc_pod.pod.verify().is_ok(),
|
||||
deserialized.pod.verify().is_ok()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ impl ToFields for PodId {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum PodType {
|
||||
None = 0,
|
||||
MockSigned = 1,
|
||||
|
|
@ -73,6 +74,17 @@ pub enum PodType {
|
|||
Signed = 3,
|
||||
Main = 4,
|
||||
}
|
||||
impl fmt::Display for PodType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
PodType::None => write!(f, "None"),
|
||||
PodType::MockSigned => write!(f, "MockSigned"),
|
||||
PodType::MockMain => write!(f, "MockMain"),
|
||||
PodType::Signed => write!(f, "Signed"),
|
||||
PodType::Main => write!(f, "Main"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PodType> for Value {
|
||||
fn from(v: PodType) -> Self {
|
||||
|
|
@ -169,7 +181,7 @@ impl Params {
|
|||
}
|
||||
|
||||
pub trait Pod: fmt::Debug + DynClone {
|
||||
fn verify(&self) -> bool;
|
||||
fn verify(&self) -> Result<()>;
|
||||
fn id(&self) -> PodId;
|
||||
fn pub_statements(&self) -> Vec<Statement>;
|
||||
/// Extract key-values from ValueOf public statements
|
||||
|
|
@ -208,8 +220,8 @@ pub trait PodSigner {
|
|||
pub struct NonePod {}
|
||||
|
||||
impl Pod for NonePod {
|
||||
fn verify(&self) -> bool {
|
||||
true
|
||||
fn verify(&self) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn id(&self) -> PodId {
|
||||
PodId(EMPTY_HASH)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue