Browse Source

Merge branch 'master' into dev

dev
Duke Leto 2 years ago
parent
commit
ed7db3c0ea
  1. 1
      AUTHORS
  2. 2
      LICENSE
  3. 113
      README.md
  4. 0
      SilentDragonPaper.png
  5. 41
      build.sh
  6. 1
      cli/.gitignore
  7. 8
      cli/Cargo.toml
  8. 58
      cli/mkrelease.sh
  9. 39
      cli/src/main.rs
  10. 2
      cli/src/version.rs
  11. BIN
      docs/paperwallet.png
  12. 10
      lib/Cargo.toml
  13. 242
      lib/src/paper.rs
  14. 110
      lib/src/pdf.rs
  15. 20
      ui/mkdockerwinlinux.sh
  16. 12
      ui/papersapling.pro
  17. 4
      ui/qtlib/Cargo.toml
  18. 12
      ui/qtlib/Makefile
  19. 2
      ui/qtlib/src/lib.rs
  20. 10
      ui/src/about.ui
  21. 9
      ui/src/main.cpp
  22. 14
      ui/src/mainwindow.cpp

1
AUTHORS

@ -1,3 +1,4 @@
# The Hush Developers
Duke Leto https://github.com/leto
Jah Way https://git.hush.is/jahway603 https://github.com/jahway603

2
LICENSE

@ -616,4 +616,4 @@ above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
copy of the Program in return for a fee.

113
README.md

@ -1,80 +1,117 @@
# hushpaperwallet
hushpaperwallet is a paper wallet generator that can run completely offline.
# SilentDragonPaper
<p align="left">
<a href="https://twitter.com/MyHushTeam">
<img src="https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2Fmyhushteam"
alt="MyHushTeam's Twitter"></a>
<a href="https://twitter.com/intent/follow?screen_name=MyHushTeam">
<img src="https://img.shields.io/twitter/follow/MyHushTeam?style=social&logo=twitter"
alt="follow on Twitter"></a>
<a href="https://fosstodon.org/@myhushteam">
<img src="https://img.shields.io/badge/Mastodon-MyHushTeam-blue"
alt="follow on Mastodon"></a>
<a href="https://www.reddit.com/r/Myhush/">
<img src="https://img.shields.io/reddit/subreddit-subscribers/Myhush?style=social"
alt="MyHushTeam's Reddit"></a>
</p>
SilentDragonPaper is a paper wallet generator that can run completely offline.
You can run it on an air-gapped computer to generate your shielded z-addresses, which will allow you to keep your keys completely offline.
*Example:*
![screenshot](hushpaperwallet.png?raw=true)
![screenshot](SilentDragonPaper.png?raw=true)
# Download
hushpaperwallet is available as pre-built binaries from our [release page](https://github.com/MyHush/hushpaperwallet/releases). Download the zip file for your platform, extract it and run the `./hushpaperwallet` binary.
## Download
# Generating wallets
To generate a Hush paper wallet, simply run `./hushpaperwallet`
### Binary installation
SilentDragonPaper is available as pre-built binaries from our [release page](https://git.hush.is/hush/SilentDragonPaper/releases). Download the zip file for your platform, extract it and run the `./SilentDragonPaper` binary.
You'll be asked to type some random characters that will add entropy to the random number generator. Run with `--help` to see all options
### Source code installation
If you decide to compile from source, then first use git to get the source code as follows:
```
git clone https://git.hush.is/hush/SilentDragonPaper
```
Then choose one of these two source compilation options to build the SilentDragonPaper CLI.
#### Recommended Option : Compile using "embedded" rust
## Saving as PDFs
To generate a Hush paper wallet and save it as a PDF, run
Here we do not need a system installed Rust to compile. The build.sh script pulls Rust version 1.48 down for us and builds with it.
```
./hushpaperwallet -z 3 --format pdf hushpaper-output.pdf
cd SilentDragonPaper
./build.sh
```
This will generate 3 shielded z-addresses and their corresponding private keys, and save them in a PDF file called `hushpaper-output.pdf`
#### Advanced Option : Compile using system installed rust
## Vanity Addresses
SilentDragonPaper is built with Rust. To compile from source, you must [install Rust 1.48](https://www.rust-lang.org/tools/install).
Older versions of Rust may work, newer versions will not.
You can generate a "vanity address" (that is, an address starting with a given prefix) by specifying a `--vanity` argument with the prefix you want.
```
cd SilentDragonPaper/cli
cargo build --release
```
Note that generating vanity addresses with a prefix longer than 4-5 characters is computationally expensive. You can run it on multiple CPUs on your computer by specifying the `--threads` option.
# Compiling from Source
#### Compiled binary location
The completed binary is available in the `cli/target/release` folder.
hushpaperwallet is built with rust. To compile from source, you [install Rust](https://www.rust-lang.org/tools/install).
## Usage Instructions
Checkout the hushpaperwallet repository and build the CLI
### Generating wallets
To generate a Hush paper wallet, simply run `./SilentDragonPaper` or `./target/release/SilentDragonPaper` or `./cli/target/release/SilentDragonPaper` depending on method you used to install.
You'll be asked to type some random characters that will add entropy to the random number generator. Run with `--help` to see all options
### Saving as PDFs
To generate a Hush paper wallet and save it as a PDF, run:
```
git clone https://github.com/MyHush/hushpaperwallet.git
cd hushpaperwallet/cli
cargo build --release
./SilentDragonPaper -z 3 --format pdf sdp.pdf
```
The binary is available in the `target/release` folder.
This will generate 3 shielded z-addresses and their corresponding private keys, and save them in a PDF file called `sdp.pdf`
### Vanity Addresses
You can generate a "vanity address" (that is, an address starting with a given prefix) by specifying a `--vanity` argument with the prefix you want.
Note that generating vanity addresses with a prefix longer than 4-5 characters is computationally expensive. You can run it on multiple CPUs on your computer by specifying the `--threads` option.
## Ensuring Security
When generating paper wallets that will store large amounts of crypto, please take special care to ensure the keys are generated and kept completely offline.
1. `hushpaperwallet` supports ARMv8 (Raspberry Pi 3+). You can put one in a Faraday cage along with a printer, and print out the PDFs securely.
2. Please ensure you supply random entropy when you run `hushpaperwallet`. Your entropy is mixed in with system-provided entropy to generate keys
1. `SilentDragonPaper` supports ARMv8 (Raspberry Pi 3+). You can put one in a Faraday cage along with a printer, and print out the PDFs securely.
2. Please ensure you supply random entropy when you run `SilentDragonPaper`. Your entropy is mixed in with system-provided entropy to generate keys
3. If you can, run with `unshare`, which will disable all network interfaces to a process, providing you with an additional layer of safety. (See next section)
4. After you've generated the keys, you can tear off the Address potion of the wallet and take it to your online computer/phone to send the address funds. Please always keep the private key offline.
5. When you're ready to spend the cold storage keys, import the private key into a full node, then don't re-use the key again.
### Run without network
If you are running a newish version of Linux, you can be doubly sure that the process is not contacting the network by running hushpaperwallet without the network namespace.
If you are running a newish version of Linux, you can be doubly sure that the process is not contacting the network by running SilentDragonPaper without the network namespace.
```
sudo unshare -n ./target/release/hushpaperwallet
sudo unshare -n ./target/release/SilentDragonPaper
```
`unshare -n` runs the process without a network interface which means you can be sure that your data is not being sent across the network.
## Help options
```
USAGE:
hushpaperwallet [FLAGS] [OPTIONS] [output]
SilentDragonPaper [FLAGS] [OPTIONS] [output]
FLAGS:
-h, --help Prints help information
-n, --nohd Don't reuse HD keys. Normally, hushpaperwallet will use the same HD key to derive multiple
-n, --nohd Don't reuse HD keys. Normally, SilentDragonPaper will use the same HD key to derive multiple
addresses. This flag will use a new seed for each address
--testnet Generate Testnet addresses
-V, --version Prints version information
OPTIONS:
@ -84,22 +121,28 @@ OPTIONS:
-t, --taddrs <t_addresses> Numbe rof T addresses to generate [default: 0]
--threads <threads> Number of threads to use for the vanity address generator. Set this to the number of
CPUs you have [default: 1]
--vanity <vanity> Generate a vanity address with the given prefix
--vanity <vanity> Generate a vanity address with the given prefix.
Note that ['b', 'i', 'o', '1'] are not allowed in addresses.
-z, --zaddrs <z_addresses> Number of Z addresses (Sapling) to generate [default: 1]
ARGS:
<output> Name of output file.
```
## Support
For support join us on [Telegram Support](https://hush.is/telegram_support), or our [Main Telegram](https://hush.is/telegram) or tweet at [@MyHushTeam](https://twitter.com/MyHushTeam), or toot at our [Mastodon](https://fosstodon.org/@myhushteam), or [file an issue](https://git.hush.is/hush/SilentDragonPaper/issues).
## Copyright
Released under the GNU Public License Version 3.
Released under the [GNU Public License Version 3](https://www.gnu.org/licenses/gpl-3.0.en.html) or later.
Copyright (c) 2019-2021 The Hush Developers
Copyright (c) 2019-2020 The Hush Developers
Copyright (c) 2019 adityapk00
## License
GPLv3.
GPLv3 or later.
See [LICENSE] file for details.
See [LICENSE](LICENSE) file for details.

0
hushpaperwallet.png → SilentDragonPaper.png

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

41
build.sh

@ -0,0 +1,41 @@
#!/bin/bash
# Copyright (c) 2016-2021 The Hush developers
# Distributed under the GPLv3 software license, see the accompanying
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
set -eu -o pipefail
# TODO: find elite Rust coders to update our shit
# to work on modern versions of rustc, lulz
PREFIX=rust-1.48.0-x86_64-unknown-linux-gnu
FILE=$PREFIX.tar.gz
SHA=950420a35b2dd9091f1b93a9ccd5abc026ca7112e667f246b1deb79204e2038b
if [ ! -f "$FILE" ]; then
wget https://static.rust-lang.org/dist/$FILE
fi
# Verify SHA256 of rust
echo "$SHA $FILE" | shasum -a 256 --check
# TWO SPACES or sadness sometimes:
# https://unix.stackexchange.com/questions/139891/why-does-verifying-sha256-checksum-with-sha256sum-fail-on-debian-and-work-on-u
echo "$SHA $FILE" | shasum -a 256 --check --status
if [ $? -ne 0 ]; then
FOUNDSHA=$(shasum -a 256 $FILE)
echo "SHA256 mismatch on $FILE!"
echo "$FOUNDSHA did not match $SHA . Aborting..."
exit 1
fi
tar zxvpf $FILE
mkdir -p build
cd $PREFIX
./install.sh --prefix=$(pwd)/../build
cd ../cli
PATH=$(pwd)/../build/bin/:$PATH
echo PATH=$PATH
cargo --version
rustc --version
../build/bin/cargo build --verbose --release

1
cli/.gitignore

@ -1,3 +1,2 @@
.vscode
test_working.pdf
target/

8
cli/Cargo.toml

@ -1,6 +1,6 @@
[package]
name = "hushpaperwallet"
version = "0.1.1"
name = "SilentDragonPaper"
version = "0.2.0"
authors = [
"ZecWallet",
"The Hush developers"
@ -9,6 +9,6 @@ edition = "2018"
[dependencies]
clap = "2.33.0"
hushpaperlib = { path = "../lib" }
silentdragonpaper = { path = "../lib" }
json = "0.11.14"
printpdf = "0.3.2"
printpdf = "0.3.2"

58
cli/mkrelease.sh

@ -32,58 +32,58 @@ cargo clean
cargo build --release
# macOS
rm -rf target/macOS-hushpaperwallet-v$APP_VERSION
mkdir -p target/macOS-hushpaperwallet-v$APP_VERSION
cp target/release/hushpaperwallet target/macOS-hushpaperwallet-v$APP_VERSION/
rm -rf target/macOS-silentdragonpaper-v$APP_VERSION
mkdir -p target/macOS-silentdragonpaper-v$APP_VERSION
cp target/release/silentdragonpaper target/macOS-silentdragonpaper-v$APP_VERSION/
# For Windows and Linux, build via docker
docker run --rm -v $(pwd)/..:/opt/hushpaperwallet rustbuild:latest bash -c "cd /opt/hushpaperwallet/cli && cargo build --release && cargo build --release --target x86_64-pc-windows-gnu && cargo build --release --target aarch64-unknown-linux-gnu"
docker run --rm -v $(pwd)/..:/opt/silentdragonpaper rustbuild:latest bash -c "cd /opt/silentdragonpaper/cli && cargo build --release && cargo build --release --target x86_64-pc-windows-gnu && cargo build --release --target aarch64-unknown-linux-gnu"
# Now sign and zip the binaries
gpg --batch --output target/macOS-hushpaperwallet-v$APP_VERSION/hushpaperwallet.sig --detach-sig target/macOS-hushpaperwallet-v$APP_VERSION/hushpaperwallet
gpg --batch --output target/macOS-silentdragonpaper-v$APP_VERSION/silentdragonpaper.sig --detach-sig target/macOS-silentdragonpaper-v$APP_VERSION/silentdragonpaper
cd target
cd macOS-hushpaperwallet-v$APP_VERSION
gsha256sum hushpaperwallet > sha256sum.txt
cd macOS-silentdragonpaper-v$APP_VERSION
gsha256sum silentdragonpaper > sha256sum.txt
cd ..
zip -r macOS-hushpaperwallet-v$APP_VERSION.zip macOS-hushpaperwallet-v$APP_VERSION
zip -r macOS-silentdragonpaper-v$APP_VERSION.zip macOS-silentdragonpaper-v$APP_VERSION
cd ..
#Linux
rm -rf target/linux-hushpaperwallet-v$APP_VERSION
mkdir -p target/linux-hushpaperwallet-v$APP_VERSION
cp target/release/hushpaperwallet target/linux-hushpaperwallet-v$APP_VERSION/
gpg --batch --output target/linux-hushpaperwallet-v$APP_VERSION/hushpaperwallet.sig --detach-sig target/linux-hushpaperwallet-v$APP_VERSION/hushpaperwallet
rm -rf target/linux-silentdragonpaper-v$APP_VERSION
mkdir -p target/linux-silentdragonpaper-v$APP_VERSION
cp target/release/silentdragonpaper target/linux-silentdragonpaper-v$APP_VERSION/
gpg --batch --output target/linux-silentdragonpaper-v$APP_VERSION/silentdragonpaper.sig --detach-sig target/linux-silentdragonpaper-v$APP_VERSION/silentdragonpaper
cd target
cd linux-hushpaperwallet-v$APP_VERSION
gsha256sum hushpaperwallet > sha256sum.txt
cd linux-silentdragonpaper-v$APP_VERSION
gsha256sum silentdragonpaper > sha256sum.txt
cd ..
zip -r linux-hushpaperwallet-v$APP_VERSION.zip linux-hushpaperwallet-v$APP_VERSION
zip -r linux-silentdragonpaper-v$APP_VERSION.zip linux-silentdragonpaper-v$APP_VERSION
cd ..
#Windows
rm -rf target/Windows-hushpaperwallet-v$APP_VERSION
mkdir -p target/Windows-hushpaperwallet-v$APP_VERSION
cp target/x86_64-pc-windows-gnu/release/hushpaperwallet.exe target/Windows-hushpaperwallet-v$APP_VERSION/
gpg --batch --output target/Windows-hushpaperwallet-v$APP_VERSION/hushpaperwallet.sig --detach-sig target/Windows-hushpaperwallet-v$APP_VERSION/hushpaperwallet.exe
rm -rf target/Windows-silentdragonpaper-v$APP_VERSION
mkdir -p target/Windows-silentdragonpaper-v$APP_VERSION
cp target/x86_64-pc-windows-gnu/release/silentdragonpaper.exe target/Windows-silentdragonpaper-v$APP_VERSION/
gpg --batch --output target/Windows-silentdragonpaper-v$APP_VERSION/silentdragonpaper.sig --detach-sig target/Windows-silentdragonpaper-v$APP_VERSION/silentdragonpaper.exe
cd target
cd Windows-hushpaperwallet-v$APP_VERSION
gsha256sum hushpaperwallet.exe > sha256sum.txt
cd Windows-silentdragonpaper-v$APP_VERSION
gsha256sum silentdragonpaper.exe > sha256sum.txt
cd ..
zip -r Windows-hushpaperwallet-v$APP_VERSION.zip Windows-hushpaperwallet-v$APP_VERSION
zip -r Windows-silentdragonpaper-v$APP_VERSION.zip Windows-silentdragonpaper-v$APP_VERSION
cd ..
# aarch64 (armv8)
rm -rf target/aarch64-hushpaperwallet-v$APP_VERSION
mkdir -p target/aarch64-hushpaperwallet-v$APP_VERSION
cp target/aarch64-unknown-linux-gnu/release/hushpaperwallet target/aarch64-hushpaperwallet-v$APP_VERSION/
gpg --batch --output target/aarch64-hushpaperwallet-v$APP_VERSION/hushpaperwallet.sig --detach-sig target/aarch64-hushpaperwallet-v$APP_VERSION/hushpaperwallet
rm -rf target/aarch64-silentdragonpaper-v$APP_VERSION
mkdir -p target/aarch64-silentdragonpaper-v$APP_VERSION
cp target/aarch64-unknown-linux-gnu/release/silentdragonpaper target/aarch64-silentdragonpaper-v$APP_VERSION/
gpg --batch --output target/aarch64-silentdragonpaper-v$APP_VERSION/silentdragonpaper.sig --detach-sig target/aarch64-silentdragonpaper-v$APP_VERSION/silentdragonpaper
cd target
cd aarch64-hushpaperwallet-v$APP_VERSION
gsha256sum hushpaperwallet > sha256sum.txt
cd aarch64-silentdragonpaper-v$APP_VERSION
gsha256sum silentdragonpaper > sha256sum.txt
cd ..
zip -r aarch64-hushpaperwallet-v$APP_VERSION.zip aarch64-hushpaperwallet-v$APP_VERSION
zip -r aarch64-silentdragonpaper-v$APP_VERSION.zip aarch64-silentdragonpaper-v$APP_VERSION
cd ..

39
cli/src/main.rs

@ -1,16 +1,16 @@
extern crate clap;
extern crate hushpaperlib;
extern crate silentdragonpaper;
mod version;
use clap::{Arg, App};
use hushpaperlib::paper::*;
use hushpaperlib::pdf;
use silentdragonpaper::paper::*;
use silentdragonpaper::pdf;
use std::io;
use std::io::prelude::*;
fn main() {
let matches = App::new("hushpaperwaller")
let matches = App::new("SilentDragonPaper")
.version(version::version())
.about("A command line Hush paper wallet generator")
.arg(Arg::with_name("format")
@ -24,7 +24,7 @@ fn main() {
.arg(Arg::with_name("nohd")
.short("n")
.long("nohd")
.help("Don't reuse HD keys. Normally, hushpaperwallet will use the same HD key to derive multiple addresses. This flag will use a new seed for each address"))
.help("Don't reuse HD keys. Normally, SilentDragonPaper will use the same HD key to derive multiple addresses. This flag will use a new seed for each address"))
.arg(Arg::with_name("output")
.short("o")
.long("output")
@ -37,7 +37,7 @@ fn main() {
.help("Provide additional entropy to the random number generator. Any random string, containing 32-64 characters"))
.arg(Arg::with_name("vanity_prefix")
.long("vanity")
.help("Generate a vanity address with the given prefix")
.help("Generate a vanity address with the given prefix. Note that ['b', 'i', 'o', '1'] are not allowed in addresses.")
.takes_value(true))
.arg(Arg::with_name("threads")
.long("threads")
@ -47,7 +47,7 @@ fn main() {
.arg(Arg::with_name("t_addresses")
.short("t")
.long("taddrs")
.help("Numbe rof T addresses to generate")
.help("Number of t-addresses to generate")
.takes_value(true)
.default_value("0")
.validator(|i:String| match i.parse::<i32>() {
@ -57,7 +57,7 @@ fn main() {
.arg(Arg::with_name("z_addresses")
.short("z")
.long("zaddrs")
.help("Number of Z addresses (Sapling) to generate")
.help("Number of z-addresses (Sapling) to generate")
.takes_value(true)
.default_value("1")
.validator(|i:String| match i.parse::<i32>() {
@ -78,16 +78,6 @@ fn main() {
return;
}
// Get the filename and output format
let filename = matches.value_of("output");
let format = matches.value_of("format").unwrap();
// Writing to PDF requires a filename
if format == "pdf" && filename.is_none() {
eprintln!("Need an output file name when writing to PDF");
return;
}
// Number of t addresses to generate
let t_addresses = matches.value_of("t_addresses").unwrap().parse::<u32>().unwrap();
@ -96,19 +86,19 @@ fn main() {
let addresses = if !matches.value_of("vanity_prefix").is_none() {
if z_addresses != 1 {
eprintln!("Can only generate 1 zaddress in vanity mode. You specified {}", z_addresses);
eprintln!("Can only generate 1 z-address in vanity mode. You specified {}", z_addresses);
return;
}
if t_addresses != 0 {
eprintln!("Can't generate vanity t-addressses yet");
eprintln!("Can't generate vanity t-addresses yet");
return;
}
let num_threads = matches.value_of("threads").unwrap().parse::<u32>().unwrap();
let prefix = matches.value_of("vanity_prefix").unwrap().to_string();
println!("Generating address starting with \"{}\"", prefix);
println!("Generating z-address starting with \"{}\"...", prefix);
let addresses = match generate_vanity_wallet(num_threads, prefix) {
Ok(w) => w,
Err(e) => {
@ -125,7 +115,8 @@ fn main() {
// If the user hasn't specified any, read from the stdin
if matches.value_of("entropy").is_none() {
// Read from stdin
println!("Provide additional entropy for generating random numbers. Type in a string of random characters, press [ENTER] when done");
println!("Provide additional entropy for generating random numbers.
Type in a string of random characters, press [ENTER] when done.");
let mut buffer = String::new();
let stdin = io::stdin();
stdin.lock().read_line(&mut buffer).unwrap();
@ -136,7 +127,7 @@ fn main() {
entropy.extend(matches.value_of("entropy").unwrap().as_bytes());
}
print!("Generating {} Sapling addresses and {} Transparent addresses...", z_addresses, t_addresses);
print!("Generating {} z-addresses and {} t-addresses...", z_addresses, t_addresses);
io::stdout().flush().ok();
let addresses = generate_wallet(nohd, z_addresses, t_addresses, &entropy);
println!("[OK]");
@ -164,4 +155,4 @@ fn main() {
}
};
}
}
}

2
cli/src/version.rs

@ -1 +1 @@
pub fn version() -> &'static str { &"0.1.1" }
pub fn version() -> &'static str { &"0.1.3" }

BIN
docs/paperwallet.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

10
lib/Cargo.toml

@ -1,9 +1,9 @@
[package]
name = "hushpaperlib"
version = "0.1.1"
name = "silentdragonpaper"
version = "0.2.0"
authors = [
"ZecWallet",
"The Hush developers"
"The Hush developers",
"ZecWallet"
]
edition = "2018"
@ -14,7 +14,7 @@ default = ["printpdf"]
rand = "0.5"
hex = "0.3"
bech32 = "0.6"
zcash_primitives = { git = "https://github.com/gilardh/librustzcash", rev = "5a48d179b8434a0318e7e19dda506e245a904092" }
zcash_primitives = { git = "https://git.hush.is/hush/librustzcash", rev = "5a48d179b8434a0318e7e19dda506e245a904092" }
json = "0.11.14"
qrcode = { version = "0.8", default-features = false }
printpdf = { version = "0.3.2", optional = true }

242
lib/src/paper.rs

@ -30,7 +30,7 @@ impl ToBase58Check for [u8] {
payload.extend_from_slice(self);
payload.extend_from_slice(suffix);
let mut checksum = double_sha256(&payload);
let checksum = double_sha256(&payload);
payload.append(&mut checksum[..4].to_vec());
payload.to_base58()
}
@ -43,11 +43,11 @@ pub fn double_sha256(payload: &[u8]) -> Vec<u8> {
h2.to_vec()
}
/// Parameters used to generate addresses and private keys. Look in chainparams.cpp (in zcashd/src)
/// Parameters used to generate addresses and private keys. Look in chainparams.cpp in hush3.git
/// to get these values.
/// Usually these will be different for testnet and for mainnet.
pub struct CoinParams {
pub taddress_version: [u8; 2],
pub taddress_version: [u8; 1],
pub tsecret_prefix : [u8; 1],
pub zaddress_prefix : String,
pub zsecret_prefix : String,
@ -57,8 +57,8 @@ pub struct CoinParams {
pub fn params() -> CoinParams {
CoinParams {
taddress_version : [0x1C, 0xB8],
tsecret_prefix : [0x80],
taddress_version : [0x3c],
tsecret_prefix : [0xBC],
zaddress_prefix : "zs".to_string(),
zsecret_prefix : "secret-extended-key-main".to_string(),
zviewkey_prefix : "zviews".to_string(),
@ -439,235 +439,3 @@ fn get_zaddress(seed: &[u8], index: u32) -> (String, String, String, json::JsonV
return (encoded, encoded_pk, encoded_vk, path);
}
// Tests
#[cfg(test)]
mod tests {
/// Test the wallet generation and that it is generating the right number and type of addresses
#[test]
fn test_wallet_generation() {
use crate::paper::generate_wallet;
use std::collections::HashSet;
// Mainnet wallet
let w = generate_wallet(false, 1, 0, &[]);
let j = json::parse(&w).unwrap();
assert_eq!(j.len(), 1);
assert!(j[0]["address"].as_str().unwrap().starts_with("zs"));
assert!(j[0]["private_key"].as_str().unwrap().starts_with("secret-extended-key-main"));
assert_eq!(j[0]["seed"]["path"].as_str().unwrap(), "m/32'/133'/0'");
// Check if all the addresses are the same
let w = generate_wallet(false, 3, 0, &[]);
let j = json::parse(&w).unwrap();
assert_eq!(j.len(), 3);
let mut set1 = HashSet::new();
let mut set2 = HashSet::new();
for i in 0..3 {
assert!(j[i]["address"].as_str().unwrap().starts_with("ztestsapling"));
assert_eq!(j[i]["seed"]["path"].as_str().unwrap(), format!("m/32'/1'/{}'", i).as_str());
set1.insert(j[i]["address"].as_str().unwrap());
set1.insert(j[i]["private_key"].as_str().unwrap());
set2.insert(j[i]["seed"]["HDSeed"].as_str().unwrap());
}
// There should be 3 + 3 distinct addresses and private keys
assert_eq!(set1.len(), 6);
// ...but only 1 seed
assert_eq!(set2.len(), 1);
}
#[test]
fn test_z_encoding() {
use crate::paper::{encode_address, encode_privatekey};
use zcash_primitives::zip32::ExtendedSpendingKey;
let main_data = "[
{'encoded' : '037d54cb810000008079a0d98ee64814bffe3f78e0b67363bdcdfd57b6a9a8f871615884ef79a001fdc59be1b24f5d75beed619d2eb3722a5f7f9d9c9e13f6c0218cd10bffe5ec0c0b21d65ad27ac913dfcd2d40425345d49c09e4fed60555a5f3346d76ed45906004f4c2cc6098f0780b9adaa0b1636976dcd8d6311812ef42f073d506ae19bbe4ff7501070410c512af68ed0141e146c69af666fe2efdeb804df33e3304ce07a0bb', 'address' : 'zs1ttwlzs7nnmdwmx7eag3k4szxzvsa82ttsakmux5zk0y9vcqp4jguecn5rqkjjdae2pgzcta4vkt', 'pk' : 'secret-extended-key-main1qd74fjupqqqqpqre5rvcaejgzjllu0mcuzm8xcaaeh740d4f4ru8zc2csnhhngqplhzehcdjfawht0hdvxwjavmj9f0hl8vuncfldspp3ngshll9asxqkgwkttf84jgnmlxj6szz2dzaf8qfunldvp245hengmtka4zeqcqy7npvccyc7puqhxk65zckx6tkmnvdvvgczth59urn65r2uxdmunlh2qg8qsgv2y40drkszs0pgmrf4anxlch0m6uqfhenuvcyecr6pwcvt7qwu'},
{'encoded' : '03747bda750000008090dd234894f208a53bec30461e9a1abe6c9ecce833b2110132576d4b135dee0cd328312ba73ae04a05e79fd81ba7d57bb4bc0a9a7a7a11ca904b604f9be62f0ea011906ac33e3dbbc0983228ed3c334373873d6bc309054c24538c93c3677e0332c848dadbee9308fe0d37241aa6e34541e3837a272a4d08e30ac1470ef389c46370ae1ca72bb87488bcfa8cb26040604ef3dd8c2a8590e3f05ee771ba6d7e89', 'address' : 'zs1ttryt8fh0hu74upauprpglddcm3avmclnr2ywsxzhpqgchcd29xyqtvpqx7wktvx94cg6522ldy', 'pk' : 'secret-extended-key-main1qd68hkn4qqqqpqysm535398jpzjnhmpsgc0f5x47dj0ve6pnkggszvjhd493xh0wpnfjsvft5uawqjs9u70asxa864amf0q2nfa85yw2jp9kqnumuchsagq3jp4vx03ah0qfsv3ga57rxsmnsu7khscfq4xzg5uvj0pkwlsrxtyy3kkma6fs3lsdxujp4fhrg4q78qm6yu4y6z8rptq5wrhn38zxxu9wrjnjhwr53z704r9jvpqxqnhnmkxz4pvsu0c9aem3hfkhazgksps0h'}
]";
let j = json::parse(&main_data.replace("'", "\"")).unwrap();
for i in j.members() {
let e = hex::decode(i["encoded"].as_str().unwrap()).unwrap();
let spk = ExtendedSpendingKey::read(&e[..]).unwrap();
assert_eq!(encode_address(&spk, false), i["address"]);
assert_eq!(encode_privatekey(&spk, false), i["pk"]);
}
let test_data = "[
{'encoded' : '03f577d7b800000080b9ae0ce9f44f7b3550e14f4662e91270b04b265ff4ba4546be72feef91b38d3397b3d25a79d67fa024a1b0d3f4d5143eff3e410c300bf615090dbdbddea6b70302bb8b73449cafa1ce1862bd4af31db2d468e39c451cfb026128ea3abe6b820ccb1b8e3a4e6faccef50f9f3c02a5cd55d9faebc4939d6d5f5271b8a66d73f443ec546c3cf583dccfed7994e856cd462a0a199cf6c89bdbe6b38c721dc07637ea', 'address' : 'ztestsapling1tsurvgycuy5me2nds2jpug806nr954ts3h3mf2de925qp8t9tyhvg0sfhe0qp3jf02vfxk3thn0', 'pk' : 'secret-extended-key-test1q06h04acqqqqpq9e4cxwnaz00v64pc20ge3wjynskp9jvhl5hfz5d0njlmhervudxwtm85j608t8lgpy5xcd8ax4zsl070jppscqhas4pyxmm0w756msxq4m3de5f890588psc4afte3mvk5dr3ec3gulvpxz28282lxhqsvevdcuwjwd7kvaag0nu7q9fwd2hvl467yjwwk6h6jwxu2vmtn73p7c4rv8n6c8hx0a4uef6zke4rz5zsennmv3x7mu6eccusacpmr06sjxk88k'},
{'encoded' : '036b781dfd000000808956fba285802d5cebf5a24142c957877fa9a6182c57d24ab394e47eafc6c781750bcb2630ce11a90faf0e976d3898255a509e049d2332de9f332e254e91770ce45c085da9b55e108b5eaef45e68ab32bb9e461fe2356ea375258377044d190b1a630c1d1471d6cbc98b9e6dc779472a797d3cfcaf3dfbe5e878dbeae58e8a48347e48cf93de87f63aa3803556e9632e97a27374aef2988205ddcf69da12c95e', 'address' : 'ztestsapling1tscd2ap27tt4eg42m3k76ahg9gxgqf0lk8ls2tsxegkf7s050v9agccg0jg2s4ja4vkvccas270', 'pk' : 'secret-extended-key-test1qd4hs80aqqqqpqyf2ma69pvq94wwhadzg9pvj4u80756vxpv2lfy4vu5u3l2l3k8s96shjexxr8pr2g04u8fwmfcnqj455y7qjwjxvk7nuejuf2wj9mseezuppw6nd27zz94ath5te52kv4mnerplc34d63h2fvrwuzy6xgtrf3sc8g5w8tvhjvtnekuw7289fuh608u4u7lhe0g0rd74evw3fyrgljge7faaplk823cqd2ka93ja9azwd62au5csgzamnmfmgfvjhs68k0x5'},
{'encoded' : '033d5066140000008099cfb65ab46e5a0e3f6891c1480fdb2f36f2fa02d75cfebb04e06513e4eaa148978f54f4e9fee05464a1574debae01ec1bd53c4c7ac4fd49414e4ab05b18a502c420031918f93c8756f054cdd134dabf36941b59f839761f2339b9d88a2d68073e53dce94d94c5118141179d1fb38f62705a3c1d27d2bb86bd0824cf72ac07d2095a13bd31975c706a7ec3e65310851363c658b76f3ac45484b4015ae93f0556', 'address' : 'ztestsapling1ts9afgw2k67qewv7wr08upf4wxe3m82u6fz432jpar7h48k60w4ksuereawhszsd0xvjyc5a5u0', 'pk' : 'secret-extended-key-test1qv74qes5qqqqpqyee7m94drwtg8r76y3c9yqlke0xme05qkhtnltkp8qv5f7f64pfztc7485a8lwq4ry59t5m6awq8kph4fuf3avfl2fg98y4vzmrzjs93pqqvv337fusat0q4xd6y6d40ekjsd4n7pewc0jxwdemz9z66q88efae62djnz3rq2pz7w3lvu0vfc950qaylfthp4apqjv7u4vqlfqjksnh5cewhrsdflv8ejnzzz3xc7xtzmk7wky2jztgq26ayls24srxx9hw'},
{'encoded' : '03a19d13b700000080ff5f4ec78697bd786cb6dfe2e8cc57fd9cd4ad7f87bb9a92607cbf23122082e6c00e3eceb438a739738262e1ac3eabdb1d9c0a44b45b759939d159739b29880ba4437024a134269e16cd9a859f86854d5ea237e542f700805364a6d0515ac70a2fed943bef0430025c4d2895b780bbe08c659e37f3d60336c1cbc0bb17bb2488d7c6b55585b0743600826e333bd058b3fed68b02228efaa94b0f6eadf0fc7b68', 'address' : 'ztestsapling1ts8mqy2kvn7j3ktj9ean07tl0wktqnv6e5amrv92x2yenlx4hxc6tmktewc79mk0wlmkxh9fh4q', 'pk' : 'secret-extended-key-test1qwse6yahqqqqpq8lta8v0p5hh4uxedklut5vc4lann226lu8hwdfycruhu33ygyzumqqu0kwksu2wwtnsf3wrtp740d3m8q2gj69kave88g4juum9xyqhfzrwqj2zdpxnctvmx59n7rg2n275gm72shhqzq9xe9x6pg443c29lkegwl0qscqyhzd9z2m0q9muzxxt83h70tqxdkpe0qtk9amyjyd03442kzmqapkqzpxuvem6pvt8lkk3vpz9rh6499s7m4d7r78k6qa4j49t'}
]";
let j = json::parse(&test_data.replace("'", "\"")).unwrap();
for i in j.members() {
let e = hex::decode(i["encoded"].as_str().unwrap()).unwrap();
let spk = ExtendedSpendingKey::read(&e[..]).unwrap();
assert_eq!(encode_address(&spk, true), i["address"]);
assert_eq!(encode_privatekey(&spk, true), i["pk"]);
}
}
#[test]
fn test_entroy() {
use crate::paper::generate_wallet;
use crate::paper::generate_vanity_wallet;
// Testnet wallet 1
let w1 = generate_wallet(true, false, 1, 1, &[0; 32]);
let j1 = json::parse(&w1).unwrap();
assert_eq!(j1.len(), 2);
// Testnet wallet 2, same user_entropy
let w2 = generate_wallet(true, false, 1, 1, &[0; 32]);
let j2 = json::parse(&w2).unwrap();
assert_eq!(j2.len(), 2);
// Make sure that the two addresses are different
assert_ne!(j1[0]["address"].as_str().unwrap(), j2[0]["address"].as_str().unwrap());
assert_ne!(j1[1]["address"].as_str().unwrap(), j2[1]["address"].as_str().unwrap());
assert_ne!(j1[0]["private_key"].as_str().unwrap(), j2[0]["private_key"].as_str().unwrap());
assert_ne!(j1[1]["private_key"].as_str().unwrap(), j2[1]["private_key"].as_str().unwrap());
// Test the vanity address generator returns different addresses for every run
let td1 = json::parse(&generate_vanity_wallet(false, 1, "te".to_string()).unwrap()).unwrap();
let td2 = json::parse(&generate_vanity_wallet(false, 1, "te".to_string()).unwrap()).unwrap();
assert!(td1[0]["address"].as_str().unwrap().starts_with("zs1te"));
assert!(td2[0]["address"].as_str().unwrap().starts_with("zs1te"));
assert_ne!(td1[0]["address"].as_str().unwrap(), td2[0]["address"].as_str().unwrap());
}
#[test]
fn test_tandz_wallet_generation() {
use crate::paper::generate_wallet;
use std::collections::HashSet;
// Testnet wallet
let w = generate_wallet(true, false, 1, 1, &[]);
let j = json::parse(&w).unwrap();
assert_eq!(j.len(), 2);
assert!(j[0]["address"].as_str().unwrap().starts_with("ztestsapling"));
assert!(j[0]["private_key"].as_str().unwrap().starts_with("secret-extended-key-test"));
assert_eq!(j[0]["seed"]["path"].as_str().unwrap(), "m/32'/1'/0'");
assert!(j[1]["address"].as_str().unwrap().starts_with("tm"));
let pk = j[1]["private_key"].as_str().unwrap();
assert!(pk.starts_with("c") || pk.starts_with("9"));
// Mainnet wallet
let w = generate_wallet(false, false, 1, 1, &[]);
let j = json::parse(&w).unwrap();
assert_eq!(j.len(), 2);
assert!(j[0]["address"].as_str().unwrap().starts_with("zs"));
assert!(j[0]["private_key"].as_str().unwrap().starts_with("secret-extended-key-main"));
assert_eq!(j[0]["seed"]["path"].as_str().unwrap(), "m/32'/133'/0'");
assert!(j[1]["address"].as_str().unwrap().starts_with("t1"));
let pk = j[1]["private_key"].as_str().unwrap();
assert!(pk.starts_with("L") || pk.starts_with("K") || pk.starts_with("5"));
// Check if all the addresses are the same
let w = generate_wallet(true, false, 3, 3, &[]);
let j = json::parse(&w).unwrap();
assert_eq!(j.len(), 6);
let mut set1 = HashSet::new();
for i in 0..6 {
set1.insert(j[i]["address"].as_str().unwrap());
set1.insert(j[i]["private_key"].as_str().unwrap());
}
// There should be 6 + 6 distinct addresses and private keys
assert_eq!(set1.len(), 12);
}
/// Test nohd address generation, which does not use the same sed.
#[test]
fn test_nohd() {
use crate::paper::generate_wallet;
use std::collections::HashSet;
// Check if all the addresses use a different seed
let w = generate_wallet(true, 3, 0, &[]);
let j = json::parse(&w).unwrap();
assert_eq!(j.len(), 3);
let mut set1 = HashSet::new();
let mut set2 = HashSet::new();
for i in 0..3 {
assert!(j[i]["address"].as_str().unwrap().starts_with("ztestsapling"));
assert_eq!(j[i]["seed"]["path"].as_str().unwrap(), "m/32'/1'/0'"); // All of them should use the same path
set1.insert(j[i]["address"].as_str().unwrap());
set1.insert(j[i]["private_key"].as_str().unwrap());
set2.insert(j[i]["seed"]["HDSeed"].as_str().unwrap());
}
// There should be 3 + 3 distinct addresses and private keys
assert_eq!(set1.len(), 6);
// ...and 3 different seeds
assert_eq!(set2.len(), 3);
}
/// Test the address derivation against the test data (see below)
fn test_address_derivation(testdata: &str) {
use crate::paper::gen_addresses_with_seed_as_json;
let td = json::parse(&testdata.replace("'", "\"")).unwrap();
for i in td.members() {
let seed = hex::decode(i["seed"].as_str().unwrap()).unwrap();
let num = i["num"].as_u32().unwrap();
let addresses = gen_addresses_with_seed_as_json(num+1, 0, |child| (seed.clone(), child));
let j = json::parse(&addresses).unwrap();
assert_eq!(j[num as usize]["address"], i["addr"]);
assert_eq!(j[num as usize]["private_key"], i["pk"]);
}
}
#[test]
fn test_vanity() {
use crate::paper::generate_vanity_wallet;
// Single thread
let td = json::parse(&generate_vanity_wallet(false, 1, "te".to_string()).unwrap()).unwrap();
assert_eq!(td.len(), 1);
assert!(td[0]["address"].as_str().unwrap().starts_with("zs1te"));
// Multi thread
let td = json::parse(&generate_vanity_wallet(false, 4, "tt".to_string()).unwrap()).unwrap();
assert_eq!(td.len(), 1);
assert!(td[0]["address"].as_str().unwrap().starts_with("zs1tt"));
// Testnet
let td = json::parse(&generate_vanity_wallet(true, 4, "ts".to_string()).unwrap()).unwrap();
assert_eq!(td.len(), 1);
assert!(td[0]["address"].as_str().unwrap().starts_with("ztestsapling1ts"));
// Test for invalid chars
generate_vanity_wallet(false, 1, "b".to_string()).expect_err("b is not allowed");
generate_vanity_wallet(false, 1, "o".to_string()).expect_err("o is not allowed");
generate_vanity_wallet(false, 1, "i".to_string()).expect_err("i is not allowed");
generate_vanity_wallet(false, 1, "1".to_string()).expect_err("1 is not allowed");
}
}

110
lib/src/pdf.rs

@ -16,7 +16,7 @@ use printpdf::*;
* Save the list of wallets (address + private keys) to the given PDF file name.
*/
pub fn save_to_pdf(addresses: &str, filename: &str) -> Result<(), String> {
let (doc, page1, layer1) = PdfDocument::new("Hush Paper Wallet", Mm(210.0), Mm(297.0), "Layer 1");
let (doc, page1, layer1) = PdfDocument::new("SilentDragonPaper Wallet", Mm(210.0), Mm(297.0), "Layer 1");
let font = doc.add_builtin_font(BuiltinFont::Courier).unwrap();
let font_bold = doc.add_builtin_font(BuiltinFont::CourierBold).unwrap();
@ -78,8 +78,8 @@ pub fn save_to_pdf(addresses: &str, filename: &str) -> Result<(), String> {
current_layer.set_outline_thickness(2.0);
// Set title
current_layer.use_text("Speak and Transact Freely", 32, Mm(19.0), Mm(277.0), &font_bold);
current_layer.use_text("Private Cryptocurrency and Messenger on Zero Knowledge Proof Encryption", 13, Mm(7.0), Mm(266.0), &font_bold);
current_layer.use_text("Speak and Transact Freely", 32f64, Mm(19.0), Mm(277.0), &font_bold);
current_layer.use_text("Private Cryptocurrency and Messenger on Zero Knowledge Proof Encryption", 13f64, Mm(7.0), Mm(266.0), &font_bold);
// Draw lines
current_layer.add_shape(line1);
@ -144,7 +144,7 @@ fn qrcode_scaled(data: &str, scalefactor: usize) -> (Vec<u8>, usize) {
* Add a footer at the bottom of the page
*/
fn add_footer_to_page(current_layer: &PdfLayerReference, font: &IndirectFontRef, footer: &str) {
current_layer.use_text(footer, 10, Mm(5.0), Mm(5.0), &font);
current_layer.use_text(footer, 10f64, Mm(5.0), Mm(5.0), &font);
}
@ -156,18 +156,18 @@ fn add_address_to_page(current_layer: &PdfLayerReference, font: &IndirectFontRef
// page_height top_margin vertical_padding position
let ypos = 297.0 - 5.0 - 77.0 - (140.0 * pos as f64);
let title = if is_taddr {"T Address"} else {"HUSH Address"};
let title = if is_taddr {"HUSH t-address"} else {"HUSH z-address"};
add_address_at(current_layer, font, font_bold, title, address, &scaledimg, finalsize, ypos);
}
fn add_address_at(current_layer: &PdfLayerReference, font: &IndirectFontRef, font_bold: &IndirectFontRef, title: &str, address: &str, qrcode: &Vec<u8>, finalsize: usize, ypos: f64) {
add_qrcode_image_to_page(current_layer, qrcode, finalsize, Mm(10.0), Mm(ypos));
current_layer.use_text(title, 14, Mm(55.0), Mm(ypos+22.5), &font_bold);
current_layer.use_text(title, 14f64, Mm(55.0), Mm(ypos+22.5), &font_bold);
let strs = split_to_max(&address, 39, 39); // No spaces, so user can copy the address
for i in 0..strs.len() {
current_layer.use_text(strs[i].clone(), 12, Mm(55.0), Mm(ypos+15.0-((i*5) as f64)), &font);
current_layer.use_text(strs[i].clone(), 12f64, Mm(55.0), Mm(ypos+15.0-((i*5) as f64)), &font);
}
}
@ -182,23 +182,23 @@ fn add_pk_to_page(current_layer: &PdfLayerReference, font: &IndirectFontRef, fon
add_qrcode_image_to_page(current_layer, &scaledimg, finalsize, Mm(145.0), Mm(ypos-17.5));
current_layer.use_text("Private Key", 14, Mm(10.0), Mm(ypos+37.5), &font_bold);
current_layer.use_text("Private Key", 14f64, Mm(10.0), Mm(ypos+37.5), &font_bold);
let strs = split_to_max(&pk, 45, 45); // No spaces, so user can copy the private key
for i in 0..strs.len() {
current_layer.use_text(strs[i].clone(), 12, Mm(10.0), Mm(ypos+32.5-((i*5) as f64)), &font);
current_layer.use_text(strs[i].clone(), 12f64, Mm(10.0), Mm(ypos+32.5-((i*5) as f64)), &font);
}
// Add the address a second time below the private key
let title = if is_taddr {"T Address"} else {"HUSH Address"};
current_layer.use_text(title, 12, Mm(10.0), Mm(ypos-10.0), &font_bold);
let title = if is_taddr {"HUSH t-address"} else {"HUSH z-address"};
current_layer.use_text(title, 12f64, Mm(10.0), Mm(ypos-10.0), &font_bold);
let strs = split_to_max(&address, 39, 39); // No spaces, so user can copy the address
for i in 0..strs.len() {
current_layer.use_text(strs[i].clone(), 12, Mm(10.0), Mm(ypos-15.0-((i*5) as f64)), &font);
current_layer.use_text(strs[i].clone(), 12f64, Mm(10.0), Mm(ypos-15.0-((i*5) as f64)), &font);
}
// And add the seed too.
if !seed.is_empty() {
current_layer.use_text(format!("HDSeed: {}, Path: {}", seed, path).as_str(), 8, Mm(10.0), Mm(ypos-35.0), &font);
current_layer.use_text(format!("HDSeed: {}, Path: {}", seed, path).as_str(), 8f64, Mm(10.0), Mm(ypos-35.0), &font);
}
}
@ -259,87 +259,3 @@ fn split_to_max(s: &str, max: usize, blocksize: usize) -> Vec<String> {
// Add spaces
return ans;
}
#[cfg(test)]
mod tests {
#[test]
fn test_qrcode_scale() {
use array2d::Array2D;
use qrcode::QrCode;
use crate::pdf::qrcode_scaled;
let testdata = "This is some testdata";
let code = QrCode::new(testdata.as_bytes()).unwrap();
let width = code.width();
let factor = 10;
let padding = 10;
let (scaled, size) = qrcode_scaled(testdata, factor);
let scaled_size = (width * factor)+(2*padding);
assert_eq!(size, scaled_size);
// 3 bytes per pixel
let scaled_qrcode = Array2D::from_row_major(&scaled, scaled_size, scaled_size*3);
for i in 0..scaled_size {
for j in 0..scaled_size {
// The padding should be white
if i < padding || i >= (width*factor) + padding ||
j < padding || j >= (width*factor) + padding {
for px in 0..3 {
assert_eq!(scaled_qrcode[(i, j*3+px)], 255u8);
}
} else {
// Should match the QR code module
let module_i = (i-padding)/factor;
let module_j = (j-padding)/factor;
// This should really be (i,j), but I think there's a bug in the qrcode
// module that is returning it the other way.
let color = if code[(module_j, module_i)] == qrcode::Color::Light {
// Light color is white
255u8
} else {
// Dark color is black
0u8
};
for px in 0..3 {
assert_eq!(scaled_qrcode[(i, j*3+px)], color);
}
}
}
}
}
#[test]
fn test_split() {
use crate::pdf::split_to_max;
assert_eq!(split_to_max("a", 1, 1).join("\n"), "a\n");
// Test the address splitting using max/blocksize we'll know we use
let addr = "ztestsapling1w00pdjthkzmzgut4c3y7hu6q6c8ferjczyvc03xwu0rvdgtre8a25em5w3w6jxghvcar5jzehnn";
assert_eq!(split_to_max(addr, 44, 8).join("\n"), "ztestsap ling1w00 pdjthkzm zgut4c3y 7hu6q6c8 ferj\nczyvc03x wu0rvdgt re8a25em 5w3w6jxg hvcar5jz ehnn\n");
assert_eq!(split_to_max(addr, 44, 8).join(" ").replace(" ", ""), addr);
assert_eq!(split_to_max(addr, 42, 8).join(" ").replace(" ", ""), addr);
assert_eq!(split_to_max(addr, 39, 39).join(" ").replace(" ", ""), addr);
// Test the PK splitting using max/blocksize we'll know we use
let pk = "secret-extended-key-test1qj7vst8eqqqqqqpu2w6r0p2ykewm95h3d28k7r7y87e9p4v5zhzd4hj2y57clsprjveg997vqk7ak9tr2pnyyxmfzyzs6dhtuflt3aea9srp08teskpqfy2dtm07n08z3dyra407xumf3fk9ds4x06rzur7mgfyu39krj2g28lsxsxtv7swzu0j9vw4qf8rn5z72ztgeqj6u5zehylqm75c7d3um9ds9zvek4tdyta7qhln5fkc0dks6qwmkvr48fvgucpc3542kmdc97uqzt";
assert_eq!(split_to_max(pk, 44, 8).join(" ").replace(" ", ""), pk);
assert_eq!(split_to_max(pk, 45, 10).join(" ").replace(" ", ""), pk);
assert_eq!(split_to_max(pk, 45, 45).join(" ").replace(" ", ""), pk);
// Test random combinations of block size and spaces to ensure that
// the string is always preserved
for m in 1..100 {
for b in 1..40 {
assert_eq!(split_to_max(addr, m, b).join(" ").replace(" ", ""), addr);
assert_eq!(split_to_max(pk, m, b).join(" ").replace(" ", ""), pk);
}
}
}
}

20
ui/mkdockerwinlinux.sh

@ -29,30 +29,30 @@ if [ -z $APP_VERSION ]; then
exit 1;
fi
cd /opt/hushpaperwallet/ui
cd /opt/silentdragonpaper/ui
source ~/.cargo/env
# We need to run qmake before we run disclean
/opt/Qt/5.11.2/static/bin/qmake papersapling.pro CONFIG+=release
make distclean
rm -rf artifacts/linux-hushpaperwallet-v$APP_VERSION
mkdir -p artifacts/linux-hushpaperwallet-v$APP_VERSION
rm -rf artifacts/linux-silentdragonpaper-v$APP_VERSION
mkdir -p artifacts/linux-silentdragonpaper-v$APP_VERSION
/opt/Qt/5.11.2/static/bin/qmake papersapling.pro CONFIG+=release
make -j4
strip hushpaperwalletui
cp hushpaperwalletui artifacts/linux-hushpaperwallet-v$APP_VERSION
strip silentdragonpaperui
cp silentdragonpaperui artifacts/linux-silentdragonpaper-v$APP_VERSION
# Run qmake before distclean
/opt/mxe/usr/bin/x86_64-w64-mingw32.static-qmake-qt5 papersapling.pro CONFIG+=release
make distclean
rm -rf artifacts/Windows-hushpaperwallet-v$APP_VERSION
mkdir -p artifacts/Windows-hushpaperwallet-v$APP_VERSION
rm -rf artifacts/Windows-silentdragonpaper-v$APP_VERSION
mkdir -p artifacts/Windows-silentdragonpaper-v$APP_VERSION
/opt/mxe/usr/bin/x86_64-w64-mingw32.static-qmake-qt5 papersapling.pro CONFIG+=release
make -j4
strip release/hushpaperwalletui.exe
cp release/hushpaperwalletui.exe artifacts/Windows-hushpaperwallet-v$APP_VERSION
strip release/silentdragonpaperui.exe
cp release/silentdragonpaperui.exe artifacts/Windows-silentdragonpaper-v$APP_VERSION
# Cleanup before exiting
make distclean
make distclean

12
ui/papersapling.pro

@ -14,21 +14,9 @@ TEMPLATE = app
MOC_DIR = bin
OBJECTS_DIR = bin
UI_DIR = src
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++14
CONFIG += precompile_header
PRECOMPILED_HEADER = src/precompiled.h

4
ui/qtlib/Cargo.toml

@ -1,7 +1,7 @@
[package]
name = "qtlib"
version = "0.1.0"
authors = ["ZecWallet"]
authors = ["The Hush Developers", "ZecWallet"]
edition = "2018"
[lib]
@ -10,4 +10,4 @@ crate-type = ["staticlib"]
[dependencies]
libc = "0.2.58"
hushpaperlib = { path = "../../lib" }
silentdragonpaperlib = { path = "../../lib" }

12
ui/qtlib/Makefile

@ -6,18 +6,18 @@ endif
all: release
winrelease: target/x86_64-pc-windows-gnu/release/zecpaperrust.lib
winrelease: target/x86_64-pc-windows-gnu/release/silentdragonpaper.lib
target/x86_64-pc-windows-gnu/release/zecpaperrust.lib: src/lib.rs Cargo.toml
target/x86_64-pc-windows-gnu/release/silentdragonpaper.lib: src/lib.rs Cargo.toml
cargo build --lib --release --target x86_64-pc-windows-gnu
release: target/release/zecpaperrust.$(EXT)
debug: target/debug/zecpaperrust.$(EXT)
release: target/release/silentdragonpaper.$(EXT)
debug: target/debug/silentdragonpaper.$(EXT)
target/release/zecpaperrust.$(EXT): src/lib.rs Cargo.toml
target/release/silentdragonpaper.$(EXT): src/lib.rs Cargo.toml
cargo build --lib --release
target/debug/zecpaperrust.$(EXT): src/lib.rs Cargo.toml
target/debug/silentdragonpaper.$(EXT): src/lib.rs Cargo.toml
cargo build --lib
clean:

2
ui/qtlib/src/lib.rs

@ -1,6 +1,6 @@
use libc::{c_char};
use std::ffi::{CStr, CString};
use hushpaperlib::{pdf, paper};
use silentdragonpaperlib::{pdf, paper};
/**
* Call into rust to generate a paper wallet. Returns the paper wallet in JSON form.

10
ui/src/about.ui

File diff suppressed because one or more lines are too long

9
ui/src/main.cpp

@ -1,3 +1,6 @@
// Copyright (c) 2016-2020 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include "mainwindow.h"
#include "version.h"
#include <QApplication>
@ -7,8 +10,8 @@ int main(int argc, char *argv[])
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setOrganizationDomain("hushwallet.co");
QCoreApplication::setOrganizationName("hushpaperwallet");
QCoreApplication::setOrganizationDomain("hush.is");
QCoreApplication::setOrganizationName("Hush");
#ifdef Q_OS_LINUX
QFontDatabase::addApplicationFont(":/fonts/res/Ubuntu-R.ttf");
@ -18,7 +21,7 @@ int main(int argc, char *argv[])
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle(QString("hushpaperwallet ") + APP_VERSION);
w.setWindowTitle(QString("Extreme Privacy: SilentDragonPaper ") + APP_VERSION);
w.show();

14
ui/src/mainwindow.cpp

@ -1,13 +1,13 @@
// Copyright (c) 2016-2020 The Hush developers
// Distributed under the GPLv3 software license, see the accompanying
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
#include <cstring>
#include "precompiled.h"
#include "mainwindow.h"
#include "version.h"
#include "ui_mainwindow.h"
#include "ui_wallet.h"
#include "ui_about.h"
#include "hushpaperrust.h"
void SaveRestore(QDialog* d) {
@ -33,9 +33,7 @@ QString SplitIntoLines(QString s, int maxlen) {
return ans.join("\n");
}
/**
* Add a wallet (address + pk) section to the given vertical layout
*/
// Add a wallet (address + pk) section to the given vertical layout
void AddWallet(QString address, QString pk, QWidget* scroll) {
Ui_WalletWidget w;
auto g1 = new QGroupBox(scroll);
@ -172,7 +170,7 @@ MainWindow::MainWindow(QWidget *parent) :
// Help site
QObject::connect(ui->actionHelp_site, &QAction::triggered, [=]() {
QDesktopServices::openUrl(QUrl("https://docs.hushwallet.co/paper"));
QDesktopServices::openUrl(QUrl("https://faq.hush.is/sdp"));
});
// About button
@ -180,7 +178,7 @@ MainWindow::MainWindow(QWidget *parent) :
QDialog ad(this);
Ui_AboutDialog d;
d.setupUi(&ad);
d.lblVersion->setText(QString("hushpaperwallet ") + APP_VERSION + "(" + APP_BUILD_DATE + ")");
d.lblVersion->setText(QString("SilentDragonPaper ") + APP_VERSION + "(" + APP_BUILD_DATE + ")");
SaveRestore(&ad);
ad.exec();

Loading…
Cancel
Save