mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
contract/money: Finalize integration test with zk proof verification
This commit is contained in:
@@ -979,7 +979,8 @@ impl ValidatorState {
|
||||
|
||||
// Finally, verify the ZK proofs
|
||||
debug!("Verifying transaction ZK proofs");
|
||||
tx.verify_zkps(zkp_table)?;
|
||||
// FIXME XXX:
|
||||
tx.verify_zkps(&[], zkp_table)?;
|
||||
debug!("Transaction ZK proofs verified successfully!");
|
||||
|
||||
// When the verification stage has passed, just apply all the changes.
|
||||
|
||||
@@ -333,7 +333,10 @@ impl TransferMintRevealed {
|
||||
// calls in the zkas code.
|
||||
vec![
|
||||
self.coin.inner(),
|
||||
*valcom_coords.x() * tokcom_coords.y() * valcom_coords.x() * tokcom_coords.y(),
|
||||
*valcom_coords.x(),
|
||||
*valcom_coords.y(),
|
||||
*tokcom_coords.x(),
|
||||
*tokcom_coords.y(),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,15 +166,18 @@ async fn money_contract_execution() -> Result<()> {
|
||||
let sigs = tx.create_sigs(&mut OsRng, &secret_keys)?;
|
||||
tx.signatures = vec![sigs];
|
||||
|
||||
// Get our ZK verifying keys in place for the tx verification
|
||||
let vks = verifying_keys.get(&contract_id.inner().to_repr()).unwrap();
|
||||
|
||||
// Let's first execute this transaction for the faucet to see if it passes.
|
||||
// Then Alice gets the tx and also executes it.
|
||||
info!("Executing transaction on the faucet's blockchain db");
|
||||
verify_transaction(&faucet_blockchain, &tx)?;
|
||||
verify_transaction(&faucet_blockchain, vks, &tx)?;
|
||||
info!("Adding coin to faucet's Merkle tree");
|
||||
faucet_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
|
||||
|
||||
info!("Executing transaction on Alice's blockchain db");
|
||||
verify_transaction(&alice_blockchain, &tx)?;
|
||||
verify_transaction(&alice_blockchain, vks, &tx)?;
|
||||
// TODO: FIXME: Actually have a look at the `merkle_add` calls
|
||||
alice_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
|
||||
let leaf_position = alice_merkle_tree.witness().unwrap();
|
||||
@@ -227,12 +230,12 @@ async fn money_contract_execution() -> Result<()> {
|
||||
tx.signatures = vec![sigs];
|
||||
|
||||
info!("Executing transaction on the faucet's blockchain db");
|
||||
verify_transaction(&faucet_blockchain, &tx)?;
|
||||
verify_transaction(&faucet_blockchain, vks, &tx)?;
|
||||
info!("Adding coin to faucet's Merkle tree");
|
||||
faucet_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
|
||||
|
||||
info!("Executing transaction on Alice's blockchain db");
|
||||
verify_transaction(&alice_blockchain, &tx)?;
|
||||
verify_transaction(&alice_blockchain, vks, &tx)?;
|
||||
// TODO: FIXME: Actually have a look at the `merkle_add` calls
|
||||
alice_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
|
||||
let leaf_position = alice_merkle_tree.witness().unwrap();
|
||||
@@ -283,18 +286,22 @@ async fn money_contract_execution() -> Result<()> {
|
||||
tx.signatures = vec![sigs];
|
||||
|
||||
info!("Executing transaction on the faucet's blockchain db");
|
||||
verify_transaction(&faucet_blockchain, &tx)?;
|
||||
verify_transaction(&faucet_blockchain, vks, &tx)?;
|
||||
info!("Adding coin to faucet's Merkle tree");
|
||||
faucet_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
|
||||
info!("Executing transaction on Alice's blockchain db");
|
||||
verify_transaction(&alice_blockchain, &tx)?;
|
||||
verify_transaction(&alice_blockchain, vks, &tx)?;
|
||||
// TODO: FIXME: Actually have a look at the `merkle_add` calls
|
||||
alice_merkle_tree.append(&MerkleNode::from(params.outputs[0].coin));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_transaction(blockchain: &Blockchain, tx: &Transaction) -> Result<()> {
|
||||
fn verify_transaction(
|
||||
blockchain: &Blockchain,
|
||||
verifying_keys: &[(String, VerifyingKey)],
|
||||
tx: &Transaction,
|
||||
) -> Result<()> {
|
||||
info!("Begin transcation verification");
|
||||
// Table of public inputs used for ZK proof verification
|
||||
let mut zkp_table = vec![];
|
||||
@@ -336,7 +343,7 @@ fn verify_transaction(blockchain: &Blockchain, tx: &Transaction) -> Result<()> {
|
||||
info!("Signatures verified successfully");
|
||||
|
||||
info!("Verifying transaction ZK proofs");
|
||||
tx.verify_zkps(zkp_table)?;
|
||||
tx.verify_zkps(verifying_keys, zkp_table)?;
|
||||
info!("Transaction ZK proofs verified successfully");
|
||||
|
||||
// After the verification stage has passed, just apply all the changes.
|
||||
|
||||
@@ -28,7 +28,17 @@ use darkfi_serial::{Encodable, SerialDecodable, SerialEncodable};
|
||||
use log::{debug, error};
|
||||
use rand::{CryptoRng, RngCore};
|
||||
|
||||
use crate::{crypto::Proof, Error, Result};
|
||||
use crate::{
|
||||
crypto::{proof::VerifyingKey, Proof},
|
||||
Error, Result, VerifyFailed,
|
||||
};
|
||||
|
||||
macro_rules! zip {
|
||||
($x:expr) => ($x);
|
||||
($x:expr, $($y:expr), +) => (
|
||||
$x.iter().zip(zip!($($y), +))
|
||||
)
|
||||
}
|
||||
|
||||
/// A Transaction contains an arbitrary number of `ContractCall` objects,
|
||||
/// along with corresponding ZK proofs and Schnorr signatures.
|
||||
@@ -44,7 +54,37 @@ pub struct Transaction {
|
||||
|
||||
impl Transaction {
|
||||
/// Verify ZK proofs for the entire transaction.
|
||||
pub fn verify_zkps(&self, zkp_table: Vec<Vec<(String, Vec<pallas::Base>)>>) -> Result<()> {
|
||||
pub fn verify_zkps(
|
||||
&self,
|
||||
verifying_keys: &[(String, VerifyingKey)],
|
||||
zkp_table: Vec<Vec<(String, Vec<pallas::Base>)>>,
|
||||
) -> Result<()> {
|
||||
// TODO: Are we sure we should assert here?
|
||||
assert_eq!(self.calls.len(), self.proofs.len());
|
||||
assert_eq!(self.calls.len(), zkp_table.len());
|
||||
|
||||
for (call, (proofs, pubvals)) in zip!(self.calls, self.proofs, zkp_table) {
|
||||
assert_eq!(proofs.len(), pubvals.len());
|
||||
|
||||
for (i, (proof, (zk_ns, public_vals))) in proofs.iter().zip(pubvals.iter()).enumerate()
|
||||
{
|
||||
if let Some(vk) = verifying_keys.iter().find(|x| &x.0 == zk_ns) {
|
||||
// We have a verifying key for this
|
||||
debug!("public inputs: {:#?}", public_vals);
|
||||
if let Err(e) = proof.verify(&vk.1, public_vals) {
|
||||
error!("Failed verifying zk proof: {}", e);
|
||||
return Err(VerifyFailed::ProofVerifyFailed(e.to_string()).into())
|
||||
}
|
||||
} else {
|
||||
return Err(VerifyFailed::ProofVerifyFailed(format!(
|
||||
"Verifying key for {} circuit does not exist",
|
||||
zk_ns
|
||||
))
|
||||
.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user