mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
contract/money: Token Freeze API
This commit is contained in:
@@ -12,8 +12,9 @@ circuit "TokenFreeze_V1" {
|
||||
mint_public = ec_mul_base(mint_authority, NULLIFIER_K);
|
||||
mint_x = ec_get_x(mint_public);
|
||||
mint_y = ec_get_y(mint_public);
|
||||
constrain_instance(mint_x);
|
||||
constrain_instance(mint_y);
|
||||
# I don't think we need to enforce these two as public inputs
|
||||
#constrain_instance(mint_x);
|
||||
#constrain_instance(mint_y);
|
||||
|
||||
# Derive the token ID
|
||||
token_id = poseidon_hash(mint_x, mint_y);
|
||||
|
||||
94
src/contract/money/src/client/freeze_v1.rs
Normal file
94
src/contract/money/src/client/freeze_v1.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use darkfi::{
|
||||
zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit},
|
||||
zkas::ZkBinary,
|
||||
Result,
|
||||
};
|
||||
use darkfi_sdk::{
|
||||
crypto::{poseidon_hash, Keypair, TokenId},
|
||||
pasta::pallas,
|
||||
};
|
||||
use log::{debug, info};
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
use crate::model::MoneyFreezeParamsV1;
|
||||
|
||||
pub struct FreezeCallDebris {
|
||||
pub params: MoneyFreezeParamsV1,
|
||||
pub proofs: Vec<Proof>,
|
||||
}
|
||||
|
||||
pub struct TokenFreezeRevealed {
|
||||
pub token_id: TokenId,
|
||||
}
|
||||
|
||||
impl TokenFreezeRevealed {
|
||||
pub fn to_vec(&self) -> Vec<pallas::Base> {
|
||||
vec![self.token_id.inner()]
|
||||
}
|
||||
}
|
||||
|
||||
/// Struct holding necessary information to build a `Money::FreezeV1` contract call.
|
||||
pub struct FreezeCallBuilder {
|
||||
/// Mint authority keypair
|
||||
pub mint_authority: Keypair,
|
||||
/// `TokenFreeze_V1` zkas circuit ZkBinary
|
||||
pub token_freeze_zkbin: ZkBinary,
|
||||
/// Proving key for the `TokenFreeze_V1` zk circuit,
|
||||
pub token_freeze_pk: ProvingKey,
|
||||
}
|
||||
|
||||
impl FreezeCallBuilder {
|
||||
pub fn build(&self) -> Result<FreezeCallDebris> {
|
||||
debug!("Building Money::FreezeV1 contract call");
|
||||
|
||||
// For the Freeze call, we just need to produce a valid signature,
|
||||
// and enforce the correct derivation inside ZK.
|
||||
|
||||
info!("Creating token freeze proof");
|
||||
let (proof, _public_inputs) = create_token_freeze_proof(
|
||||
&self.token_freeze_zkbin,
|
||||
&self.token_freeze_pk,
|
||||
&self.mint_authority,
|
||||
)?;
|
||||
|
||||
let params = MoneyFreezeParamsV1 { signature_public: self.mint_authority.public };
|
||||
let debris = FreezeCallDebris { params, proofs: vec![proof] };
|
||||
Ok(debris)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn create_token_freeze_proof(
|
||||
zkbin: &ZkBinary,
|
||||
pk: &ProvingKey,
|
||||
mint_authority: &Keypair,
|
||||
) -> Result<(Proof, TokenFreezeRevealed)> {
|
||||
let (mint_x, mint_y) = mint_authority.public.xy();
|
||||
let token_id = TokenId::from(poseidon_hash([mint_x, mint_y]));
|
||||
|
||||
let public_inputs = TokenFreezeRevealed { token_id };
|
||||
|
||||
let prover_witnesses = vec![Witness::Base(Value::known(mint_authority.secret.inner()))];
|
||||
|
||||
let circuit = ZkCircuit::new(prover_witnesses, zkbin.clone());
|
||||
let proof = Proof::create(pk, &[circuit], &public_inputs.to_vec(), &mut OsRng)?;
|
||||
|
||||
Ok((proof, public_inputs))
|
||||
}
|
||||
@@ -41,6 +41,9 @@ pub mod swap_v1;
|
||||
/// `Money::MintV1` API
|
||||
pub mod mint_v1;
|
||||
|
||||
/// `Money::FreezeV1` API
|
||||
pub mod freeze_v1;
|
||||
|
||||
// Wallet SQL table constant names. These have to represent the `wallet.sql`
|
||||
// SQL schema.
|
||||
// TODO: They should also be prefixed with the contract ID to avoid collisions.
|
||||
|
||||
@@ -49,8 +49,8 @@ pub(crate) fn money_freeze_get_metadata_v1(
|
||||
let (mint_x, mint_y) = params.signature_public.xy();
|
||||
let token_id = poseidon_hash([mint_x, mint_y]);
|
||||
|
||||
zk_public_inputs
|
||||
.push((MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1.to_string(), vec![mint_x, mint_y, token_id]));
|
||||
// In ZK we just verify that the token ID is properly derived from the authority.
|
||||
zk_public_inputs.push((MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1.to_string(), vec![token_id]));
|
||||
|
||||
// Serialize everything gathered and return it
|
||||
let mut metadata = vec![];
|
||||
|
||||
Reference in New Issue
Block a user