mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-09 14:48:08 -05:00
Move mint and burn Rust examples into proof/ to complement zkas code.
This commit is contained in:
15
Cargo.toml
15
Cargo.toml
@@ -239,11 +239,6 @@ name = "tui"
|
||||
path = "example/tui_ex.rs"
|
||||
required-features = ["async-runtime", "tui"]
|
||||
|
||||
[[example]]
|
||||
name = "vm"
|
||||
path = "example/vm.rs"
|
||||
required-features = ["cli", "zkvm"]
|
||||
|
||||
[[example]]
|
||||
name = "tx"
|
||||
path = "example/tx.rs"
|
||||
@@ -253,3 +248,13 @@ required-features = ["node"]
|
||||
name = "tree"
|
||||
path = "example/tree.rs"
|
||||
required-features = ["crypto"]
|
||||
|
||||
[[example]]
|
||||
name = "mint"
|
||||
path = "proof/mint.rs"
|
||||
required-features = ["cli", "zkvm"]
|
||||
|
||||
[[example]]
|
||||
name = "burn"
|
||||
path = "proof/burn.rs"
|
||||
required-features = ["cli", "zkvm"]
|
||||
|
||||
3
Makefile
3
Makefile
@@ -41,8 +41,9 @@ test-tx:
|
||||
|
||||
test-vm: zkas
|
||||
./zkas proof/mint.zk
|
||||
$(CARGO) run --release --features=cli,zkvm --example mint
|
||||
./zkas proof/burn.zk
|
||||
$(CARGO) run --release --features=cli,zkvm --example vm
|
||||
$(CARGO) run --release --features=cli,zkvm --example burn
|
||||
|
||||
clean:
|
||||
rm -f $(BINS)
|
||||
|
||||
@@ -609,9 +609,9 @@ async fn start(
|
||||
let rocks = Rocks::new(expand_path(&config.database_path.clone())?.as_path())?;
|
||||
|
||||
info!("Building verifying key for the mint contract...");
|
||||
let mint_vk = VerifyingKey::build(11, MintContract::default());
|
||||
let mint_vk = VerifyingKey::build(11, &MintContract::default());
|
||||
info!("Building verifying key for the spend contract...");
|
||||
let spend_vk = VerifyingKey::build(11, SpendContract::default());
|
||||
let spend_vk = VerifyingKey::build(11, &SpendContract::default());
|
||||
|
||||
// new Client
|
||||
let gateway_urls =
|
||||
|
||||
@@ -775,9 +775,9 @@ async fn start(
|
||||
let nullifiers = RocksColumn::<columns::Nullifiers>::new(rocks);
|
||||
|
||||
info!("Building verifying key for the mint contract...");
|
||||
let mint_vk = VerifyingKey::build(11, MintContract::default());
|
||||
let mint_vk = VerifyingKey::build(11, &MintContract::default());
|
||||
info!("Building verifying key for the spend contract...");
|
||||
let spend_vk = VerifyingKey::build(11, SpendContract::default());
|
||||
let spend_vk = VerifyingKey::build(11, &SpendContract::default());
|
||||
|
||||
let state = Arc::new(Mutex::new(State {
|
||||
tree,
|
||||
|
||||
@@ -35,10 +35,10 @@ In other words, the vector of public inputs could look like this:
|
||||
```
|
||||
let public_inputs = vec![
|
||||
coin,
|
||||
*value_coords.x();
|
||||
*value_coords.y();
|
||||
*token_coords.x();
|
||||
*token_coords.y();
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
*token_coords.y(),
|
||||
];
|
||||
```
|
||||
|
||||
@@ -87,33 +87,7 @@ Knowing this we can extend our pseudo-code and build the
|
||||
before-mentioned public inputs for the circuit:
|
||||
|
||||
```rust
|
||||
let public_key = pallas::Point::random(&mut OsRng);
|
||||
let coords = public_key.to_affine().coordinates().unwrap();
|
||||
let pub_x = *coords.x();
|
||||
let pub_y = *coords.y();
|
||||
|
||||
let value = pallas::Base::from(42);
|
||||
let token = pallas::Base::from(1);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
let coin_blind = pallas::Base::random(&mut OsRng);
|
||||
|
||||
let coin = poseidon::Hash(pub_x, pub_y, value, token, serial, coin_blind);
|
||||
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let value_commit = pedersen_commitment(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_commit = pedersen_commitment(token, token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let public_inputs = vec![
|
||||
coin,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
*token_coords.y(),
|
||||
];
|
||||
{{#include ../../../../proof/mint.rs}}
|
||||
```
|
||||
|
||||
|
||||
@@ -134,13 +108,13 @@ In this case, our vector of public inputs could look like:
|
||||
```
|
||||
let public_inputs = vec![
|
||||
nullifier,
|
||||
merkle_root,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
*token_coords.y(),
|
||||
*signature_coords.x(),
|
||||
*signature_coords.y(),
|
||||
merkle_root,
|
||||
*sig_coords.x(),
|
||||
*sig_coords.y(),
|
||||
];
|
||||
```
|
||||
|
||||
@@ -188,44 +162,7 @@ Knowing this we can extend our pseudo-code and build the
|
||||
before-mentioned public inputs for the circuit:
|
||||
|
||||
```rust
|
||||
let secret_key = pallas::Base::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
|
||||
let nullifier = poseidon::Hash(secret_key, serial);
|
||||
|
||||
let tree = BridgeTree::<MerkleNode, 32>::new(100);
|
||||
tree.append(some_known_coin);
|
||||
tree.witness();
|
||||
tree.append(another_known_coin);
|
||||
tree.witness();
|
||||
|
||||
let merkle_root = tree.root();
|
||||
|
||||
let value = pallas::Base::from(42);
|
||||
let token = pallas::Base::from(1);
|
||||
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let value_commit = pedersen_commitment(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_commit = pedersen_commitment(token, token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let sig_secret = pallas::Base::random(&mut OsRng);
|
||||
let sig_public = NullifierK.generator() * mod_r_p(sig_secret);
|
||||
let signature_coords = sig_public.to_affine().coordinates().unwrap();
|
||||
|
||||
let public_inputs = vec![
|
||||
nullifier,
|
||||
merkle_root,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
*token_coords.y(),
|
||||
*signature_coords.x(),
|
||||
*signature_coords.y(),
|
||||
];
|
||||
{{#include ../../../../proof/mint.rs}}
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -105,8 +105,8 @@ fn main() -> Result<()> {
|
||||
let keypair = Keypair::random(&mut OsRng);
|
||||
|
||||
const K: u32 = 11;
|
||||
let mint_vk = VerifyingKey::build(K, MintContract::default());
|
||||
let spend_vk = VerifyingKey::build(K, SpendContract::default());
|
||||
let mint_vk = VerifyingKey::build(K, &MintContract::default());
|
||||
let spend_vk = VerifyingKey::build(K, &SpendContract::default());
|
||||
|
||||
let mut state = MemoryState {
|
||||
tree: BridgeTree::<MerkleNode, 32>::new(100),
|
||||
@@ -136,8 +136,8 @@ fn main() -> Result<()> {
|
||||
}],
|
||||
};
|
||||
|
||||
let mint_pk = ProvingKey::build(K, MintContract::default());
|
||||
let spend_pk = ProvingKey::build(K, SpendContract::default());
|
||||
let mint_pk = ProvingKey::build(K, &MintContract::default());
|
||||
let spend_pk = ProvingKey::build(K, &SpendContract::default());
|
||||
let tx = builder.build(&mint_pk, &spend_pk)?;
|
||||
|
||||
tx.verify(&state.mint_vk, &state.spend_vk).expect("tx verify");
|
||||
|
||||
248
example/vm.rs
248
example/vm.rs
@@ -1,248 +0,0 @@
|
||||
use std::time::Instant;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use halo2::{
|
||||
arithmetic::{CurveAffine, Field},
|
||||
dev::MockProver,
|
||||
};
|
||||
use halo2_gadgets::primitives::{
|
||||
poseidon,
|
||||
poseidon::{ConstantLength, P128Pow5T3},
|
||||
};
|
||||
use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
|
||||
use log::info;
|
||||
use pasta_curves::{group::Curve, pallas};
|
||||
use rand::rngs::OsRng;
|
||||
use simplelog::{ColorChoice, LevelFilter, TermLogger, TerminalMode};
|
||||
|
||||
use darkfi::{
|
||||
crypto::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
mint_proof::MintRevealedValues,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
spend_proof::SpendRevealedValues,
|
||||
Proof,
|
||||
},
|
||||
zk::vm::{Witness, ZkCircuit},
|
||||
zkas::decoder::ZkBinary,
|
||||
Result,
|
||||
};
|
||||
|
||||
fn mint_proof() -> Result<()> {
|
||||
let bincode = include_bytes!("../proof/mint.zk.bin");
|
||||
let zkbin = ZkBinary::decode(bincode)?;
|
||||
|
||||
// ======
|
||||
// Prover
|
||||
// ======
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::from(22);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
let coin_blind = pallas::Base::random(&mut OsRng);
|
||||
let public_key = PublicKey::random(&mut OsRng);
|
||||
let pk_coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
|
||||
let witnesses_prover = vec![
|
||||
Witness::Base(Some(*pk_coords.x())),
|
||||
Witness::Base(Some(*pk_coords.y())),
|
||||
Witness::Base(Some(pallas::Base::from(value))),
|
||||
Witness::Base(Some(token_id)),
|
||||
Witness::Base(Some(serial)),
|
||||
Witness::Base(Some(coin_blind)),
|
||||
Witness::Scalar(Some(value_blind)),
|
||||
Witness::Scalar(Some(token_blind)),
|
||||
];
|
||||
|
||||
let public_inputs = MintRevealedValues::compute(
|
||||
value,
|
||||
token_id,
|
||||
value_blind,
|
||||
token_blind,
|
||||
serial,
|
||||
coin_blind,
|
||||
public_key,
|
||||
)
|
||||
.make_outputs()
|
||||
.to_vec();
|
||||
|
||||
let circuit = ZkCircuit::new(witnesses_prover, zkbin.clone());
|
||||
|
||||
// let prover = MockProver::run(11, &circuit, vec![public_inputs.clone()]).unwrap();
|
||||
// assert_eq!(prover.verify(), Ok(()));
|
||||
|
||||
let start = Instant::now();
|
||||
let proving_key = ProvingKey::build(11, circuit.clone());
|
||||
info!("Prover setup: [{:?}]", Instant::now() - start);
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = Proof::create(&proving_key, &[circuit], &public_inputs)?;
|
||||
info!("Prover prove: [{:?}]", Instant::now() - start);
|
||||
|
||||
// =======
|
||||
// Verifier
|
||||
// =======
|
||||
|
||||
let witnesses_verifier = vec![
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Scalar(None),
|
||||
Witness::Scalar(None),
|
||||
];
|
||||
|
||||
let start = Instant::now();
|
||||
let circuit = ZkCircuit::new(witnesses_verifier, zkbin);
|
||||
let verifying_key = VerifyingKey::build(11, circuit);
|
||||
info!("Verifier setup: [{:?}]", Instant::now() - start);
|
||||
|
||||
let start = Instant::now();
|
||||
proof.verify(&verifying_key, &public_inputs)?;
|
||||
info!("Verifier verify: [{:?}]", Instant::now() - start);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fill_tree(coin2: pallas::Base) -> BridgeTree<MerkleNode, 32> {
|
||||
let mut tree = BridgeTree::<MerkleNode, 32>::new(100);
|
||||
let coin0 = pallas::Base::random(&mut OsRng);
|
||||
let coin1 = pallas::Base::random(&mut OsRng);
|
||||
let coin3 = pallas::Base::random(&mut OsRng);
|
||||
|
||||
tree.append(&MerkleNode(coin0));
|
||||
tree.witness();
|
||||
|
||||
tree.append(&MerkleNode(coin1));
|
||||
|
||||
tree.append(&MerkleNode(coin2));
|
||||
tree.witness();
|
||||
|
||||
tree.append(&MerkleNode(coin3));
|
||||
tree.witness();
|
||||
|
||||
tree
|
||||
}
|
||||
|
||||
fn burn_proof() -> Result<()> {
|
||||
let bincode = include_bytes!("../proof/burn.zk.bin");
|
||||
let zkbin = ZkBinary::decode(bincode)?;
|
||||
|
||||
// ======
|
||||
// Prover
|
||||
// ======
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::from(22);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
let coin_blind = pallas::Base::random(&mut OsRng);
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let sig_secret = SecretKey::random(&mut OsRng);
|
||||
|
||||
let coin = {
|
||||
let coords = PublicKey::from_secret(secret).0.to_affine().coordinates().unwrap();
|
||||
let messages =
|
||||
[*coords.x(), *coords.y(), pallas::Base::from(value), token_id, serial, coin_blind];
|
||||
|
||||
poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(messages)
|
||||
};
|
||||
|
||||
let tree = fill_tree(coin);
|
||||
let (leaf_position, merkle_path) = tree.authentication_path(&MerkleNode(coin)).unwrap();
|
||||
|
||||
// Why are these types not matched in halo2 gadgets?
|
||||
let leaf_pos: u64 = leaf_position.into();
|
||||
let leaf_pos = leaf_pos as u32;
|
||||
|
||||
let witnesses_prover = vec![
|
||||
Witness::Base(Some(secret.0)),
|
||||
Witness::Base(Some(serial)),
|
||||
Witness::Base(Some(pallas::Base::from(value))),
|
||||
Witness::Base(Some(token_id)),
|
||||
Witness::Base(Some(coin_blind)),
|
||||
Witness::Scalar(Some(value_blind)),
|
||||
Witness::Scalar(Some(token_blind)),
|
||||
Witness::Uint32(Some(leaf_pos)),
|
||||
Witness::MerklePath(Some(merkle_path.clone().try_into().unwrap())),
|
||||
Witness::Base(Some(sig_secret.0)),
|
||||
];
|
||||
|
||||
let public_inputs = SpendRevealedValues::compute(
|
||||
value,
|
||||
token_id,
|
||||
value_blind,
|
||||
token_blind,
|
||||
serial,
|
||||
coin_blind,
|
||||
secret,
|
||||
leaf_position,
|
||||
merkle_path,
|
||||
sig_secret,
|
||||
)
|
||||
.make_outputs()
|
||||
.to_vec();
|
||||
|
||||
let circuit = ZkCircuit::new(witnesses_prover, zkbin.clone());
|
||||
|
||||
// let prover = MockProver::run(11, &circuit, vec![public_inputs.clone()])?;
|
||||
// assert_eq!(prover.verify(), Ok(()));
|
||||
|
||||
let start = Instant::now();
|
||||
let proving_key = ProvingKey::build(11, circuit.clone());
|
||||
info!("Prover setup: [{:?}]", Instant::now() - start);
|
||||
|
||||
let start = Instant::now();
|
||||
let proof = Proof::create(&proving_key, &[circuit], &public_inputs)?;
|
||||
info!("Prover prove: [{:?}]", Instant::now() - start);
|
||||
|
||||
// ========
|
||||
// Verifier
|
||||
// ========
|
||||
|
||||
let witnesses_verifier = vec![
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Scalar(None),
|
||||
Witness::Scalar(None),
|
||||
Witness::Uint32(None),
|
||||
Witness::MerklePath(None),
|
||||
Witness::Base(None),
|
||||
];
|
||||
|
||||
let start = Instant::now();
|
||||
let circuit = ZkCircuit::new(witnesses_verifier, zkbin);
|
||||
let verifying_key = VerifyingKey::build(11, circuit);
|
||||
info!("Verifier setup: [{:?}]", Instant::now() - start);
|
||||
|
||||
let start = Instant::now();
|
||||
proof.verify(&verifying_key, &public_inputs)?;
|
||||
info!("Verifier verify: [{:?}]", Instant::now() - start);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
TermLogger::init(
|
||||
LevelFilter::Debug,
|
||||
//LevelFilter::Info,
|
||||
simplelog::Config::default(),
|
||||
TerminalMode::Mixed,
|
||||
ColorChoice::Auto,
|
||||
)?;
|
||||
|
||||
info!("Executing Mint proof");
|
||||
mint_proof()?;
|
||||
|
||||
info!("Executing Burn proof");
|
||||
burn_proof()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
146
proof/burn.rs
Normal file
146
proof/burn.rs
Normal file
@@ -0,0 +1,146 @@
|
||||
use darkfi::{
|
||||
crypto::{
|
||||
keypair::{PublicKey, SecretKey},
|
||||
merkle_node::MerkleNode,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
Proof,
|
||||
},
|
||||
zk::vm::{Witness, ZkCircuit},
|
||||
zkas::decoder::ZkBinary,
|
||||
Result,
|
||||
};
|
||||
use halo2_gadgets::primitives::{
|
||||
poseidon,
|
||||
poseidon::{ConstantLength, P128Pow5T3},
|
||||
};
|
||||
use incrementalmerkletree::{bridgetree::BridgeTree, Frontier, Tree};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, Field},
|
||||
group::Curve,
|
||||
pallas,
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use simplelog::{ColorChoice::Auto, Config, LevelFilter::Debug, TermLogger, TerminalMode::Mixed};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
TermLogger::init(Debug, Config::default(), Mixed, Auto)?;
|
||||
|
||||
let bincode = include_bytes!("burn.zk.bin");
|
||||
let zkbin = ZkBinary::decode(bincode)?;
|
||||
|
||||
// ======
|
||||
// Prover
|
||||
// ======
|
||||
|
||||
// Witness values
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::from(22);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
let coin_blind = pallas::Base::random(&mut OsRng);
|
||||
let secret = SecretKey::random(&mut OsRng);
|
||||
let sig_secret = SecretKey::random(&mut OsRng);
|
||||
|
||||
// Build the coin
|
||||
let coin2 = {
|
||||
let coords = PublicKey::from_secret(secret).0.to_affine().coordinates().unwrap();
|
||||
let messages =
|
||||
[*coords.x(), *coords.y(), pallas::Base::from(value), token_id, serial, coin_blind];
|
||||
|
||||
poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(messages)
|
||||
};
|
||||
|
||||
// Fill the merkle tree with some random coins that we want to witness,
|
||||
// and also add the above coin.
|
||||
let mut tree = BridgeTree::<MerkleNode, 32>::new(100);
|
||||
let coin0 = pallas::Base::random(&mut OsRng);
|
||||
let coin1 = pallas::Base::random(&mut OsRng);
|
||||
let coin3 = pallas::Base::random(&mut OsRng);
|
||||
|
||||
tree.append(&MerkleNode(coin0));
|
||||
tree.witness();
|
||||
tree.append(&MerkleNode(coin1));
|
||||
tree.append(&MerkleNode(coin2));
|
||||
tree.witness();
|
||||
tree.append(&MerkleNode(coin3));
|
||||
tree.witness();
|
||||
|
||||
let (leaf_pos, merkle_path) = tree.authentication_path(&MerkleNode(coin2)).unwrap();
|
||||
let leaf_pos: u64 = leaf_pos.into();
|
||||
let leaf_pos = leaf_pos as u32;
|
||||
|
||||
let prover_witnesses = vec![
|
||||
Witness::Base(Some(secret.0)),
|
||||
Witness::Base(Some(serial)),
|
||||
Witness::Base(Some(pallas::Base::from(value))),
|
||||
Witness::Base(Some(token_id)),
|
||||
Witness::Base(Some(coin_blind)),
|
||||
Witness::Scalar(Some(value_blind)),
|
||||
Witness::Scalar(Some(token_blind)),
|
||||
Witness::Uint32(Some(leaf_pos)),
|
||||
Witness::MerklePath(Some(merkle_path.try_into().unwrap())),
|
||||
Witness::Base(Some(sig_secret.0)),
|
||||
];
|
||||
|
||||
// Create the public inputs
|
||||
let nullifier = [secret.0, serial];
|
||||
let nullifier = poseidon::Hash::init(P128Pow5T3, ConstantLength::<2>).hash(nullifier);
|
||||
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let sig_pubkey = PublicKey::from_secret(sig_secret);
|
||||
let sig_coords = sig_pubkey.0.to_affine().coordinates().unwrap();
|
||||
|
||||
let merkle_root = tree.root();
|
||||
|
||||
let public_inputs = vec![
|
||||
nullifier,
|
||||
*value_coords.x(),
|
||||
*value_coords.y(),
|
||||
*token_coords.x(),
|
||||
*token_coords.y(),
|
||||
merkle_root.0,
|
||||
*sig_coords.x(),
|
||||
*sig_coords.y(),
|
||||
];
|
||||
|
||||
// Create the circuit
|
||||
let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
|
||||
|
||||
// Build the proving key and create the zero-knowledge proof
|
||||
let proving_key = ProvingKey::build(11, &circuit);
|
||||
let proof = Proof::create(&proving_key, &[circuit], &public_inputs)?;
|
||||
|
||||
// ========
|
||||
// Verifier
|
||||
// ========
|
||||
|
||||
// Construct empty witnesses
|
||||
let verifier_witnesses = vec![
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Scalar(None),
|
||||
Witness::Scalar(None),
|
||||
Witness::Uint32(None),
|
||||
Witness::MerklePath(None),
|
||||
Witness::Base(None),
|
||||
];
|
||||
|
||||
// Create the circuit
|
||||
let circuit = ZkCircuit::new(verifier_witnesses, zkbin);
|
||||
|
||||
// Build the verifying key and verify the zero-knowledge proof
|
||||
let verifying_key = VerifyingKey::build(11, &circuit);
|
||||
proof.verify(&verifying_key, &public_inputs)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
99
proof/mint.rs
Normal file
99
proof/mint.rs
Normal file
@@ -0,0 +1,99 @@
|
||||
use darkfi::{
|
||||
crypto::{
|
||||
keypair::PublicKey,
|
||||
proof::{ProvingKey, VerifyingKey},
|
||||
util::{mod_r_p, pedersen_commitment_scalar, pedersen_commitment_u64},
|
||||
Proof,
|
||||
},
|
||||
zk::vm::{Witness, ZkCircuit},
|
||||
zkas::decoder::ZkBinary,
|
||||
Result,
|
||||
};
|
||||
use halo2_gadgets::primitives::{
|
||||
poseidon,
|
||||
poseidon::{ConstantLength, P128Pow5T3},
|
||||
};
|
||||
use pasta_curves::{
|
||||
arithmetic::{CurveAffine, Field},
|
||||
group::Curve,
|
||||
pallas,
|
||||
};
|
||||
use rand::rngs::OsRng;
|
||||
use simplelog::{ColorChoice::Auto, Config, LevelFilter::Debug, TermLogger, TerminalMode::Mixed};
|
||||
|
||||
fn main() -> Result<()> {
|
||||
TermLogger::init(Debug, Config::default(), Mixed, Auto)?;
|
||||
|
||||
let bincode = include_bytes!("mint.zk.bin");
|
||||
let zkbin = ZkBinary::decode(bincode)?;
|
||||
|
||||
// ======
|
||||
// Prover
|
||||
// ======
|
||||
|
||||
// Witness values
|
||||
let value = 42;
|
||||
let token_id = pallas::Base::from(22);
|
||||
let value_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let token_blind = pallas::Scalar::random(&mut OsRng);
|
||||
let serial = pallas::Base::random(&mut OsRng);
|
||||
let coin_blind = pallas::Base::random(&mut OsRng);
|
||||
let public_key = PublicKey::random(&mut OsRng);
|
||||
let coords = public_key.0.to_affine().coordinates().unwrap();
|
||||
|
||||
let prover_witnesses = vec![
|
||||
Witness::Base(Some(*coords.x())),
|
||||
Witness::Base(Some(*coords.y())),
|
||||
Witness::Base(Some(pallas::Base::from(value))),
|
||||
Witness::Base(Some(token_id)),
|
||||
Witness::Base(Some(serial)),
|
||||
Witness::Base(Some(coin_blind)),
|
||||
Witness::Scalar(Some(value_blind)),
|
||||
Witness::Scalar(Some(token_blind)),
|
||||
];
|
||||
|
||||
// Create the public inputs
|
||||
let msgs = [*coords.x(), *coords.y(), pallas::Base::from(value), token_id, serial, coin_blind];
|
||||
let coin = poseidon::Hash::init(P128Pow5T3, ConstantLength::<6>).hash(msgs);
|
||||
|
||||
let value_commit = pedersen_commitment_u64(value, value_blind);
|
||||
let value_coords = value_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let token_commit = pedersen_commitment_scalar(mod_r_p(token_id), token_blind);
|
||||
let token_coords = token_commit.to_affine().coordinates().unwrap();
|
||||
|
||||
let public_inputs =
|
||||
vec![coin, *value_coords.x(), *value_coords.y(), *token_coords.x(), *token_coords.y()];
|
||||
|
||||
// Create the circuit
|
||||
let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
|
||||
|
||||
// Build the proving key and create the zero-knowledge proof
|
||||
let proving_key = ProvingKey::build(11, &circuit);
|
||||
let proof = Proof::create(&proving_key, &[circuit], &public_inputs)?;
|
||||
|
||||
// ========
|
||||
// Verifier
|
||||
// ========
|
||||
|
||||
// Construct empty witnesses
|
||||
let verifier_witnesses = vec![
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Base(None),
|
||||
Witness::Scalar(None),
|
||||
Witness::Scalar(None),
|
||||
];
|
||||
|
||||
// Create the circuit
|
||||
let circuit = ZkCircuit::new(verifier_witnesses, zkbin);
|
||||
|
||||
// Build the verifying key and verify the zero-knowledge proof
|
||||
let verifying_key = VerifyingKey::build(11, &circuit);
|
||||
proof.verify(&verifying_key, &public_inputs)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -22,9 +22,9 @@ pub struct VerifyingKey {
|
||||
}
|
||||
|
||||
impl VerifyingKey {
|
||||
pub fn build(k: u32, c: impl Circuit<DrkCircuitField>) -> Self {
|
||||
pub fn build(k: u32, c: &impl Circuit<DrkCircuitField>) -> Self {
|
||||
let params = Params::new(k);
|
||||
let vk = plonk::keygen_vk(¶ms, &c).unwrap();
|
||||
let vk = plonk::keygen_vk(¶ms, c).unwrap();
|
||||
VerifyingKey { params, vk }
|
||||
}
|
||||
}
|
||||
@@ -36,10 +36,10 @@ pub struct ProvingKey {
|
||||
}
|
||||
|
||||
impl ProvingKey {
|
||||
pub fn build(k: u32, c: impl Circuit<DrkCircuitField>) -> Self {
|
||||
pub fn build(k: u32, c: &impl Circuit<DrkCircuitField>) -> Self {
|
||||
let params = Params::new(k);
|
||||
let vk = plonk::keygen_vk(¶ms, &c).unwrap();
|
||||
let pk = plonk::keygen_pk(¶ms, vk, &c).unwrap();
|
||||
let vk = plonk::keygen_vk(¶ms, c).unwrap();
|
||||
let pk = plonk::keygen_pk(¶ms, vk, c).unwrap();
|
||||
ProvingKey { params, pk }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,9 +115,9 @@ impl Client {
|
||||
|
||||
// TODO: These should go to a better place.
|
||||
debug!("Building proving key for the mint contract...");
|
||||
let mint_pk = ProvingKey::build(11, MintContract::default());
|
||||
let mint_pk = ProvingKey::build(11, &MintContract::default());
|
||||
debug!("Building proving key for the spend contract...");
|
||||
let spend_pk = ProvingKey::build(11, SpendContract::default());
|
||||
let spend_pk = ProvingKey::build(11, &SpendContract::default());
|
||||
|
||||
let client = Client { main_keypair, gateway, wallet, mint_pk, spend_pk };
|
||||
Ok(client)
|
||||
|
||||
Reference in New Issue
Block a user