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

Commit 5e73ade

Browse files
authored
Taddress priv key import (#83)
* t address refactor * fix test * import t key flow + test * Fix assert
1 parent 1d56113 commit 5e73ade

File tree

6 files changed

+571
-146
lines changed

6 files changed

+571
-146
lines changed

lib/src/blaze/fetch_taddr_txns.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ mod test {
150150
use zcash_primitives::transaction::{Transaction, TransactionData};
151151

152152
use crate::lightwallet::keys::Keys;
153+
use crate::lightwallet::wallettkey::WalletTKey;
153154

154155
use super::FetchTaddrTxns;
155156

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

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

lib/src/lightclient.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
use self::lightclient_config::LightClientConfig;
2-
use crate::{blaze::{
2+
use crate::{
3+
blaze::{
34
block_witness_data::BlockAndWitnessData, fetch_compact_blocks::FetchCompactBlocks,
45
fetch_full_tx::FetchFullTxns, fetch_taddr_txns::FetchTaddrTxns, sync_status::SyncStatus,
56
syncdata::BlazeSyncData, trial_decryptions::TrialDecryptions, update_notes::UpdateNotes,
6-
}, compact_formats::RawTransaction, grpc_connector::GrpcConnector, lightclient::lightclient_config::MAX_REORG, lightwallet::{self, LightWallet, data::WalletTx, message::Message, now}};
7+
},
8+
compact_formats::RawTransaction,
9+
grpc_connector::GrpcConnector,
10+
lightclient::lightclient_config::MAX_REORG,
11+
lightwallet::{self, data::WalletTx, message::Message, now, LightWallet},
12+
};
713
use futures::future::join_all;
814
use json::{array, object, JsonValue};
915
use log::{error, info, warn};
@@ -928,14 +934,34 @@ impl LightClient {
928934
} else if key.starts_with(self.config.hrp_sapling_viewing_key()) {
929935
self.do_import_vk(key, birthday).await
930936
} else if key.starts_with("K") || key.starts_with("L") {
931-
Err(format!("Can't import t-address keys yet!"))
937+
self.do_import_tk(key).await
932938
} else {
933-
Err(format!("'{}' was not recognized as either a spending key or a viewing key because it didn't start with either '{}' or '{}'",
934-
key, self.config.hrp_sapling_private_key(), self.config.hrp_sapling_viewing_key()))
939+
Err(format!(
940+
"'{}' was not recognized as either a spending key or a viewing key",
941+
key,
942+
))
935943
}
936944
}
937945

938-
/// Import a new private key
946+
/// Import a new transparent private key
947+
pub async fn do_import_tk(&self, sk: String) -> Result<JsonValue, String> {
948+
if !self.wallet.is_unlocked_for_spending().await {
949+
error!("Wallet is locked");
950+
return Err("Wallet is locked".to_string());
951+
}
952+
953+
let address = self.wallet.add_imported_tk(sk).await;
954+
if address.starts_with("Error") {
955+
let e = address;
956+
error!("{}", e);
957+
return Err(e);
958+
}
959+
960+
self.do_save().await?;
961+
Ok(array![address])
962+
}
963+
964+
/// Import a new z-address private key
939965
pub async fn do_import_sk(&self, sk: String, birthday: u64) -> Result<JsonValue, String> {
940966
if !self.wallet.is_unlocked_for_spending().await {
941967
error!("Wallet is locked");

lib/src/lightclient/tests.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use group::GroupEncoding;
33
use json::JsonValue;
44
use jubjub::ExtendedPoint;
55
use rand::rngs::OsRng;
6-
use secp256k1::{PublicKey, Secp256k1};
76
use tempdir::TempDir;
87
use tokio::runtime::Runtime;
98
use tonic::transport::Channel;
@@ -663,7 +662,6 @@ async fn z_incoming_viewkey() {
663662

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1004999
let mut ftx = FakeTransaction::new();

lib/src/lightwallet.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::compact_formats::TreeState;
22
use crate::lightwallet::data::WalletTx;
3+
use crate::lightwallet::wallettkey::WalletTKey;
34
use crate::{
45
blaze::fetch_full_tx::FetchFullTxns,
56
lightclient::lightclient_config::LightClientConfig,
@@ -51,6 +52,7 @@ pub(crate) mod keys;
5152
pub(crate) mod message;
5253
pub(crate) mod utils;
5354
pub(crate) mod wallet_txns;
55+
pub(crate) mod wallettkey;
5456
mod walletzkey;
5557

5658
pub fn now() -> u64 {
@@ -104,7 +106,7 @@ pub struct WalletOptions {
104106
impl Default for WalletOptions {
105107
fn default() -> Self {
106108
WalletOptions {
107-
download_memos: MemoDownloadOption::WalletMemos
109+
download_memos: MemoDownloadOption::WalletMemos,
108110
}
109111
}
110112
}
@@ -114,7 +116,6 @@ impl WalletOptions {
114116
return 1;
115117
}
116118

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

@@ -123,13 +124,14 @@ impl WalletOptions {
123124
1 => MemoDownloadOption::WalletMemos,
124125
2 => MemoDownloadOption::AllMemos,
125126
v => {
126-
return Err(io::Error::new(io::ErrorKind::InvalidData, format!("Bad download option {}", v)));
127+
return Err(io::Error::new(
128+
io::ErrorKind::InvalidData,
129+
format!("Bad download option {}", v),
130+
));
127131
}
128132
};
129133

130-
Ok(Self {
131-
download_memos
132-
})
134+
Ok(Self { download_memos })
133135
}
134136

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

476+
pub async fn add_imported_tk(&self, sk: String) -> String {
477+
if self.keys.read().await.encrypted {
478+
return "Error: Can't import transparent address key while wallet is encrypted".to_string();
479+
}
480+
481+
let sk = match WalletTKey::from_sk_string(&self.config, sk) {
482+
Err(e) => return format!("Error: {}", e),
483+
Ok(k) => k,
484+
};
485+
486+
let address = sk.address.clone();
487+
488+
if self
489+
.keys
490+
.read()
491+
.await
492+
.tkeys
493+
.iter()
494+
.find(|&tk| tk.address == address)
495+
.is_some()
496+
{
497+
return "Error: Key already exists".to_string();
498+
}
499+
500+
self.keys.write().await.tkeys.push(sk);
501+
return address;
502+
}
503+
474504
// Add a new imported spending key to the wallet
475505
/// NOTE: This will not rescan the wallet
476506
pub async fn add_imported_sk(&self, sk: String, birthday: u64) -> String {
@@ -832,7 +862,6 @@ impl LightWallet {
832862
if highest_account.unwrap() == 0 {
833863
// Remove unused addresses
834864
self.keys.write().await.tkeys.truncate(1);
835-
self.keys.write().await.taddresses.truncate(1);
836865
}
837866
}
838867

@@ -1326,7 +1355,6 @@ impl LightWallet {
13261355

13271356
#[cfg(test)]
13281357
mod test {
1329-
use secp256k1::{PublicKey, Secp256k1};
13301358
use zcash_primitives::transaction::components::Amount;
13311359

13321360
use crate::{
@@ -1426,10 +1454,9 @@ mod test {
14261454
assert_eq!(utxos.len(), 0);
14271455

14281456
// 4. Get an incoming tx to a t address
1429-
let secp = Secp256k1::new();
1430-
let sk = lc.wallet.keys().read().await.tkeys[0];
1431-
let pk = PublicKey::from_secret_key(&secp, &sk);
1432-
let taddr = lc.wallet.keys().read().await.address_from_sk(&sk);
1457+
let sk = lc.wallet.keys().read().await.tkeys[0].clone();
1458+
let pk = sk.pubkey().unwrap();
1459+
let taddr = sk.address;
14331460
let tvalue = 100_000;
14341461

14351462
let mut ftx = FakeTransaction::new();

0 commit comments

Comments
 (0)