Skip to content
This repository has been archived by the owner on Sep 26, 2023. It is now read-only.

Commit

Permalink
Taddress priv key import (#83)
Browse files Browse the repository at this point in the history
* t address refactor

* fix test

* import t key flow + test

* Fix assert
  • Loading branch information
adityapk00 authored Oct 13, 2021
1 parent 1d56113 commit 5e73ade
Show file tree
Hide file tree
Showing 6 changed files with 571 additions and 146 deletions.
3 changes: 2 additions & 1 deletion lib/src/blaze/fetch_taddr_txns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ mod test {
use zcash_primitives::transaction::{Transaction, TransactionData};

use crate::lightwallet::keys::Keys;
use crate::lightwallet::wallettkey::WalletTKey;

use super::FetchTaddrTxns;

Expand All @@ -158,7 +159,7 @@ mod test {
// 5 t addresses
let mut keys = Keys::new_empty();
let gened_taddrs: Vec<_> = (0..5).into_iter().map(|n| format!("taddr{}", n)).collect();
keys.taddresses = gened_taddrs.clone();
keys.tkeys = gened_taddrs.iter().map(|ta| WalletTKey::empty(ta)).collect::<Vec<_>>();

let ftt = FetchTaddrTxns::new(Arc::new(RwLock::new(keys)));

Expand Down
38 changes: 32 additions & 6 deletions lib/src/lightclient.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
use self::lightclient_config::LightClientConfig;
use crate::{blaze::{
use crate::{
blaze::{
block_witness_data::BlockAndWitnessData, fetch_compact_blocks::FetchCompactBlocks,
fetch_full_tx::FetchFullTxns, fetch_taddr_txns::FetchTaddrTxns, sync_status::SyncStatus,
syncdata::BlazeSyncData, trial_decryptions::TrialDecryptions, update_notes::UpdateNotes,
}, compact_formats::RawTransaction, grpc_connector::GrpcConnector, lightclient::lightclient_config::MAX_REORG, lightwallet::{self, LightWallet, data::WalletTx, message::Message, now}};
},
compact_formats::RawTransaction,
grpc_connector::GrpcConnector,
lightclient::lightclient_config::MAX_REORG,
lightwallet::{self, data::WalletTx, message::Message, now, LightWallet},
};
use futures::future::join_all;
use json::{array, object, JsonValue};
use log::{error, info, warn};
Expand Down Expand Up @@ -928,14 +934,34 @@ impl LightClient {
} else if key.starts_with(self.config.hrp_sapling_viewing_key()) {
self.do_import_vk(key, birthday).await
} else if key.starts_with("K") || key.starts_with("L") {
Err(format!("Can't import t-address keys yet!"))
self.do_import_tk(key).await
} else {
Err(format!("'{}' was not recognized as either a spending key or a viewing key because it didn't start with either '{}' or '{}'",
key, self.config.hrp_sapling_private_key(), self.config.hrp_sapling_viewing_key()))
Err(format!(
"'{}' was not recognized as either a spending key or a viewing key",
key,
))
}
}

/// Import a new private key
/// Import a new transparent private key
pub async fn do_import_tk(&self, sk: String) -> Result<JsonValue, String> {
if !self.wallet.is_unlocked_for_spending().await {
error!("Wallet is locked");
return Err("Wallet is locked".to_string());
}

let address = self.wallet.add_imported_tk(sk).await;
if address.starts_with("Error") {
let e = address;
error!("{}", e);
return Err(e);
}

self.do_save().await?;
Ok(array![address])
}

/// Import a new z-address private key
pub async fn do_import_sk(&self, sk: String, birthday: u64) -> Result<JsonValue, String> {
if !self.wallet.is_unlocked_for_spending().await {
error!("Wallet is locked");
Expand Down
29 changes: 12 additions & 17 deletions lib/src/lightclient/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use group::GroupEncoding;
use json::JsonValue;
use jubjub::ExtendedPoint;
use rand::rngs::OsRng;
use secp256k1::{PublicKey, Secp256k1};
use tempdir::TempDir;
use tokio::runtime::Runtime;
use tonic::transport::Channel;
Expand Down Expand Up @@ -663,7 +662,6 @@ async fn z_incoming_viewkey() {

#[tokio::test]
async fn t_incoming_t_outgoing() {
let secp = Secp256k1::new();
let (data, config, ready_rx, stop_tx, h1) = create_test_server().await;

ready_rx.await.unwrap();
Expand All @@ -675,9 +673,9 @@ async fn t_incoming_t_outgoing() {
mine_random_blocks(&mut fcbl, &data, &lc, 10).await;

// 2. Get an incoming tx to a t address
let sk = lc.wallet.keys().read().await.tkeys[0];
let pk = PublicKey::from_secret_key(&secp, &sk);
let taddr = lc.wallet.keys().read().await.address_from_sk(&sk);
let sk = lc.wallet.keys().read().await.tkeys[0].clone();
let pk = sk.pubkey().unwrap();
let taddr = sk.address;
let value = 100_000;

let mut ftx = FakeTransaction::new();
Expand Down Expand Up @@ -762,7 +760,6 @@ async fn t_incoming_t_outgoing() {

#[tokio::test]
async fn mixed_txn() {
let secp = Secp256k1::new();
let (data, config, ready_rx, stop_tx, h1) = create_test_server().await;

ready_rx.await.unwrap();
Expand All @@ -782,9 +779,9 @@ async fn mixed_txn() {
mine_random_blocks(&mut fcbl, &data, &lc, 5).await;

// 3. Send an incoming t-address txn
let sk = lc.wallet.keys().read().await.tkeys[0];
let pk = PublicKey::from_secret_key(&secp, &sk);
let taddr = lc.wallet.keys().read().await.address_from_sk(&sk);
let sk = lc.wallet.keys().read().await.tkeys[0].clone();
let pk = sk.pubkey().unwrap();
let taddr = sk.address;
let tvalue = 200_000;

let mut ftx = FakeTransaction::new();
Expand Down Expand Up @@ -865,7 +862,6 @@ async fn mixed_txn() {

#[tokio::test]
async fn aborted_resync() {
let secp = Secp256k1::new();
let (data, config, ready_rx, stop_tx, h1) = create_test_server().await;

ready_rx.await.unwrap();
Expand All @@ -885,9 +881,9 @@ async fn aborted_resync() {
mine_random_blocks(&mut fcbl, &data, &lc, 5).await;

// 3. Send an incoming t-address txn
let sk = lc.wallet.keys().read().await.tkeys[0];
let pk = PublicKey::from_secret_key(&secp, &sk);
let taddr = lc.wallet.keys().read().await.address_from_sk(&sk);
let sk = lc.wallet.keys().read().await.tkeys[0].clone();
let pk = sk.pubkey().unwrap();
let taddr = sk.address;
let tvalue = 200_000;

let mut ftx = FakeTransaction::new();
Expand Down Expand Up @@ -976,7 +972,6 @@ async fn aborted_resync() {

#[tokio::test]
async fn no_change() {
let secp = Secp256k1::new();
let (data, config, ready_rx, stop_tx, h1) = create_test_server().await;

ready_rx.await.unwrap();
Expand All @@ -996,9 +991,9 @@ async fn no_change() {
mine_random_blocks(&mut fcbl, &data, &lc, 5).await;

// 3. Send an incoming t-address txn
let sk = lc.wallet.keys().read().await.tkeys[0];
let pk = PublicKey::from_secret_key(&secp, &sk);
let taddr = lc.wallet.keys().read().await.address_from_sk(&sk);
let sk = lc.wallet.keys().read().await.tkeys[0].clone();
let pk = sk.pubkey().unwrap();
let taddr = sk.address;
let tvalue = 200_000;

let mut ftx = FakeTransaction::new();
Expand Down
51 changes: 39 additions & 12 deletions lib/src/lightwallet.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::compact_formats::TreeState;
use crate::lightwallet::data::WalletTx;
use crate::lightwallet::wallettkey::WalletTKey;
use crate::{
blaze::fetch_full_tx::FetchFullTxns,
lightclient::lightclient_config::LightClientConfig,
Expand Down Expand Up @@ -51,6 +52,7 @@ pub(crate) mod keys;
pub(crate) mod message;
pub(crate) mod utils;
pub(crate) mod wallet_txns;
pub(crate) mod wallettkey;
mod walletzkey;

pub fn now() -> u64 {
Expand Down Expand Up @@ -104,7 +106,7 @@ pub struct WalletOptions {
impl Default for WalletOptions {
fn default() -> Self {
WalletOptions {
download_memos: MemoDownloadOption::WalletMemos
download_memos: MemoDownloadOption::WalletMemos,
}
}
}
Expand All @@ -114,7 +116,6 @@ impl WalletOptions {
return 1;
}


pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
let _version = reader.read_u64::<LittleEndian>()?;

Expand All @@ -123,13 +124,14 @@ impl WalletOptions {
1 => MemoDownloadOption::WalletMemos,
2 => MemoDownloadOption::AllMemos,
v => {
return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Bad download option {}", v)));
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("Bad download option {}", v),
));
}
};

Ok(Self {
download_memos
})
Ok(Self { download_memos })
}

pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
Expand Down Expand Up @@ -471,6 +473,34 @@ impl LightWallet {
}
}

pub async fn add_imported_tk(&self, sk: String) -> String {
if self.keys.read().await.encrypted {
return "Error: Can't import transparent address key while wallet is encrypted".to_string();
}

let sk = match WalletTKey::from_sk_string(&self.config, sk) {
Err(e) => return format!("Error: {}", e),
Ok(k) => k,
};

let address = sk.address.clone();

if self
.keys
.read()
.await
.tkeys
.iter()
.find(|&tk| tk.address == address)
.is_some()
{
return "Error: Key already exists".to_string();
}

self.keys.write().await.tkeys.push(sk);
return address;
}

// Add a new imported spending key to the wallet
/// NOTE: This will not rescan the wallet
pub async fn add_imported_sk(&self, sk: String, birthday: u64) -> String {
Expand Down Expand Up @@ -832,7 +862,6 @@ impl LightWallet {
if highest_account.unwrap() == 0 {
// Remove unused addresses
self.keys.write().await.tkeys.truncate(1);
self.keys.write().await.taddresses.truncate(1);
}
}

Expand Down Expand Up @@ -1326,7 +1355,6 @@ impl LightWallet {

#[cfg(test)]
mod test {
use secp256k1::{PublicKey, Secp256k1};
use zcash_primitives::transaction::components::Amount;

use crate::{
Expand Down Expand Up @@ -1426,10 +1454,9 @@ mod test {
assert_eq!(utxos.len(), 0);

// 4. Get an incoming tx to a t address
let secp = Secp256k1::new();
let sk = lc.wallet.keys().read().await.tkeys[0];
let pk = PublicKey::from_secret_key(&secp, &sk);
let taddr = lc.wallet.keys().read().await.address_from_sk(&sk);
let sk = lc.wallet.keys().read().await.tkeys[0].clone();
let pk = sk.pubkey().unwrap();
let taddr = sk.address;
let tvalue = 100_000;

let mut ftx = FakeTransaction::new();
Expand Down
Loading

0 comments on commit 5e73ade

Please sign in to comment.