return specific errors for VerifyFailed

This commit is contained in:
narodnik
2021-05-16 07:53:21 +02:00
parent 5e5992e9cf
commit ec78bf9ac9
4 changed files with 64 additions and 17 deletions

View File

@@ -16,8 +16,33 @@ use sapvi::crypto::{
};
use sapvi::error::{Error, Result};
use sapvi::serial::{Decodable, Encodable, VarInt};
use sapvi::state::{state_transition, ProgramState, StateUpdates};
use sapvi::tx;
struct MemoryState {
mint_pvk: groth16::PreparedVerifyingKey<Bls12>,
spend_pvk: groth16::PreparedVerifyingKey<Bls12>,
cashier_public: jubjub::SubgroupPoint
}
impl ProgramState for MemoryState {
fn is_valid_cashier_public_key(&self, public: &jubjub::SubgroupPoint) -> bool {
public == &self.cashier_public
}
fn mint_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
&self.mint_pvk
}
fn spend_pvk(&self) -> &groth16::PreparedVerifyingKey<Bls12> {
&self.spend_pvk
}
}
impl MemoryState {
fn apply(updates: StateUpdates) {
}
}
fn main() {
// Auto create trusted ceremony parameters if they don't exist
if !Path::new("mint.params").exists() {
@@ -38,6 +63,12 @@ fn main() {
// This is their public key
let cashier_public = zcash_primitives::constants::SPENDING_KEY_GENERATOR * cashier_secret;
let state = MemoryState {
mint_pvk,
spend_pvk,
cashier_public
};
// Wallet 1 creates a secret key
let secret = jubjub::Fr::random(&mut OsRng);
// This is their public key
@@ -79,12 +110,13 @@ fn main() {
}
// Now we receive the tx data
let note = {
let txx = tx::Transaction::decode(&tx_data[..]).unwrap();
let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
// Check the public key in the clear inputs
// It should be a valid public key for the cashier
assert_eq!(tx.clear_inputs[0].signature_public, cashier_public);
let update = state_transition(&state, txx).expect("step 2 state transition failed");
// Check the tx verifies correctly
assert!(tx.verify(&mint_pvk, &spend_pvk));
//assert!(tx.verify(&mint_pvk, &spend_pvk));
// Add the new coins to the merkle tree
tree.append(Coin::new(tx.outputs[0].revealed.coin))
.expect("append merkle");
@@ -172,6 +204,6 @@ fn main() {
// Verify it's valid
{
let tx = tx::Transaction::decode(&tx_data[..]).unwrap();
assert!(tx.verify(&mint_pvk, &spend_pvk));
//assert!(tx.verify(&mint_pvk, &spend_pvk));
}
}

View File

@@ -1,9 +1,10 @@
use std::fmt;
use rusqlite;
use crate::net::error::NetError;
use crate::service::ServicesError;
use crate::state;
use crate::vm::ZKVMError;
use rusqlite;
pub type Result<T> = std::result::Result<T, Error>;
@@ -46,6 +47,7 @@ pub enum Error {
NoteDecryptionFailed,
ServicesError(ServicesError),
ZMQError(zeromq::ZmqError),
VerifyFailed(state::VerifyFailed),
}
impl std::error::Error for Error {}
@@ -92,6 +94,7 @@ impl fmt::Display for Error {
Error::NoteDecryptionFailed => f.write_str("Unable to decrypt mint note"),
Error::ServicesError(ref err) => write!(f, "Services error: {}", err),
Error::ZMQError(ref err) => write!(f, "zmq error: {}", err),
Error::VerifyFailed(ref err) => write!(f, "Verify failed: {}", err),
}
}
}
@@ -174,3 +177,10 @@ impl From<std::string::FromUtf8Error> for Error {
Error::Utf8Error
}
}
impl From<state::VerifyFailed> for Error {
fn from(err: state::VerifyFailed) -> Error {
Error::VerifyFailed(err)
}
}

View File

@@ -16,6 +16,7 @@ pub mod net;
pub mod rpc;
pub mod serial;
pub mod service;
pub mod state;
pub mod system;
pub mod tx;
pub mod vm;

View File

@@ -17,6 +17,7 @@ use crate::crypto::{
use crate::error::{Error, Result};
use crate::impl_vec;
use crate::serial::{Decodable, Encodable, VarInt};
use crate::state;
pub struct TransactionBuilder {
pub clear_inputs: Vec<TransactionBuilderClearInputInfo>,
@@ -267,43 +268,46 @@ impl Transaction {
&self,
mint_pvk: &groth16::PreparedVerifyingKey<Bls12>,
spend_pvk: &groth16::PreparedVerifyingKey<Bls12>,
) -> bool {
) -> std::result::Result<(), state::VerifyFailed> {
let mut valcom_total = jubjub::SubgroupPoint::identity();
for input in &self.clear_inputs {
valcom_total += Self::compute_value_commit(input.value, &input.valcom_blind);
}
for input in &self.inputs {
for (i, input) in self.inputs.iter().enumerate() {
if !verify_spend_proof(spend_pvk, &input.spend_proof, &input.revealed) {
return false;
return Err(state::VerifyFailed::SpendProof(i));
}
valcom_total += &input.revealed.value_commit;
}
for output in &self.outputs {
for (i, output) in self.outputs.iter().enumerate() {
if !verify_mint_proof(mint_pvk, &output.mint_proof, &output.revealed) {
println!("mint fail");
return false;
return Err(state::VerifyFailed::SpendProof(i));
}
valcom_total -= &output.revealed.value_commit;
}
if valcom_total != jubjub::SubgroupPoint::identity() {
return Err(state::VerifyFailed::MissingFunds);
}
// Verify signatures
let mut unsigned_tx_data = vec![];
self.encode_without_signature(&mut unsigned_tx_data)
.expect("TODO handle this");
for input in &self.clear_inputs {
for (i, input) in self.clear_inputs.iter().enumerate() {
let public = schnorr::PublicKey(input.signature_public.clone());
if !public.verify(&unsigned_tx_data[..], &input.signature) {
return false;
return Err(state::VerifyFailed::ClearInputSignature(i));
}
}
for input in &self.inputs {
for (i, input) in self.inputs.iter().enumerate() {
let public = schnorr::PublicKey(input.revealed.signature_public.clone());
if !public.verify(&unsigned_tx_data[..], &input.signature) {
return false;
return Err(state::VerifyFailed::InputSignature(i));
}
}
valcom_total == jubjub::SubgroupPoint::identity()
Ok(())
}
}