contract/deployooor: Remove redundant ZK proof creation and verification

This commit is contained in:
parazyd
2024-02-20 14:41:57 +01:00
parent b82aee8cd3
commit dc203e12f0
11 changed files with 19 additions and 181 deletions

View File

@@ -16,13 +16,6 @@ PKGNAME = $(shell grep '^name = ' Cargo.toml | cut -d' ' -f3 | tr -d '"')
# wasm contract binary
WASM_BIN = $(PKGNAME:=.wasm)
# zkas compiler binary
ZKAS = ../../../zkas
# zkas circuits
PROOFS_SRC = $(shell find proof -type f -name '*.zk')
PROOFS_BIN = $(PROOFS_SRC:=.bin)
# wasm source files
WASM_SRC = \
Cargo.toml \
@@ -35,10 +28,7 @@ WASM_SRC = \
all: $(WASM_BIN)
$(PROOFS_BIN): $(ZKAS) $(PROOFS_SRC)
$(ZKAS) $(basename $@) -o $@
$(WASM_BIN): $(WASM_SRC) $(PROOFS_BIN)
$(WASM_BIN): $(WASM_SRC)
RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) build --target=$(WASM_TARGET) \
--release --package $(PKGNAME)
cp -f ../../../target/$(WASM_TARGET)/release/$@ $@
@@ -64,6 +54,6 @@ clean:
--release --package $(PKGNAME)
RUSTFLAGS="$(RUSTFLAGS)" $(CARGO) clean --target=$(RUST_TARGET) \
--release --package $(PKGNAME)
rm -f $(PROOFS_BIN) $(WASM_BIN)
rm -f $(WASM_BIN)
.PHONY: all test-integration test clippy clean

View File

@@ -1,27 +0,0 @@
k = 13;
field = "pallas";
constant "DeriveContractID" {
EcFixedPointBase NULLIFIER_K,
}
witness "DeriveContractID" {
# Deploy key used for signing and contract ID derivation
Base deploy_key,
}
circuit "DeriveContractID" {
# ContractID derivation path (See darkfi_sdk::crypto::ContractId)
derivation_path = witness_base(42);
# Derive the public key used for the signature
signature_public = ec_mul_base(deploy_key, NULLIFIER_K);
signature_x = ec_get_x(signature_public);
signature_y = ec_get_y(signature_public);
constrain_instance(signature_x);
constrain_instance(signature_y);
# Derive the Contract ID
contract_id = poseidon_hash(derivation_path, signature_x, signature_y);
constrain_instance(contract_id);
}

View File

