|
|
|
|
@@ -30,27 +30,31 @@ use darkfi_money_contract::{
|
|
|
|
|
};
|
|
|
|
|
use darkfi_sdk::{
|
|
|
|
|
crypto::{
|
|
|
|
|
ecvrf::VrfProof, note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_base,
|
|
|
|
|
pedersen_commitment_u64, poseidon_hash, MerkleNode, MerkleTree, Nullifier, PublicKey,
|
|
|
|
|
SecretKey,
|
|
|
|
|
ecvrf::VrfProof, note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_u64,
|
|
|
|
|
poseidon_hash, Keypair, MerkleNode, MerkleTree, Nullifier, PublicKey, SecretKey,
|
|
|
|
|
},
|
|
|
|
|
incrementalmerkletree::{Hashable, Tree},
|
|
|
|
|
pasta::{group::ff::FromUniformBytes, pallas},
|
|
|
|
|
};
|
|
|
|
|
use log::debug;
|
|
|
|
|
use log::{debug, info};
|
|
|
|
|
use rand::rngs::OsRng;
|
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
|
client::common::{ConsensusBurnInputInfo, ConsensusMintOutputInfo},
|
|
|
|
|
model::{
|
|
|
|
|
ConsensusProposalParamsV1, HEADSTART, MU_RHO_PREFIX, MU_Y_PREFIX, REWARD, REWARD_PALLAS,
|
|
|
|
|
SEED_PREFIX, SERIAL_PREFIX,
|
|
|
|
|
ConsensusProposalParamsV1, HEADSTART, MU_RHO_PREFIX, MU_Y_PREFIX, REWARD, SEED_PREFIX,
|
|
|
|
|
SERIAL_PREFIX,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub struct ConsensusProposalCallDebris {
|
|
|
|
|
/// Payload params
|
|
|
|
|
pub params: ConsensusProposalParamsV1,
|
|
|
|
|
/// ZK proofs
|
|
|
|
|
pub proofs: Vec<Proof>,
|
|
|
|
|
/// The new output keypair (used in the minted coin)
|
|
|
|
|
pub keypair: Keypair,
|
|
|
|
|
/// Secret key used to sign the transaction
|
|
|
|
|
pub signature_secret: SecretKey,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -59,11 +63,10 @@ pub struct ConsensusProposalRevealed {
|
|
|
|
|
pub epoch: u64,
|
|
|
|
|
pub public_key: PublicKey,
|
|
|
|
|
pub merkle_root: MerkleNode,
|
|
|
|
|
pub value_commit: pallas::Point,
|
|
|
|
|
pub new_serial: pallas::Base,
|
|
|
|
|
pub new_serial_commit: pallas::Point,
|
|
|
|
|
pub new_value_commit: pallas::Point,
|
|
|
|
|
pub new_coin: Coin,
|
|
|
|
|
pub input_value_commit: pallas::Point,
|
|
|
|
|
pub reward: u64,
|
|
|
|
|
pub output_value_commit: pallas::Point,
|
|
|
|
|
pub output_coin: Coin,
|
|
|
|
|
pub vrf_proof: VrfProof,
|
|
|
|
|
pub mu_y: pallas::Base,
|
|
|
|
|
pub y: pallas::Base,
|
|
|
|
|
@@ -71,40 +74,36 @@ pub struct ConsensusProposalRevealed {
|
|
|
|
|
pub rho: pallas::Base,
|
|
|
|
|
pub sigma1: pallas::Base,
|
|
|
|
|
pub sigma2: pallas::Base,
|
|
|
|
|
pub headstart: pallas::Base,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ConsensusProposalRevealed {
|
|
|
|
|
pub fn to_vec(&self) -> Vec<pallas::Base> {
|
|
|
|
|
let epoch_palas = pallas::Base::from(self.epoch);
|
|
|
|
|
fn to_vec(&self) -> Vec<pallas::Base> {
|
|
|
|
|
let (pub_x, pub_y) = self.public_key.xy();
|
|
|
|
|
let value_coords = self.value_commit.to_affine().coordinates().unwrap();
|
|
|
|
|
let new_serial_coords = self.new_serial_commit.to_affine().coordinates().unwrap();
|
|
|
|
|
let reward_pallas = pallas::Base::from(REWARD);
|
|
|
|
|
let new_value_coords = self.new_value_commit.to_affine().coordinates().unwrap();
|
|
|
|
|
let input_value_coords = self.input_value_commit.to_affine().coordinates().unwrap();
|
|
|
|
|
let output_value_coords = self.output_value_commit.to_affine().coordinates().unwrap();
|
|
|
|
|
|
|
|
|
|
// NOTE: It's important to keep these in the same order
|
|
|
|
|
// as the `constrain_instance` calls in the zkas code.
|
|
|
|
|
vec![
|
|
|
|
|
self.nullifier.inner(),
|
|
|
|
|
epoch_palas,
|
|
|
|
|
pallas::Base::from(self.epoch),
|
|
|
|
|
pub_x,
|
|
|
|
|
pub_y,
|
|
|
|
|
self.merkle_root.inner(),
|
|
|
|
|
*value_coords.x(),
|
|
|
|
|
*value_coords.y(),
|
|
|
|
|
*new_serial_coords.x(),
|
|
|
|
|
*new_serial_coords.y(),
|
|
|
|
|
reward_pallas,
|
|
|
|
|
*new_value_coords.x(),
|
|
|
|
|
*new_value_coords.y(),
|
|
|
|
|
self.new_coin.inner(),
|
|
|
|
|
*input_value_coords.x(),
|
|
|
|
|
*input_value_coords.y(),
|
|
|
|
|
pallas::Base::from(self.reward),
|
|
|
|
|
*output_value_coords.x(),
|
|
|
|
|
*output_value_coords.y(),
|
|
|
|
|
self.output_coin.inner(),
|
|
|
|
|
self.mu_y,
|
|
|
|
|
self.y,
|
|
|
|
|
self.mu_rho,
|
|
|
|
|
self.rho,
|
|
|
|
|
self.sigma1,
|
|
|
|
|
self.sigma2,
|
|
|
|
|
HEADSTART,
|
|
|
|
|
self.headstart,
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -112,7 +111,7 @@ impl ConsensusProposalRevealed {
|
|
|
|
|
/// Struct holding necessary information to build a proposal transaction.
|
|
|
|
|
pub struct ConsensusProposalCallBuilder {
|
|
|
|
|
/// `ConsensusOwnCoin` we're given to use in this builder
|
|
|
|
|
pub coin: ConsensusOwnCoin,
|
|
|
|
|
pub owncoin: ConsensusOwnCoin,
|
|
|
|
|
/// Rewarded slot checkpoint
|
|
|
|
|
pub slot_checkpoint: SlotCheckpoint,
|
|
|
|
|
/// Extending fork last proposal/block hash
|
|
|
|
|
@@ -120,7 +119,7 @@ pub struct ConsensusProposalCallBuilder {
|
|
|
|
|
/// Extending fork second to last proposal/block hash
|
|
|
|
|
pub fork_previous_hash: blake3::Hash,
|
|
|
|
|
/// Merkle tree of coins used to create inclusion proofs
|
|
|
|
|
pub tree: MerkleTree,
|
|
|
|
|
pub merkle_tree: MerkleTree,
|
|
|
|
|
/// `Proposal_V1` zkas circuit ZkBinary
|
|
|
|
|
pub proposal_zkbin: ZkBinary,
|
|
|
|
|
/// Proving key for the `Proposal_V1` zk circuit
|
|
|
|
|
@@ -129,129 +128,148 @@ pub struct ConsensusProposalCallBuilder {
|
|
|
|
|
|
|
|
|
|
impl ConsensusProposalCallBuilder {
|
|
|
|
|
pub fn build(&self) -> Result<ConsensusProposalCallDebris> {
|
|
|
|
|
debug!("Building Consensus::ProposalBurnV1 contract call for proposal");
|
|
|
|
|
let value = self.coin.note.value;
|
|
|
|
|
assert!(value != 0);
|
|
|
|
|
info!("Building Consensus::ProposalBurnV1 contract call");
|
|
|
|
|
assert!(self.owncoin.note.value != 0);
|
|
|
|
|
|
|
|
|
|
debug!("Building Consensus::ProposalV1 anonymous input");
|
|
|
|
|
let leaf_position = self.coin.leaf_position;
|
|
|
|
|
let root = self.tree.root(0).unwrap();
|
|
|
|
|
let merkle_path = self.tree.authentication_path(leaf_position, &root).unwrap();
|
|
|
|
|
let root = self.merkle_tree.root(0).unwrap();
|
|
|
|
|
let merkle_path =
|
|
|
|
|
self.merkle_tree.authentication_path(self.owncoin.leaf_position, &root).unwrap();
|
|
|
|
|
|
|
|
|
|
let input = ConsensusBurnInputInfo {
|
|
|
|
|
leaf_position,
|
|
|
|
|
leaf_position: self.owncoin.leaf_position,
|
|
|
|
|
merkle_path,
|
|
|
|
|
secret: self.coin.secret,
|
|
|
|
|
note: self.coin.note.clone(),
|
|
|
|
|
secret: self.owncoin.secret,
|
|
|
|
|
note: self.owncoin.note.clone(),
|
|
|
|
|
value_blind: pallas::Scalar::random(&mut OsRng),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
debug!("Building anonymous output");
|
|
|
|
|
let reward_blind = pallas::Scalar::random(&mut OsRng);
|
|
|
|
|
let new_value_blind = input.value_blind + reward_blind;
|
|
|
|
|
let new_coin_blind = pallas::Base::random(&mut OsRng);
|
|
|
|
|
let output = ConsensusMintOutputInfo {
|
|
|
|
|
value: self.coin.note.value + REWARD,
|
|
|
|
|
epoch: 0,
|
|
|
|
|
public_key: PublicKey::from_secret(self.coin.secret),
|
|
|
|
|
value_blind: new_value_blind,
|
|
|
|
|
serial: self.coin.note.serial,
|
|
|
|
|
coin_blind: new_coin_blind,
|
|
|
|
|
};
|
|
|
|
|
debug!("Finished building output");
|
|
|
|
|
debug!("Building Consensus::ProposalV1 anonymous output");
|
|
|
|
|
let output_coin_blind = pallas::Base::random(&mut OsRng);
|
|
|
|
|
let output_reward_blind = pallas::Scalar::random(&mut OsRng);
|
|
|
|
|
let output_value_blind = input.value_blind + output_reward_blind;
|
|
|
|
|
|
|
|
|
|
debug!("Building Consensus::ProposalV1 contract call for proposal");
|
|
|
|
|
// We create a new random keypair for the output
|
|
|
|
|
let output_keypair = Keypair::random(&mut OsRng);
|
|
|
|
|
|
|
|
|
|
// The output's serial is derived from the old serial
|
|
|
|
|
let new_serial =
|
|
|
|
|
poseidon_hash([SERIAL_PREFIX, self.owncoin.secret.inner(), self.owncoin.note.serial]);
|
|
|
|
|
|
|
|
|
|
let output = ConsensusMintOutputInfo {
|
|
|
|
|
value: self.owncoin.note.value + REWARD,
|
|
|
|
|
epoch: 0, // We set the epoch as 0 here to eliminate a potential timelock
|
|
|
|
|
public_key: output_keypair.public,
|
|
|
|
|
value_blind: output_value_blind,
|
|
|
|
|
serial: new_serial,
|
|
|
|
|
coin_blind: output_coin_blind,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
info!("Building Consensus::ProposalV1 VRF proof");
|
|
|
|
|
let mut vrf_input = Vec::with_capacity(32 + blake3::OUT_LEN + 32);
|
|
|
|
|
vrf_input.extend_from_slice(&self.slot_checkpoint.previous_eta.to_repr());
|
|
|
|
|
vrf_input.extend_from_slice(self.fork_previous_hash.as_bytes());
|
|
|
|
|
vrf_input.extend_from_slice(&pallas::Base::from(self.slot_checkpoint.slot).to_repr());
|
|
|
|
|
let vrf_proof = VrfProof::prove(input.secret, &vrf_input, &mut OsRng);
|
|
|
|
|
|
|
|
|
|
info!("Building Consensus::ProposalV1 ZK proof");
|
|
|
|
|
let (proof, public_inputs) = create_proposal_proof(
|
|
|
|
|
&self.proposal_zkbin,
|
|
|
|
|
&self.proposal_pk,
|
|
|
|
|
&input,
|
|
|
|
|
&output,
|
|
|
|
|
&self.slot_checkpoint,
|
|
|
|
|
self.fork_hash,
|
|
|
|
|
self.fork_previous_hash,
|
|
|
|
|
&vrf_proof,
|
|
|
|
|
)?;
|
|
|
|
|
|
|
|
|
|
let input = ConsensusInput {
|
|
|
|
|
epoch: self.coin.note.epoch,
|
|
|
|
|
coin: self.coin.coin,
|
|
|
|
|
value_commit: public_inputs.value_commit,
|
|
|
|
|
let tx_input = ConsensusInput {
|
|
|
|
|
epoch: input.note.epoch,
|
|
|
|
|
value_commit: public_inputs.input_value_commit,
|
|
|
|
|
nullifier: public_inputs.nullifier,
|
|
|
|
|
merkle_root: public_inputs.merkle_root,
|
|
|
|
|
signature_public: public_inputs.public_key,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Encrypted note
|
|
|
|
|
// Output's encrypted note
|
|
|
|
|
let note = ConsensusNote {
|
|
|
|
|
serial: public_inputs.new_serial,
|
|
|
|
|
serial: output.serial,
|
|
|
|
|
value: output.value,
|
|
|
|
|
epoch: 0,
|
|
|
|
|
coin_blind: new_coin_blind,
|
|
|
|
|
value_blind: new_value_blind,
|
|
|
|
|
epoch: output.epoch,
|
|
|
|
|
coin_blind: output.coin_blind,
|
|
|
|
|
value_blind: output.value_blind,
|
|
|
|
|
reward: REWARD,
|
|
|
|
|
reward_blind,
|
|
|
|
|
reward_blind: output_reward_blind,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let encrypted_note = AeadEncryptedNote::encrypt(¬e, &output.public_key, &mut OsRng)?;
|
|
|
|
|
|
|
|
|
|
let output = ConsensusOutput {
|
|
|
|
|
value_commit: public_inputs.new_value_commit,
|
|
|
|
|
coin: public_inputs.new_coin,
|
|
|
|
|
let tx_output = ConsensusOutput {
|
|
|
|
|
value_commit: public_inputs.output_value_commit,
|
|
|
|
|
coin: public_inputs.output_coin,
|
|
|
|
|
note: encrypted_note,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// We now fill this with necessary stuff
|
|
|
|
|
let new_serial_commit = public_inputs.new_serial_commit;
|
|
|
|
|
let slot = self.slot_checkpoint.slot;
|
|
|
|
|
let vrf_proof = public_inputs.vrf_proof;
|
|
|
|
|
let y = public_inputs.y;
|
|
|
|
|
let rho = public_inputs.rho;
|
|
|
|
|
// Construct params
|
|
|
|
|
let params = ConsensusProposalParamsV1 {
|
|
|
|
|
input,
|
|
|
|
|
output,
|
|
|
|
|
input: tx_input,
|
|
|
|
|
output: tx_output,
|
|
|
|
|
reward: REWARD,
|
|
|
|
|
reward_blind,
|
|
|
|
|
new_serial_commit,
|
|
|
|
|
slot,
|
|
|
|
|
reward_blind: output_reward_blind,
|
|
|
|
|
slot: self.slot_checkpoint.slot,
|
|
|
|
|
fork_hash: self.fork_hash,
|
|
|
|
|
fork_previous_hash: self.fork_previous_hash,
|
|
|
|
|
vrf_proof,
|
|
|
|
|
y,
|
|
|
|
|
rho,
|
|
|
|
|
y: public_inputs.y,
|
|
|
|
|
rho: public_inputs.rho,
|
|
|
|
|
};
|
|
|
|
|
let proofs = vec![proof];
|
|
|
|
|
|
|
|
|
|
// Now we should have all the params, zk proofs and signature secret.
|
|
|
|
|
// We return it all and let the caller deal with it.
|
|
|
|
|
let debris =
|
|
|
|
|
ConsensusProposalCallDebris { params, proofs, signature_secret: self.coin.secret };
|
|
|
|
|
// Construct debris
|
|
|
|
|
let debris = ConsensusProposalCallDebris {
|
|
|
|
|
params,
|
|
|
|
|
proofs: vec![proof],
|
|
|
|
|
keypair: output_keypair,
|
|
|
|
|
signature_secret: input.secret,
|
|
|
|
|
};
|
|
|
|
|
Ok(debris)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn create_proposal_proof(
|
|
|
|
|
fn create_proposal_proof(
|
|
|
|
|
zkbin: &ZkBinary,
|
|
|
|
|
pk: &ProvingKey,
|
|
|
|
|
input: &ConsensusBurnInputInfo,
|
|
|
|
|
output: &ConsensusMintOutputInfo,
|
|
|
|
|
slot_checkpoint: &SlotCheckpoint,
|
|
|
|
|
_fork_hash: blake3::Hash,
|
|
|
|
|
fork_previous_hash: blake3::Hash,
|
|
|
|
|
checkpoint: &SlotCheckpoint,
|
|
|
|
|
vrf_proof: &VrfProof,
|
|
|
|
|
) -> Result<(Proof, ConsensusProposalRevealed)> {
|
|
|
|
|
// TODO: fork_hash to be used as part of rank constrain in the proof
|
|
|
|
|
// Proof parameters
|
|
|
|
|
// Calculate lottery parameters
|
|
|
|
|
let seed = poseidon_hash([SEED_PREFIX, input.note.serial]);
|
|
|
|
|
|
|
|
|
|
let mut eta = [0u8; 64];
|
|
|
|
|
eta[..blake3::OUT_LEN].copy_from_slice(vrf_proof.hash_output().as_bytes());
|
|
|
|
|
let eta = pallas::Base::from_uniform_bytes(&eta);
|
|
|
|
|
|
|
|
|
|
let mu_y = poseidon_hash([MU_Y_PREFIX, eta, pallas::Base::from(checkpoint.slot)]);
|
|
|
|
|
let y = poseidon_hash([seed, mu_y]);
|
|
|
|
|
let mu_rho = poseidon_hash([MU_RHO_PREFIX, eta, pallas::Base::from(checkpoint.slot)]);
|
|
|
|
|
let rho = poseidon_hash([seed, mu_rho]);
|
|
|
|
|
|
|
|
|
|
// Derive the input's nullifier
|
|
|
|
|
let nullifier = Nullifier::from(poseidon_hash([input.secret.inner(), input.note.serial]));
|
|
|
|
|
let epoch = input.note.epoch;
|
|
|
|
|
let epoch_pallas = pallas::Base::from(epoch);
|
|
|
|
|
let value_pallas = pallas::Base::from(input.note.value);
|
|
|
|
|
let value_commit = pedersen_commitment_u64(input.note.value, input.value_blind);
|
|
|
|
|
|
|
|
|
|
// Create the value commitment for the input
|
|
|
|
|
let input_value_commit = pedersen_commitment_u64(input.note.value, input.value_blind);
|
|
|
|
|
|
|
|
|
|
// Merkle inclusion proof for the input
|
|
|
|
|
let public_key = PublicKey::from_secret(input.secret);
|
|
|
|
|
let (pub_x, pub_y) = public_key.xy();
|
|
|
|
|
|
|
|
|
|
// Burnt coin and its merkle_root
|
|
|
|
|
let coin = poseidon_hash([
|
|
|
|
|
pub_x,
|
|
|
|
|
pub_y,
|
|
|
|
|
value_pallas,
|
|
|
|
|
epoch_pallas,
|
|
|
|
|
pallas::Base::from(input.note.value),
|
|
|
|
|
pallas::Base::from(input.note.epoch),
|
|
|
|
|
input.note.serial,
|
|
|
|
|
input.note.coin_blind,
|
|
|
|
|
]);
|
|
|
|
|
@@ -270,79 +288,56 @@ pub fn create_proposal_proof(
|
|
|
|
|
current
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// New coin
|
|
|
|
|
let new_serial = poseidon_hash([SERIAL_PREFIX, input.secret.inner(), input.note.serial]);
|
|
|
|
|
let new_serial_blind = pallas::Scalar::random(&mut OsRng);
|
|
|
|
|
let new_serial_commit = pedersen_commitment_base(new_serial, new_serial_blind);
|
|
|
|
|
let new_value_commit = pedersen_commitment_u64(output.value, output.value_blind);
|
|
|
|
|
let new_value_pallas = pallas::Base::from(output.value);
|
|
|
|
|
let (new_pub_x, new_pub_y) = output.public_key.xy();
|
|
|
|
|
|
|
|
|
|
let new_coin = Coin::from(poseidon_hash([
|
|
|
|
|
new_pub_x,
|
|
|
|
|
new_pub_y,
|
|
|
|
|
new_value_pallas,
|
|
|
|
|
pallas::Base::ZERO,
|
|
|
|
|
new_serial,
|
|
|
|
|
// Derive the new output coin
|
|
|
|
|
let (output_x, output_y) = output.public_key.xy();
|
|
|
|
|
let output_coin = Coin::from(poseidon_hash([
|
|
|
|
|
output_x,
|
|
|
|
|
output_y,
|
|
|
|
|
pallas::Base::from(output.value),
|
|
|
|
|
pallas::Base::from(output.epoch),
|
|
|
|
|
output.serial,
|
|
|
|
|
output.coin_blind,
|
|
|
|
|
]));
|
|
|
|
|
|
|
|
|
|
let slot_pallas = pallas::Base::from(slot_checkpoint.slot);
|
|
|
|
|
let seed = poseidon_hash([SEED_PREFIX, input.note.serial]);
|
|
|
|
|
let mut vrf_input = Vec::with_capacity(32 + blake3::OUT_LEN + 32);
|
|
|
|
|
vrf_input.extend_from_slice(&slot_checkpoint.previous_eta.to_repr());
|
|
|
|
|
vrf_input.extend_from_slice(fork_previous_hash.as_bytes());
|
|
|
|
|
vrf_input.extend_from_slice(&slot_pallas.to_repr());
|
|
|
|
|
let vrf_proof = VrfProof::prove(input.secret, &vrf_input, &mut OsRng);
|
|
|
|
|
let mut eta = [0u8; 64];
|
|
|
|
|
eta[..blake3::OUT_LEN].copy_from_slice(vrf_proof.hash_output().as_bytes());
|
|
|
|
|
let eta = pallas::Base::from_uniform_bytes(&eta);
|
|
|
|
|
let mu_y = poseidon_hash([MU_Y_PREFIX, eta, slot_pallas]);
|
|
|
|
|
let y = poseidon_hash([seed, mu_y]);
|
|
|
|
|
let mu_rho = poseidon_hash([MU_RHO_PREFIX, eta, slot_pallas]);
|
|
|
|
|
let rho = poseidon_hash([seed, mu_rho]);
|
|
|
|
|
let (sigma1, sigma2) = (slot_checkpoint.sigma1, slot_checkpoint.sigma2);
|
|
|
|
|
|
|
|
|
|
// Generate public inputs, witnesses and proof
|
|
|
|
|
// Create the ZK proof
|
|
|
|
|
let public_inputs = ConsensusProposalRevealed {
|
|
|
|
|
nullifier,
|
|
|
|
|
epoch,
|
|
|
|
|
epoch: input.note.epoch,
|
|
|
|
|
public_key,
|
|
|
|
|
merkle_root,
|
|
|
|
|
value_commit,
|
|
|
|
|
new_serial,
|
|
|
|
|
new_serial_commit,
|
|
|
|
|
new_value_commit,
|
|
|
|
|
new_coin,
|
|
|
|
|
vrf_proof,
|
|
|
|
|
input_value_commit,
|
|
|
|
|
reward: REWARD,
|
|
|
|
|
output_value_commit: pedersen_commitment_u64(output.value, output.value_blind),
|
|
|
|
|
output_coin,
|
|
|
|
|
vrf_proof: *vrf_proof,
|
|
|
|
|
mu_y,
|
|
|
|
|
y,
|
|
|
|
|
mu_rho,
|
|
|
|
|
rho,
|
|
|
|
|
sigma1,
|
|
|
|
|
sigma2,
|
|
|
|
|
sigma1: checkpoint.sigma1,
|
|
|
|
|
sigma2: checkpoint.sigma2,
|
|
|
|
|
headstart: HEADSTART,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let prover_witnesses = vec![
|
|
|
|
|
Witness::Base(Value::known(input.secret.inner())),
|
|
|
|
|
Witness::Base(Value::known(input.note.serial)),
|
|
|
|
|
Witness::Base(Value::known(pallas::Base::from(input.note.value))),
|
|
|
|
|
Witness::Base(Value::known(epoch_pallas)),
|
|
|
|
|
Witness::Base(Value::known(REWARD_PALLAS)),
|
|
|
|
|
Witness::Base(Value::known(pallas::Base::from(input.note.epoch))),
|
|
|
|
|
Witness::Base(Value::known(pallas::Base::from(REWARD))),
|
|
|
|
|
Witness::Scalar(Value::known(input.value_blind)),
|
|
|
|
|
Witness::Base(Value::known(input.note.coin_blind)),
|
|
|
|
|
Witness::Uint32(Value::known(u64::from(input.leaf_position).try_into().unwrap())),
|
|
|
|
|
Witness::MerklePath(Value::known(input.merkle_path.clone().try_into().unwrap())),
|
|
|
|
|
Witness::Scalar(Value::known(new_serial_blind)),
|
|
|
|
|
Witness::Base(Value::known(new_pub_x)),
|
|
|
|
|
Witness::Base(Value::known(new_pub_y)),
|
|
|
|
|
Witness::Base(Value::known(output_x)),
|
|
|
|
|
Witness::Base(Value::known(output_y)),
|
|
|
|
|
Witness::Scalar(Value::known(output.value_blind)),
|
|
|
|
|
Witness::Base(Value::known(output.coin_blind)),
|
|
|
|
|
Witness::Base(Value::known(mu_y)),
|
|
|
|
|
Witness::Base(Value::known(mu_rho)),
|
|
|
|
|
Witness::Base(Value::known(sigma1)),
|
|
|
|
|
Witness::Base(Value::known(sigma2)),
|
|
|
|
|
Witness::Base(Value::known(HEADSTART)),
|
|
|
|
|
Witness::Base(Value::known(public_inputs.mu_y)),
|
|
|
|
|
Witness::Base(Value::known(public_inputs.mu_rho)),
|
|
|
|
|
Witness::Base(Value::known(public_inputs.sigma1)),
|
|
|
|
|
Witness::Base(Value::known(public_inputs.sigma2)),
|
|
|
|
|
Witness::Base(Value::known(public_inputs.headstart)),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
|
|
|
|
|
|