mirror of
https://github.com/Qortal/piratewallet-light-cli.git
synced 2025-02-01 03:12:15 +00:00
Derive addresses from seed
This commit is contained in:
parent
d7ff2a8792
commit
5bd8b754df
@ -21,6 +21,7 @@ hex = "0.3"
|
|||||||
protobuf = "2"
|
protobuf = "2"
|
||||||
rustyline = "5.0.2"
|
rustyline = "5.0.2"
|
||||||
byteorder = "1"
|
byteorder = "1"
|
||||||
|
rand = "0.5.6"
|
||||||
|
|
||||||
[dependencies.bellman]
|
[dependencies.bellman]
|
||||||
path = "../../librustzcash/bellman"
|
path = "../../librustzcash/bellman"
|
||||||
@ -50,4 +51,4 @@ features = ["ff_derive"]
|
|||||||
tower-grpc-build = { git = "https://github.com/tower-rs/tower-grpc", features = ["tower-hyper"] }
|
tower-grpc-build = { git = "https://github.com/tower-rs/tower-grpc", features = ["tower-hyper"] }
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = true
|
#debug = true
|
@ -68,7 +68,7 @@ impl LightClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_address(&self) {
|
pub fn do_address(&self) {
|
||||||
println!("Address: {}", self.wallet.address());
|
println!("Address: {}", self.wallet.address(0)); // TODO: This is showing only the default address
|
||||||
println!("Balance: {}", self.wallet.balance());
|
println!("Balance: {}", self.wallet.balance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ use zcash_primitives::{
|
|||||||
TxId, Transaction
|
TxId, Transaction
|
||||||
},
|
},
|
||||||
note_encryption::{Memo, try_sapling_note_decryption},
|
note_encryption::{Memo, try_sapling_note_decryption},
|
||||||
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey},
|
zip32::{ExtendedFullViewingKey, ExtendedSpendingKey, ChildIndex},
|
||||||
JUBJUB,
|
JUBJUB,
|
||||||
primitives::{Diversifier, Note, PaymentAddress},
|
primitives::{Diversifier, Note, PaymentAddress},
|
||||||
jubjub::{
|
jubjub::{
|
||||||
@ -349,9 +349,15 @@ impl SpendableNote {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct LightWallet {
|
pub struct LightWallet {
|
||||||
extsks: [ExtendedSpendingKey; 1],
|
seed: [u8; 32], // Seed phrase for this wallet.
|
||||||
extfvks: [ExtendedFullViewingKey; 1],
|
|
||||||
address: PaymentAddress<Bls12>,
|
// List of keys, actually in this wallet. This may include more
|
||||||
|
// than keys derived from the seed, for example, if user imports
|
||||||
|
// a private key
|
||||||
|
extsks: Vec<ExtendedSpendingKey>,
|
||||||
|
extfvks: Vec<ExtendedFullViewingKey>,
|
||||||
|
address: Vec<PaymentAddress<Bls12>>,
|
||||||
|
|
||||||
blocks: Arc<RwLock<Vec<BlockData>>>,
|
blocks: Arc<RwLock<Vec<BlockData>>>,
|
||||||
pub txs: Arc<RwLock<HashMap<TxId, WalletTx>>>,
|
pub txs: Arc<RwLock<HashMap<TxId, WalletTx>>>,
|
||||||
}
|
}
|
||||||
@ -361,15 +367,40 @@ impl LightWallet {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
fn get_pk_from_seed(seed: &[u8; 32]) ->
|
||||||
let extsk = ExtendedSpendingKey::master(&[1; 32]); // New key
|
(ExtendedSpendingKey, ExtendedFullViewingKey, PaymentAddress<Bls12>) {
|
||||||
|
let extsk: ExtendedSpendingKey = ExtendedSpendingKey::from_path(
|
||||||
|
&ExtendedSpendingKey::master(seed),
|
||||||
|
&[
|
||||||
|
ChildIndex::Hardened(32),
|
||||||
|
ChildIndex::Hardened(1), // TODO: Cointype should be 133 for mainnet
|
||||||
|
ChildIndex::Hardened(0)
|
||||||
|
],
|
||||||
|
);
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
||||||
let address = extfvk.default_address().unwrap().1;
|
let address = extfvk.default_address().unwrap().1;
|
||||||
|
|
||||||
|
(extsk, extfvk, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new() -> Self {
|
||||||
|
use rand::{FromEntropy, ChaChaRng, Rng};
|
||||||
|
|
||||||
|
// Create a random seed.
|
||||||
|
let mut system_rng = ChaChaRng::from_entropy();
|
||||||
|
let mut seed_bytes = [0u8; 32];
|
||||||
|
system_rng.fill(&mut seed_bytes);
|
||||||
|
|
||||||
|
// Derive only the first address
|
||||||
|
// TODO: We need to monitor addresses, and always keep 1 "free" address, so
|
||||||
|
// users can import a seed phrase and automatically get all used addresses
|
||||||
|
let (extsk, extfvk, address) = LightWallet::get_pk_from_seed(&seed_bytes);
|
||||||
|
|
||||||
LightWallet {
|
LightWallet {
|
||||||
extsks: [extsk],
|
seed: seed_bytes,
|
||||||
extfvks: [extfvk],
|
extsks: vec![extsk],
|
||||||
address,
|
extfvks: vec![extfvk],
|
||||||
|
address: vec![address],
|
||||||
blocks: Arc::new(RwLock::new(vec![])),
|
blocks: Arc::new(RwLock::new(vec![])),
|
||||||
txs: Arc::new(RwLock::new(HashMap::new())),
|
txs: Arc::new(RwLock::new(HashMap::new())),
|
||||||
}
|
}
|
||||||
@ -379,6 +410,21 @@ impl LightWallet {
|
|||||||
let version = reader.read_u64::<LittleEndian>()?;
|
let version = reader.read_u64::<LittleEndian>()?;
|
||||||
assert_eq!(version, LightWallet::serialized_version());
|
assert_eq!(version, LightWallet::serialized_version());
|
||||||
|
|
||||||
|
// Seed
|
||||||
|
let mut seed_bytes = [0u8; 32];
|
||||||
|
reader.read_exact(&mut seed_bytes)?;
|
||||||
|
|
||||||
|
// Read the spending keys
|
||||||
|
let extsks = Vector::read(&mut reader, |r| ExtendedSpendingKey::read(r))?;
|
||||||
|
|
||||||
|
// Calculate the viewing keys
|
||||||
|
let extfvks = extsks.iter().map(|sk| ExtendedFullViewingKey::from(sk))
|
||||||
|
.collect::<Vec<ExtendedFullViewingKey>>();
|
||||||
|
|
||||||
|
// Calculate the addresses
|
||||||
|
let addresses = extfvks.iter().map( |fvk| fvk.default_address().unwrap().1 )
|
||||||
|
.collect::<Vec<PaymentAddress<Bls12>>>();
|
||||||
|
|
||||||
let blocks = Vector::read(&mut reader, |r| BlockData::read(r))?;
|
let blocks = Vector::read(&mut reader, |r| BlockData::read(r))?;
|
||||||
|
|
||||||
let txs_tuples = Vector::read(&mut reader, |r| {
|
let txs_tuples = Vector::read(&mut reader, |r| {
|
||||||
@ -389,15 +435,11 @@ impl LightWallet {
|
|||||||
})?;
|
})?;
|
||||||
let txs = txs_tuples.into_iter().collect::<HashMap<TxId, WalletTx>>();
|
let txs = txs_tuples.into_iter().collect::<HashMap<TxId, WalletTx>>();
|
||||||
|
|
||||||
|
|
||||||
let extsk = ExtendedSpendingKey::master(&[1; 32]); // New key
|
|
||||||
let extfvk = ExtendedFullViewingKey::from(&extsk);
|
|
||||||
let address = extfvk.default_address().unwrap().1;
|
|
||||||
|
|
||||||
Ok(LightWallet{
|
Ok(LightWallet{
|
||||||
extsks: [extsk],
|
seed: seed_bytes,
|
||||||
extfvks: [extfvk],
|
extsks: extsks,
|
||||||
address,
|
extfvks: extfvks,
|
||||||
|
address: addresses,
|
||||||
blocks: Arc::new(RwLock::new(blocks)),
|
blocks: Arc::new(RwLock::new(blocks)),
|
||||||
txs: Arc::new(RwLock::new(txs))
|
txs: Arc::new(RwLock::new(txs))
|
||||||
})
|
})
|
||||||
@ -407,7 +449,13 @@ impl LightWallet {
|
|||||||
// Write the version
|
// Write the version
|
||||||
writer.write_u64::<LittleEndian>(LightWallet::serialized_version())?;
|
writer.write_u64::<LittleEndian>(LightWallet::serialized_version())?;
|
||||||
|
|
||||||
// TODO: Write the keys properly. Right now, they're just hardcoded
|
// Write the seed
|
||||||
|
writer.write_all(&self.seed)?;
|
||||||
|
|
||||||
|
// Write all the spending keys
|
||||||
|
Vector::write(&mut writer, &self.extsks,
|
||||||
|
|w, sk| sk.write(w)
|
||||||
|
)?;
|
||||||
|
|
||||||
Vector::write(&mut writer, &self.blocks.read().unwrap(), |w, b| b.write(w))?;
|
Vector::write(&mut writer, &self.blocks.read().unwrap(), |w, b| b.write(w))?;
|
||||||
|
|
||||||
@ -487,8 +535,8 @@ impl LightWallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn address(&self) -> String {
|
pub fn address(&self, account: usize) -> String {
|
||||||
encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &self.address)
|
encode_payment_address(HRP_SAPLING_PAYMENT_ADDRESS, &self.address[account])
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn balance(&self) -> u64 {
|
pub fn balance(&self) -> u64 {
|
||||||
|
Loading…
Reference in New Issue
Block a user