diff --git a/CHANGELOG.md b/CHANGELOG.md index 544e8bb..692390d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -59,6 +59,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Update `dusk-jubjub` `0.12` -> `0.13` - Update `poseidon-merkle` `0.2.1-rc.0` -> `0.3` - Update `rusk-abi` `0.10.0-piecrust.0.6` -> `0.11` +- Update dependencies +- Update `phoenix-core`: 0.21 -> 0.26 +- Update `dusk-jubjub`: 0.13 -> 0.14 +- Replace `dusk-schnorr` with `jubjub-schnorr` 0.2 +- Replace `dusk-bls12_381-sign` with `bls12_381-bls` 0.2 +- Update `dusk-poseidon` 0.31 -> 0.33 +- Update `dusk-plonk` 0.16 -> 0.19 +- Update `poseidon-merkle` 0.3 -> 0.5 +- Rename `Wallet::public_key` to `Wallet::stake_public_key` +- Rename `Wallet::public_spend_key` to `Wallet::public_key` +- Rename `derive_sk` to `derive_stake_sk` +- Rename `derive_ssk` to `derive_sk` +- Rename `retrieve_sk` to `retrieve_stake_sk` +- Rename `retrieve_ssk` to `retrieve_sk` +- Rename `ffi::public_spend_key` to `ffi::public_key ### Fixed @@ -70,6 +85,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Remove `get_block_height` from the `StateClient` trait [#58] - Delete `extend_stake` since the stake contract removed it [#46] +- Remove `dusk-pki` dependency ## [0.5.1] - 2021-01-26 diff --git a/Cargo.toml b/Cargo.toml index 8683593..a4a5e09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,20 +9,20 @@ license = "MPL-2.0" rand_core = "^0.6" rand_chacha = { version = "^0.3", default-features = false } sha2 = { version = "^0.10", default-features = false } -phoenix-core = { version = "0.21", default-features = false, features = ["alloc", "rkyv-impl"] } -dusk-pki = { version = "0.13", default-features = false } +phoenix-core = { version = "0.26", default-features = false, features = ["alloc", "rkyv-impl"] } dusk-bytes = "^0.1" -dusk-schnorr = { version = "0.14", default-features = false } -dusk-jubjub = { version = "0.13", default-features = false } -dusk-poseidon = { version = "0.31", default-features = false } -poseidon-merkle = { version = "0.3", features = ["rkyv-impl"] } -dusk-plonk = { version = "0.16", default-features = false } -rusk-abi = { version = "0.12.0-rc", default-features = false } -dusk-bls12_381-sign = { version = "0.5", default-features = false } +jubjub-schnorr = { version = "0.2", default-features = false, features = ["double"] } +dusk-jubjub = { version = "0.14", default-features = false } +dusk-poseidon = { version = "0.33", default-features = false } +poseidon-merkle = { version = "0.5", features = ["rkyv-impl"] } +dusk-plonk = { version = "0.19", default-features = false } +bls12_381-bls = { version = "0.2", default-features = false } rkyv = { version = "0.7", default-features = false } ff = { version = "0.13", default-features = false } -stake-contract-types = "0.0.1-rc.2" +# rusk dependencies +rusk-abi = { version = "0.13.0-rc", default-features = false } +stake-contract-types = "0.1.0-rc" [dev-dependencies] rand = "^0.8" diff --git a/rust-toolchain b/rust-toolchain index 67946b1..47c90f7 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2023-01-05 +nightly-2023-11-10 diff --git a/src/ffi.rs b/src/ffi.rs index e9be31c..07150ee 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -13,14 +13,12 @@ use core::mem; use core::num::NonZeroU32; use core::ptr; -use dusk_bls12_381_sign::PublicKey; -use dusk_bytes::Write; -use dusk_bytes::{DeserializableSlice, Serializable}; +use bls12_381_bls::PublicKey as StakePublicKey; +use dusk_bytes::{DeserializableSlice, Serializable, Write}; use dusk_jubjub::{BlsScalar, JubJubAffine, JubJubScalar}; -use dusk_pki::{PublicSpendKey, ViewKey}; use dusk_plonk::prelude::Proof; use dusk_schnorr::Signature; -use phoenix_core::{Crossover, Fee, Note}; +use phoenix_core::{Crossover, Fee, Note, PublicKey, ViewKey}; use poseidon_merkle::Opening as PoseidonOpening; use rand_core::{ impls::{next_u32_via_fill, next_u64_via_fill}, @@ -85,7 +83,7 @@ extern "C" { /// sequence, little endian, to the given buffer. If there is no value and /// eligibility, the first 16 bytes should be zero. fn fetch_stake( - pk: *const [u8; PublicKey::SIZE], + stake_pk: *const [u8; StakePublicKey::SIZE], stake: *mut [u8; StakeInfo::SIZE], ) -> u8; @@ -142,12 +140,12 @@ pub unsafe extern "C" fn free(ptr: *mut u8, cap: u32) { /// Get the public spend key with the given index. #[no_mangle] -pub unsafe extern "C" fn public_spend_key( +pub unsafe extern "C" fn public_key( index: *const u64, - psk: *mut [u8; PublicSpendKey::SIZE], + pk: *mut [u8; PublicKey::SIZE], ) -> u8 { - let key = unwrap_or_bail!(WALLET.public_spend_key(*index)).to_bytes(); - ptr::copy_nonoverlapping(&key[0], &mut (*psk)[0], key.len()); + let key = unwrap_or_bail!(WALLET.public_key(*index)).to_bytes(); + ptr::copy_nonoverlapping(&key[0], &mut (*pk)[0], key.len()); 0 } @@ -160,7 +158,7 @@ pub unsafe extern "C" fn execute( call_data_ptr: *mut u8, call_data_len: *const u32, sender_index: *const u64, - refund: *const [u8; PublicSpendKey::SIZE], + refund: *const [u8; PublicKey::SIZE], gas_limit: *const u64, gas_price: *const u64, ) -> u8 { @@ -182,7 +180,7 @@ pub unsafe extern "C" fn execute( call_data_len as usize, ); - let refund = unwrap_or_bail!(PublicSpendKey::from_bytes(&*refund)); + let refund = unwrap_or_bail!(PublicKey::from_bytes(&*refund)); unwrap_or_bail!(WALLET.execute( &mut FfiRng, @@ -202,15 +200,15 @@ pub unsafe extern "C" fn execute( #[no_mangle] pub unsafe extern "C" fn transfer( sender_index: *const u64, - refund: *const [u8; PublicSpendKey::SIZE], - receiver: *const [u8; PublicSpendKey::SIZE], + refund: *const [u8; PublicKey::SIZE], + receiver: *const [u8; PublicKey::SIZE], value: *const u64, gas_limit: *const u64, gas_price: *const u64, ref_id: Option<&u64>, ) -> u8 { - let refund = unwrap_or_bail!(PublicSpendKey::from_bytes(&*refund)); - let receiver = unwrap_or_bail!(PublicSpendKey::from_bytes(&*receiver)); + let refund = unwrap_or_bail!(PublicKey::from_bytes(&*refund)); + let receiver = unwrap_or_bail!(PublicKey::from_bytes(&*receiver)); let ref_id = BlsScalar::from(ref_id.copied().unwrap_or_else(|| FfiRng.next_u64())); @@ -234,12 +232,12 @@ pub unsafe extern "C" fn transfer( pub unsafe extern "C" fn stake( sender_index: *const u64, staker_index: *const u64, - refund: *const [u8; PublicSpendKey::SIZE], + refund: *const [u8; PublicKey::SIZE], value: *const u64, gas_limit: *const u64, gas_price: *const u64, ) -> u8 { - let refund = unwrap_or_bail!(PublicSpendKey::from_bytes(&*refund)); + let refund = unwrap_or_bail!(PublicKey::from_bytes(&*refund)); unwrap_or_bail!(WALLET.stake( &mut FfiRng, @@ -259,11 +257,11 @@ pub unsafe extern "C" fn stake( pub unsafe extern "C" fn unstake( sender_index: *const u64, staker_index: *const u64, - refund: *const [u8; PublicSpendKey::SIZE], + refund: *const [u8; PublicKey::SIZE], gas_limit: *const u64, gas_price: *const u64, ) -> u8 { - let refund = unwrap_or_bail!(PublicSpendKey::from_bytes(&*refund)); + let refund = unwrap_or_bail!(PublicKey::from_bytes(&*refund)); unwrap_or_bail!(WALLET.unstake( &mut FfiRng, @@ -283,11 +281,11 @@ pub unsafe extern "C" fn unstake( pub unsafe extern "C" fn withdraw( sender_index: *const u64, staker_index: *const u64, - refund: *const [u8; PublicSpendKey::SIZE], + refund: *const [u8; PublicKey::SIZE], gas_limit: *const u64, gas_price: *const u64, ) -> u8 { - let refund = unwrap_or_bail!(PublicSpendKey::from_bytes(&*refund)); + let refund = unwrap_or_bail!(PublicKey::from_bytes(&*refund)); unwrap_or_bail!(WALLET.withdraw( &mut FfiRng, @@ -304,10 +302,10 @@ pub unsafe extern "C" fn withdraw( /// Gets the balance of a secret spend key. #[no_mangle] pub unsafe extern "C" fn get_balance( - ssk_index: *const u64, + sk_index: *const u64, balance: *mut [u8; BalanceInfo::SIZE], ) -> u8 { - let b = unwrap_or_bail!(WALLET.get_balance(*ssk_index)).to_bytes(); + let b = unwrap_or_bail!(WALLET.get_balance(*sk_index)).to_bytes(); ptr::copy_nonoverlapping(&b[0], &mut (*balance)[0], b.len()); 0 } @@ -496,12 +494,15 @@ impl StateClient for FfiStateClient { Ok(branch) } - fn fetch_stake(&self, pk: &PublicKey) -> Result { - let pk = pk.to_bytes(); + fn fetch_stake( + &self, + stake_pk: &StakePublicKey, + ) -> Result { + let stake_pk = stake_pk.to_bytes(); let mut stake_buf = [0u8; StakeInfo::SIZE]; unsafe { - let r = fetch_stake(&pk, &mut stake_buf); + let r = fetch_stake(&stake_pk, &mut stake_buf); if r != 0 { return Err(r); } diff --git a/src/imp.rs b/src/imp.rs index b0ca7d9..6f9db38 100644 --- a/src/imp.rs +++ b/src/imp.rs @@ -14,16 +14,20 @@ use core::convert::Infallible; use alloc::string::{FromUtf8Error, String}; use alloc::vec::Vec; -use dusk_bls12_381_sign::PublicKey; +use bls12_381_bls::PublicKey as StakePublicKey; use dusk_bytes::{Error as BytesError, Serializable}; use dusk_jubjub::{BlsScalar, JubJubScalar}; -use dusk_pki::{ - Ownable, PublicSpendKey, SecretKey as SchnorrKey, SecretSpendKey, -}; -use dusk_schnorr::Signature as SchnorrSignature; use ff::Field; -use phoenix_core::transaction::{stct_signature_message, Transaction}; -use phoenix_core::{Error as PhoenixError, Fee, Note, NoteType}; +use jubjub_schnorr::SecretKey as NoteSecretKey; +use phoenix_core::transaction::{ + allow_signature_message, stake_signature_message, stct_signature_message, + unstake_signature_message, withdraw_signature_message, Allow, Stake, + Transaction, Unstake, Withdraw, +}; +use phoenix_core::{ + Error as PhoenixError, Fee, Note, NoteType, Ownable, PublicKey, SecretKey, + ViewKey, +}; use rand_core::{CryptoRng, Error as RngError, RngCore}; use rkyv::ser::serializers::{ AllocScratchError, AllocSerializer, CompositeSerializerError, @@ -32,11 +36,6 @@ use rkyv::ser::serializers::{ use rkyv::validation::validators::CheckDeserializeError; use rkyv::Serialize; use rusk_abi::ContractId; -use stake_contract_types::{ - allow_signature_message, stake_signature_message, - unstake_signature_message, withdraw_signature_message, -}; -use stake_contract_types::{Allow, Stake, Unstake, Withdraw}; const MAX_INPUT_NOTES: usize = 4; @@ -80,7 +79,7 @@ pub enum Error { /// staked for a key and the user tries to make a stake transaction. AlreadyStaked { /// The key that already has a stake. - key: PublicKey, + key: StakePublicKey, /// Information about the key's stake. stake: StakeInfo, }, @@ -88,7 +87,7 @@ pub enum Error { /// staked and the user tries to make an unstake transaction. NotStaked { /// The key that is not staked. - key: PublicKey, + key: StakePublicKey, /// Information about the key's stake. stake: StakeInfo, }, @@ -96,7 +95,7 @@ pub enum Error { /// stake contract and the user tries to make a withdraw transaction. NoReward { /// The key that has no reward. - key: PublicKey, + key: StakePublicKey, /// Information about the key's stake. stake: StakeInfo, }, @@ -208,24 +207,24 @@ where PC: ProverClient, { /// Retrieve the public spend key with the given index. - pub fn public_spend_key( + pub fn public_key( &self, index: u64, - ) -> Result> { + ) -> Result> { self.store - .retrieve_ssk(index) - .map(|ssk| ssk.public_spend_key()) + .retrieve_sk(index) + .map(|sk| PublicKey::from(sk)) .map_err(Error::from_store_err) } /// Retrieve the public key with the given index. - pub fn public_key( + pub fn stake_public_key( &self, index: u64, - ) -> Result> { + ) -> Result> { self.store - .retrieve_sk(index) - .map(|sk| From::from(&sk)) + .retrieve_stake_sk(index) + .map(|stake_sk| From::from(&stake_sk)) .map_err(Error::from_store_err) } @@ -233,15 +232,15 @@ where /// are still available for spending. fn unspent_notes( &self, - ssk: &SecretSpendKey, + sk: &SecretKey, ) -> Result, Error> { - let vk = ssk.view_key(); + let vk = ViewKey::from(sk); let notes = self.state.fetch_notes(&vk).map_err(Error::from_state_err)?; let nullifiers: Vec<_> = - notes.iter().map(|(n, _)| n.gen_nullifier(ssk)).collect(); + notes.iter().map(|(n, _)| n.gen_nullifier(sk)).collect(); let existing_nullifiers = self .state @@ -268,8 +267,8 @@ where fn inputs_and_change_output( &self, rng: &mut Rng, - sender: &SecretSpendKey, - refund: &PublicSpendKey, + sender: &SecretKey, + refund: &PublicKey, value: u64, ) -> Result< ( @@ -281,7 +280,7 @@ where let notes = self.unspent_notes(sender)?; let mut notes_and_values = Vec::with_capacity(notes.len()); - let sender_vk = sender.view_key(); + let sender_vk = ViewKey::from(sender); let mut accumulated_value = 0; for note in notes.into_iter() { @@ -325,7 +324,7 @@ where call_name: String, call_data: C, sender_index: u64, - refund: &PublicSpendKey, + refund: &PublicKey, gas_limit: u64, gas_price: u64, ) -> Result> @@ -335,7 +334,7 @@ where { let sender = self .store - .retrieve_ssk(sender_index) + .retrieve_sk(sender_index) .map_err(Error::from_store_err)?; let (inputs, outputs) = self.inputs_and_change_output( @@ -373,8 +372,8 @@ where &self, rng: &mut Rng, sender_index: u64, - refund: &PublicSpendKey, - receiver: &PublicSpendKey, + refund: &PublicKey, + receiver: &PublicKey, value: u64, gas_limit: u64, gas_price: u64, @@ -382,7 +381,7 @@ where ) -> Result> { let sender = self .store - .retrieve_ssk(sender_index) + .retrieve_sk(sender_index) .map_err(Error::from_store_err)?; let (inputs, mut outputs) = self.inputs_and_change_output( @@ -424,21 +423,21 @@ where rng: &mut Rng, sender_index: u64, staker_index: u64, - refund: &PublicSpendKey, + refund: &PublicKey, value: u64, gas_limit: u64, gas_price: u64, ) -> Result> { let sender = self .store - .retrieve_ssk(sender_index) + .retrieve_sk(sender_index) .map_err(Error::from_store_err)?; - let sk = self + let stake_sk = self .store - .retrieve_sk(staker_index) + .retrieve_stake_sk(staker_index) .map_err(Error::from_store_err)?; - let pk = PublicKey::from(&sk); + let stake_pk = StakePublicKey::from(&stake_sk); let (inputs, outputs) = self.inputs_and_change_output( rng, @@ -447,13 +446,18 @@ where value + gas_limit * gas_price, )?; - let stake = - self.state.fetch_stake(&pk).map_err(Error::from_state_err)?; + let stake = self + .state + .fetch_stake(&stake_pk) + .map_err(Error::from_state_err)?; if stake.amount.is_some() { - return Err(Error::AlreadyStaked { key: pk, stake }); + return Err(Error::AlreadyStaked { + key: stake_pk, + stake, + }); } - let blinder = JubJubScalar::random(rng); + let blinder = JubJubScalar::random(&mut *rng); let note = Note::obfuscated(rng, refund, value, blinder); let (mut fee, crossover) = note .try_into() @@ -472,9 +476,9 @@ where let stct_message = dusk_poseidon::sponge::hash(&stct_message); let sk_r = *sender.sk_r(fee.stealth_address()).as_ref(); - let secret = SchnorrKey::from(sk_r); + let secret = NoteSecretKey::from(sk_r); - let stct_signature = SchnorrSignature::new(&secret, rng, stct_message); + let stct_signature = secret.sign(rng, stct_message); let spend_proof = self .prover @@ -491,11 +495,11 @@ where .to_vec(); let msg = stake_signature_message(stake.counter, value); - let signature = sk.sign(&pk, &msg); + let stake_sig = stake_sk.sign(&stake_pk, &msg); let stake = Stake { - public_key: pk, - signature, + public_key: stake_pk, + signature: stake_sig, value, proof: spend_proof, }; @@ -527,20 +531,20 @@ where rng: &mut Rng, sender_index: u64, staker_index: u64, - refund: &PublicSpendKey, + refund: &PublicKey, gas_limit: u64, gas_price: u64, ) -> Result> { let sender = self .store - .retrieve_ssk(sender_index) + .retrieve_sk(sender_index) .map_err(Error::from_store_err)?; - let sk = self + let stake_sk = self .store - .retrieve_sk(staker_index) + .retrieve_stake_sk(staker_index) .map_err(Error::from_store_err)?; - let public_key = PublicKey::from(&sk); + let stake_pk = StakePublicKey::from(&stake_sk); let (inputs, outputs) = self.inputs_and_change_output( rng, @@ -551,14 +555,14 @@ where let stake = self .state - .fetch_stake(&public_key) + .fetch_stake(&stake_pk) .map_err(Error::from_state_err)?; let (value, _) = stake.amount.ok_or(Error::NotStaked { - key: public_key, + key: stake_pk, stake, })?; - let blinder = JubJubScalar::random(rng); + let blinder = JubJubScalar::random(&mut *rng); // Since we're not transferring value *to* the contract the crossover // shouldn't contain a value. As such the note used to create it should @@ -572,7 +576,7 @@ where fee.gas_price = gas_price; let unstake_note = - Note::transparent(rng, &sender.public_spend_key(), value); + Note::transparent(rng, &PublicKey::from(&sender), value); let unstake_blinder = unstake_note .blinding_factor(None) .expect("Note is transparent so blinding factor is unencrypted"); @@ -588,16 +592,16 @@ where .to_bytes() .to_vec(); - let unstake_note = unstake_note.to_bytes(); + let unstake_note = unstake_note; let signature_message = unstake_signature_message(stake.counter, unstake_note); - let signature = sk.sign(&public_key, &signature_message); + let stake_sig = stake_sk.sign(&stake_pk, &signature_message); let unstake = Unstake { - public_key, - signature, - note: unstake_note.to_vec(), + public_key: stake_pk, + signature: stake_sig, + note: unstake_note, proof: unstake_proof, }; @@ -632,21 +636,21 @@ where rng: &mut Rng, sender_index: u64, staker_index: u64, - refund: &PublicSpendKey, + refund: &PublicKey, gas_limit: u64, gas_price: u64, ) -> Result> { let sender = self .store - .retrieve_ssk(sender_index) + .retrieve_sk(sender_index) .map_err(Error::from_store_err)?; - let sender_psk = sender.public_spend_key(); + let sender_pk = PublicKey::from(sender); - let sk = self + let stake_sk = self .store - .retrieve_sk(staker_index) + .retrieve_stake_sk(staker_index) .map_err(Error::from_store_err)?; - let pk = PublicKey::from(&sk); + let stake_pk = StakePublicKey::from(&stake_sk); let (inputs, outputs) = self.inputs_and_change_output( rng, @@ -655,23 +659,28 @@ where gas_limit * gas_price, )?; - let stake = - self.state.fetch_stake(&pk).map_err(Error::from_state_err)?; + let stake = self + .state + .fetch_stake(&stake_pk) + .map_err(Error::from_state_err)?; if stake.reward == 0 { - return Err(Error::NoReward { key: pk, stake }); + return Err(Error::NoReward { + key: stake_pk, + stake, + }); } - let withdraw_r = JubJubScalar::random(rng); - let address = sender_psk.gen_stealth_address(&withdraw_r); + let withdraw_r = JubJubScalar::random(&mut *rng); + let address = sender_pk.gen_stealth_address(&withdraw_r); let nonce = BlsScalar::random(&mut *rng); let msg = withdraw_signature_message(stake.counter, address, nonce); - let signature = sk.sign(&pk, &msg); + let stake_sig = stake_sk.sign(&stake_pk, &msg); // Since we're not transferring value *to* the contract the crossover // shouldn't contain a value. As such the note used to created it should // be valueless as well. - let blinder = JubJubScalar::random(rng); + let blinder = JubJubScalar::random(&mut *rng); let note = Note::obfuscated(rng, refund, 0, blinder); let (mut fee, crossover) = note .try_into() @@ -681,8 +690,8 @@ where fee.gas_price = gas_price; let withdraw = Withdraw { - public_key: pk, - signature, + public_key: stake_pk, + signature: stake_sig, address, nonce, }; @@ -715,21 +724,21 @@ where rng: &mut Rng, sender_index: u64, owner_index: u64, - refund: &PublicSpendKey, - staker: &PublicKey, + refund: &PublicKey, + staker: &StakePublicKey, gas_limit: u64, gas_price: u64, ) -> Result> { let sender = self .store - .retrieve_ssk(sender_index) + .retrieve_sk(sender_index) .map_err(Error::from_store_err)?; let owner_sk = self .store - .retrieve_sk(owner_index) + .retrieve_stake_sk(owner_index) .map_err(Error::from_store_err)?; - let owner_pk = PublicKey::from(&owner_sk); + let owner_pk = StakePublicKey::from(&owner_sk); let (inputs, outputs) = self.inputs_and_change_output( rng, @@ -743,13 +752,13 @@ where .fetch_stake(&owner_pk) .map_err(Error::from_state_err)?; - let msg = allow_signature_message(stake.counter, staker); - let signature = owner_sk.sign(&owner_pk, &msg); + let msg = allow_signature_message(stake.counter, *staker); + let stake_sig = owner_sk.sign(&owner_pk, &msg); // Since we're not transferring value *to* the contract the crossover // shouldn't contain a value. As such the note used to created it should // be valueless as well. - let blinder = JubJubScalar::random(rng); + let blinder = JubJubScalar::random(&mut *rng); let note = Note::obfuscated(rng, refund, 0, blinder); let (mut fee, crossover) = note .try_into() @@ -761,7 +770,7 @@ where let allow = Allow { public_key: *staker, owner: owner_pk, - signature, + signature: stake_sig, }; let call_data = rkyv::to_bytes::<_, MAX_CALL_SIZE>(&allow)?.to_vec(); @@ -788,13 +797,13 @@ where /// Gets the balance of a key. pub fn get_balance( &self, - ssk_index: u64, + sk_index: u64, ) -> Result> { let sender = self .store - .retrieve_ssk(ssk_index) + .retrieve_sk(sk_index) .map_err(Error::from_store_err)?; - let vk = sender.view_key(); + let vk = ViewKey::from(sender); let notes = self.unspent_notes(&sender)?; let mut values = Vec::with_capacity(notes.len()); @@ -816,14 +825,17 @@ where &self, sk_index: u64, ) -> Result> { - let sk = self + let stake_sk = self .store - .retrieve_sk(sk_index) + .retrieve_stake_sk(sk_index) .map_err(Error::from_store_err)?; - let pk = PublicKey::from(&sk); + let stake_pk = StakePublicKey::from(&stake_sk); - let s = self.state.fetch_stake(&pk).map_err(Error::from_state_err)?; + let s = self + .state + .fetch_stake(&stake_pk) + .map_err(Error::from_state_err)?; Ok(s) } @@ -909,19 +921,19 @@ fn pick_lexicographic bool>( /// Generates an obfuscated note for the given public spend key. fn generate_obfuscated_note( rng: &mut Rng, - psk: &PublicSpendKey, + pk: &PublicKey, value: u64, nonce: BlsScalar, ) -> (Note, JubJubScalar) { - let r = JubJubScalar::random(rng); - let blinder = JubJubScalar::random(rng); + let r = JubJubScalar::random(&mut *rng); + let blinder = JubJubScalar::random(&mut *rng); ( Note::deterministic( NoteType::Obfuscated, &r, nonce, - psk, + pk, value, blinder, ), @@ -939,13 +951,13 @@ mod tests { fn gen_notes(values: &[u64]) -> Vec<(Note, u64, JubJubScalar)> { let mut rng = StdRng::seed_from_u64(0xbeef); - let ssk = SecretSpendKey::random(&mut rng); - let psk = ssk.public_spend_key(); + let sk = SecretKey::random(&mut rng); + let pk = PublicKey::from(sk); let mut notes_and_values = Vec::with_capacity(values.len()); for value in values { - let note = Note::transparent(&mut rng, &psk, *value); + let note = Note::transparent(&mut rng, &pk, *value); let blinder = JubJubScalar::random(&mut rng); notes_and_values.push((note, *value, blinder)); diff --git a/src/lib.rs b/src/lib.rs index 8269f65..b1685a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,13 +21,12 @@ mod imp; mod tx; use alloc::vec::Vec; -use dusk_bls12_381_sign::{PublicKey, SecretKey}; +use bls12_381_bls::{PublicKey as StakePublicKey, SecretKey as StakeSecretKey}; use dusk_bytes::{DeserializableSlice, Serializable, Write}; use dusk_jubjub::{BlsScalar, JubJubAffine, JubJubScalar}; -use dusk_pki::{SecretSpendKey, ViewKey}; -use dusk_plonk::proof_system::Proof; -use dusk_schnorr::Signature; -use phoenix_core::{Crossover, Fee, Note}; +use dusk_plonk::prelude::Proof; +use jubjub_schnorr::Signature; +use phoenix_core::{Crossover, Fee, Note, SecretKey, ViewKey}; use poseidon_merkle::Opening as PoseidonOpening; use rand_chacha::ChaCha12Rng; use rand_core::SeedableRng; @@ -54,12 +53,12 @@ pub trait Store { /// Retrieves a derived secret spend key from the store. /// /// The provided implementation simply gets the seed and regenerates the key - /// every time with [`generate_ssk`]. It may be reimplemented to + /// every time with [`generate_sk`]. It may be reimplemented to /// provide a cache for keys, or implement a different key generation /// algorithm. - fn retrieve_ssk(&self, index: u64) -> Result { + fn retrieve_sk(&self, index: u64) -> Result { let seed = self.get_seed()?; - Ok(derive_ssk(&seed, index)) + Ok(derive_sk(&seed, index)) } /// Retrieves a derived secret key from the store. @@ -68,9 +67,12 @@ pub trait Store { /// every time with [`generate_sk`]. It may be reimplemented to /// provide a cache for keys, or implement a different key generation /// algorithm. - fn retrieve_sk(&self, index: u64) -> Result { + fn retrieve_stake_sk( + &self, + index: u64, + ) -> Result { let seed = self.get_seed()?; - Ok(derive_sk(&seed, index)) + Ok(derive_stake_sk(&seed, index)) } } @@ -80,7 +82,7 @@ pub trait Store { /// `index` are passed through SHA-256. A constant is then mixed in and the /// resulting hash is then used to seed a `ChaCha12` CSPRNG, which is /// subsequently used to generate the key. -pub fn derive_ssk(seed: &[u8; 64], index: u64) -> SecretSpendKey { +pub fn derive_sk(seed: &[u8; 64], index: u64) -> SecretKey { let mut hash = Sha256::new(); hash.update(seed); @@ -90,7 +92,7 @@ pub fn derive_ssk(seed: &[u8; 64], index: u64) -> SecretSpendKey { let hash = hash.finalize().into(); let mut rng = ChaCha12Rng::from_seed(hash); - SecretSpendKey::random(&mut rng) + SecretKey::random(&mut rng) } /// Generates a secret key from its seed and index. @@ -99,7 +101,7 @@ pub fn derive_ssk(seed: &[u8; 64], index: u64) -> SecretSpendKey { /// `index` are passed through SHA-256. A constant is then mixed in and the /// resulting hash is then used to seed a `ChaCha12` CSPRNG, which is /// subsequently used to generate the key. -pub fn derive_sk(seed: &[u8; 64], index: u64) -> SecretKey { +pub fn derive_stake_sk(seed: &[u8; 64], index: u64) -> StakeSecretKey { let mut hash = Sha256::new(); hash.update(seed); @@ -109,7 +111,7 @@ pub fn derive_sk(seed: &[u8; 64], index: u64) -> SecretKey { let hash = hash.finalize().into(); let mut rng = ChaCha12Rng::from_seed(hash); - SecretKey::random(&mut rng) + StakeSecretKey::random(&mut rng) } /// Types that are client of the prover. @@ -178,7 +180,10 @@ pub trait StateClient { /// Queries the node for the stake of a key. If the key has no stake, a /// `Default` stake info should be returned. - fn fetch_stake(&self, pk: &PublicKey) -> Result; + fn fetch_stake( + &self, + pk: &StakePublicKey, + ) -> Result; } /// Information about the balance of a particular key. diff --git a/src/tx.rs b/src/tx.rs index 578c1ed..02efdd2 100644 --- a/src/tx.rs +++ b/src/tx.rs @@ -12,12 +12,11 @@ use alloc::vec::Vec; use dusk_bytes::{ DeserializableSlice, Error as BytesError, Serializable, Write, }; -use dusk_jubjub::{BlsScalar, JubJubAffine, JubJubExtended}; -use dusk_pki::{Ownable, SecretSpendKey}; -use dusk_plonk::prelude::{JubJubScalar, Proof}; -use dusk_schnorr::Proof as SchnorrSig; +use dusk_jubjub::{BlsScalar, JubJubAffine, JubJubExtended, JubJubScalar}; +use dusk_plonk::prelude::Proof; +use jubjub_schnorr::SignatureDouble; use phoenix_core::transaction::Transaction; -use phoenix_core::{Crossover, Fee, Note}; +use phoenix_core::{Crossover, Fee, Note, Ownable, SecretKey}; use poseidon_merkle::Opening as PoseidonOpening; use rand_core::{CryptoRng, RngCore}; use rusk_abi::hash::Hasher; @@ -32,22 +31,22 @@ pub struct UnprovenTransactionInput { value: u64, blinder: JubJubScalar, pk_r_prime: JubJubExtended, - sig: SchnorrSig, + sig: SignatureDouble, } impl UnprovenTransactionInput { fn new( rng: &mut Rng, - ssk: &SecretSpendKey, + sk: &SecretKey, note: Note, value: u64, blinder: JubJubScalar, opening: PoseidonOpening<(), POSEIDON_TREE_DEPTH, 4>, tx_hash: BlsScalar, ) -> Self { - let nullifier = note.gen_nullifier(ssk); - let sk_r = ssk.sk_r(note.stealth_address()); - let sig = SchnorrSig::new(&sk_r, rng, tx_hash); + let nullifier = note.gen_nullifier(sk); + let sk_r = sk.sk_r(note.stealth_address()); + let sig = sk_r.sign_double(rng, tx_hash); let pk_r_prime = dusk_jubjub::GENERATOR_NUMS_EXTENDED * sk_r.as_ref(); @@ -74,7 +73,7 @@ impl UnprovenTransactionInput { BlsScalar::SIZE + Note::SIZE + JubJubAffine::SIZE - + SchnorrSig::SIZE + + SignatureDouble::SIZE + u64::SIZE + JubJubScalar::SIZE + opening_bytes.len(), @@ -101,7 +100,7 @@ impl UnprovenTransactionInput { let blinder = JubJubScalar::from_reader(&mut bytes)?; let pk_r_prime = JubJubExtended::from(JubJubAffine::from_reader(&mut bytes)?); - let sig = SchnorrSig::from_reader(&mut bytes)?; + let sig = SignatureDouble::from_reader(&mut bytes)?; // `to_vec` is required here otherwise `rkyv` will throw an alignment // error @@ -151,7 +150,7 @@ impl UnprovenTransactionInput { } /// Returns the input's signature. - pub fn signature(&self) -> &SchnorrSig { + pub fn signature(&self) -> &SignatureDouble { &self.sig } } @@ -174,7 +173,7 @@ impl UnprovenTransaction { pub(crate) fn new( rng: &mut Rng, state: &SC, - sender: &SecretSpendKey, + sender: &SecretKey, inputs: Vec<(Note, u64, JubJubScalar)>, outputs: Vec<(Note, u64, JubJubScalar)>, fee: Fee, diff --git a/tests/derive_keys.rs b/tests/derive_keys.rs new file mode 100644 index 0000000..4b0913b --- /dev/null +++ b/tests/derive_keys.rs @@ -0,0 +1,36 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. +// +// Copyright (c) DUSK NETWORK. All rights reserved. + +use dusk_bytes::Serializable; +use dusk_wallet_core::{derive_sk, derive_stake_sk}; + +const SEED: [u8; 64] = [0; 64]; +const INDEX: u64 = 42; + +#[test] +fn test_derive_sk() { + // it is important that derive_sk always derives the same key from a seed + let sk_bytes = [ + 12, 16, 72, 188, 33, 76, 44, 178, 86, 123, 107, 153, 230, 149, 238, + 131, 87, 30, 94, 88, 52, 129, 247, 167, 30, 167, 163, 246, 68, 254, 14, + 9, 218, 135, 245, 104, 11, 190, 143, 129, 83, 202, 64, 179, 157, 248, + 175, 120, 157, 220, 98, 211, 141, 50, 224, 8, 1, 125, 29, 180, 206, + 195, 34, 0, + ]; + assert_eq!(derive_sk(&SEED, INDEX).to_bytes(), sk_bytes); +} + +#[test] +fn test_derive_stake_sk() { + // it is important that derive_stake_sk always derives the same key from a + // seed + let sk_bytes = [ + 95, 35, 167, 191, 106, 171, 71, 158, 159, 39, 84, 1, 132, 238, 152, + 235, 154, 5, 250, 158, 255, 195, 79, 95, 193, 58, 36, 189, 0, 99, 230, + 86, + ]; + assert_eq!(derive_stake_sk(&SEED, INDEX).to_bytes(), sk_bytes); +} diff --git a/tests/mock.rs b/tests/mock.rs index 730a8e2..4ba91a1 100644 --- a/tests/mock.rs +++ b/tests/mock.rs @@ -6,17 +6,16 @@ //! Mocks of the traits supplied by the user of the crate.. -use dusk_bls12_381_sign::PublicKey; +use bls12_381_bls::PublicKey as StakePublicKey; use dusk_jubjub::{BlsScalar, JubJubAffine, JubJubScalar}; -use dusk_pki::{PublicSpendKey, ViewKey}; use dusk_plonk::prelude::Proof; -use dusk_schnorr::Signature; use dusk_wallet_core::{ EnrichedNote, ProverClient, StakeInfo, StateClient, Store, Transaction, UnprovenTransaction, Wallet, POSEIDON_TREE_DEPTH, }; use ff::Field; -use phoenix_core::{Crossover, Fee, Note, NoteType}; +use jubjub_schnorr::Signature; +use phoenix_core::{Crossover, Fee, Note, NoteType, PublicKey, ViewKey}; use poseidon_merkle::{Item, Opening as PoseidonOpening, Tree}; use rand_core::{CryptoRng, RngCore}; @@ -43,9 +42,9 @@ pub fn mock_wallet( note_values: &[u64], ) -> Wallet { let store = TestStore::new(rng); - let psk = store.retrieve_ssk(0).unwrap().public_spend_key(); + let pk = PublicKey::from(store.retrieve_sk(0).unwrap()); - let notes = new_notes(rng, &psk, note_values); + let notes = new_notes(rng, &pk, note_values); let anchor = BlsScalar::random(&mut *rng); let opening = default_opening(); @@ -62,9 +61,9 @@ pub fn mock_canon_wallet( note_values: &[u64], ) -> Wallet { let store = TestStore::new(rng); - let psk = store.retrieve_ssk(0).unwrap().public_spend_key(); + let pk = PublicKey::from(store.retrieve_sk(0).unwrap()); - let notes = new_notes(rng, &psk, note_values); + let notes = new_notes(rng, &pk, note_values); let anchor = BlsScalar::random(&mut *rng); let opening = default_opening(); @@ -83,9 +82,9 @@ pub fn mock_serde_wallet( note_values: &[u64], ) -> Wallet { let store = TestStore::new(rng); - let psk = store.retrieve_ssk(0).unwrap().public_spend_key(); + let pk = PublicKey::from(store.retrieve_sk(0).unwrap()); - let notes = new_notes(rng, &psk, note_values); + let notes = new_notes(rng, &pk, note_values); let anchor = BlsScalar::random(&mut *rng); let opening = default_opening(); @@ -100,14 +99,14 @@ pub fn mock_serde_wallet( /// Returns obfuscated notes with the given value. fn new_notes( rng: &mut Rng, - psk: &PublicSpendKey, + pk: &PublicKey, note_values: &[u64], ) -> Vec { note_values .iter() .map(|val| { - let blinder = JubJubScalar::random(rng); - (Note::new(rng, NoteType::Obfuscated, psk, *val, blinder), 0) + let blinder = JubJubScalar::random(&mut *rng); + (Note::new(rng, NoteType::Obfuscated, pk, *val, blinder), 0) }) .collect() } @@ -186,7 +185,10 @@ impl StateClient for TestStateClient { Ok(self.opening) } - fn fetch_stake(&self, _pk: &PublicKey) -> Result { + fn fetch_stake( + &self, + _stake_pk: &StakePublicKey, + ) -> Result { Ok(StakeInfo { amount: Some((100, 0)), reward: 0, diff --git a/tests/wallet.rs b/tests/wallet.rs index 0101e24..e3847f6 100644 --- a/tests/wallet.rs +++ b/tests/wallet.rs @@ -37,12 +37,12 @@ fn serde() { let wallet = mock_serde_wallet(&mut rng, &[2500, 2500, 5000]); - let send_psk = wallet.public_spend_key(0).unwrap(); - let recv_psk = wallet.public_spend_key(1).unwrap(); + let send_pk = wallet.public_key(0).unwrap(); + let recv_pk = wallet.public_key(1).unwrap(); let ref_id = BlsScalar::random(&mut rng); wallet - .transfer(&mut rng, 0, &send_psk, &recv_psk, 100, 100, 1, ref_id) + .transfer(&mut rng, 0, &send_pk, &recv_pk, 100, 100, 1, ref_id) .expect("Transaction creation to be successful"); } @@ -52,12 +52,12 @@ fn canon() { let wallet = mock_canon_wallet(&mut rng, &[2500, 2500, 5000]); - let send_psk = wallet.public_spend_key(0).unwrap(); - let recv_psk = wallet.public_spend_key(1).unwrap(); + let send_pk = wallet.public_key(0).unwrap(); + let recv_pk = wallet.public_key(1).unwrap(); let ref_id = BlsScalar::random(&mut rng); wallet - .transfer(&mut rng, 0, &send_psk, &recv_psk, 100, 100, 1, ref_id) + .transfer(&mut rng, 0, &send_pk, &recv_pk, 100, 100, 1, ref_id) .expect("Transaction creation to be successful"); } @@ -67,12 +67,12 @@ fn transfer() { let wallet = mock_wallet(&mut rng, &[2500, 2500, 5000]); - let send_psk = wallet.public_spend_key(0).unwrap(); - let recv_psk = wallet.public_spend_key(1).unwrap(); + let send_pk = wallet.public_key(0).unwrap(); + let recv_pk = wallet.public_key(1).unwrap(); let ref_id = BlsScalar::random(&mut rng); wallet - .transfer(&mut rng, 0, &send_psk, &recv_psk, 100, 100, 1, ref_id) + .transfer(&mut rng, 0, &send_pk, &recv_pk, 100, 100, 1, ref_id) .expect("Transaction creation to be successful"); }