Browse Source

Add support for t addresses

duke
Aditya Kulkarni 5 years ago
parent
commit
01bc59dea5
  1. 4
      lib/Cargo.toml
  2. 49
      lib/src/paper.rs
  3. 4
      web/src/lib.rs
  4. 7
      web/www/index.html
  5. 22
      web/www/index.js

4
lib/Cargo.toml

@ -5,7 +5,7 @@ authors = ["ZecWallet"]
edition = "2018"
[features]
default = ["printpdf", "secp256k1"]
default = ["printpdf"]
[dependencies]
rand = "0.5"
@ -16,7 +16,7 @@ zcash_primitives = { git = "https://github.com/adityapk00/librustzcash", branch
json = "0.11.14"
qrcode = { version = "0.8", default-features = false }
printpdf = { version = "0.2.8", optional = true }
secp256k1 = { version = "0.13.0", features = ["rand"], optional = true }
libsecp256k1 = "0.2.2"
ripemd160 = "0.8.0"
sha2 = "0.8.0"
base58 = "0.1.0"

49
lib/src/paper.rs

@ -377,44 +377,49 @@ fn gen_addresses_with_seed_as_json<F>(is_testnet: bool, zcount: u32, tcount: u32
}
// Next generate the T addresses
#[cfg(feature = "secp256k1")]
{
// derive a RNG from the seed
let mut rng = ChaChaRng::from_seed(rng_seed);
for i in 0..tcount {
let (addr, pk_wif) = get_taddress(is_testnet, &mut rng);
ans.push(object!{
"num" => i,
"address" => addr,
"private_key" => pk_wif,
"type" => "taddr"
}).unwrap();
}
// derive a RNG from the seed
let mut rng = ChaChaRng::from_seed(rng_seed);
for i in 0..tcount {
let (addr, pk_wif) = get_taddress(is_testnet, &mut rng);
ans.push(object!{
"num" => i,
"address" => addr,
"private_key" => pk_wif,
"type" => "taddr"
}).unwrap();
}
return json::stringify_pretty(ans, 2);
}
/// Generate a t address
#[cfg(feature = "secp256k1")]
fn get_taddress(is_testnet: bool, mut rng: &mut ChaChaRng) -> (String, String) {
fn get_taddress(is_testnet: bool, rng: &mut ChaChaRng) -> (String, String) {
use secp256k1;
use ripemd160::{Ripemd160, Digest};
// SECP256k1 context
let ctx = secp256k1::Secp256k1::default();
let mut sk_bytes: [u8; 32] = [0;32];
let (sk, pubkey) = ctx.generate_keypair(&mut rng);
// There's a small chance the generated private key bytes are invalid, so
// we loop till we find bytes that are
let sk = loop {
rng.fill(&mut sk_bytes);
match secp256k1::SecretKey::parse(&sk_bytes) {
Ok(s) => break s,
Err(_) => continue
}
};
let pubkey = secp256k1::PublicKey::from_secret_key(&sk);
// Address
let mut hash160 = Ripemd160::new();
hash160.input(sha2::Sha256::digest(&pubkey.serialize().to_vec()));
hash160.input(sha2::Sha256::digest(&pubkey.serialize_compressed().to_vec()));
let addr = hash160.result().to_base58check(&params(is_testnet).taddress_version, &[]);
// Private Key
let sk_bytes: &[u8] = &sk[..];
let pk_wif = sk_bytes.to_base58check(&params(is_testnet).tsecret_prefix, &[0x01]);
return (addr, pk_wif);

4
web/src/lib.rs

@ -11,7 +11,7 @@ static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
#[wasm_bindgen]
pub fn get_wallet(zaddrs: u32, entropy: String) -> String {
let w = generate_wallet(false, false, zaddrs, 0, &double_sha256(entropy.as_bytes()));
pub fn get_wallet(zaddrs: u32, taddrs: u32, entropy: String) -> String {
let w = generate_wallet(false, false, zaddrs, taddrs, &double_sha256(entropy.as_bytes()));
return w;
}

7
web/www/index.html

@ -117,8 +117,11 @@
</div>
<div class="modal-body">
<div class="form-group">
<label for="numAddresses">Number of Addresses</label>
<input type="text" class="form-control" id="numAddresses" value="2" onkeypress="if ( isNaN( String.fromCharCode(event.keyCode) )) return false;">
<label for="numAddresses">Number of z Addresses</label>
<input type="text" class="form-control" id="numzAddresses" value="2" onkeypress="if ( isNaN( String.fromCharCode(event.keyCode) )) return false;">
<label for="numAddresses">Number of t Addresses</label>
<input type="text" class="form-control" id="numtAddresses" value="2" onkeypress="if ( isNaN( String.fromCharCode(event.keyCode) )) return false;">
</div>
<p>Move around your mouse or type random characters
into the box below until the bar is full.

22
web/www/index.js

@ -9,7 +9,13 @@ function add_section(wallet_item) {
let htmls = `
<div class="row address-section">
<div class="col-sm-9" style="word-break: break-word;">
<h1> Address (Sapling) </h1>
<h1> Address
${(() => {
if (wallet_item["address"].startsWith("z")) { return "(Sapling)"; }
else { return "(Transparent)"; }
}) ()
}
</h1>
<p class="fixed-width"> ${wallet_item["address"]} </p>
</div>
<div class="col-sm-3">
@ -36,7 +42,12 @@ function add_section(wallet_item) {
<br/>
<h2> Address </h2>
<p class="fixed-width"> ${wallet_item["address"]} </p>
<code> HD Key: ${wallet_item["seed"]["HDSeed"]}, path: ${wallet_item["seed"]["path"]} </code>
${(() => {
if (wallet_item.seed) {
return `<code> HD Key: ${wallet_item["seed"]["HDSeed"]}, path: ${wallet_item["seed"]["path"]} </code>`;
} else { return ""; }
}) ()
}
</div>
</div>
<div class='h-divider'></div>
@ -45,7 +56,7 @@ function add_section(wallet_item) {
jQuery("#wallet").append(pk_section);
QRCode.toCanvas(document.getElementById("qrcode_pk_"+address_number),
wallet_item["private_key"], {
scale: 3.5
scale: wallet_item["private_key"].length < 60 ? 6.5 : 3.5
});
address_number++;
@ -124,13 +135,14 @@ jQuery("#configdialog").on("hidden.bs.modal", function (e) {
window.crypto.getRandomValues(buf);
let system_entropy = toHexString(buf);
let numAddresses = jQuery("#numAddresses").val();
let numzAddresses = jQuery("#numzAddresses").val();
let numtAddresses = jQuery("#numtAddresses").val();
jQuery("#pleasewait").modal('show');
// Run this async so that the please wait dialog can show
setTimeout(() => {
let w = JSON.parse(wasm.get_wallet(numAddresses, user_entropy + system_entropy));
let w = JSON.parse(wasm.get_wallet(numzAddresses, numtAddresses, user_entropy + system_entropy));
w.forEach(wallet_item => {
add_section(wallet_item);

Loading…
Cancel
Save