Move transparent account keys to zcash_primitives.
This commit is contained in:
parent
72c2e54a7b
commit
f58d191439
|
@ -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::{
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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`].
|
||||
|
|
|
@ -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;
|
||||
///
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 = []
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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> {
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue