diff --git a/Cargo.lock b/Cargo.lock index 6f101f053..5e140e426 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1818,8 +1818,6 @@ dependencies = [ "darkfi-serial", "easy-parallel", "futures", - "hex", - "libsqlite3-sys", "log", "rand 0.8.5", "rustls-pemfile", @@ -1828,7 +1826,6 @@ dependencies = [ "signal-hook", "signal-hook-async-std", "simplelog", - "sled", "smol", "structopt", "structopt-toml", diff --git a/bin/drk/src/rpc_swap.rs b/bin/drk/src/rpc_swap.rs index 618002f03..9492a55da 100644 --- a/bin/drk/src/rpc_swap.rs +++ b/bin/drk/src/rpc_swap.rs @@ -31,9 +31,8 @@ use darkfi_money_contract::{ }; use darkfi_sdk::{ crypto::{ - contract_id::MONEY_CONTRACT_ID, - pedersen::{pedersen_commitment_base, pedersen_commitment_u64}, - poseidon_hash, PublicKey, SecretKey, TokenId, + contract_id::MONEY_CONTRACT_ID, pedersen::pedersen_commitment_u64, poseidon_hash, + PublicKey, SecretKey, TokenId, }, pasta::pallas, tx::ContractCall, @@ -52,7 +51,7 @@ pub struct PartialSwapData { value_pair: (u64, u64), token_pair: (TokenId, TokenId), value_blinds: Vec, - token_blinds: Vec, + token_blinds: Vec, } impl fmt::Display for PartialSwapData { @@ -129,7 +128,7 @@ impl Drk { // Since we're creating the first half, we generate the blinds. let value_blinds = [pallas::Scalar::random(&mut OsRng), pallas::Scalar::random(&mut OsRng)]; - let token_blinds = [pallas::Scalar::random(&mut OsRng), pallas::Scalar::random(&mut OsRng)]; + let token_blinds = [pallas::Base::random(&mut OsRng), pallas::Base::random(&mut OsRng)]; // Now we should have everything we need to build the swap half eprintln!("Creating Mint and Burn circuit proving keys"); @@ -370,7 +369,7 @@ impl Drk { } let valcom = pedersen_commitment_u64(note.value, note.value_blind); - let tokcom = pedersen_commitment_base(note.token_id.inner(), note.token_blind); + let tokcom = poseidon_hash([note.token_id.inner(), note.token_blind]); if valcom != params.outputs[output_idx].value_commit { eprintln!( diff --git a/bin/drk/src/wallet_money.rs b/bin/drk/src/wallet_money.rs index 8cda8a70d..2ace6a389 100644 --- a/bin/drk/src/wallet_money.rs +++ b/bin/drk/src/wallet_money.rs @@ -319,7 +319,7 @@ impl Drk { let value_blind: pallas::Scalar = deserialize(&value_blind_bytes)?; let token_blind_bytes: Vec = serde_json::from_value(row[8].clone())?; - let token_blind: pallas::Scalar = deserialize(&token_blind_bytes)?; + let token_blind: pallas::Base = deserialize(&token_blind_bytes)?; let secret_bytes: Vec = serde_json::from_value(row[9].clone())?; let secret: SecretKey = deserialize(&secret_bytes)?; diff --git a/src/contract/consensus/src/client/genesis_stake_v1.rs b/src/contract/consensus/src/client/genesis_stake_v1.rs index 52934dc1f..1a732fb54 100644 --- a/src/contract/consensus/src/client/genesis_stake_v1.rs +++ b/src/contract/consensus/src/client/genesis_stake_v1.rs @@ -64,7 +64,7 @@ impl ConsensusGenesisStakeCallBuilder { // enforce that the clear input and the anon output have the same // commitments. let value_blind = pallas::Scalar::random(&mut OsRng); - let token_blind = pallas::Scalar::random(&mut OsRng); + let token_blind = pallas::Base::random(&mut OsRng); let reward_blind = pallas::Scalar::random(&mut OsRng); // FIXME: The coin's serial number here is arbitrary, and allows grinding attacks. @@ -76,7 +76,7 @@ impl ConsensusGenesisStakeCallBuilder { pub fn build_with_params( &self, value_blind: pallas::Scalar, - token_blind: pallas::Scalar, + token_blind: pallas::Base, reward_blind: pallas::Scalar, serial: pallas::Base, ) -> Result { diff --git a/src/contract/money/proof/burn_v1.zk b/src/contract/money/proof/burn_v1.zk index cef429501..ee9a046f6 100644 --- a/src/contract/money/proof/burn_v1.zk +++ b/src/contract/money/proof/burn_v1.zk @@ -1,11 +1,14 @@ +# The k parameter defining the number of rows used in our circuit (2^k) k = 13; +# The constants we define for our circuit constant "Burn_V1" { EcFixedPointShort VALUE_COMMIT_VALUE, EcFixedPoint VALUE_COMMIT_RANDOM, EcFixedPointBase NULLIFIER_K, } +# The witness values we define for our circuit witness "Burn_V1" { # The value of this coin Base value, @@ -14,7 +17,7 @@ witness "Burn_V1" { # Random blinding factor for value commitment Scalar value_blind, # Random blinding factor for the token ID - Scalar token_blind, + Base token_blind, # Unique serial number corresponding to this coin Base serial, # Allows composing this ZK proof to invoke other contracts @@ -33,6 +36,7 @@ witness "Burn_V1" { Base signature_secret, } +# The definition of our circuit circuit "Burn_V1" { # Poseidon hash of the nullifier nullifier = poseidon_hash(secret, serial); @@ -47,22 +51,17 @@ circuit "Burn_V1" { constrain_instance(ec_get_x(value_commit)); constrain_instance(ec_get_y(value_commit)); - # Pedersen commitment for coin's token ID - tcv = ec_mul_base(token, NULLIFIER_K); - tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM); - token_commit = ec_add(tcv, tcr); - # Since token_commit is also a curve point, we'll do the same - # coordinate dance: - constrain_instance(ec_get_x(token_commit)); - constrain_instance(ec_get_y(token_commit)); + # Commitment for coin's token ID. We do a poseidon hash since it's + # cheaper than EC operations and doesn't need the homomorphic prop. + token_commit = poseidon_hash(token, token_blind); + constrain_instance(token_commit); - # Coin hash + # Derive the public key used in the coin from its secret counterpart pub = ec_mul_base(secret, NULLIFIER_K); - pub_x = ec_get_x(pub); - pub_y = ec_get_y(pub); + # Coin hash C = poseidon_hash( - pub_x, - pub_y, + ec_get_x(pub), + ec_get_y(pub), value, token, serial, @@ -91,10 +90,8 @@ circuit "Burn_V1" { # Finally, we derive a public key for the signature and # constrain its coordinates: signature_public = ec_mul_base(signature_secret, NULLIFIER_K); - signature_x = ec_get_x(signature_public); - signature_y = ec_get_y(signature_public); - constrain_instance(signature_x); - constrain_instance(signature_y); + constrain_instance(ec_get_x(signature_public)); + constrain_instance(ec_get_y(signature_public)); # At this point we've enforced all of our public inputs. } diff --git a/src/contract/money/proof/mint_v1.zk b/src/contract/money/proof/mint_v1.zk index 651e6c663..fbcdbbe71 100644 --- a/src/contract/money/proof/mint_v1.zk +++ b/src/contract/money/proof/mint_v1.zk @@ -1,11 +1,14 @@ +# The k parameter defining the number of rows used in our circuit (2^k) k = 13; +# The constants we define for our circuit constant "Mint_V1" { EcFixedPointShort VALUE_COMMIT_VALUE, EcFixedPoint VALUE_COMMIT_RANDOM, EcFixedPointBase NULLIFIER_K, } +# The witness values we define for our circuit witness "Mint_V1" { # X coordinate for public key Base pub_x, @@ -24,9 +27,10 @@ witness "Mint_V1" { # Random blinding factor for the value commitment Scalar value_blind, # Random blinding factor for the token ID - Scalar token_blind, + Base token_blind, } +# The definition of our circuit circuit "Mint_V1" { # Poseidon hash of the coin C = poseidon_hash( @@ -49,14 +53,10 @@ circuit "Mint_V1" { constrain_instance(ec_get_x(value_commit)); constrain_instance(ec_get_y(value_commit)); - # Pedersen commitment for coin's token ID - tcv = ec_mul_base(token, NULLIFIER_K); - tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM); - token_commit = ec_add(tcv, tcr); - # Since token_commit is also a curve point, we'll do the same - # coordinate dance: - constrain_instance(ec_get_x(token_commit)); - constrain_instance(ec_get_y(token_commit)); + # Commitment for coin's token ID. We do a poseidon hash since it's + # cheaper than EC operations and doesn't need the homomorphic prop. + token_commit = poseidon_hash(token, token_blind); + constrain_instance(token_commit); # At this point we've enforced all of our public inputs. } diff --git a/src/contract/money/proof/token_mint_v1.zk b/src/contract/money/proof/token_mint_v1.zk index e504c5fc1..dea5091e2 100644 --- a/src/contract/money/proof/token_mint_v1.zk +++ b/src/contract/money/proof/token_mint_v1.zk @@ -26,12 +26,10 @@ witness "TokenMint_V1" { # Random blinding factor for the value commitment Scalar value_blind, # Random blinding factor for the token ID - Scalar token_blind, + Base token_blind, } circuit "TokenMint_V1" { - # TODO: verify if supply must be > 0 and add corresponding opcode - # TokenID derivation path (See darkfi_sdk::crypto::TokenId) derivation_path = witness_base(69); @@ -65,10 +63,7 @@ circuit "TokenMint_V1" { constrain_instance(ec_get_x(value_commit)); constrain_instance(ec_get_y(value_commit)); - # Pedersen commitment for the token ID - tcv = ec_mul_base(token_id, NULLIFIER_K); - tcr = ec_mul(token_blind, VALUE_COMMIT_RANDOM); - token_commit = ec_add(tcv, tcr); - constrain_instance(ec_get_x(token_commit)); - constrain_instance(ec_get_y(token_commit)); + # Commitment for the coin's token ID + token_commit = poseidon_hash(token_id, token_blind); + constrain_instance(token_commit); } diff --git a/src/contract/money/src/client/genesis_mint_v1.rs b/src/contract/money/src/client/genesis_mint_v1.rs index 3dad501d6..2f08b8f71 100644 --- a/src/contract/money/src/client/genesis_mint_v1.rs +++ b/src/contract/money/src/client/genesis_mint_v1.rs @@ -47,23 +47,16 @@ pub struct GenesisMintCallDebris { pub struct GenesisMintRevealed { pub coin: Coin, pub value_commit: pallas::Point, - pub token_commit: pallas::Point, + pub token_commit: pallas::Base, } impl GenesisMintRevealed { pub fn to_vec(&self) -> Vec { let valcom_coords = self.value_commit.to_affine().coordinates().unwrap(); - let tokcom_coords = self.token_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.coin.inner(), - *valcom_coords.x(), - *valcom_coords.y(), - *tokcom_coords.x(), - *tokcom_coords.y(), - ] + vec![self.coin.inner(), *valcom_coords.x(), *valcom_coords.y(), self.token_commit] } } @@ -104,12 +97,11 @@ impl GenesisMintCallBuilder { public_key: self.keypair.public, }; - // We just create the pedersen commitment blinds here. We simply - // enforce that the clear input and the anon output have the same - // commitments. Not sure if this can be avoided, but also is it - // really necessary to avoid? + // We just create the commitment blinds here. We simply encofce + // that the clear input and the anon output have the same commitments. + // Not sure if this can be avoided, but also is it really necessary to avoid? let value_blind = pallas::Scalar::random(&mut OsRng); - let token_blind = pallas::Scalar::random(&mut OsRng); + let token_blind = pallas::Base::random(&mut OsRng); let c_input = ClearInput { value: input.value, diff --git a/src/contract/money/src/client/mod.rs b/src/contract/money/src/client/mod.rs index acab52809..10dd9355c 100644 --- a/src/contract/money/src/client/mod.rs +++ b/src/contract/money/src/client/mod.rs @@ -112,7 +112,7 @@ pub struct MoneyNote { /// Blinding factor for the value pedersen commitment pub value_blind: pallas::Scalar, /// Blinding factor for the token ID pedersen commitment - pub token_blind: pallas::Scalar, + pub token_blind: pallas::Base, /// Attached memo (arbitrary data) pub memo: Vec, } @@ -158,7 +158,7 @@ impl From for MoneyNote { spend_hook: pallas::Base::ZERO, user_data: pallas::Base::ZERO, value_blind: consensus_note.value_blind, - token_blind: pallas::Scalar::ZERO, + token_blind: pallas::Base::ZERO, memo: vec![], } } diff --git a/src/contract/money/src/client/stake_v1.rs b/src/contract/money/src/client/stake_v1.rs index 185ae8dac..20f7ae220 100644 --- a/src/contract/money/src/client/stake_v1.rs +++ b/src/contract/money/src/client/stake_v1.rs @@ -27,8 +27,8 @@ use darkfi_sdk::{ bridgetree, bridgetree::Hashable, crypto::{ - pasta_prelude::*, pedersen_commitment_base, pedersen_commitment_u64, poseidon_hash, - MerkleNode, MerkleTree, Nullifier, PublicKey, SecretKey, DARK_TOKEN_ID, + pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, MerkleNode, MerkleTree, + Nullifier, PublicKey, SecretKey, DARK_TOKEN_ID, }, pasta::pallas, }; @@ -49,7 +49,7 @@ pub struct MoneyStakeCallDebris { pub struct MoneyStakeBurnRevealed { pub value_commit: pallas::Point, - pub token_commit: pallas::Point, + pub token_commit: pallas::Base, pub nullifier: Nullifier, pub merkle_root: MerkleNode, pub spend_hook: pallas::Base, @@ -60,7 +60,6 @@ pub struct MoneyStakeBurnRevealed { impl MoneyStakeBurnRevealed { pub fn to_vec(&self) -> Vec { let valcom_coords = self.value_commit.to_affine().coordinates().unwrap(); - let tokcom_coords = self.token_commit.to_affine().coordinates().unwrap(); let sigpub_coords = self.signature_public.inner().to_affine().coordinates().unwrap(); // NOTE: It's important to keep these in the same order @@ -69,8 +68,7 @@ impl MoneyStakeBurnRevealed { self.nullifier.inner(), *valcom_coords.x(), *valcom_coords.y(), - *tokcom_coords.x(), - *tokcom_coords.y(), + self.token_commit, self.merkle_root.inner(), self.user_data_enc, pallas::Base::ZERO, // We force spend_hook==0 here @@ -117,7 +115,7 @@ impl MoneyStakeCallBuilder { // Create new random blinds and an ephemeral signature key let value_blind = pallas::Scalar::random(&mut OsRng); - let token_blind = pallas::Scalar::random(&mut OsRng); + let token_blind = pallas::Base::random(&mut OsRng); let signature_secret = SecretKey::random(&mut OsRng); let user_data_blind = pallas::Base::random(&mut OsRng); @@ -158,7 +156,7 @@ pub fn create_stake_burn_proof( pk: &ProvingKey, input: &TransactionBuilderInputInfo, value_blind: pallas::Scalar, - token_blind: pallas::Scalar, + token_blind: pallas::Base, user_data_blind: pallas::Base, signature_secret: SecretKey, ) -> Result<(Proof, MoneyStakeBurnRevealed)> { @@ -194,7 +192,7 @@ pub fn create_stake_burn_proof( let user_data_enc = poseidon_hash([input.note.user_data, user_data_blind]); let value_commit = pedersen_commitment_u64(input.note.value, value_blind); - let token_commit = pedersen_commitment_base(input.note.token_id.inner(), token_blind); + let token_commit = poseidon_hash([input.note.token_id.inner(), token_blind]); let public_inputs = MoneyStakeBurnRevealed { value_commit, @@ -210,7 +208,7 @@ pub fn create_stake_burn_proof( Witness::Base(Value::known(pallas::Base::from(input.note.value))), Witness::Base(Value::known(input.note.token_id.inner())), Witness::Scalar(Value::known(value_blind)), - Witness::Scalar(Value::known(token_blind)), + Witness::Base(Value::known(token_blind)), Witness::Base(Value::known(input.note.serial)), Witness::Base(Value::known(input.note.spend_hook)), Witness::Base(Value::known(input.note.user_data)), diff --git a/src/contract/money/src/client/swap_v1.rs b/src/contract/money/src/client/swap_v1.rs index f1a67ddef..a21f2379c 100644 --- a/src/contract/money/src/client/swap_v1.rs +++ b/src/contract/money/src/client/swap_v1.rs @@ -76,7 +76,7 @@ pub struct SwapCallBuilder { /// `token_blinds`. pub value_blinds: [pallas::Scalar; 2], /// The blinds to be used for token ID pedersen commitments - pub token_blinds: [pallas::Scalar; 2], + pub token_blinds: [pallas::Base; 2], /// The coin to be used as the input to the swap pub coin: OwnCoin, /// Merkle tree of coins used to create inclusion proofs diff --git a/src/contract/money/src/client/token_mint_v1.rs b/src/contract/money/src/client/token_mint_v1.rs index c145479ef..bc12e4dad 100644 --- a/src/contract/money/src/client/token_mint_v1.rs +++ b/src/contract/money/src/client/token_mint_v1.rs @@ -23,8 +23,8 @@ use darkfi::{ }; use darkfi_sdk::{ crypto::{ - note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_base, - pedersen_commitment_u64, poseidon_hash, Keypair, PublicKey, TokenId, + note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, Keypair, + PublicKey, TokenId, }, pasta::pallas, }; @@ -49,14 +49,13 @@ pub struct TokenMintRevealed { pub token_id: TokenId, pub coin: Coin, pub value_commit: pallas::Point, - pub token_commit: pallas::Point, + pub token_commit: pallas::Base, } impl TokenMintRevealed { pub fn to_vec(&self) -> Vec { let (sig_x, sig_y) = self.signature_public.xy(); let valcom_coords = self.value_commit.to_affine().coordinates().unwrap(); - let tokcom_coords = self.token_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. @@ -67,8 +66,7 @@ impl TokenMintRevealed { self.coin.inner(), *valcom_coords.x(), *valcom_coords.y(), - *tokcom_coords.x(), - *tokcom_coords.y(), + self.token_commit, ] } } @@ -117,7 +115,7 @@ impl TokenMintCallBuilder { // commitments. Not sure if this can be avoided, but also is it // really necessary to avoid? let value_blind = pallas::Scalar::random(&mut OsRng); - let token_blind = pallas::Scalar::random(&mut OsRng); + let token_blind = pallas::Base::random(&mut OsRng); let c_input = ClearInput { value: input.value, @@ -175,7 +173,7 @@ pub fn create_token_mint_proof( output: &TransactionBuilderOutputInfo, mint_authority: &Keypair, value_blind: pallas::Scalar, - token_blind: pallas::Scalar, + token_blind: pallas::Base, serial: pallas::Base, spend_hook: pallas::Base, user_data: pallas::Base, @@ -183,7 +181,7 @@ pub fn create_token_mint_proof( let token_id = TokenId::derive(mint_authority.secret); let value_commit = pedersen_commitment_u64(output.value, value_blind); - let token_commit = pedersen_commitment_base(token_id.inner(), token_blind); + let token_commit = poseidon_hash([token_id.inner(), token_blind]); let (rcpt_x, rcpt_y) = output.public_key.xy(); @@ -214,7 +212,7 @@ pub fn create_token_mint_proof( Witness::Base(Value::known(spend_hook)), Witness::Base(Value::known(user_data)), Witness::Scalar(Value::known(value_blind)), - Witness::Scalar(Value::known(token_blind)), + Witness::Base(Value::known(token_blind)), ]; let circuit = ZkCircuit::new(prover_witnesses, zkbin); diff --git a/src/contract/money/src/client/transfer_v1.rs b/src/contract/money/src/client/transfer_v1.rs index c13c7caea..bc624510c 100644 --- a/src/contract/money/src/client/transfer_v1.rs +++ b/src/contract/money/src/client/transfer_v1.rs @@ -27,9 +27,8 @@ use darkfi_sdk::{ bridgetree, bridgetree::Hashable, crypto::{ - note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_base, - pedersen_commitment_u64, poseidon_hash, Keypair, MerkleNode, MerkleTree, Nullifier, - PublicKey, SecretKey, TokenId, + note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, Keypair, + MerkleNode, MerkleTree, Nullifier, PublicKey, SecretKey, TokenId, }, pasta::pallas, }; @@ -62,29 +61,22 @@ pub struct TransferCallDebris { pub struct TransferMintRevealed { pub coin: Coin, pub value_commit: pallas::Point, - pub token_commit: pallas::Point, + pub token_commit: pallas::Base, } impl TransferMintRevealed { pub fn to_vec(&self) -> Vec { let valcom_coords = self.value_commit.to_affine().coordinates().unwrap(); - let tokcom_coords = self.token_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.coin.inner(), - *valcom_coords.x(), - *valcom_coords.y(), - *tokcom_coords.x(), - *tokcom_coords.y(), - ] + vec![self.coin.inner(), *valcom_coords.x(), *valcom_coords.y(), self.token_commit] } } pub struct TransferBurnRevealed { pub value_commit: pallas::Point, - pub token_commit: pallas::Point, + pub token_commit: pallas::Base, pub nullifier: Nullifier, pub merkle_root: MerkleNode, pub spend_hook: pallas::Base, @@ -95,7 +87,6 @@ pub struct TransferBurnRevealed { impl TransferBurnRevealed { pub fn to_vec(&self) -> Vec { let valcom_coords = self.value_commit.to_affine().coordinates().unwrap(); - let tokcom_coords = self.token_commit.to_affine().coordinates().unwrap(); let sigpub_coords = self.signature_public.inner().to_affine().coordinates().unwrap(); // NOTE: It's important to keep these in the same order @@ -104,8 +95,7 @@ impl TransferBurnRevealed { self.nullifier.inner(), *valcom_coords.x(), *valcom_coords.y(), - *tokcom_coords.x(), - *tokcom_coords.y(), + self.token_commit, self.merkle_root.inner(), self.user_data_enc, self.spend_hook, @@ -259,7 +249,7 @@ impl TransferCallBuilder { let mut params = MoneyTransferParamsV1 { clear_inputs: vec![], inputs: vec![], outputs: vec![] }; - let token_blind = pallas::Scalar::random(&mut OsRng); + let token_blind = pallas::Base::random(&mut OsRng); for input in clear_inputs { let signature_public = PublicKey::from_secret(input.signature_secret); let value_blind = pallas::Scalar::random(&mut OsRng); @@ -393,7 +383,7 @@ pub fn create_transfer_burn_proof( pk: &ProvingKey, input: &TransactionBuilderInputInfo, value_blind: pallas::Scalar, - token_blind: pallas::Scalar, + token_blind: pallas::Base, user_data_blind: pallas::Base, signature_secret: SecretKey, ) -> Result<(Proof, TransferBurnRevealed)> { @@ -429,7 +419,7 @@ pub fn create_transfer_burn_proof( let user_data_enc = poseidon_hash([input.note.user_data, user_data_blind]); let value_commit = pedersen_commitment_u64(input.note.value, value_blind); - let token_commit = pedersen_commitment_base(input.note.token_id.inner(), token_blind); + let token_commit = poseidon_hash([input.note.token_id.inner(), token_blind]); let public_inputs = TransferBurnRevealed { value_commit, @@ -445,7 +435,7 @@ pub fn create_transfer_burn_proof( Witness::Base(Value::known(pallas::Base::from(input.note.value))), Witness::Base(Value::known(input.note.token_id.inner())), Witness::Scalar(Value::known(value_blind)), - Witness::Scalar(Value::known(token_blind)), + Witness::Base(Value::known(token_blind)), Witness::Base(Value::known(input.note.serial)), Witness::Base(Value::known(input.note.spend_hook)), Witness::Base(Value::known(input.note.user_data)), @@ -468,13 +458,13 @@ pub fn create_transfer_mint_proof( pk: &ProvingKey, output: &TransactionBuilderOutputInfo, value_blind: pallas::Scalar, - token_blind: pallas::Scalar, + token_blind: pallas::Base, serial: pallas::Base, spend_hook: pallas::Base, user_data: pallas::Base, ) -> Result<(Proof, TransferMintRevealed)> { let value_commit = pedersen_commitment_u64(output.value, value_blind); - let token_commit = pedersen_commitment_base(output.token_id.inner(), token_blind); + let token_commit = poseidon_hash([output.token_id.inner(), token_blind]); let (pub_x, pub_y) = output.public_key.xy(); let coin = Coin::from(poseidon_hash([ @@ -498,7 +488,7 @@ pub fn create_transfer_mint_proof( Witness::Base(Value::known(spend_hook)), Witness::Base(Value::known(user_data)), Witness::Scalar(Value::known(value_blind)), - Witness::Scalar(Value::known(token_blind)), + Witness::Base(Value::known(token_blind)), ]; let circuit = ZkCircuit::new(prover_witnesses, zkbin); diff --git a/src/contract/money/src/client/unstake_v1.rs b/src/contract/money/src/client/unstake_v1.rs index c63b7a76f..baee00d98 100644 --- a/src/contract/money/src/client/unstake_v1.rs +++ b/src/contract/money/src/client/unstake_v1.rs @@ -25,9 +25,8 @@ use darkfi::{ }; use darkfi_sdk::{ crypto::{ - note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_base, - pedersen_commitment_u64, poseidon_hash, MerkleNode, Nullifier, PublicKey, TokenId, - DARK_TOKEN_ID, + note::AeadEncryptedNote, pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, + MerkleNode, Nullifier, PublicKey, TokenId, DARK_TOKEN_ID, }, pasta::pallas, }; @@ -47,23 +46,16 @@ pub struct MoneyUnstakeCallDebris { pub struct MoneyMintRevealed { pub coin: Coin, pub value_commit: pallas::Point, - pub token_commit: pallas::Point, + pub token_commit: pallas::Base, } impl MoneyMintRevealed { pub fn to_vec(&self) -> Vec { let valcom_coords = self.value_commit.to_affine().coordinates().unwrap(); - let tokcom_coords = self.token_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.coin.inner(), - *valcom_coords.x(), - *valcom_coords.y(), - *tokcom_coords.x(), - *tokcom_coords.y(), - ] + vec![self.coin.inner(), *valcom_coords.x(), *valcom_coords.y(), self.token_commit] } } @@ -108,7 +100,7 @@ impl MoneyUnstakeCallBuilder { let serial = pallas::Base::random(&mut OsRng); let spend_hook = pallas::Base::ZERO; let user_data_enc = pallas::Base::random(&mut OsRng); - let token_blind = pallas::Scalar::ZERO; + let token_blind = pallas::Base::ZERO; info!("Building Money::UnstakeV1 Mint ZK proof"); let (proof, public_inputs) = create_unstake_mint_proof( @@ -167,13 +159,13 @@ pub fn create_unstake_mint_proof( pk: &ProvingKey, output: &TransactionBuilderOutputInfo, value_blind: pallas::Scalar, - token_blind: pallas::Scalar, + token_blind: pallas::Base, serial: pallas::Base, spend_hook: pallas::Base, user_data: pallas::Base, ) -> Result<(Proof, MoneyMintRevealed)> { let value_commit = pedersen_commitment_u64(output.value, value_blind); - let token_commit = pedersen_commitment_base(output.token_id.inner(), token_blind); + let token_commit = poseidon_hash([output.token_id.inner(), token_blind]); let (pub_x, pub_y) = output.public_key.xy(); let coin = Coin::from(poseidon_hash([ @@ -197,7 +189,7 @@ pub fn create_unstake_mint_proof( Witness::Base(Value::known(spend_hook)), Witness::Base(Value::known(user_data)), Witness::Scalar(Value::known(value_blind)), - Witness::Scalar(Value::known(token_blind)), + Witness::Base(Value::known(token_blind)), ]; let circuit = ZkCircuit::new(prover_witnesses, zkbin); diff --git a/src/contract/money/src/entrypoint/genesis_mint_v1.rs b/src/contract/money/src/entrypoint/genesis_mint_v1.rs index 5d54a0408..365ba0447 100644 --- a/src/contract/money/src/entrypoint/genesis_mint_v1.rs +++ b/src/contract/money/src/entrypoint/genesis_mint_v1.rs @@ -17,10 +17,7 @@ */ use darkfi_sdk::{ - crypto::{ - pasta_prelude::*, pedersen_commitment_base, pedersen_commitment_u64, ContractId, - DARK_TOKEN_ID, - }, + crypto::{pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, DARK_TOKEN_ID}, db::{db_contains_key, db_lookup}, error::ContractError, msg, @@ -52,7 +49,6 @@ pub(crate) fn money_genesis_mint_get_metadata_v1( // Grab the pedersen commitment from the anonymous output let value_coords = params.output.value_commit.to_affine().coordinates().unwrap(); - let token_coords = params.output.token_commit.to_affine().coordinates().unwrap(); zk_public_inputs.push(( MONEY_CONTRACT_ZKAS_MINT_NS_V1.to_string(), @@ -60,8 +56,7 @@ pub(crate) fn money_genesis_mint_get_metadata_v1( params.output.coin.inner(), *value_coords.x(), *value_coords.y(), - *token_coords.x(), - *token_coords.y(), + params.output.token_commit, ], )); @@ -115,7 +110,7 @@ pub(crate) fn money_genesis_mint_process_instruction_v1( return Err(MoneyError::ValueMismatch.into()) } - if pedersen_commitment_base(params.input.token_id.inner(), params.input.token_blind) != + if poseidon_hash([params.input.token_id.inner(), params.input.token_blind]) != params.output.token_commit { msg!("[GenesisMintV1] Error: Token commitment mismatch"); diff --git a/src/contract/money/src/entrypoint/stake_v1.rs b/src/contract/money/src/entrypoint/stake_v1.rs index eb3d9c6ff..c32a70f0e 100644 --- a/src/contract/money/src/entrypoint/stake_v1.rs +++ b/src/contract/money/src/entrypoint/stake_v1.rs @@ -17,10 +17,7 @@ */ use darkfi_sdk::{ - crypto::{ - pasta_prelude::*, pedersen_commitment_base, ContractId, CONSENSUS_CONTRACT_ID, - DARK_TOKEN_ID, - }, + crypto::{pasta_prelude::*, poseidon_hash, ContractId, CONSENSUS_CONTRACT_ID, DARK_TOKEN_ID}, db::{db_contains_key, db_lookup, db_set}, error::{ContractError, ContractResult}, msg, @@ -54,7 +51,6 @@ pub(crate) fn money_stake_get_metadata_v1( // Grab the pedersen commitments and signature pubkeys from the // anonymous input let value_coords = input.value_commit.to_affine().coordinates().unwrap(); - let token_coords = input.token_commit.to_affine().coordinates().unwrap(); let (sig_x, sig_y) = input.signature_public.xy(); // It is very important that these are in the same order as the @@ -66,8 +62,7 @@ pub(crate) fn money_stake_get_metadata_v1( input.nullifier.inner(), *value_coords.x(), *value_coords.y(), - *token_coords.x(), - *token_coords.y(), + input.token_commit, input.merkle_root.inner(), input.user_data_enc, pallas::Base::ZERO, // We enforce spend_hook==0 @@ -112,7 +107,7 @@ pub(crate) fn money_stake_process_instruction_v1( } // Only native token can be staked - if input.token_commit != pedersen_commitment_base(DARK_TOKEN_ID.inner(), params.token_blind) { + if input.token_commit != poseidon_hash([DARK_TOKEN_ID.inner(), params.token_blind]) { msg!("[MoneyStakeV1] Error: Input used non-native token"); return Err(MoneyError::StakeInputNonNativeToken.into()) } diff --git a/src/contract/money/src/entrypoint/token_freeze_v1.rs b/src/contract/money/src/entrypoint/token_freeze_v1.rs index eb471df58..e08e2fd0a 100644 --- a/src/contract/money/src/entrypoint/token_freeze_v1.rs +++ b/src/contract/money/src/entrypoint/token_freeze_v1.rs @@ -75,7 +75,6 @@ pub(crate) fn money_token_freeze_process_instruction_v1( // We just check if the mint was already frozen beforehand let token_freeze_db = db_lookup(cid, MONEY_CONTRACT_TOKEN_FREEZE_TREE)?; - let token_id = TokenId::derive_public(params.signature_public); // Check that the mint is not frozen diff --git a/src/contract/money/src/entrypoint/token_mint_v1.rs b/src/contract/money/src/entrypoint/token_mint_v1.rs index c027ce59a..3c726fbf3 100644 --- a/src/contract/money/src/entrypoint/token_mint_v1.rs +++ b/src/contract/money/src/entrypoint/token_mint_v1.rs @@ -18,8 +18,7 @@ use darkfi_sdk::{ crypto::{ - pasta_prelude::*, pedersen_commitment_base, pedersen_commitment_u64, ContractId, - MerkleNode, TokenId, + pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, MerkleNode, TokenId, }, db::{db_contains_key, db_lookup, db_set}, error::{ContractError, ContractResult}, @@ -59,7 +58,6 @@ pub(crate) fn money_token_mint_get_metadata_v1( let token_id = TokenId::derive_public(params.input.signature_public); let value_coords = params.output.value_commit.to_affine().coordinates().unwrap(); - let token_coords = params.output.token_commit.to_affine().coordinates().unwrap(); zk_public_inputs.push(( MONEY_CONTRACT_ZKAS_TOKEN_MINT_NS_V1.to_string(), @@ -70,8 +68,7 @@ pub(crate) fn money_token_mint_get_metadata_v1( params.output.coin.inner(), *value_coords.x(), *value_coords.y(), - *token_coords.x(), - *token_coords.y(), + params.output.token_commit, ], )); @@ -126,7 +123,7 @@ pub(crate) fn money_token_mint_process_instruction_v1( return Err(MoneyError::ValueMismatch.into()) } - if pedersen_commitment_base(params.input.token_id.inner(), params.input.token_blind) != + if poseidon_hash([params.input.token_id.inner(), params.input.token_blind]) != params.output.token_commit { msg!("[MintV1] Error: Token commitment mismatch"); diff --git a/src/contract/money/src/entrypoint/transfer_v1.rs b/src/contract/money/src/entrypoint/transfer_v1.rs index 728ab48a4..0deec4229 100644 --- a/src/contract/money/src/entrypoint/transfer_v1.rs +++ b/src/contract/money/src/entrypoint/transfer_v1.rs @@ -18,8 +18,8 @@ use darkfi_sdk::{ crypto::{ - pasta_prelude::*, pedersen_commitment_base, pedersen_commitment_u64, ContractId, - MerkleNode, PublicKey, DARK_TOKEN_ID, + pasta_prelude::*, pedersen_commitment_u64, poseidon_hash, ContractId, MerkleNode, + PublicKey, DARK_TOKEN_ID, }, db::{db_contains_key, db_get, db_lookup, db_set}, error::{ContractError, ContractResult}, @@ -61,7 +61,6 @@ pub(crate) fn money_transfer_get_metadata_v1( // anonymous inputs for input in ¶ms.inputs { let value_coords = input.value_commit.to_affine().coordinates().unwrap(); - let token_coords = input.token_commit.to_affine().coordinates().unwrap(); let (sig_x, sig_y) = input.signature_public.xy(); // It is very important that these are in the same order as the @@ -73,8 +72,7 @@ pub(crate) fn money_transfer_get_metadata_v1( input.nullifier.inner(), *value_coords.x(), *value_coords.y(), - *token_coords.x(), - *token_coords.y(), + input.token_commit, input.merkle_root.inner(), input.user_data_enc, input.spend_hook, @@ -89,17 +87,10 @@ pub(crate) fn money_transfer_get_metadata_v1( // Grab the pedersen commitments from the anonymous outputs for output in ¶ms.outputs { let value_coords = output.value_commit.to_affine().coordinates().unwrap(); - let token_coords = output.token_commit.to_affine().coordinates().unwrap(); zk_public_inputs.push(( MONEY_CONTRACT_ZKAS_MINT_NS_V1.to_string(), - vec![ - output.coin.inner(), - *value_coords.x(), - *value_coords.y(), - *token_coords.x(), - *token_coords.y(), - ], + vec![output.coin.inner(), *value_coords.x(), *value_coords.y(), output.token_commit], )); } @@ -247,7 +238,7 @@ pub(crate) fn money_transfer_process_instruction_v1( params .clear_inputs .iter() - .any(|x| pedersen_commitment_base(x.token_id.inner(), x.token_blind) != tokcom); + .any(|x| poseidon_hash([x.token_id.inner(), x.token_blind]) != tokcom); if failed_tokcom { msg!("[TransferV1] Error: Token commitments do not match"); diff --git a/src/contract/money/src/entrypoint/unstake_v1.rs b/src/contract/money/src/entrypoint/unstake_v1.rs index 6bdcf8567..5a216e260 100644 --- a/src/contract/money/src/entrypoint/unstake_v1.rs +++ b/src/contract/money/src/entrypoint/unstake_v1.rs @@ -18,8 +18,8 @@ use darkfi_sdk::{ crypto::{ - pasta_prelude::*, pedersen_commitment_base, ContractId, MerkleNode, PublicKey, - CONSENSUS_CONTRACT_ID, DARK_TOKEN_ID, + pasta_prelude::*, poseidon_hash, ContractId, MerkleNode, PublicKey, CONSENSUS_CONTRACT_ID, + DARK_TOKEN_ID, }, db::{db_contains_key, db_lookup, db_set}, error::{ContractError, ContractResult}, @@ -54,7 +54,6 @@ pub(crate) fn money_unstake_get_metadata_v1( // Grab the pedersen commitment from the anonymous output let value_coords = params.output.value_commit.to_affine().coordinates().unwrap(); - let token_coords = params.output.token_commit.to_affine().coordinates().unwrap(); zk_public_inputs.push(( MONEY_CONTRACT_ZKAS_MINT_NS_V1.to_string(), @@ -62,8 +61,7 @@ pub(crate) fn money_unstake_get_metadata_v1( params.output.coin.inner(), *value_coords.x(), *value_coords.y(), - *token_coords.x(), - *token_coords.y(), + params.output.token_commit, ], )); @@ -128,8 +126,7 @@ pub(crate) fn money_unstake_process_instruction_v1( // Only native token can be minted here. // Since consensus coins don't have token commitments, we use zero as // the token blind for the token commitment of the newly minted token - if output.token_commit != pedersen_commitment_base(DARK_TOKEN_ID.inner(), pallas::Scalar::ZERO) - { + if output.token_commit != poseidon_hash([DARK_TOKEN_ID.inner(), pallas::Base::ZERO]) { msg!("[MoneyUnstakeV1] Error: Input used non-native token"); return Err(MoneyError::StakeInputNonNativeToken.into()) } diff --git a/src/contract/money/src/model.rs b/src/contract/money/src/model.rs index ef91eaf69..4c7246d78 100644 --- a/src/contract/money/src/model.rs +++ b/src/contract/money/src/model.rs @@ -68,7 +68,7 @@ pub struct ClearInput { /// Blinding factor for `value` pub value_blind: pallas::Scalar, /// Blinding factor for `token_id` - pub token_blind: pallas::Scalar, + pub token_blind: pallas::Base, /// Public key for the signature pub signature_public: PublicKey, } @@ -78,8 +78,8 @@ pub struct ClearInput { pub struct Input { /// Pedersen commitment for the input's value pub value_commit: pallas::Point, - /// Pedersen commitment for the input's token ID - pub token_commit: pallas::Point, + /// Commitment for the input's token ID + pub token_commit: pallas::Base, /// Revealed nullifier pub nullifier: Nullifier, /// Revealed Merkle root @@ -116,8 +116,8 @@ pub struct ConsensusInput { pub struct Output { /// Pedersen commitment for the output's value pub value_commit: pallas::Point, - /// Pedersen commitment for the output's token ID - pub token_commit: pallas::Point, + /// Commitment for the output's token ID + pub token_commit: pallas::Base, /// Minted coin pub coin: Coin, /// AEAD encrypted note @@ -192,7 +192,7 @@ pub struct MoneyTokenFreezeUpdateV1 { // ANCHOR: MoneyStakeParams pub struct MoneyStakeParamsV1 { /// Blinding factor for `token_id` - pub token_blind: pallas::Scalar, + pub token_blind: pallas::Base, /// Anonymous input pub input: Input, } diff --git a/src/contract/test-harness/src/consensus_genesis_stake.rs b/src/contract/test-harness/src/consensus_genesis_stake.rs index 4f7aa7c9d..d0fcc48fb 100644 --- a/src/contract/test-harness/src/consensus_genesis_stake.rs +++ b/src/contract/test-harness/src/consensus_genesis_stake.rs @@ -60,7 +60,7 @@ impl TestHarness { } .build_with_params( pallas::Scalar::random(&mut OsRng), - pallas::Scalar::random(&mut OsRng), + pallas::Base::random(&mut OsRng), pallas::Scalar::random(&mut OsRng), pallas::Base::from(28), )?; diff --git a/src/contract/test-harness/src/money_otc_swap.rs b/src/contract/test-harness/src/money_otc_swap.rs index 3cf39aeae..e0e05c07f 100644 --- a/src/contract/test-harness/src/money_otc_swap.rs +++ b/src/contract/test-harness/src/money_otc_swap.rs @@ -25,7 +25,7 @@ use darkfi_money_contract::{ MoneyFunction, MONEY_CONTRACT_ZKAS_BURN_NS_V1, MONEY_CONTRACT_ZKAS_MINT_NS_V1, }; use darkfi_sdk::{ - crypto::{MerkleNode, ValueBlind, MONEY_CONTRACT_ID}, + crypto::{MerkleNode, MONEY_CONTRACT_ID}, pasta::pallas, ContractCall, }; @@ -62,10 +62,10 @@ impl TestHarness { let rcpt_user_data_blind = pallas::Base::random(&mut OsRng); // Generating swap blinds - let value_send_blind = ValueBlind::random(&mut OsRng); - let value_recv_blind = ValueBlind::random(&mut OsRng); - let token_send_blind = ValueBlind::random(&mut OsRng); - let token_recv_blind = ValueBlind::random(&mut OsRng); + let value_send_blind = pallas::Scalar::random(&mut OsRng); + let value_recv_blind = pallas::Scalar::random(&mut OsRng); + let token_send_blind = pallas::Base::random(&mut OsRng); + let token_recv_blind = pallas::Base::random(&mut OsRng); // Builder first holder part let builder = SwapCallBuilder { diff --git a/src/sdk/python/src/point.rs b/src/sdk/python/src/point.rs index e930db6ad..bbcd72f53 100644 --- a/src/sdk/python/src/point.rs +++ b/src/sdk/python/src/point.rs @@ -23,7 +23,6 @@ use darkfi_sdk::{ VALUE_COMMITMENT_V_BYTES, }, util::mod_r_p, - ValueCommit, }, pasta::{ arithmetic::CurveExt, @@ -55,7 +54,7 @@ impl Point { #[staticmethod] fn mul_short(value: &Base) -> Self { - let hasher = ValueCommit::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); + let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); let v = hasher(&VALUE_COMMITMENT_V_BYTES); Self(v * mod_r_p(value.0)) } @@ -70,7 +69,7 @@ impl Point { // Why not a pycell? #[staticmethod] fn mul_r_generator(blind: &Scalar) -> Self { - let hasher = ValueCommit::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); + let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); let r = hasher(&VALUE_COMMITMENT_R_BYTES); let r = Self(r); Self(r.0 * blind.0) diff --git a/src/sdk/src/crypto/mod.rs b/src/sdk/src/crypto/mod.rs index 01bdd136d..19851d3bc 100644 --- a/src/sdk/src/crypto/mod.rs +++ b/src/sdk/src/crypto/mod.rs @@ -51,7 +51,7 @@ pub use nullifier::Nullifier; /// Pedersen commitment utilities pub mod pedersen; -pub use pedersen::{pedersen_commitment_base, pedersen_commitment_u64, ValueBlind, ValueCommit}; +pub use pedersen::{pedersen_commitment_base, pedersen_commitment_u64}; /// Schnorr signature traits pub mod schnorr; diff --git a/src/sdk/src/crypto/pedersen.rs b/src/sdk/src/crypto/pedersen.rs index 764474781..5d7ab5492 100644 --- a/src/sdk/src/crypto/pedersen.rs +++ b/src/sdk/src/crypto/pedersen.rs @@ -29,13 +29,10 @@ use super::{ util::mod_r_p, }; -pub type ValueBlind = pallas::Scalar; -pub type ValueCommit = pallas::Point; - /// Pedersen commitment for a full-width base field element. #[allow(non_snake_case)] -pub fn pedersen_commitment_base(value: pallas::Base, blind: ValueBlind) -> ValueCommit { - let hasher = ValueCommit::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); +pub fn pedersen_commitment_base(value: pallas::Base, blind: pallas::Scalar) -> pallas::Point { + let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); let V = NullifierK.generator(); let R = hasher(&VALUE_COMMITMENT_R_BYTES); @@ -44,8 +41,8 @@ pub fn pedersen_commitment_base(value: pallas::Base, blind: ValueBlind) -> Value /// Pedersen commitment for a 64-bit value, in the base field. #[allow(non_snake_case)] -pub fn pedersen_commitment_u64(value: u64, blind: ValueBlind) -> ValueCommit { - let hasher = ValueCommit::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); +pub fn pedersen_commitment_u64(value: u64, blind: pallas::Scalar) -> pallas::Point { + let hasher = pallas::Point::hash_to_curve(VALUE_COMMITMENT_PERSONALIZATION); let V = hasher(&VALUE_COMMITMENT_V_BYTES); let R = hasher(&VALUE_COMMITMENT_R_BYTES);