Move transparent account keys to zcash_primitives.

This commit is contained in:
Kris Nuttycombe 2022-01-24 18:02:25 -07:00
parent 72c2e54a7b
commit f58d191439
20 changed files with 190 additions and 186 deletions

View File

@ -11,14 +11,14 @@ use zcash_primitives::{
merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::{Node, Nullifier, PaymentAddress},
transaction::{components::Amount, Transaction, TxId},
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use crate::{
address::RecipientAddress,
decrypt::DecryptedOutput,
proto::compact_formats::CompactBlock,
wallet::{AccountId, SpendableNote, WalletTx},
wallet::{SpendableNote, WalletTx},
};
#[cfg(feature = "transparent-inputs")]
@ -307,12 +307,12 @@ pub mod testing {
merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::{Node, Nullifier, PaymentAddress},
transaction::{components::Amount, Transaction, TxId},
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use crate::{
proto::compact_formats::CompactBlock,
wallet::{AccountId, SpendableNote, WalletTransparentOutput},
wallet::{SpendableNote, WalletTransparentOutput},
};
use super::{

View File

@ -84,7 +84,7 @@ use zcash_primitives::{
consensus::{self, BlockHeight, NetworkUpgrade},
merkle_tree::CommitmentTree,
sapling::Nullifier,
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use crate::{
@ -93,7 +93,7 @@ use crate::{
BlockSource, PrunedBlock, WalletWrite,
},
proto::compact_formats::CompactBlock,
wallet::{AccountId, WalletTx},
wallet::WalletTx,
welding_rig::scan_block,
};

View File

@ -6,10 +6,9 @@ use zcash_primitives::{
consensus::BlockHeight,
sapling::Node,
transaction::{builder, components::amount::Amount, TxId},
zip32::AccountId,
};
use crate::wallet::AccountId;
#[derive(Debug)]
pub enum ChainInvalid {
/// The hash of the parent block given by a proposed new chain tip does

View File

@ -8,11 +8,11 @@ use zcash_primitives::{
components::{amount::DEFAULT_FEE, Amount},
Transaction,
},
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
zip32::{AccountId, ExtendedFullViewingKey, ExtendedSpendingKey},
};
#[cfg(feature = "transparent-inputs")]
use zcash_primitives::{sapling::keys::OutgoingViewingKey, transparent};
use zcash_primitives::{legacy::keys as transparent, sapling::keys::OutgoingViewingKey};
use crate::{
address::RecipientAddress,
@ -20,7 +20,7 @@ use crate::{
error::Error, DecryptedTransaction, SentTransaction, SentTransactionOutput, WalletWrite,
},
decrypt_transaction,
wallet::{AccountId, OvkPolicy},
wallet::OvkPolicy,
zip321::{Payment, TransactionRequest},
};
@ -102,12 +102,13 @@ where
/// consensus::{self, Network},
/// constants::testnet::COIN_TYPE,
/// transaction::{TxId, components::Amount},
/// zip32::AccountId,
/// };
/// use zcash_proofs::prover::LocalTxProver;
/// use zcash_client_backend::{
/// keys::sapling,
/// data_api::{wallet::create_spend_to_address, error::Error, testing},
/// wallet::{AccountId, OvkPolicy},
/// wallet::OvkPolicy,
/// };
///
/// # fn main() {

View File

@ -8,11 +8,9 @@ use zcash_primitives::{
Note, PaymentAddress,
},
transaction::Transaction,
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use crate::wallet::AccountId;
/// A decrypted shielded output.
pub struct DecryptedOutput {
/// The index of the output within [`shielded_outputs`].

View File

@ -100,11 +100,11 @@ impl<P: consensus::Parameters> AddressCodec<P> for TransparentAddress {
/// ```
/// use zcash_primitives::{
/// constants::testnet::{COIN_TYPE, HRP_SAPLING_EXTENDED_SPENDING_KEY},
/// zip32::AccountId,
/// };
/// use zcash_client_backend::{
/// encoding::encode_extended_spending_key,
/// keys::sapling,
/// wallet::AccountId,
/// };
///
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId(0));
@ -132,11 +132,11 @@ pub fn decode_extended_spending_key(
/// ```
/// use zcash_primitives::{
/// constants::testnet::{COIN_TYPE, HRP_SAPLING_EXTENDED_FULL_VIEWING_KEY},
/// zip32::AccountId,
/// };
/// use zcash_client_backend::{
/// encoding::encode_extended_full_viewing_key,
/// keys::sapling,
/// wallet::AccountId,
/// };
/// use zcash_primitives::zip32::ExtendedFullViewingKey;
///

View File

@ -1,13 +1,13 @@
//! Helper functions for managing light client key material.
use crate::wallet::AccountId;
use zcash_primitives::consensus;
use zcash_primitives::{consensus, zip32::AccountId};
#[cfg(feature = "transparent-inputs")]
use zcash_primitives::legacy::keys as legacy;
pub mod sapling {
use zcash_primitives::zip32::ChildIndex;
use zcash_primitives::zip32::{AccountId, ChildIndex};
pub use zcash_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey};
use crate::wallet::AccountId;
/// Derives the ZIP 32 [`ExtendedSpendingKey`] for a given coin type and account from the
/// given seed.
///
@ -18,10 +18,12 @@ pub mod sapling {
/// # Examples
///
/// ```
/// use zcash_primitives::{constants::testnet::COIN_TYPE};
/// use zcash_primitives::{
/// constants::testnet::COIN_TYPE,
/// zip32::AccountId,
/// };
/// use zcash_client_backend::{
/// keys::sapling,
/// wallet::AccountId,
/// };
///
/// let extsk = sapling::spending_key(&[0; 32][..], COIN_TYPE, AccountId(0));
@ -46,89 +48,8 @@ pub mod sapling {
#[cfg(feature = "transparent-inputs")]
pub mod transparent {
use bs58::{self, decode::Error as Bs58Error};
use hdwallet::{ExtendedPrivKey, ExtendedPubKey, KeyIndex};
use secp256k1::key::SecretKey;
use crate::wallet::AccountId;
use zcash_primitives::{
consensus,
transparent::{ExternalPrivKey, ExternalPubKey},
};
/// A type representing a BIP-44 private key at the account path level
/// `m/44'/<coin_type>'/<account>'
#[derive(Clone, Debug)]
pub struct AccountPrivKey(ExtendedPrivKey);
impl AccountPrivKey {
/// Perform derivation of the extended private key for the BIP-44 path:
/// `m/44'/<coin_type>'/<account>'
///
/// This produces the extended private key for the external (non-change)
/// address at the specified index for the provided account.
pub fn from_seed<P: consensus::Parameters>(
params: &P,
seed: &[u8],
account: AccountId,
) -> Result<AccountPrivKey, hdwallet::error::Error> {
ExtendedPrivKey::with_seed(&seed)?
.derive_private_key(KeyIndex::hardened_from_normalize_index(44)?)?
.derive_private_key(KeyIndex::hardened_from_normalize_index(params.coin_type())?)?
.derive_private_key(KeyIndex::hardened_from_normalize_index(account.0)?)
.map(AccountPrivKey)
}
pub fn from_extended_privkey(extprivkey: ExtendedPrivKey) -> Self {
AccountPrivKey(extprivkey)
}
pub fn extended_privkey(&self) -> &ExtendedPrivKey {
&self.0
}
pub fn to_account_pubkey(&self) -> AccountPubKey {
AccountPubKey(ExtendedPubKey::from_private_key(&self.0))
}
/// Derive BIP-44 private key at the external child path
/// `m/44'/<coin_type>'/<account>'/0/<child_index>
pub fn derive_external_secret_key(
&self,
child_index: u32,
) -> Result<ExternalPrivKey, hdwallet::error::Error> {
self.0
.derive_private_key(KeyIndex::Normal(0))?
.derive_private_key(KeyIndex::Normal(child_index))
.map(ExternalPrivKey)
}
}
/// A type representing a BIP-44 public key at the account path level
/// `m/44'/<coin_type>'/<account>'
#[derive(Clone, Debug)]
pub struct AccountPubKey(ExtendedPubKey);
impl AccountPubKey {
/// Derive BIP-44 public key at the external child path
/// `m/44'/<coin_type>'/<account>'/0/<child_index>
pub fn derive_external_pubkey(
&self,
child_index: u32,
) -> Result<ExternalPubKey, hdwallet::error::Error> {
self.0
.derive_public_key(KeyIndex::Normal(0))?
.derive_public_key(KeyIndex::Normal(child_index))
.map(ExternalPubKey)
}
pub fn from_extended_pubkey(extpubkey: ExtendedPubKey) -> Self {
AccountPubKey(extpubkey)
}
pub fn extended_pubkey(&self) -> &ExtendedPubKey {
&self.0
}
}
use secp256k1::SecretKey;
use zcash_primitives::consensus;
/// Wallet Import Format encoded transparent private key.
#[derive(Clone, Debug, Eq, PartialEq)]
@ -196,7 +117,7 @@ pub enum DerivationError {
pub struct UnifiedSpendingKey {
account: AccountId,
#[cfg(feature = "transparent-inputs")]
transparent: transparent::AccountPrivKey,
transparent: legacy::AccountPrivKey,
sapling: sapling::ExtendedSpendingKey,
}
@ -211,7 +132,7 @@ impl UnifiedSpendingKey {
}
#[cfg(feature = "transparent-inputs")]
let transparent = transparent::AccountPrivKey::from_seed(params, seed, account)
let transparent = legacy::AccountPrivKey::from_seed(params, seed, account)
.map_err(DerivationError::Transparent)?;
Ok(UnifiedSpendingKey {
@ -238,7 +159,7 @@ impl UnifiedSpendingKey {
/// Returns the transparent component of the unified key at the
/// BIP44 path `m/44'/<coin_type>'/<account>'`.
#[cfg(feature = "transparent-inputs")]
pub fn transparent(&self) -> &transparent::AccountPrivKey {
pub fn transparent(&self) -> &legacy::AccountPrivKey {
&self.transparent
}
@ -255,7 +176,7 @@ impl UnifiedSpendingKey {
pub struct UnifiedFullViewingKey {
account: AccountId,
#[cfg(feature = "transparent-inputs")]
transparent: Option<transparent::AccountPubKey>,
transparent: Option<legacy::AccountPubKey>,
sapling: Option<sapling::ExtendedFullViewingKey>,
}
@ -263,7 +184,7 @@ impl UnifiedFullViewingKey {
/// Construct a new unified full viewing key, if the required components are present.
pub fn new(
account: AccountId,
#[cfg(feature = "transparent-inputs")] transparent: Option<transparent::AccountPubKey>,
#[cfg(feature = "transparent-inputs")] transparent: Option<legacy::AccountPubKey>,
sapling: Option<sapling::ExtendedFullViewingKey>,
) -> Option<UnifiedFullViewingKey> {
if sapling.is_none() {
@ -287,7 +208,7 @@ impl UnifiedFullViewingKey {
#[cfg(feature = "transparent-inputs")]
/// Returns the transparent component of the unified key at the
/// BIP44 path `m/44'/<coin_type>'/<account>'`.
pub fn transparent(&self) -> Option<&transparent::AccountPubKey> {
pub fn transparent(&self) -> Option<&legacy::AccountPubKey> {
self.transparent.as_ref()
}
@ -301,12 +222,14 @@ impl UnifiedFullViewingKey {
#[cfg(test)]
mod tests {
use super::sapling;
use crate::wallet::AccountId;
use zcash_primitives::zip32::AccountId;
#[cfg(feature = "transparent-inputs")]
use {
super::transparent, crate::encoding::AddressCodec, secp256k1::key::SecretKey,
zcash_primitives::consensus::MAIN_NETWORK,
super::transparent,
crate::encoding::AddressCodec,
secp256k1::key::SecretKey,
zcash_primitives::{consensus::MAIN_NETWORK, legacy},
};
#[cfg(feature = "transparent-inputs")]
@ -324,7 +247,7 @@ mod tests {
#[cfg(feature = "transparent-inputs")]
#[test]
fn sk_to_wif() {
let sk = transparent::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
let sk = legacy::keys::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
.unwrap()
.derive_external_secret_key(0)
.unwrap();
@ -343,14 +266,14 @@ mod tests {
let sk: SecretKey = (&sk_wif).to_secret_key(&MAIN_NETWORK).expect("invalid wif");
let secp = secp256k1::Secp256k1::new();
let pubkey = secp256k1::key::PublicKey::from_secret_key(&secp, &sk);
let taddr = zcash_primitives::transparent::pubkey_to_address(&pubkey).encode(&MAIN_NETWORK);
let taddr = legacy::keys::pubkey_to_address(&pubkey).encode(&MAIN_NETWORK);
assert_eq!(taddr, "t1PKtYdJJHhc3Pxowmznkg7vdTwnhEsCvR4".to_string());
}
#[cfg(feature = "transparent-inputs")]
#[test]
fn pk_from_seed() {
let pk = transparent::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
let pk = legacy::keys::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
.unwrap()
.derive_external_secret_key(0)
.unwrap()
@ -365,7 +288,7 @@ mod tests {
#[cfg(feature = "transparent-inputs")]
#[test]
fn pk_to_taddr() {
let pk = transparent::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
let pk = legacy::keys::AccountPrivKey::from_seed(&MAIN_NETWORK, &seed(), AccountId(0))
.unwrap()
.derive_external_secret_key(0)
.unwrap()

View File

@ -1,8 +1,6 @@
//! Structs representing transaction data scanned from the block chain by a wallet or
//! light client.
use subtle::{Choice, ConditionallySelectable};
use zcash_note_encryption::EphemeralKeyBytes;
use zcash_primitives::{
merkle_tree::IncrementalWitness,
@ -10,6 +8,7 @@ use zcash_primitives::{
keys::OutgoingViewingKey, Diversifier, Node, Note, Nullifier, PaymentAddress, Rseed,
},
transaction::{components::Amount, TxId},
zip32::AccountId,
};
#[cfg(feature = "transparent-inputs")]
@ -19,28 +18,6 @@ use zcash_primitives::{
transaction::components::{OutPoint, TxOut},
};
/// A type-safe wrapper for account identifiers.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AccountId(pub u32);
impl From<u32> for AccountId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl Default for AccountId {
fn default() -> Self {
AccountId(0)
}
}
impl ConditionallySelectable for AccountId {
fn conditional_select(a0: &Self, a1: &Self, c: Choice) -> Self {
AccountId(u32::conditional_select(&a0.0, &a1.0, c))
}
}
/// A subset of a [`Transaction`] relevant to wallets and light clients.
///
/// [`Transaction`]: zcash_primitives::transaction::Transaction

View File

@ -13,11 +13,11 @@ use zcash_primitives::{
Node, Note, Nullifier, PaymentAddress, SaplingIvk,
},
transaction::components::sapling::CompactOutputDescription,
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use crate::proto::compact_formats::{CompactBlock, CompactOutput};
use crate::wallet::{AccountId, WalletShieldedOutput, WalletShieldedSpend, WalletTx};
use crate::wallet::{WalletShieldedOutput, WalletShieldedSpend, WalletTx};
/// Scans a [`CompactOutput`] with a set of [`ScanningKey`]s.
///
@ -317,12 +317,11 @@ mod tests {
SaplingIvk,
},
transaction::components::Amount,
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
zip32::{AccountId, ExtendedFullViewingKey, ExtendedSpendingKey},
};
use super::scan_block;
use crate::proto::compact_formats::{CompactBlock, CompactOutput, CompactSpend, CompactTx};
use crate::wallet::AccountId;
fn random_compact_tx(mut rng: impl RngCore) -> CompactTx {
let fake_nf = {

View File

@ -45,7 +45,7 @@ use zcash_primitives::{
merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::{Node, Nullifier, PaymentAddress},
transaction::{components::Amount, Transaction, TxId},
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use zcash_client_backend::{
@ -55,7 +55,7 @@ use zcash_client_backend::{
},
encoding::encode_payment_address,
proto::compact_formats::CompactBlock,
wallet::{AccountId, SpendableNote},
wallet::SpendableNote,
};
use crate::error::SqliteClientError;
@ -707,7 +707,7 @@ mod tests {
};
#[cfg(feature = "transparent-inputs")]
use zcash_client_backend::keys::transparent;
use zcash_primitives::legacy;
use zcash_primitives::{
block::BlockHash,
@ -762,7 +762,7 @@ mod tests {
#[cfg(feature = "transparent-inputs")]
{
let tkey = Some(
transparent::AccountPrivKey::from_seed(&network(), &seed, AccountId(0))
legacy::keys::AccountPrivKey::from_seed(&network(), &seed, AccountId(0))
.unwrap()
.to_account_pubkey(),
);

View File

@ -19,7 +19,7 @@ use zcash_primitives::{
merkle_tree::{CommitmentTree, IncrementalWitness},
sapling::{Node, Note, Nullifier, PaymentAddress},
transaction::{components::Amount, Transaction, TxId},
zip32::ExtendedFullViewingKey,
zip32::{AccountId, ExtendedFullViewingKey},
};
use zcash_client_backend::{
@ -28,7 +28,7 @@ use zcash_client_backend::{
decode_extended_full_viewing_key, decode_payment_address, encode_extended_full_viewing_key,
encode_payment_address_p, encode_transparent_address_p,
},
wallet::{AccountId, WalletShieldedOutput, WalletTx},
wallet::{WalletShieldedOutput, WalletTx},
DecryptedOutput,
};

View File

@ -288,7 +288,7 @@ mod tests {
use zcash_client_backend::keys::{sapling, UnifiedFullViewingKey, UnifiedSpendingKey};
#[cfg(feature = "transparent-inputs")]
use zcash_client_backend::keys::transparent;
use zcash_primitives::legacy::keys as transparent;
use zcash_primitives::{
block::BlockHash,

View File

@ -10,9 +10,10 @@ use zcash_primitives::{
merkle_tree::IncrementalWitness,
sapling::{Diversifier, Rseed},
transaction::components::Amount,
zip32::AccountId,
};
use zcash_client_backend::wallet::{AccountId, SpendableNote};
use zcash_client_backend::wallet::SpendableNote;
use crate::{error::SqliteClientError, WalletDb};
@ -169,7 +170,7 @@ mod tests {
};
#[cfg(feature = "transparent-inputs")]
use zcash_client_backend::keys::transparent;
use zcash_primitives::legacy::keys as transparent;
use crate::{
chain::init::init_cache_database,

View File

@ -22,6 +22,7 @@ bip0039 = { version = "0.9", features = ["std", "all-languages"] }
blake2b_simd = "1"
blake2s_simd = "1"
bls12_381 = "0.6"
bs58 = { version = "0.4", features = ["check"], optional = true }
byteorder = "1"
chacha20poly1305 = "0.9"
equihash = { version = "0.1", path = "../components/equihash" }
@ -61,7 +62,7 @@ orchard = { version = "=0.1.0-beta.1", features = ["test-dependencies"] }
pprof = { version = "=0.6.1", features = ["criterion", "flamegraph"] }
[features]
transparent-inputs = ["ripemd160", "hdwallet", "secp256k1"]
transparent-inputs = ["bs58", "hdwallet", "ripemd160", "secp256k1"]
test-dependencies = ["proptest", "orchard/test-dependencies"]
zfuture = []

View File

@ -0,0 +1,20 @@
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
pub const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
/// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bHash {
prf_expand_vec(sk, &[t])
}
pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bHash {
let mut h = Blake2bParams::new()
.hash_length(64)
.personal(PRF_EXPAND_PERSONALIZATION)
.to_state();
h.update(sk);
for t in ts {
h.update(t);
}
h.finalize()
}

View File

@ -6,6 +6,9 @@ use std::ops::Shl;
use zcash_encoding::Vector;
#[cfg(feature = "transparent-inputs")]
pub mod keys;
/// Minimal subset of script opcodes.
enum OpCode {
// push value

View File

@ -1,13 +1,91 @@
use crate::{legacy::TransparentAddress, sapling::keys::prf_expand_vec};
use hdwallet::{ExtendedPrivKey, ExtendedPubKey};
use hdwallet::{ExtendedPrivKey, ExtendedPubKey, KeyIndex};
use secp256k1::PublicKey;
use sha2::{Digest, Sha256};
use std::convert::TryInto;
use crate::{consensus, keys::prf_expand_vec, zip32::AccountId};
use super::TransparentAddress;
/// A type representing a BIP-44 private key at the account path level
/// `m/44'/<coin_type>'/<account>'
#[derive(Clone, Debug)]
pub struct AccountPrivKey(ExtendedPrivKey);
impl AccountPrivKey {
/// Perform derivation of the extended private key for the BIP-44 path:
/// `m/44'/<coin_type>'/<account>'
///
/// This produces the extended private key for the external (non-change)
/// address at the specified index for the provided account.
pub fn from_seed<P: consensus::Parameters>(
params: &P,
seed: &[u8],
account: AccountId,
) -> Result<AccountPrivKey, hdwallet::error::Error> {
ExtendedPrivKey::with_seed(&seed)?
.derive_private_key(KeyIndex::hardened_from_normalize_index(44)?)?
.derive_private_key(KeyIndex::hardened_from_normalize_index(params.coin_type())?)?
.derive_private_key(KeyIndex::hardened_from_normalize_index(account.0)?)
.map(AccountPrivKey)
}
pub fn from_extended_privkey(extprivkey: ExtendedPrivKey) -> Self {
AccountPrivKey(extprivkey)
}
pub fn extended_privkey(&self) -> &ExtendedPrivKey {
&self.0
}
pub fn to_account_pubkey(&self) -> AccountPubKey {
AccountPubKey(ExtendedPubKey::from_private_key(&self.0))
}
/// Derive BIP-44 private key at the external child path
/// `m/44'/<coin_type>'/<account>'/0/<child_index>
pub fn derive_external_secret_key(
&self,
child_index: u32,
) -> Result<ExternalPrivKey, hdwallet::error::Error> {
self.0
.derive_private_key(KeyIndex::Normal(0))?
.derive_private_key(KeyIndex::Normal(child_index))
.map(ExternalPrivKey)
}
}
/// A type representing a BIP-44 public key at the account path level
/// `m/44'/<coin_type>'/<account>'
#[derive(Clone, Debug)]
pub struct AccountPubKey(ExtendedPubKey);
impl AccountPubKey {
/// Derive BIP-44 public key at the external child path
/// `m/44'/<coin_type>'/<account>'/0/<child_index>
pub fn derive_external_pubkey(
&self,
child_index: u32,
) -> Result<ExternalPubKey, hdwallet::error::Error> {
self.0
.derive_public_key(KeyIndex::Normal(0))?
.derive_public_key(KeyIndex::Normal(child_index))
.map(ExternalPubKey)
}
pub fn from_extended_pubkey(extpubkey: ExtendedPubKey) -> Self {
AccountPubKey(extpubkey)
}
pub fn extended_pubkey(&self) -> &ExtendedPubKey {
&self.0
}
}
/// A type representing a private key at the BIP-44 external child
/// level `m/44'/<coin_type>'/<account>'/0/<child_index>
#[derive(Clone, Debug)]
pub struct ExternalPrivKey(pub ExtendedPrivKey);
pub struct ExternalPrivKey(ExtendedPrivKey);
impl ExternalPrivKey {
/// Returns the external public key corresponding to this private key
@ -30,7 +108,7 @@ pub fn pubkey_to_address(pubkey: &secp256k1::key::PublicKey) -> TransparentAddre
/// A type representing a public key at the BIP-44 external child
/// level `m/44'/<coin_type>'/<account>'/0/<child_index>
#[derive(Clone, Debug)]
pub struct ExternalPubKey(pub ExtendedPubKey);
pub struct ExternalPubKey(ExtendedPubKey);
impl std::convert::TryFrom<&[u8; 65]> for ExternalPubKey {
type Error = hdwallet::error::Error;
@ -62,7 +140,7 @@ impl ExternalPubKey {
/// transparent fvk. As specified in [ZIP 316][transparent-ovk].
///
/// [transparent-ovk]: https://zips.z.cash/zip-0316#deriving-internal-keys
fn ovk_for_shielding(&self) -> (InternalOvk, ExternalOvk) {
pub fn ovks_for_shielding(&self) -> (InternalOvk, ExternalOvk) {
let i_ovk = prf_expand_vec(
&self.chain_code(),
&[&[0xd0], &self.public_key().serialize()],
@ -76,12 +154,12 @@ impl ExternalPubKey {
/// Derives the internal ovk corresponding to this transparent fvk.
pub fn internal_ovk(&self) -> InternalOvk {
self.ovk_for_shielding().0
self.ovks_for_shielding().0
}
/// Derives the external ovk corresponding to this transparent fvk.
pub fn external_ovk(&self) -> ExternalOvk {
self.ovk_for_shielding().1
self.ovks_for_shielding().1
}
pub fn serialize(&self) -> Vec<u8> {

View File

@ -12,13 +12,12 @@
pub mod block;
pub mod consensus;
pub mod constants;
pub mod keys;
pub mod legacy;
pub mod memo;
pub mod merkle_tree;
pub mod sapling;
pub mod transaction;
#[cfg(feature = "transparent-inputs")]
pub mod transparent;
pub mod zip32;
pub mod zip339;

View File

@ -8,30 +8,12 @@ use crate::{
constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
sapling::{ProofGenerationKey, ViewingKey},
};
use blake2b_simd::{Hash as Blake2bHash, Params as Blake2bParams};
use ff::PrimeField;
use group::{Group, GroupEncoding};
use std::io::{self, Read, Write};
use subtle::CtOption;
pub const PRF_EXPAND_PERSONALIZATION: &[u8; 16] = b"Zcash_ExpandSeed";
/// PRF^expand(sk, t) := BLAKE2b-512("Zcash_ExpandSeed", sk || t)
pub fn prf_expand(sk: &[u8], t: &[u8]) -> Blake2bHash {
prf_expand_vec(sk, &[t])
}
pub fn prf_expand_vec(sk: &[u8], ts: &[&[u8]]) -> Blake2bHash {
let mut h = Blake2bParams::new()
.hash_length(64)
.personal(PRF_EXPAND_PERSONALIZATION)
.to_state();
h.update(sk);
for t in ts {
h.update(t);
}
h.finalize()
}
pub use crate::keys::{prf_expand, prf_expand_vec};
/// An outgoing viewing key
#[derive(Clone, Copy, Debug, PartialEq)]

View File

@ -8,6 +8,7 @@ use byteorder::{ByteOrder, LittleEndian, ReadBytesExt, WriteBytesExt};
use fpe::ff1::{BinaryNumeralString, FF1};
use std::convert::TryInto;
use std::ops::AddAssign;
use subtle::{Choice, ConditionallySelectable};
use crate::{
constants::{PROOF_GENERATION_KEY_GENERATOR, SPENDING_KEY_GENERATOR},
@ -23,6 +24,28 @@ pub const ZIP32_SAPLING_MASTER_PERSONALIZATION: &[u8; 16] = b"ZcashIP32Sapling";
pub const ZIP32_SAPLING_FVFP_PERSONALIZATION: &[u8; 16] = b"ZcashSaplingFVFP";
pub const ZIP32_SAPLING_INT_PERSONALIZATION: &[u8; 16] = b"Zcash_SaplingInt";
/// A type-safe wrapper for account identifiers.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AccountId(pub u32);
impl From<u32> for AccountId {
fn from(id: u32) -> Self {
Self(id)
}
}
impl Default for AccountId {
fn default() -> Self {
AccountId(0)
}
}
impl ConditionallySelectable for AccountId {
fn conditional_select(a0: &Self, a1: &Self, c: Choice) -> Self {
AccountId(u32::conditional_select(&a0.0, &a1.0, c))
}
}
// Common helper functions
fn derive_child_ovk(parent: &OutgoingViewingKey, i_l: &[u8]) -> OutgoingViewingKey {