@@ -16,19 +16,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use darkfi::{
zk::{Proof, ProvingKey},
zkas::ZkBinary,
Result,
};
use darkfi::Result;
use darkfi_sdk::{crypto::Keypair, deploy::DeployParamsV1};
use log::{debug, info};
use super::create_derive_contractid_proof;
use log::info;
pub struct DeployCallDebris {
pub params: DeployParamsV1,
pub proofs: Vec<Proof>,
}
/// Struct holding necessary information to build a `Deployooor::DeployV1` contract call.
@@ -39,10 +32,6 @@ pub struct DeployCallBuilder {
pub wasm_bincode: Vec<u8>,
/// Serialized deployment payload instruction
pub deploy_ix: Vec<u8>,
/// `DeriveContractID` zkas circuit ZkBinary
pub derivecid_zkbin: ZkBinary,
/// Proving key for the `DeriveContractID` zk circuit
pub derivecid_pk: ProvingKey,
}
impl DeployCallBuilder {
@@ -50,20 +39,13 @@ impl DeployCallBuilder {
info!("Building Deployooor::DeployV1 contract call");
assert!(!self.wasm_bincode.is_empty());
debug!("Creating DeriveContractID ZK proof");
let (proof, _public_inputs) = create_derive_contractid_proof(
&self.derivecid_zkbin,
&self.derivecid_pk,
&self.deploy_keypair,
)?;
let params = DeployParamsV1 {
wasm_bincode: self.wasm_bincode.clone(),
public_key: self.deploy_keypair.public,
ix: self.deploy_ix.clone(),
};
let debris = DeployCallDebris { params, proofs: vec![proof] };
let debris = DeployCallDebris { params };
Ok(debris)
}

View File

@@ -16,45 +16,28 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use darkfi::{
zk::{Proof, ProvingKey},
zkas::ZkBinary,
Result,
};
use darkfi::Result;
use darkfi_sdk::crypto::Keypair;
use log::{debug, info};
use log::info;
use super::create_derive_contractid_proof;
use crate::model::LockParamsV1;
pub struct LockCallDebris {
pub params: LockParamsV1,
pub proofs: Vec<Proof>,
}
/// Struct holding necessary information to build a `Deployooor::LockV1` contract call.
pub struct LockCallBuilder {
/// Contract deploy keypair
pub deploy_keypair: Keypair,
/// `DeriveContractID` zkas circuit ZkBinary,
pub derivecid_zkbin: ZkBinary,
/// Proving key for the `DeriveContractId` zk circuit
pub derivecid_pk: ProvingKey,
}
impl LockCallBuilder {
pub fn build(&self) -> Result<LockCallDebris> {
info!("Building Deployooor::LockV1 contract call");
debug!("Creating DeriveContractID ZK proof");
let (proof, _public_inputs) = create_derive_contractid_proof(
&self.derivecid_zkbin,
&self.derivecid_pk,
&self.deploy_keypair,
)?;
let params = LockParamsV1 { public_key: self.deploy_keypair.public };
let debris = LockCallDebris { params, proofs: vec![proof] };
let debris = LockCallDebris { params };
Ok(debris)
}

View File

@@ -19,45 +19,8 @@
//! This module implements the client-side API for deploying arbitrary contracts
//! on the DarkFi network.
use darkfi::{
zk::{halo2::Value, Proof, ProvingKey, Witness, ZkCircuit},
zkas::ZkBinary,
Result,
};
use darkfi_sdk::{
crypto::{ContractId, Keypair, PublicKey},
pasta::pallas,
};
use rand::rngs::OsRng;
/// `Deployooor::DeployV1` API
pub mod deploy_v1;
/// `Deployooor::LockV1` API
pub mod lock_v1;
pub struct DeriveContractIdRevealed {
pub public_key: PublicKey,
pub contract_id: ContractId,
}
impl DeriveContractIdRevealed {
pub fn to_vec(&self) -> Vec<pallas::Base> {
let (pub_x, pub_y) = self.public_key.xy();
vec![pub_x, pub_y, self.contract_id.inner()]
}
}
pub fn create_derive_contractid_proof(
zkbin: &ZkBinary,
pk: &ProvingKey,
deploy_key: &Keypair,
) -> Result<(Proof, DeriveContractIdRevealed)> {
let contract_id = ContractId::derive(deploy_key.secret);
let public_inputs = DeriveContractIdRevealed { public_key: deploy_key.public, contract_id };
let prover_witnesses = vec![Witness::Base(Value::known(deploy_key.secret.inner()))];
let circuit = ZkCircuit::new(prover_witnesses, zkbin);
let proof = Proof::create(pk, &[circuit], &public_inputs.to_vec(), &mut OsRng)?;
Ok((proof, public_inputs))
}

View File

@@ -19,7 +19,7 @@
use darkfi_sdk::{
crypto::ContractId,
dark_tree::DarkLeaf,
db::{db_init, db_lookup, db_set, zkas_db_set},
db::{db_init, db_lookup, db_set},
error::ContractResult,
util::set_return_data,
ContractCall,
@@ -51,10 +51,6 @@ darkfi_sdk::define_contract!(
/// We use this function to initialize all the necessary databases and prepare them
/// with initial data if necessary.
fn init_contract(cid: ContractId, _ix: &[u8]) -> ContractResult {
// Set up the zkas circuit tree
let derive_cid_bincode = include_bytes!("../proof/derive_contract_id.zk.bin");
zkas_db_set(&derive_cid_bincode[..])?;
// Set up a database tree for arbitrary data
let info_db = match db_lookup(cid, DEPLOY_CONTRACT_INFO_TREE) {
Ok(v) => v,

View File

@@ -32,10 +32,7 @@ use wasmparser::{
Payload::ExportSection,
};
use crate::{
error::DeployError, model::DeployUpdateV1, DeployFunction, DEPLOY_CONTRACT_LOCK_TREE,
DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1,
};
use crate::{error::DeployError, model::DeployUpdateV1, DeployFunction, DEPLOY_CONTRACT_LOCK_TREE};
/// `get_metadata` function for `Deploy::DeployV1`
pub(crate) fn deploy_get_metadata_v1(
@@ -47,20 +44,10 @@ pub(crate) fn deploy_get_metadata_v1(
let params: DeployParamsV1 = deserialize(&self_.data.data[1..])?;
// Public inputs for the ZK proofs we have to verify
let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
let zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
// Public keys for the transaction signatures we have to verify
let signature_pubkeys: Vec<PublicKey> = vec![params.public_key];
// Derive the ContractID from the public key
let (sig_x, sig_y) = params.public_key.xy();
let contract_id = ContractId::derive_public(params.public_key);
// Append the ZK public inputs
zk_public_inputs.push((
DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1.to_string(),
vec![sig_x, sig_y, contract_id.inner()],
));
// Serialize everything gathered and return it
let mut metadata = vec![];
zk_public_inputs.encode(&mut metadata)?;

View File

@@ -30,7 +30,7 @@ use darkfi_serial::{deserialize, serialize, Encodable, WriteExt};
use crate::{
error::DeployError,
model::{LockParamsV1, LockUpdateV1},
DeployFunction, DEPLOY_CONTRACT_LOCK_TREE, DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1,
DeployFunction, DEPLOY_CONTRACT_LOCK_TREE,
};
/// `get_metadata` function for `Deploy::LockV1`
@@ -43,20 +43,10 @@ pub(crate) fn lock_get_metadata_v1(
let params: LockParamsV1 = deserialize(&self_.data.data[1..])?;
// Public inputs for the ZK proofs we have to verify
let mut zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
let zk_public_inputs: Vec<(String, Vec<pallas::Base>)> = vec![];
// Public keys for the transaction signatures we have to verify
let signature_pubkeys: Vec<PublicKey> = vec![params.public_key];
// Derive the ContractID from the public key
let (sig_x, sig_y) = params.public_key.xy();
let contract_id = ContractId::derive_public(params.public_key);
// Append the ZK public inputs
zk_public_inputs.push((
DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1.to_string(),
vec![sig_x, sig_y, contract_id.inner()],
));
// Serialize everything gathered and return it
let mut metadata = vec![];
zk_public_inputs.encode(&mut metadata)?;

View File

@@ -59,6 +59,3 @@ pub const DEPLOY_CONTRACT_LOCK_TREE: &str = "lock";
// These are keys inside the info tree
pub const DEPLOY_CONTRACT_DB_VERSION: &[u8] = b"db_version";
/// zkas derive circuit namespace
pub const DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1: &str = "DeriveContractID";

View File

@@ -20,9 +20,7 @@ use darkfi::{
tx::{ContractCallLeaf, Transaction, TransactionBuilder},
Result,
};
use darkfi_deployooor_contract::{
client::deploy_v1::DeployCallBuilder, DeployFunction, DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1,
};
use darkfi_deployooor_contract::{client::deploy_v1::DeployCallBuilder, DeployFunction};
use darkfi_money_contract::{
client::{MoneyNote, OwnCoin},
model::MoneyFeeParamsV1,
@@ -50,17 +48,8 @@ impl TestHarness {
let wallet = self.holders.get(holder).unwrap();
let deploy_keypair = wallet.contract_deploy_authority;
let (derivecid_pk, derivecid_zkbin) =
self.proving_keys.get(&DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1.to_string()).unwrap();
// Build the contract call
let builder = DeployCallBuilder {
deploy_keypair,
wasm_bincode,
deploy_ix: vec![],
derivecid_zkbin: derivecid_zkbin.clone(),
derivecid_pk: derivecid_pk.clone(),
};
let builder = DeployCallBuilder { deploy_keypair, wasm_bincode, deploy_ix: vec![] };
let debris = builder.build()?;
// Encode the call
@@ -68,7 +57,7 @@ impl TestHarness {
debris.params.encode_async(&mut data).await?;
let call = ContractCall { contract_id: *DEPLOYOOOR_CONTRACT_ID, data };
let mut tx_builder =
TransactionBuilder::new(ContractCallLeaf { call, proofs: debris.proofs }, vec![])?;
TransactionBuilder::new(ContractCallLeaf { call, proofs: vec![] }, vec![])?;
// If we have tx fees enabled, make an offering
let mut fee_params = None;

View File

@@ -36,21 +36,20 @@ use darkfi_dao_contract::{
DAO_CONTRACT_ZKAS_DAO_PROPOSE_MAIN_NS, DAO_CONTRACT_ZKAS_DAO_VOTE_INPUT_NS,
DAO_CONTRACT_ZKAS_DAO_VOTE_MAIN_NS,
};
use darkfi_deployooor_contract::DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1;
use darkfi_money_contract::{
MONEY_CONTRACT_ZKAS_AUTH_TOKEN_MINT_NS_V1, MONEY_CONTRACT_ZKAS_BURN_NS_V1,
MONEY_CONTRACT_ZKAS_FEE_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1,
MONEY_CONTRACT_ZKAS_TOKEN_FRZ_NS_V1, MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1,
};
use darkfi_sdk::crypto::{contract_id::DEPLOYOOOR_CONTRACT_ID, DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
use darkfi_sdk::crypto::{DAO_CONTRACT_ID, MONEY_CONTRACT_ID};
use darkfi_serial::{deserialize, serialize};
use log::debug;
/// Update these if any circuits are changed.
/// Delete the existing cachefiles, and enable debug logging, you will see the new hashes.
const VKS_HASH: &str = "605a72d885e6194ac346a328482504ca37f0c990c2d636ad1b548a8bfb05542b";
const PKS_HASH: &str = "277228a59ed3cc1df8a9d9e61b3230b4417512d649b4aca1fb3e5f02514a2e96";
const PKS_HASH: &str = "b19792d5c813eebe339af055fc3459cdad8e97e766a35a79f3e42964a2d6e610";
const VKS_HASH: &str = "9a92231ef4edfc20c2043d5255b558de5c07a9a4efda07718b689c299ac9440e";
/// Build a `PathBuf` to a cachefile
fn cache_path(typ: &str) -> Result<PathBuf> {
@@ -137,8 +136,6 @@ pub fn get_cached_pks_and_vks() -> Result<(Pks, Vks)> {
&include_bytes!("../../dao/proof/exec.zk.bin")[..],
&include_bytes!("../../dao/proof/auth-money-transfer.zk.bin")[..],
&include_bytes!("../../dao/proof/auth-money-transfer-enc-coin.zk.bin")[..],
// Deployooor
&include_bytes!("../../deployooor/proof/derive_contract_id.zk.bin")[..],
];
let mut pks = vec![];
@@ -184,12 +181,10 @@ pub fn inject(sled_db: &sled::Db, vks: &Vks) -> Result<()> {
// Derive the database names for the specific contracts
let money_db_name = MONEY_CONTRACT_ID.hash_state_id(SMART_CONTRACT_ZKAS_DB_NAME);
let dao_db_name = DAO_CONTRACT_ID.hash_state_id(SMART_CONTRACT_ZKAS_DB_NAME);
let deployooor_db_name = DEPLOYOOOR_CONTRACT_ID.hash_state_id(SMART_CONTRACT_ZKAS_DB_NAME);
// Create the db trees
let money_tree = sled_db.open_tree(money_db_name)?;
let dao_tree = sled_db.open_tree(dao_db_name)?;
let deployooor_tree = sled_db.open_tree(deployooor_db_name)?;
for (bincode, namespace, vk) in vks.iter() {
match namespace.as_str() {
@@ -219,13 +214,6 @@ pub fn inject(sled_db: &sled::Db, vks: &Vks) -> Result<()> {
dao_tree.insert(key, value)?;
}
// Deployooor contract circuits
DEPLOY_CONTRACT_ZKAS_DERIVE_NS_V1 => {
let key = serialize(&namespace.as_str());
let value = serialize(&(bincode.clone(), vk.clone()));
deployooor_tree.insert(key, value)?;
}
x => panic!("Found unhandled zkas namespace {}", x),
}
}