diff --git a/.travis.yml b/.travis.yml index 0651152..6cded8f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: rust +rust: + - 1.41.0 matrix: include: @@ -16,14 +18,15 @@ before_script: before_install: - - rustup component add rustfmt --toolchain stable-x86_64-unknown-linux-gnu + - rustup component add rustfmt --toolchain 1.41.0-x86_64-unknown-linux-gnu - gem install bundler - - curl -sSL https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly --profile=minimal + - curl -sSL https://sh.rustup.rs | sh -s -- -y --default-toolchain=stable --profile=minimal - export PATH="$PATH:$HOME/.cargo/bin" - - sudo add-apt-repository ppa:beineri/opt-qt591-xenial -y + - sudo add-apt-repository ppa:beineri/opt-qt-5.14.2-xenial -y - sudo apt-get update -qq - - sudo apt-get install qt59base qt59websockets libgl1-mesa-dev - - source /opt/qt59/bin/qt59-env.sh + - sudo apt-get install libsodium-dev pkg-config + - sudo apt-get install qt514base qt514websockets libgl1-mesa-dev + - source /opt/qt514/bin/qt514-env.sh - chmod +x res/libsodium/buildlibsodium.sh script: diff --git a/README.md b/README.md index aadbe50..ccb24c5 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ sudo apt install torsocks ``` ## Connection to our TOR onion service Server ``` -* Open SDL Edit->Settings->LightwalletServer->rnhk4pwlsbaqzx7wcqfy47lijf2opklstaukq35reiz5rn76crfqpjqd.onion:9067 +* Open SDL Edit->Settings->LightwalletServer->6onaaujm4ozaokzu.onion:80 * Open the folder of SDL in a Terminal -> Enter: TORSOCKS_LOG_LEVEL=1 torsocks -i ./SilentDragonLite ``` ## Note Management diff --git a/application.qrc b/application.qrc index 4c5ae9c..b5aa1a5 100644 --- a/application.qrc +++ b/application.qrc @@ -47,6 +47,11 @@ res/addContactBlack.png res/unknownBlack.png res/unknownWhite.png + res/dark-01.png + res/money-mouth.png + res/money-outgoing.png + res/hush-money-white.png + res/hushdlogo.gif @@ -57,6 +62,26 @@ res/loaderblack.gif res/loaderwhite.gif + + res/emoji/emoji1.png + res/emoji/laughing.png + res/emoji/money-mouth.png + res/emoji/joy.png + res/emoji/innocent.png + res/emoji/partying_face.png + res/emoji/face_with_3hearts.png + res/emoji/face-with-rolling-eyes.png + res/emoji/face-with-tongue.png + res/emoji/heart_shaped_eyes.png + res/emoji/nauseated-face.png + res/emoji/pile-of-poo.png + res/emoji/serious-face-with-symbols-covering-mouth.png + res/emoji/smiling-face-with-sunglasses.png + res/emoji/stuck-out.png + res/emoji/sweet_smile.png + res/emoji/hush-money-white.png + res/emoji/SD.png + res/silentdragonlite_de.qm res/silentdragonlite_es.qm @@ -67,6 +92,7 @@ res/silentdragonlite_fa.qm res/silentdragonlite_id.qm res/silentdragonlite_ar.qm + res/silentdragonlite_ro.qm res/css/Blue.css @@ -74,6 +100,7 @@ res/css/Default.css res/css/Light.css res/css/Midnight.css + res/css/test.css res/images/blue/unchecked.png @@ -85,4 +112,7 @@ res/images/blue/blue_rightArrow_small.png res/images/blue/blue_qtreeview_selected.png + + res/images/tile.png + diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 3c5dbf4..c6b8ef0 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -128,14 +128,6 @@ name = "base58" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "base64" version = "0.11.0" @@ -194,6 +186,20 @@ dependencies = [ "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "blake3" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayref 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -301,16 +307,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "core-foundation" -version = "0.6.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -584,7 +590,7 @@ dependencies = [ [[package]] name = "h2" -version = "0.2.1" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -596,8 +602,8 @@ dependencies = [ "indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -673,23 +679,23 @@ dependencies = [ [[package]] name = "hyper" -version = "0.13.2" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures-channel 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1036,7 +1042,7 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "1.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1175,9 +1181,10 @@ dependencies = [ name = "qtlib" version = "0.1.0" dependencies = [ + "blake3 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=d2887d07879a93bdd9b2c8bd12504bb977e82fe0)", + "silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=6c3f6f22bfc642c714c1e43f6e09cb4d34c7a1de)", ] [[package]] @@ -1475,10 +1482,10 @@ dependencies = [ [[package]] name = "rustls" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.16.11 (registry+https://github.com/rust-lang/crates.io-index)", "sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1487,13 +1494,13 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.1.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1542,21 +1549,22 @@ dependencies = [ [[package]] name = "security-framework" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1640,7 +1648,7 @@ dependencies = [ [[package]] name = "silentdragonlitelib" version = "0.1.0" -source = "git+https://github.com/MyHush/silentdragonlite-cli?rev=d2887d07879a93bdd9b2c8bd12504bb977e82fe0#d2887d07879a93bdd9b2c8bd12504bb977e82fe0" +source = "git+https://github.com/MyHush/silentdragonlite-cli?rev=6c3f6f22bfc642c714c1e43f6e09cb4d34c7a1de#6c3f6f22bfc642c714c1e43f6e09cb4d34c7a1de" dependencies = [ "base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bellman 0.1.0 (git+https://github.com/MyHush/librustzcash.git?rev=1a0204113d487cdaaf183c2967010e5214ff9e37)", @@ -1667,9 +1675,9 @@ dependencies = [ "sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "sodiumoxide 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tonic 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tonic 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tonic-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "webpki-roots 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1828,7 +1836,7 @@ dependencies = [ [[package]] name = "tokio" -version = "0.2.11" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1845,13 +1853,13 @@ dependencies = [ "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-macros 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-macros" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1861,18 +1869,18 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "webpki 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-util" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1880,31 +1888,31 @@ dependencies = [ "futures-sink 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tonic" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "async-stream 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "async-trait 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures-util 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "prost-derive 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustls-native-certs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tower 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tower-balance 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-load 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1953,7 +1961,7 @@ dependencies = [ "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-discover 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-load 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1970,7 +1978,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tracing 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1998,7 +2006,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2011,7 +2019,7 @@ dependencies = [ "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-discover 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2032,7 +2040,7 @@ name = "tower-make" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2045,7 +2053,7 @@ dependencies = [ "futures-util 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2056,7 +2064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures-core 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2072,7 +2080,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", "tower-layer 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2453,7 +2461,6 @@ dependencies = [ "checksum backtrace 0.3.43 (registry+https://github.com/rust-lang/crates.io-index)" = "7f80256bc78f67e7df7e36d77366f636ed976895d91fe2ab9efa3973e8fe8c4f" "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum bech32 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cdcf67bb7ba7797a081cd19009948ab533af7c355d5caf1d08c777582d351e9c" "checksum bellman 0.1.0 (git+https://github.com/MyHush/librustzcash.git?rev=1a0204113d487cdaaf183c2967010e5214ff9e37)" = "" @@ -2461,6 +2468,7 @@ dependencies = [ "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum blake2b_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" "checksum blake2s_simd 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab9e07352b829279624ceb7c64adb4f585dacdb81d35cafae81139ccd617cf44" +"checksum blake3 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "423897d97e11b810c9da22458400b28ec866991c711409073662eb34dc44bfff" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" @@ -2476,8 +2484,8 @@ dependencies = [ "checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19" "checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" @@ -2512,7 +2520,7 @@ dependencies = [ "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" "checksum group 0.1.0 (git+https://github.com/MyHush/librustzcash.git?rev=1a0204113d487cdaaf183c2967010e5214ff9e37)" = "" -"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" +"checksum h2 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" "checksum hashbrown 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" @@ -2522,7 +2530,7 @@ dependencies = [ "checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum hyper 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fa1c527bbc634be72aa7ba31e4e4def9bbb020f5416916279b7c705cd838893e" +"checksum hyper 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7655b9594024ad0ee439f3b5a7299369dc2a3f459b47c696f9ff676f9aa1f" "checksum indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b54058f0a6ff80b6803da8faf8997cde53872b38f4023728f6830b06cd3c0dc" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" @@ -2562,7 +2570,7 @@ dependencies = [ "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "006c038a43a45995a9670da19e67600114740e8511d4333bf97a56e66a7542d9" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum petgraph 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29c127eea4a29ec6c85d153c59dc1213f33ec74cead30fe4730aecc88cc1fd92" "checksum pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" "checksum pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" @@ -2612,16 +2620,16 @@ dependencies = [ "checksum rust-embed-utils 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97655158074ccb2d2cfb1ccb4c956ef0f4054e43a2c1e71146d4991e6961e105" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b25a18b1bf7387f0145e7f8324e700805aade3842dd3db2e74e4cdeb4677c09e" -"checksum rustls-native-certs 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51ffebdbb48c14f84eba0b715197d673aff1dd22cc1007ca647e28483bbcc307" +"checksum rustls 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1" +"checksum rustls-native-certs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a75ffeb84a6bd9d014713119542ce415db3a3e4748f0bfce1e1416cd224a23a5" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum sct 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" "checksum secp256k1 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e0344a794ff109f85547039536028e12f313178ac1545e49fdf16a530d900a7b" -"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" -"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" +"checksum security-framework 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "97bbedbe81904398b6ebb054b3e912f99d55807125790f3198ac990d98def5b0" +"checksum security-framework-sys 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" @@ -2631,7 +2639,7 @@ dependencies = [ "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha2 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0" "checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" -"checksum silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=d2887d07879a93bdd9b2c8bd12504bb977e82fe0)" = "" +"checksum silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=6c3f6f22bfc642c714c1e43f6e09cb4d34c7a1de)" = "" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" @@ -2649,11 +2657,11 @@ dependencies = [ "checksum thread-id 3.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny-bip39 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c1c5676413eaeb1ea35300a0224416f57abc3bd251657e0fafc12c47ff98c060" -"checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" -"checksum tokio-macros 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4b1e7ed7d5d4c2af3d999904b0eebe76544897cdbfb2b9684bed2174ab20f7c" -"checksum tokio-rustls 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "141afec0978abae6573065a48882c6bae44c5cc61db9b511ac4abf6a09bfd9cc" -"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" -"checksum tonic 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08283643b1d483eb7f3fc77069e63b5cba3e4db93514b3d45470e67f123e4e48" +"checksum tokio 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" +"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" +"checksum tokio-rustls 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4adb8b3e5f86b707f1b54e7c15b6de52617a823608ccda98a15d3a24222f265a" +"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" +"checksum tonic 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4afef9ce97ea39593992cf3fa00ff33b1ad5eb07665b31355df63a690e38c736" "checksum tonic-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0436413ba71545bcc6c2b9a0f9d78d72deb0123c6a75ccdfe7c056f9930f5e52" "checksum tower 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd3169017c090b7a28fce80abaad0ab4f5566423677c9331bb320af7e49cfe62" "checksum tower-balance 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a792277613b7052448851efcf98a2c433e6f1d01460832dc60bef676bc275d4c" diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 39a70e9..d0c3d50 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -11,4 +11,5 @@ crate-type = ["staticlib"] [dependencies] libc = "0.2.58" lazy_static = "1.4.0" -silentdragonlitelib = { git = "https://github.com/MyHush/silentdragonlite-cli", rev = "d2887d07879a93bdd9b2c8bd12504bb977e82fe0" } +blake3 = "0.3.4" +silentdragonlitelib = { git = "https://github.com/MyHush/silentdragonlite-cli", rev = "6c3f6f22bfc642c714c1e43f6e09cb4d34c7a1de" } diff --git a/lib/silentdragonlitelib.h b/lib/silentdragonlitelib.h index 4546e70..4e1c983 100644 --- a/lib/silentdragonlitelib.h +++ b/lib/silentdragonlitelib.h @@ -6,13 +6,14 @@ extern "C" { #endif extern bool litelib_wallet_exists (const char* chain_name); -extern char * litelib_initialize_new (bool dangerous, const char* server); +extern char * litelib_initialize_new (const char* server); extern char * litelib_initialize_new_from_phrase - (bool dangerous, const char* server, const char* seed, - unsigned long long birthday); -extern char * litelib_initialize_existing (bool dangerous, const char* server); + (const char* server, const char* seed, + unsigned long long birthday, unsigned long long number); +extern char * litelib_initialize_existing (const char* server); extern char * litelib_execute (const char* s, const char* args); extern void litelib_rust_free_string (char* s); +extern char * blake3_PW (char* pw); #ifdef __cplusplus } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 8be7c55..3314c90 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -29,11 +29,35 @@ pub extern fn litelib_wallet_exists(chain_name: *const c_char) -> bool { println!("Wallet exists: {}", config.wallet_exists()); config.wallet_exists() +} + +//////hash blake3 + +#[no_mangle] +pub extern fn blake3_PW(pw: *const c_char) -> *mut c_char{ + + let passwd = unsafe { + assert!(!pw.is_null()); + + CStr::from_ptr(pw).to_string_lossy().into_owned() + }; + + let data = passwd.as_bytes(); +// Hash an input all at once. +let hash1 = blake3::hash(data).to_hex(); +println!("\nBlake3 Hash: {}", hash1); + +//let sttring = CString::new(hash1).unwrap(); +let e_str = CString::new(format!("{}", hash1)).unwrap(); +return e_str.into_raw(); + + + } /// Create a new wallet and return the seed for the newly created wallet. #[no_mangle] -pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) -> *mut c_char { +pub extern fn litelib_initialize_new(server: *const c_char) -> *mut c_char { let server_str = unsafe { assert!(!server.is_null()); @@ -41,7 +65,7 @@ pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) -> }; let server = LightClientConfig::get_server_or_default(Some(server_str)); - let (config, latest_block_height) = match LightClientConfig::create(server, dangerous) { + let (config, latest_block_height) = match LightClientConfig::create(server) { Ok((c, h)) => (c, h), Err(e) => { let e_str = CString::new(format!("Error: {}", e)).unwrap(); @@ -77,8 +101,8 @@ pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) -> /// Restore a wallet from the seed phrase #[no_mangle] -pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const c_char, - seed: *const c_char, birthday: u64) -> *mut c_char { +pub extern fn litelib_initialize_new_from_phrase(server: *const c_char, + seed: *const c_char, birthday: u64, number: u64, overwrite: bool) -> *mut c_char { let server_str = unsafe { assert!(!server.is_null()); @@ -92,7 +116,7 @@ pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const }; let server = LightClientConfig::get_server_or_default(Some(server_str)); - let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) { + let (config, _latest_block_height) = match LightClientConfig::create(server) { Ok((c, h)) => (c, h), Err(e) => { let e_str = CString::new(format!("Error: {}", e)).unwrap(); @@ -100,7 +124,7 @@ pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const } }; - let lightclient = match LightClient::new_from_phrase(seed_str, &config, birthday) { + let lightclient = match LightClient::new_from_phrase(seed_str, &config, birthday, number, overwrite) { Ok(l) => l, Err(e) => { let e_str = CString::new(format!("Error: {}", e)).unwrap(); @@ -119,7 +143,7 @@ pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const // Initialize a new lightclient and store its value #[no_mangle] -pub extern fn litelib_initialize_existing(dangerous: bool, server: *const c_char) -> *mut c_char { +pub extern fn litelib_initialize_existing(server: *const c_char) -> *mut c_char { let server_str = unsafe { assert!(!server.is_null()); @@ -127,7 +151,7 @@ pub extern fn litelib_initialize_existing(dangerous: bool, server: *const c_char }; let server = LightClientConfig::get_server_or_default(Some(server_str)); - let (config, _latest_block_height) = match LightClientConfig::create(server, dangerous) { + let (config, _latest_block_height) = match LightClientConfig::create(server) { Ok((c, h)) => (c, h), Err(e) => { let e_str = CString::new(format!("Error: {}", e)).unwrap(); diff --git a/res/SilentDragonLite.png b/res/SilentDragonLite.png new file mode 100644 index 0000000..a6339b3 Binary files /dev/null and b/res/SilentDragonLite.png differ diff --git a/res/css/test.css b/res/css/test.css new file mode 100644 index 0000000..ddb7f35 --- /dev/null +++ b/res/css/test.css @@ -0,0 +1,239 @@ + +QWidget, QMainWindow, QMenuBar, QMenu, QDialog, QTabWidget, QTableView, QTableView::item, QScrollArea, QGroupBox, QPlainTextEdit, QLineEdit, QLabel, MainWindow +{ + /* background-color: #303335; */ + background: transparent; + color: #ffffff; +} + +QMainWindow +{ + border-image: url(':images/res/images/tile.png') 0 0 0 0 repeat repeat; + color: #ffffff; +} + +QTabWidget QTabBar::tab { +padding-left:20px; +padding-right:20px; +padding-top:5px; +padding-bottom:5px; +border: 1px solid #525355; +/*background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #747577, stop: 1 #3E4244);*/ +background-color: rgba(0, 0, 0, 128); +} + +QTabWidget QTabBar::tab:selected { +min-height: 10px; +/*background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #525355, stop: 1 #303335);*/ +background-color: rgba(0, 64, 0, 128); +color:#fff; +border: 1px ridge #000; +} + +QTabWidget QTabBar::tab:hover { +/*background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #747577, stop: 1 #3E4244);*/ +background-color: rgba(0, 0, 0, 32); +color:#fff; +border: 1px ridge #fff; +min-height: 20px +} + +QTabWidget::pane { + background-color: rgba(0, 0, 0, 128); + border: 2px solid rgb(0, 0, 0); + border-top-left-radius: 0px; + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-top-right-radius: 4px; + top: -2px; +} + +QStatusBar { + background-color: rgba(0, 0, 64, 128); +} + +QHeaderView { /* Table Header */ +/* background-color:#303335;*/ +background-color: rgba(0, 0, 0, 64); +border:1px solid #fff; +} + +QHeaderView::section { /* Table Header Sections */ +qproperty-alignment:center; +/*background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #747577, stop: 1 #3E4244);*/ +background: transparent; +color:#fff; +min-height:25px; +font-weight:bold; +font-size:11px; +outline:0; +border:1px solid #525355; +border-right:1px solid #fff; +border-left:1px solid #fff; +padding-left:5px; +padding-right:5px; +padding-top:2px; +padding-bottom:2px; +} + +QHeaderView::section:last { +border-right: 0px solid #d7d7d7; +} + +QScrollArea { +background:transparent; +border:0px; +} + +QTableView { /* Table - has to be selected as a class otherwise it throws off QCalendarWidget */ +/*background:#303335;*/ +background: transparent; +} + +QTableView::item { /* Table Item */ +/*background-color:#303335;*/ +background: transparent; +border:1px solid #fff; +font-size:12px; +} + +QTableView::item:selected { /* Table Item Selected */ +background-color:#fff; +color:#000; +} + +QMenuBar { +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #525355, stop: 1 #303335); +color: #fff; +} + +QMenuBar::item { +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #525355, stop: 1 #303335); +color: #fff; +} + +QMenuBar::item:selected { +background-color:qlineargradient(x1: 0, y1: 0, x2: 0, y2: 0.25, stop: 0 #747577, stop: 1 #3E4244); +} + +QTabBar::tab { + background-color: rgba(0, 0, 0, 128); + min-width: 150px; + padding: 4px; + border-bottom: 2px solid rgb(68, 49, 141); + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} + +QTabBar::tab:selected { + /* font: bold; */ + border: 2px solid rgb(68, 49, 141); + border-bottom: none; +} + + +QTabBar::tab:hover { + /* font: bold; */ + border: 2px solid rgb(68, 49, 141); +} + + +QGroupBox { + background-color: rgba(0, 0, 0, 128); + font-weight: bold; + font-style: italic; + border: 1px solid rgba(0, 128, 0, 128); + border-radius: 4px; + padding: 4px; + margin-top: 16px; +} + +QGroupBox::title { + subcontrol-origin: margin; + subcontrol-position: top left; + left: 8px; + padding-left: 3px; + padding-right: 3px; + padding-top: 6px; + padding-bottom: 8px; +} + +QLineEdit, QPushButton, QPlainTextEdit { + background-color: rgba(10, 7, 20, 128); + min-width: 100px; + border: 1px solid rgb(68, 49, 141); + border-radius: 4px; + padding:5px; +} + +QLineEdit:focus, QPushButton:pressed, QPlainTextEdit:focus { + border: 1px solid rgb(216, 00, 255); +} + +QLineEdit:hover, QPushButton:hover, QPlainTextEdit:hover { + border: 1px solid rgb(216, 00, 255); +} + +QLineEdit:disabled, QPushButton:disabled, QPlainTextEdit:disabled { + border: 1px solid rgb(64, 64, 64); +} + +QComboBox { + background-color: rgba(10, 7, 20, 128); + min-height: 28px; + min-width: 80px; + border: 1px solid rgb(68, 49, 141); + border-radius: 4px; +} + +QComboBox:hover { + border: 1px solid rgb(216, 00, 255); +} + +QComboBox QAbstractItemView { + background-color: rgb(0, 0, 0); + border: 1px solid rgb(68, 49, 141); + border-radius: 4px; +} + +QComboBox::item { + background-color: rgb(0, 0, 0); + border: 1px solid rgb(0, 0, 0); + border-radius: 4px; + height:28px; +} + +QComboBox::item:selected { /* when user selects item using mouse or keyboard */ + background-color: rgb(20, 15, 40); + border: 1px solid rgb(68, 49, 141); + border-radius: 4px; + +} + + +QCheckBox::indicator, QRadioButton::indicator { + border: 2px solid rgb(68, 49, 141); + border-radius: 6px; +} + +QCheckBox::indicator:checked, QRadioButton::indicator:checked { + background-color: rgba(0, 255, 0, 128); +} + +QCheckBox::indicator:unchecked, QRadioButton::indicator:unchecked { + background-color: rgba(0, 16, 0, 128); +} + +QCheckBox::indicator:hover, QRadioButton::indicator:hover { + border: 2px solid rgb(0, 192, 0); +} + +QCheckBox::indicator:disabled, QRadioButton::indicator:disabled { + border: 2px solid rgb(64, 64, 64); +} + +QWidget.FilledIconLabel /* targets custom ui widget by class name */ +{ + background-color: rgba(255, 255, 255, 64); + border: 2px solid rgb(255, 0, 0); +} diff --git a/res/dark-01.png b/res/dark-01.png new file mode 100644 index 0000000..bcfc33d Binary files /dev/null and b/res/dark-01.png differ diff --git a/res/emoji/SD.png b/res/emoji/SD.png new file mode 100644 index 0000000..a68ab62 Binary files /dev/null and b/res/emoji/SD.png differ diff --git a/res/emoji/emoji1.png b/res/emoji/emoji1.png new file mode 100644 index 0000000..7179819 Binary files /dev/null and b/res/emoji/emoji1.png differ diff --git a/res/emoji/face-with-rolling-eyes.png b/res/emoji/face-with-rolling-eyes.png new file mode 100644 index 0000000..2ac0b71 Binary files /dev/null and b/res/emoji/face-with-rolling-eyes.png differ diff --git a/res/emoji/face-with-tongue.png b/res/emoji/face-with-tongue.png new file mode 100644 index 0000000..b83c921 Binary files /dev/null and b/res/emoji/face-with-tongue.png differ diff --git a/res/emoji/face_with_3hearts.png b/res/emoji/face_with_3hearts.png new file mode 100644 index 0000000..b8b9f5d Binary files /dev/null and b/res/emoji/face_with_3hearts.png differ diff --git a/res/emoji/heart_shaped_eyes.png b/res/emoji/heart_shaped_eyes.png new file mode 100644 index 0000000..ddeefdc Binary files /dev/null and b/res/emoji/heart_shaped_eyes.png differ diff --git a/res/emoji/hush-money-white.png b/res/emoji/hush-money-white.png new file mode 100644 index 0000000..d0e1ebd Binary files /dev/null and b/res/emoji/hush-money-white.png differ diff --git a/res/emoji/innocent.png b/res/emoji/innocent.png new file mode 100644 index 0000000..c58bd37 Binary files /dev/null and b/res/emoji/innocent.png differ diff --git a/res/emoji/joy.png b/res/emoji/joy.png new file mode 100644 index 0000000..cb80d82 Binary files /dev/null and b/res/emoji/joy.png differ diff --git a/res/emoji/laughing.png b/res/emoji/laughing.png new file mode 100644 index 0000000..701c1de Binary files /dev/null and b/res/emoji/laughing.png differ diff --git a/res/emoji/money-mouth.png b/res/emoji/money-mouth.png new file mode 100644 index 0000000..fc262f4 Binary files /dev/null and b/res/emoji/money-mouth.png differ diff --git a/res/emoji/nauseated-face.png b/res/emoji/nauseated-face.png new file mode 100644 index 0000000..88b70c6 Binary files /dev/null and b/res/emoji/nauseated-face.png differ diff --git a/res/emoji/partying_face.png b/res/emoji/partying_face.png new file mode 100644 index 0000000..625c1e8 Binary files /dev/null and b/res/emoji/partying_face.png differ diff --git a/res/emoji/pile-of-poo.png b/res/emoji/pile-of-poo.png new file mode 100644 index 0000000..f063a77 Binary files /dev/null and b/res/emoji/pile-of-poo.png differ diff --git a/res/emoji/serious-face-with-symbols-covering-mouth.png b/res/emoji/serious-face-with-symbols-covering-mouth.png new file mode 100644 index 0000000..917b8fc Binary files /dev/null and b/res/emoji/serious-face-with-symbols-covering-mouth.png differ diff --git a/res/emoji/smiling-face-with-sunglasses.png b/res/emoji/smiling-face-with-sunglasses.png new file mode 100644 index 0000000..4fe13e3 Binary files /dev/null and b/res/emoji/smiling-face-with-sunglasses.png differ diff --git a/res/emoji/stuck-out.png b/res/emoji/stuck-out.png new file mode 100644 index 0000000..fa98c80 Binary files /dev/null and b/res/emoji/stuck-out.png differ diff --git a/res/emoji/sweet_smile.png b/res/emoji/sweet_smile.png new file mode 100644 index 0000000..53b9d41 Binary files /dev/null and b/res/emoji/sweet_smile.png differ diff --git a/res/hush-money-white.png b/res/hush-money-white.png new file mode 100644 index 0000000..7ee8d9a Binary files /dev/null and b/res/hush-money-white.png differ diff --git a/res/hush-money.png b/res/hush-money.png new file mode 100644 index 0000000..eb27d4e Binary files /dev/null and b/res/hush-money.png differ diff --git a/res/images/tile.png b/res/images/tile.png new file mode 100644 index 0000000..eeba408 Binary files /dev/null and b/res/images/tile.png differ diff --git a/res/money-mouth.png b/res/money-mouth.png new file mode 100644 index 0000000..fc262f4 Binary files /dev/null and b/res/money-mouth.png differ diff --git a/res/money-outgoing.png b/res/money-outgoing.png new file mode 100644 index 0000000..c40b09b Binary files /dev/null and b/res/money-outgoing.png differ diff --git a/res/silentdragonlite.desktop b/res/silentdragonlite.desktop new file mode 100644 index 0000000..bf5b057 --- /dev/null +++ b/res/silentdragonlite.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Name=SilentDragonLite +Comment=Lightclient UI wallet for Hush +GenericName=Wallet +Exec=SilentDragonLite %u +Icon=SilentDragonLite +Type=Application +StartupNotify=true +StartupWMClass=SilentDragonLite +Categories=Utility; +MimeType=x-scheme-handler/hush; +Keywords=SilentDragonLite; + diff --git a/res/silentdragonlite_ar.qm b/res/silentdragonlite_ar.qm index cdef56c..cc809ec 100644 Binary files a/res/silentdragonlite_ar.qm and b/res/silentdragonlite_ar.qm differ diff --git a/res/silentdragonlite_ar.ts b/res/silentdragonlite_ar.ts index 1590186..3572309 100644 --- a/res/silentdragonlite_ar.ts +++ b/res/silentdragonlite_ar.ts @@ -4,1145 +4,901 @@ AddressBookModel - + Label - + - + Address - - - - - Avatar - - - - - HushChatAddress - - - - - CID - + BalancesTableModel - + Address - + - + Amount - - - - - ChatBubbleMe - - - Form - - - - - Lorem ipsum dolor sit amet - - - - - 12/03/2020 12:34 - - - - - ChatBubblePartner - - - Form - - - - - Lorem ipsum dolor sit amet - - - - - 12/03/2020 12:34 - + ConnectionDialog - + SilentDragonLite - + - - The Dragon Awakens... - + + Starting Up + Controller - + Wallet Password - + - + Your wallet is encrypted. Please enter your wallet password - + - - + + Wallet Decryption Failed - + - + Please enter a valid password - + - + Failed to unlock wallet - + CreateWalletForm - Create New SDL Wallet - - - - - Confirm Passphrase: - + Form + - + Restore wallet from seed - + - + Restore an existing wallet, using the 24-word seed. - - - - - Create a new wallet - - - - - Encryption Passphrase: - + - - <html><head/><body><p><span style=" font-style:italic;">Passphrase don't match</span></p></body></html> - + + Create a new Wallet + - - <html><head/><body><p><span style=" font-style:italic;">16 letters minimum</span></p></body></html> - - - - + Create a new wallet with a randomly generated seed. - - - - - Dialog - - - Send Contact Request - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Insert a nickname for your contact:</span></p></body></html> - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Choose an avatar for your contact:</span></p></body></html> - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Insert a memo for your request:</span></p></body></html> - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Your HushChat Address:</span></p></body></html> - - - - - Create New Address - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Insert the address of your contact:</span></p></body></html> - - - - - <html><head/><body><p><span style=" color:#d3d7cf;">Generate your HushChat Address - please wait a second - </span></p></body></html> - - - - - SDLogo - - - - - Duke - - - - - Denio - - - - - Berg - - - - - Stag - - - - - Sharpee - - - - - Elsa - - - - - Yoda - - - - - Garfield - - - - - Snoopy - - - - - Popey - - - - - Pinguin - - - - - Mickey - - - - - 0/512 - - - - - Add a memo to your request - - - - - Cancel - - - - - Add Contact and Send Request - + MainWindow - + SilentDragonLite - + - + Balance - + - + Summary - + - + Shielded - + - + Notarized - + - + Transparent - + - + Total - + - + Your node is still syncing, balances may not be updated. - + - + Some transactions are not yet confirmed. Balances may change. - + - + Address Balances - + - - + + Send - + - + Total notarized funds available: - + - + Send To - + - + Recipient - + - - - + + + Address - + - + Address Book - + - - + + Amount - + - + Max Available - + - - - + + + Memo - + - + Add Recipient - + - + + Recurring payment + + + + + Every month, starting 12-May-2012, for 6 payments + + + + + Edit Schedule + + + + Miner Fee - + - + 0 - + - + Cancel - + - + Receive - + - + Address Type - + - + z-Addr - + - + t-Addr - + - + Next Address - + - + Information about Hush - + - + <html><head/><body><p align="center"><span style=" font-weight:600;">Hush Blockchain Information</span></p></body></html> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + <html><head/><body><p align="center">|</p></body></html> - + - + Next Halving - + - + Difficulty - + - + Last Notarized Block - + - + Total Supply - + - + Longestchain - + - + BlockHeight - + - + Supply zAddr - + - + Supply tAddr - + - + <html><head/><body><p align="center"><span style=" font-weight:600;">Hush Market Information</span></p></body></html> - + - + Market Cap - + - + Volume on Exchanges - + - + <html><head/><body><p align="center">This is a Lightwallet, you cant mine with it!</p></body></html> - + - + View All Addresses - + - + Label - + - + Update Label - + - + Address balance - + - + Optional - + - - + + Export Private Key - + - + Your node is still syncing, balances may not be updated - + - + Transactions - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + Loading... - + - + Version hushlightd - + - + Vendor - - - - - Deposit Hush - + - HushChat - - - - - Incoming contact request - - - - - Add a new contact - - - - - Get a new Address - - - - - <html><head/><body><p align="center"><span style=" font-weight:600; text-decoration: underline;">Contactlist</span></p></body></html> - - - - - <html><head/><body><p align="center"><span style=" font-weight:600;">Contact Name :</span></p></body></html> - - - - - <html><head/><body><p align="center"><br/></p></body></html> - - - - - The locks shows you the status of the message. Red lock = unconfirmed, green lock = min. 1 confirmations, orange lock = message is notarized - - - - &File - + - + &Help - + - + &Apps - + - + &Edit - + - + E&xit - + - + &About - + - + &Settings - + - + Ctrl+P - + - + &Send DenioD Feedback - + - + &Hush Discord - + - + &Hush Website - + - + Check github.com for &updates - + - + &Export all private keys - + - + Address &book - + - + Ctrl+B - + - + &Export seed phrase - + - - + + Export transactions - + - + Pay hush &URI... - + - + Connect mobile &app - + - + Ctrl+M - + - + &Recurring Payments - + - + Request hush... - + - + File a bug... - + - + Encrypt Wallet - + - + Remove Wallet Encryption - + - + Rescan - + + + + + Wallet is already encrypted + + + + + Your wallet is already encrypted with a password. +Please use 'Remove Wallet Encryption' if you want to remove the wallet encryption. + - + Passwords don't match - + - - + + Error was: + + + + + + Wallet Encrypted + + + + + Your wallet was successfully encrypted! The password will be needed to send funds or export private keys. + + + + + Wallet Encryption Failed - + - + Wallet is not encrypted - + - - - Copy txid - + + Your wallet is not encrypted with a password. + - - - Copy block explorer link - + + Wallet Password + - - View tx on block explorer - + + Please enter your wallet password + - - Refresh - + + + + Wallet Decryption Failed + - - Restart - + + Please enter a password to decrypt your wallet! + - - Please restart Silentdragonlite to have the theme apply - + + Wallet Encryption Removed + - - Currency Change - + + Your wallet was successfully decrypted! You will no longer need a password to send funds or export private keys. + - - Some feedback about SilentDragonlite or Hush... - + + + Copy txid + - - This change can take a few seconds. - + + + Copy block explorer link + - - - Wallet Encryption Success - + + View tx on block explorer + - - Your wallet is not encrypted with a passphrase. + + Refresh + + + Restart + + + + + Please restart Silentdragonlite to have the theme apply + + + + + Currency Change + + - Wallet decryption Success - + Some feedback about SilentDragonlite or Hush... + - - You still have plaintext data on your disk! - + + This change can take a few seconds. + - + or SilentDragonLite - + - + Send DenioD some private and shielded feedback about - + - + Paste HUSH URI - + - + Error paying HUSH URI - + - + URI should be of the form 'hush:<addr>?amt=x&memo=y - + - + Error - + - + Error exporting transactions, file was not saved - + - + This is your wallet seed. Please back it up carefully and safely. - + - - + + Save File - + - - + + Unable to open file - + - + Error getting private keys - + - + Error loading private keys: - + - + These are all the private keys for all the addresses in your wallet - + - + Private key for - + - - + + Copy address - + - - - - + + + Copied to clipboard - + - + Get private key - + - - + + View on block explorer - + - + View Payment Request - + - + View Memo - + - + Reply to - + - - Copied message to clipboard - - - - - Copied Txid to clipboard - - - - + Created new t-Addr - + - + Copy Address - + - + Address has been previously used - + - + Address is unused - + Cannot support multiple addresses - + Recurring payments doesn't currently support multiple addresses - + Recipient - + Only z-addresses can have memos - - - - - Transaction Error - - - - - - Please wait... - - - - - Computing your transaction - - - - - - Done! - + - - - - Recipient Address - + + Memos can only be used with z-addresses + - - - You have to select a contact and insert a Memo - - - - - - You have selected no Contact from Contactlist, + + The memo field can only be used with a z-address. - + - - + -or your Memo is empty - +doesn't look like a z-address + - - - Your Message is too long - + + Transaction Error + - - - You can only write messages with 235 character maximum - - + + Please wait... + - - - - Please reduce your message to 235 character. - + + Computing your transaction + - - - Message Error - + + Done! + + + + + Recipient Address + - - - + is Invalid - + - - - + Amount for address '%1' is invalid! - + - - - + Not enough available funds to send this transaction Have: %1 Need: %2 -Note: Funds need 1 confirmations before they can be spent - - - - - Missing HushChat Address - - - - - You have to create your HushChat address to send a contact request, - - - - - - Your contact request will be sent - +Note: Funds need 5 confirmations before they can be spent + @@ -1151,12 +907,12 @@ Note: Funds need 1 confirmations before they can be spent Memo - + Include Reply Address - + @@ -1164,7 +920,7 @@ Note: Funds need 1 confirmations before they can be spent Reply to - + @@ -1172,94 +928,86 @@ Note: Funds need 1 confirmations before they can be spent Migration Turnstile - + Migration History - + Migrated Amount - + Unmigrated Amount - + Sprout -> Sapling migration enabled - + If enabled, hushd will slowly migrate your Sprout shielded funds to your Sapling address. - + MobileAppConnector - Mobile Connector App - + Connect Mobile App + Scan this QRCode from your silentdragon companion app to connect your phone - + QR Code - + Connection String - + Allow connections over the internet via silentdragon wormhole - + silentdragon Companion App - + Disconnect - + TextLabel - + Last seen: - + Connection type: - - - - - NewOrRestorePage - - - Passphrase don't match or You have entered too few letters (16 minimum) - + @@ -1267,35 +1015,35 @@ Note: Funds need 1 confirmations before they can be spent Form - + This is your new wallet's seed phrase. PLEASE BACK IT UP SECURELY. - + - + The seed phrase is the only way to restore the wallet. If you forget the seed phrase, THERE IS NO WAY TO RESTORE YOUR WALLET AND THE FUNDS in it - + NewSeedPage - + Error creating a wallet - + - + Failed to save wallet - + - + Couldn't save the wallet - + @@ -1303,315 +1051,285 @@ Note: Funds need 1 confirmations before they can be spent Private Keys - + QObject - + Pick - + - - - + Address or Label Error - + - - - + Address or Label cannot be empty - + - - - + Address Format Error - + - - - + %1 doesn't seem to be a valid hush address. - + - + Label Error - - - - - The label '%1' already exists. Please remove the existing label. - - - - - - Added Contact - + - - - successfully added your new contact - + + The label '%1' already exists. Please remove the existing label. + - + Import Address Book - + - + Unable to open file - + - + Address Book Import Done - + - + Imported %1 new Address book entries - + - + Copy address - + - + Copied to clipboard - + - + Delete label - + - + Attempting to initialize library with - + - + Using existing wallet. - + - + Create/restore wallet. - + - - + + Connection Error - + - - - - - + + + Transaction Error - + - + There was an error sending the transaction. The error was: - + - - + + No Connection - + + + + + There was an error connecting to hushd. The error was + - - - + - + Tx - + - - - + - + failed - + - - - - + + The transaction with id - + - - - - + + failed. The error was - - - - - There was an error connecting to the server. Please check your internet connection. The error was - + - + Update Available - + - + A new release v%1 is available! You have v%2. Would you like to visit the releases page? - + - + No updates available - + - + You already have the latest release v%1 - + - - + Please wait for SilentDragonLite to exit - + - - + Waiting for hushd to exit - + No hush price was available to convert from USD - + View on block explorer - + View Error - + Reported Error - + Are you sure you want to delete the recurring payment? - + All future payments will be cancelled. - + - + Tx submitted (right click to copy) txid: - + Type - + Address - + Date/Time - + Confirmations - + Amount - + Connected directly - + Connected over the internet via silentdragon wormhole service - + Node is still syncing. - + No sapling or transparent addresses with enough balance to spend. - + RecurringDialog - Reccuring Dialog + Dialog View - + Delete - + @@ -1619,45 +1337,45 @@ Would you like to visit the releases page? Amount - + Schedule - + Payments Left - + Next Payment - + To - + Every - + None - + RecurringPayments - Reocurring Payments - + Payments + @@ -1665,111 +1383,111 @@ Would you like to visit the releases page? Date - + Status - + Txid - + Not due yet - + Pending - + Skipped - + Paid - + Error - + Unknown - + RecurringPending - Recurring Multiple Payments - + Dialog + No payments will be processed. You can manually pay them from the Recurring Payments Dialog box - + Schedule - + How should silentdragon proceed? - + Pay All in 1 Tx - + Only the latest pending payment will be processed. All previous pending payments will be skipped - + Pay Latest Only - + Pay None - + All pending payments collected, added up and paid in a single transaction - + Description - + To - + The following recurring payment has multiple payments pending - + @@ -1777,292 +1495,288 @@ Would you like to visit the releases page? Payment Request - + - + AddressBook - + - + Request From - + - + My Address - + - + Amount in - + - + z address - + - + Amount - + - + The recipient will see this address in the "to" field when they pay your request. - + - + Amount USD - + - + Memo - + - + TextLabel - + - + Request payment from a Sapling address. You'll send a hush 0.0001 transaction to the address with a hush payment URI. The memo will be included in the transaction when the address pays you. - + Error paying hush URI - + URI should be of the form 'hush:<addr>?amt=x&memo=y - + Pay To - + Pay - + You are paying a payment request. Your address will not be visible to the person requesting this payment. - + Can only request from Sapling addresses - + RestoreSeedForm - Restore Wallet Seed - + Form + Please enter your 24-word seed below - + Wallet Seed - + Wallet Birthday - + 0 - + Wallet birthday is the block height at which the wallet had the first transaction. If you don't know this, you can leave it as "0" (It'll take longer to rescan) - + RestoreSeedPage - - + + Failed to restore wallet - + - + SilentDragonLite needs 24 words to restore wallet - + - + Failed to parse wallet birthday - + - + Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be. - + - + Couldn't restore the wallet - + - + Failed to save wallet - + - + Couldn't save the wallet - + Settings - + Settings - + - + Connection - + - + Lightwallet Server - + - + Options - - - - - Dark - + - - Midnight - + + default + - - Light - + + blue + - - Blue - + + light + - - Default - + + dark + - + Fetch hush prices - + - + Check github for updates at startup - + - + Connect to github on startup to check for updates - + - + Theme - + - + Connect to the internet to fetch hush prices - + - + Currency - + - + AUD - + - + BTC - + - + CAD - + - + CHF - + - + CNY - + - + EUR - + - + GBP - + - + INR - + - + RUB - + - + USD - + @@ -2070,12 +1784,12 @@ Would you like to visit the releases page? All Addresses - + Export All Keys - + @@ -2083,12 +1797,12 @@ Would you like to visit the releases page? Address - + Balance (%1) - + @@ -2096,7 +1810,7 @@ Would you like to visit the releases page? About - + @@ -2104,117 +1818,32 @@ Would you like to visit the releases page? Address Book - + - + Add New Address - + - + Address (z-Addr or t-Addr) - - - - - <html><head/><body><p>Nickname :</p></body></html> - - - - - HushChat Address - give this Address only to your contact - - - - - <html><head/><body><p>Conversation ID:</p></body></html> - - - - - SDLogo - - - - - Duke - - - - - Denio - - - - - Berg - - - - - Sharpee - - - - - Elsa - - - - - Yoda - - - - - Garflied - - - - - Snoopy - - - - - Popey - - - - - Pinguin - - - - - Mickey - - - - - Stag - + - - <html><head/><body><p>Avatar :</p></body></html> - - - - - Create a new HushChat zaddr - + + Label + - + Add to Address Book - + - + Import Address Book - + @@ -2222,27 +1851,27 @@ Would you like to visit the releases page? Confirm Transaction - + To - + Recurring Payment - + TextLabel - + You are sending a transaction while your node is still syncing. This may not work. - + @@ -2250,180 +1879,80 @@ Would you like to visit the releases page? Configure hush.conf - + Your hush node will be configured for you automatically - + Show Advanced Configuration - + Allow connections to the internet to check for updates, get hush prices etc... - + Use custom datadir - + Choose directory - + Please note that you'll need to already have a Tor service configured on port 9050 - + Connect to the internet for updates and price feeds - + Please choose a directory to store your wallet.dat and blockchain - + Connect over Tor - - - - - deposithush - - - Deposit Hush - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Ubuntu'; font-size:16pt;">Please use the following hush address to transfer funds to SilentDragonLite. You can either copy the address or use the QR Code. </span></p></body></html> - - - - - <html><head/><body><p align="center">QR Code of your Hush Address</p></body></html> - - - - - <html><head/><body><p align="center"><span style=" text-decoration: underline;">Your Hush Address </span></p></body></html> - - - - - Hush zaddr - - - - - Copy Address - + encryptionDialog - + Encrypt Your Wallet - - - - - Encryption Passphrase: - - - - - <html><head/><body><p><span style=" font-size:14pt; color:#ef2929;">WARNING:</span> If you forget your passphrase, the only way to recover the wallet is from the seed phrase. If you don't have a backup of your seed phrase, please do it now!</p></body></html> - - - - - Confirm Passphrase: - - - - - <html><head/><body><p><span style=" font-style:italic;">Passphrase don't match</span></p></body></html> - - - - - <html><head/><body><p><span style=" font-style:italic;">16 letters minimum</span></p></body></html> - - - - - hushrequest - - - Request Payment - - - - - TextLabel - - - - - Request payment from a Sapling address. You'll send a hush 0.0001 transaction to the address with a hush payment URI. The memo will be included in the transaction when the address pays you. - - - - - Request From - - - - - zaddr - - - - - Amount in - - - - - Amount - + - - Amount USD - + + Encryption Password: + - - Memo - + + Confirm Password: + - - My Address - + + Passwords don't match + - - The recipient will see this address in the "to" field when they pay your request. - + + WARNING: If you forget your password, the only way to recover the wallet is from the seed phrase. + @@ -2431,221 +1960,47 @@ p, li { white-space: pre-wrap; } Edit Schedule - + Payment Description - + Schedule - + Next Payment - + Amount - + Memo - + To - + From - + Number of payments - - - - - removeencryption - - - Decrypt Your Wallet - - - - - <html><head/><body><p><span style=" font-size:14pt; color:#ef2929;">WARNING:</span> If you remove your wallet.dat encryption, all your transactions and contacts are plaintext on disk!<br/><br/>Messages sent and received are always encrypted.</p></body></html> - - - - - <html><head/><body><p><span style=" font-style:italic;">16 letters minimum</span></p></body></html> - - - - - Encryption Passphrase: - - - - - Confirm Passphrase: - - - - - <html><head/><body><p><span style=" font-style:italic;">Passphrase don't match</span></p></body></html> - - - - - requestDialog - - - Incoming Contact Request - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Memo of the request</span></p></body></html> - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Open requests</span></p></body></html> - - - - - Request from: - - - - - Add New Contact - - - - - <html><head/><body><p>Choose an avatar for your contact:</p></body></html> - - - - - My Zaddr: - - - - - Cancel - - - - - SDLogo - - - - - Duke - - - - - Denio - - - - - Berg - - - - - Sharpee - - - - - Elsa - - - - - Yoda - - - - - Garfield - - - - - Snoopy - - - - - Popey - - - - - Pinguin - - - - - Mickey - - - - - Stag - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Recently closed requests</span></p></body></html> - - - - - <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Details of the request</span></p></body></html> - - - - - Give a Nickname: - - - - - startup - - - SDL Startup Decryption - - - - - <html><head/><body><p>If you have forgotten your passphrase, restore your wallet with your seed!</p></body></html> - - - - - Encryption Passphrase: - + diff --git a/res/silentdragonlite_ro.qm b/res/silentdragonlite_ro.qm new file mode 100644 index 0000000..185fba5 Binary files /dev/null and b/res/silentdragonlite_ro.qm differ diff --git a/res/silentdragonlite_ro.ts b/res/silentdragonlite_ro.ts new file mode 100644 index 0000000..4075e9f --- /dev/null +++ b/res/silentdragonlite_ro.ts @@ -0,0 +1,2001 @@ + + + + + AddressBookModel + + + Label + Eticheta + + + + Address + Adresa + + + + BalancesTableModel + + + Address + Adresa + + + + Amount + Valoare + + + + ConnectionDialog + + + SilentDragonLite + SilentDragonLite + + + + Starting Up + Se Porneste + + + + Controller + + + Wallet Password + Parola Portofelului + + + + Your wallet is encrypted. +Please enter your wallet password + Portofelul Dvs. este criptat + + + + + Wallet Decryption Failed + Decriptarea Portofelului a Esuat + + + + Please enter a valid password + Rugam sa introduceti parola valida + + + + Failed to unlock wallet + Deblocarea portofelului a esuat + + + + CreateWalletForm + + + Form + Forma + + + + Restore wallet from seed + Recuperati portmoneul cu ajutorul semnaturii + + + + Restore an existing wallet, using the 24-word seed. + Recuperati portofel existent folosind semnatura de 24 de cuvinte + + + + Create a new Wallet + Creati Portofel Nou + + + + Create a new wallet with a randomly generated seed. + Creati portofel nou cu ajutorul semnaturii, generate aleatoriu + + + + MainWindow + + + SilentDragonLite + SilentDragonLite + + + + Balance + Soldul + + + + Summary + Rezumat + + + + Shielded + Ecranat + + + + Notarized + Notarizat + + + + Transparent + Transparent + + + + Total + Total + + + + Your node is still syncing, balances may not be updated. + Are loc sincronizarea nodului, soldurile pot fi neactualizate. + + + + Some transactions are not yet confirmed. Balances may change. + Tranzactia nu este inca confirmata. Soldul poate schimba. + + + + Address Balances + Soldul Adresei + + + + + Send + Trimite + + + + Total notarized funds available: + Totalul fondurlor notarizate valabile: + + + + Send To + Trimite Catre + + + + Recipient + Destinatar + + + + + + + + Address + Adesa + + + + + Address Book + Carte de Adrese + + + + + + + Amount + Valoare + + + + Max Available + Maxim Disponibil + + + + + + + Memo + + + + + Add Recipient + Adauga Destinatar + + + + Recurring payment + Plata recurenta + + + + Every month, starting 12-May-2012, for 6 payments + Fiecare luna, incepind cu 12-Mai-2012 + + + + Edit Schedule + Editati Programul + + + + + Miner Fee + Taxa Minerului + + + + 0 + 0 + + + + Cancel + Anulare + + + + Receive + Primeste + + + + Address Type + Tipul Adresei + + + + z-Addr + Adresa-z + + + + t-Addr + Adresa-t + + + + Next Address + Adresa Urmatoare + + + + Information about Hush + Informatia despre Hush + + + + <html><head/><body><p align="center"><span style=" font-weight:600;">Hush Blockchain Information</span></p></body></html> + + + + + + + + + + + + + + + + <html><head/><body><p align="center">|</p></body></html> + + + + + Next Halving + Halving Urmator + + + + Difficulty + Dificultate + + + + Last Notarized Block + Ultimul Bloc Notarizat + + + + Total Supply + Cantitatea Totala + + + + Longestchain + Cel mai lung lant + + + + BlockHeight + Inaltimea Blocului + + + + Supply zAddr + Cantitatea adreselor z + + + + Supply tAddr + Cantitatea adreselor t + + + + <html><head/><body><p align="center"><span style=" font-weight:600;">Hush Market Information</span></p></body></html> + + + + + Market Cap + Capitalizarea Pietii + + + + Volume on Exchanges + Volumul Schimbului Valutar + + + + <html><head/><body><p align="center">This is a Lightwallet, you cant mine with it!</p></body></html> + + + + + View All Addresses + Vizualizati Toate Adresele + + + + Label + Eticheta + + + + Update Label + Actualizati Eticheta + + + + Address balance + Soldul Adresei + + + + Optional + Optional + + + + + Export Private Key + Exporta Cheia Privata + + + + Your node is still syncing, balances may not be updated + Are loc sincronizarea nodului, soldurile pot fi neactualizate. + + + + Transactions + Tranzactii + + + + + + + + + + + + + + + Loading... + Se Incarca... + + + + Version hushlightd + Versiunea hushlighttd + + + + Vendor + Furnizor + + + + &File + &Fisier + + + + &Help + &Ajutor + + + + &Apps + &Aplicatii + + + + &Edit + &Editati + + + + E&xit + &Iesire + + + + &About + &Despre + + + + &Settings + &Setari + + + + Ctrl+P + Ctrl+P + + + + &Send DenioD Feedback + Trimite Feedback lui Duke + + + + &Hush Discord + Hush Discord + + + + &Hush Website + Hush Website + + + + Check github.com for &updates + Verifica github.com pentru &actualizari + + + + &Export all private keys + &Exporta toate cheile private + + + + Address &book + &Carte de Adrese + + + + Ctrl+B + Ctrl+B + + + + &Export seed phrase + &Exporta semnatura + + + + + Export transactions + Exporta tranzactiile + + + + Pay hush &URI... + Plateste HUSH &URI... + + + + Connect mobile &app + Conecteaza aplicatia &mobila + + + + Ctrl+M + Ctrl+M + + + + &Recurring Payments + &Solicitarea Platilor + + + + Request hush... + Solicita HUSH... + + + + File a bug... + Depune Eroare + + + + Encrypt Wallet + Criptati Portofelul + + + + Remove Wallet Encryption + Eliminati Criptarea Portofelului + + + + Rescan + Rescanati + + + + Wallet is already encrypted + Portofelul e deja criptat + + + + Your wallet is already encrypted with a password. +Please use 'Remove Wallet Encryption' if you want to remove the wallet encryption. + Portofelul dvs. este deja criptat cu parola. +Rugam sa folositi 'Eliminati Criptarea Portofelului' daca doriti sa eliminati criptarea portofelului. + + + + Passwords don't match + Parole nu coincid + + + + Error was: + + Eroarea este: + + + + Wallet Encrypted + Portofel Criptat + + + + Your wallet was successfully encrypted! The password will be needed to send funds or export private keys. + Portofelul a fost criptat cu succes! Folosirea parolei va fi necesara in cazul transferului sau exportului fondurilor. + + + + + Wallet Encryption Failed + Criptarea Portofelului a Esuat + + + + Wallet is not encrypted + Portofelul nu este criptat + + + + Your wallet is not encrypted with a password. + Portofelul dvs. nu este criptat cu parola. + + + + Wallet Password + Parola Portofelului + + + + Please enter your wallet password + Rugam sa introduceti parola portofelului + + + + + + Wallet Decryption Failed + Decriptarea Portofelului a Esuat + + + + Please enter a password to decrypt your wallet! + Rugam sa introduceti parola pentru a decripta portofelul! + + + + Wallet Encryption Removed + Criptarea Portofelului a fost Scoasa + + + + Your wallet was successfully decrypted! You will no longer need a password to send funds or export private keys. + Portofelul Dvs. a fost decriptat cu succes! Folosirea parolei nu va fi necesara in cazul transferului sau exportului cheilor private. + + + + + Copy txid + Copiati tranzactia ID + + + + + Copy block explorer link + Copiati link-ul exploratorului de blocuri + + + + View tx on block explorer + Vizualizati tranzactia in explorator de blocuri + + + + Refresh + Actualizare + + + + Restart + Reporniti + + + + Please restart Silentdragonlite to have the theme apply + Rugam sa reporniti SilentDragon pentru aplicarea temei + + + + Currency Change + Schimbarea Valutei + + + + Some feedback about SilentDragonlite or Hush... + Feedback despre SilentDragonLite sau Hush... + + + + This change can take a few seconds. + Aceasta schimbare poate dura citeva secunde. + + + + or SilentDragonLite + sau SilentDragonLite + + + + Send DenioD some private and shielded feedback about + Trimite lui DenioD feedback privat sau ecranat + + + + Paste HUSH URI + Lipeste HUSH URI + + + + Error paying HUSH URI + Eroarea platii HUSH URI + + + + URI should be of the form 'hush:<addr>?amt=x&memo=y + Uri trebuie sa fie de forma 'hush:<addr>?amt=x&memo=y + + + + Error + Eroare + + + + Error exporting transactions, file was not saved + Eroare in timpul exportului tranzactiei, fisierul nu a fost salvat + + + + This is your wallet seed. Please back it up carefully and safely. + Aceasta este semnatura dvs. Rugam sa o copiati atent si cu siguranta. + + + + + Save File + Salveaza Fisierul + + + + + Unable to open file + Fisierul nu poate fi deschis + + + + Error getting private keys + Eroare la primirea cheilor private + + + + Error loading private keys: + Eroare la incarcarea cheilor private: + + + + These are all the private keys for all the addresses in your wallet + Acestea sint toate cheile private adreselor din portofel + + + + Private key for + Cheia privata privata + + + + + Copy address + Copiaza adresa + + + + + + Copied to clipboard + Copiata \EEn clipboard + + + + Get private key + Obtine cheia privata + + + + + View on block explorer + Vizualizare pe exploator de bloc + + + + View Payment Request + Vizualizati Plata Solicitata + + + + View Memo + Vizualizati Memo + + + + Reply to + Raspunde + + + + Created new t-Addr + O noua t-Addr a fost creata + + + + Copy Address + Copiati Adresa + + + + Address has been previously used + Adresa data a fost folosita anterior + + + + Address is unused + Adresa nu poate fi utilizata + + + + Cannot support multiple addresses + Nu poate suporta adrese multiple + + + + Recurring payments doesn't currently support multiple addresses + In momentul dat platile recurente nu suporta adrese multiple + + + + Recipient + Destinatar + + + + Only z-addresses can have memos + Doar adrese-z pot avea memo + + + + Memos can only be used with z-addresses + Memo pot fi folosite doar cu adrese-z + + + + The memo field can only be used with a z-address. + + Cimpul cu memo poate fi folosit doar cu adrese-z + + + + +doesn't look like a z-address + nu arata ca adresaz- + + + + Transaction Error + Eroarea de Tranzactie + + + + Please wait... + Rugam sa asteptati + + + + Computing your transaction + Calcularea tranzactiei + + + + Done! + Terminat! + + + + Recipient Address + Adresa Recipientului + + + + is Invalid + Este Nevalid + + + + Amount for address '%1' is invalid! + Valoarea adresei '%1' este nevalida! + + + + Not enough available funds to send this transaction + +Disponibil: %1 +Necesar: %2 + +Note: Funds need 5 confirmations before they can be spent + Nu sint suficiente fondurile pentru a trimite aceasta transactie +Aveti: %1 +Este Nevoie: %2 +Nota: Fondurile au nevoie de 5 confirmatii inainte ca sa fiu transmise + + + + MemoDialog + + + + Memo + Memo + + + + Include Reply Address + Include adresa de raspuns + + + + MemoEdit + + + Reply to + Raspunde + + + + MigrationDialog + + + Migration Turnstile + Migrarea Turnstile + + + + Migration History + Istoria Migrarii + + + + Migrated Amount + Valoarea Migrata + + + + Unmigrated Amount + Valoarea Nemigrata + + + + Sprout -> Sapling migration enabled + Sprout -> Sapling migrarea este aplicata + + + + If enabled, hushd will slowly migrate your Sprout shielded funds to your Sapling address. + Daca este aplicat, hushd va migra fondurile ecranate Sprout spre Sapling adrese. + + + + MobileAppConnector + + + Connect Mobile App + Conectati Aplicatia Mobila + + + + Scan this QRCode from your silentdragon companion app to connect your phone + Scanati acest QRcod pe de aplicatia SilentDragon Companion pentru a conecta telefonul + + + + QR Code + QR Cod + + + + Connection String + Sirul de conexiune + + + + Allow connections over the internet via silentdragon wormhole + Permiteti conexiunea prin internet cu ajutorl SilentDragon wormhole + + + + silentdragon Companion App + Aplicatia SilentDragon Companion + + + + Disconnect + Deconectati + + + + + TextLabel + TextMarca + + + + Last seen: + Vazut ultima data + + + + Connection type: + Tipul Conexiunii + + + + NewSeedForm + + + Form + Forma + + + + This is your new wallet's seed phrase. PLEASE BACK IT UP SECURELY. + Aceasta este semnatura portofelului nou. RUGAM SA O COPIATI CU SIGURANTA. + + + + The seed phrase is the only way to restore the wallet. If you forget the seed phrase, THERE IS NO WAY TO RESTORE YOUR WALLET AND THE FUNDS in it + Semnatura este unica solutie pentru restabilirea portofelului. Daca uitati semnatura, NU EXISTA NICI O SOLUTIE PENTRU RESTABILIREA PORTOFELULUI SI FONDURILOR. + + + + NewSeedPage + + + Error creating a wallet + Eroarea crearii portofelului + + + + Failed to save wallet + Salvarea portofelului a esuat + + + + Couldn't save the wallet + Salvarea portofelului nu a fost posibila + + + + PrivKey + + + Private Keys + Cheia Privata + + + + QObject + + + Pick + Alege + + + + Address or Label Error + Eroarea Marcii sau Adresei + + + + Address or Label cannot be empty + Adresa sau Marca nu pot fi goi + + + + Address Format Error + Eroarea Formatului Adresei + + + + %1 doesn't seem to be a valid hush address. + nu este o adresa HUSH valida + + + + Label Error + Eroare de Marca + + + + The label '%1' already exists. Please remove the existing label. + Marca '%1' deja exista. Rugam sa eliminati marca existenta + + + + Import Address Book + Importa Cartea de Adrese + + + + Unable to open file + Accesarea fisierului nu este posibila + + + + Address Book Import Done + typ>Importul Cartii de Adrese este Terminat + + + + Imported %1 new Address book entries + Importul %1 adresei noi a fost efectuat + + + + Copy address + Copiati adresa + + + + Copied to clipboard + Copiat in clipboard + + + + Delete label + Sterge marca + + + + Attempting to initialize library with + Incercare de initiere a bibliotecii cu + + + + Using existing wallet. + Folosirea portofelului existent. + + + + Create/restore wallet. + Creati/Restabiliti portofelul. + + + + + Connection Error + Eroare la Conexiune + + + + + + Transaction Error + Eroarea de Tranzactie + + + + There was an error sending the transaction. The error was: + A avut loc eroarea la transmiterea tranzactiei. Eroarea a fost de tip: + + + + + No Connection + Conexiunea nu exista + + + + There was an error connecting to hushd. The error was + A fost eroarea conexiunii la hushd. Eroarea a fost + + + + + + Tx + Tranzactia + + + + + + failed + a esuat + + + + + The transaction with id + Tranzactia cu id + + + + + failed. The error was + a esuat. Eroarea a fost + + + + Update Available + Update Valabil + + + + A new release v%1 is available! You have v%2. + +Would you like to visit the releases page? + O noua veriune V%1 este valabila! Tu ai v%2 +Doriti sa vizitati pagina veriunii? + + + + No updates available + Update nu este valabil + + + + You already have the latest release v%1 + Deja aveti cea mai recenta versiune v%1 + + + + Please wait for SilentDragonLite to exit + Rugam sa asteptati pina ce SilentDragonLite sa o sa iasa + + + + Waiting for hushd to exit + Asteptam ca hushd sa iasa + + + + No hush price was available to convert from USD + Nici un pret al hush nu a fost valabil pentru convertare in USD + + + + View on block explorer + Vizualizare pe expoator de bloc + + + + View Error + Vizualizati Erorea + + + + Reported Error + Eroare Raportata + + + + + Are you sure you want to delete the recurring payment? + Sinteti siguri in stergerea platii recurente? + + + + All future payments will be cancelled. + Toate platile viitoare vor fi anulate. + + + + Tx submitted (right click to copy) txid: + Tranzactia a fost inaintata (clic drept pentru a copia) tranzactia ID:> + + + + Type + Tipul + + + + Address + Adresa + + + + Date/Time + Data/Tipul + + + + Confirmations + Confirmatii + + + + Amount + Valoare + + + + Connected directly + Conectat direct + + + + Connected over the internet via silentdragon wormhole service + Conectat la internet prin serviciul SilentDragon wormhole + + + + + Node is still syncing. + Nodul inca se sincronizeaza + + + + + No sapling or transparent addresses with enough balance to spend. + Nici o adreasa Sapling sau transparenta cu sold suficient pentru transmitere. + + + + RecurringDialog + + + Dialog + Dialog + + + + View + Vizualizare + + + + Delete + Sterge + + + + RecurringListViewModel + + + Amount + Valoare + + + + Schedule + Programa + + + + Payments Left + Platile ramase + + + + Next Payment + Urmatoarea Plata + + + + To + Catre + + + + Every + Fiecare + + + + None + Nici unul + + + + RecurringPayments + + + Payments + Platile + + + + RecurringPaymentsListViewModel + + + Date + Data + + + + Status + Stare + + + + Txid + Tranzactia ID + + + + Not due yet + Inca nu + + + + Pending + In asteptare + + + + Skipped + Omit + + + + Paid + Platit + + + + Error + Eroare + + + + + Unknown + Necunoscut + + + + RecurringPending + + + Dialog + Dialog + + + + No payments will be processed. You can manually pay them from the Recurring Payments Dialog box + Platile nu vor fi procesate. Ele pot fi platite manual din Caseta de Dialog a Platilor Recurente + + + + Schedule + Programa + + + + How should silentdragon proceed? + Cum Silent Dragon trebuie sa procedeze? + + + + Pay All in 1 Tx + Platiti tot in 1 Tranzactie + + + + Only the latest pending payment will be processed. All previous pending payments will be skipped + Doar cea mai recenta plata va fi procesata. Toate platile anterioare vor fi omise + + + + Pay Latest Only + Platiti doar plata recenta + + + + Pay None + Nu plati niciuna + + + + All pending payments collected, added up and paid in a single transaction + Toate platile in asteptare au fost colectate, combinate si platite intr-o singura tranzatie + + + + Description + Descriptie + + + + To + Catre + + + + The following recurring payment has multiple payments pending + Urmatoarea plata recurenta are plati multiple, in asteptare + + + + RequestDialog + + + Payment Request + Plata Solicitata + + + + AddressBook + Carte de Adrese + + + + Request From + Solicita De la + + + + My Address + Adresa Mea + + + + Amount in + Valoare in + + + + z address + adresa z + + + + Amount + Valoare + + + + The recipient will see this address in the "to" field when they pay your request. + Destinatarul va vedea aceasta adresa in cimpul \ABpentru\BB la platirea solicitarii + + + + Amount USD + Valoarea USD + + + + Memo + Memo + + + + TextLabel + TextMarca + + + + Request payment from a Sapling address. You'll send a hush 0.0001 transaction to the address with a hush payment URI. The memo will be included in the transaction when the address pays you. + Solicita plata de pe Sapling adresa. HUSH 0.0001 tranzactia va fi transmisa la adresa cu plata HUSH URI. Memo va fi inclus in tranzactie cind adresa va plati. + + + + Error paying hush URI + Eroare platii HUSH URI + + + + URI should be of the form 'hush:<addr>?amt=x&memo=y + URI trebuie sa fie de forma 'hush:<addr>?amt=x&memo=y + + + + Pay To + Platiti lui + + + + Pay + Platiti + + + + You are paying a payment request. Your address will not be visible to the person requesting this payment. + Platiti plata solicitata. Adresa voastra nu va fi vizibila persoanei care solicita aceasta plata. + + + + Can only request from Sapling addresses + Puteti doar solicita de la adresa Sapling + + + + RestoreSeedForm + + + Form + Forma + + + + Please enter your 24-word seed below + Rugam, sa introduceti semnatura de 24 de cuvinte mai jos + + + + Wallet Seed + Semnatura Portofelului + + + + Wallet Birthday + Ziua de Nastere a Portofelului + + + + 0 + 0 + + + + Wallet birthday is the block height at which the wallet had the first transaction. If you don't know this, you can leave it as "0" (It'll take longer to rescan) + Ziua de nastere a portofelului e inaltimea blocului cind a avut loc prima tranzactie a portofelului. Daca nu o cunoasteti, lasati-o ca "0" (Rescanarea va dura mai mult timp) + + + + RestoreSeedPage + + + + Failed to restore wallet + Restabilirea portofelului a esuat + + + + SilentDragonLite needs 24 words to restore wallet + SilentDragonLite are nevoie de semnatura de 24 de cuvinte pentru restabilirea portofelului + + + + Failed to parse wallet birthday + Analizarea zilei de nastere a portofelului a esuat + + + + Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be. + Ziua de nastere a portofelului nu este inteleasa. Aceasta trebuie sa fe inaltimea blocului de unde rescanarea va avea loc. O puteti lasa ca '0' in caz daca nu cunoasteti care e. + + + + Couldn't restore the wallet + Restaurarea portofelului nu s-a putut + + + + Failed to save wallet + Salvarea portofelului a esuat + + + + Couldn't save the wallet + Salvarea portofelului nu s-a putut + + + + Settings + + + Settings + Setari + + + + Connection + Conexiuni + + + + Lightwallet Server + Lightwallet Server + + + + Options + Optiuni + + + + default + mod implicit + + + + blue + albastru + + + + light + deschis + + + + dark + inchis + + + + Fetch hush prices + Vezi pretul hush + + + + Check github for updates at startup + Verificati actualizarile pe github la pornire + + + + Connect to github on startup to check for updates + Conectati github la pornire pentru verificarea actualizarilor + + + + Theme + Teme + + + + Connect to the internet to fetch hush prices + Conectati la internet pentru a vedea pretul HUSH + + + + Currency + Valuta + + + + AUD + AUD + + + + BTC + BTC + + + + CAD + CAD + + + + CHF + CHF + + + + CNY + CNY + + + + EUR + EUR + + + + GBP + GBP + + + + INR + INR + + + + RUB + RUB + + + + USD + USD + + + + ViewAddressesDialog + + + All Addresses + Toate Adrese + + + + Export All Keys + Exporta Toate Cheile + + + + ViewAllAddressesModel + + + Address + Adresa + + + + Balance (%1) + Soldul (1%) + + + + about + + + About + Despre + + + + addressBook + + + Address Book + Carte de Adrese + + + + Add New Address + Adauga Adresa Noua + + + + Address (z-Addr or t-Addr) + Adresa (z-Addr sau t-Addr) + + + + Label + Marca + + + + Add to Address Book + Adauga in Carte de Adrese + + + + Import Address Book + Importa Cartea de Adrese + + + + confirm + + + Confirm Transaction + Confirma Tranzactia + + + + To + Catre + + + + Recurring Payment + Plata recurenta + + + + TextLabel + TextMarca + + + + You are sending a transaction while your node is still syncing. This may not work. + Trimiteti tranzactia in timp ce are loc sincronizarea nodului.E posibil aceasta sa nu functioneze. + + + + createhushConf + + + Configure hush.conf + Configureaza hush.conf + + + + Your hush node will be configured for you automatically + Nodul Hush va fi configurat in mod automat + + + + Show Advanced Configuration + Arata configuratii avansate + + + + Allow connections to the internet to check for updates, get hush prices etc... + Permiteti conexiunea prin internet pentru verificarea actualizarilor, pretului hush, etc... + + + + Use custom datadir + Indica directia stocarii datelor + + + + Choose directory + Alege locatia + + + + Please note that you'll need to already have a Tor service configured on port 9050 + Rugam sa retineti ca serviciul Tor trebuie sa fie deja configurat prin port 9050 + + + + Connect to the internet for updates and price feeds + Conectati-va la internet pentru actualizari si feed-uri preturilor + + + + Please choose a directory to store your wallet.dat and blockchain + Rugam sa alegeti locatia stocarii wallet.dat si a lantului de blocuri + + + + Connect over Tor + Conecteaza prin Tor + + + + encryptionDialog + + + Encrypt Your Wallet + Criptati Portofelul Dvs. + + + + Encryption Password: + Parola Criptarii + + + + Confirm Password: + Confirma Parola + + + + Passwords don't match + Parola nu se potriveste + + + + WARNING: If you forget your password, the only way to recover the wallet is from the seed phrase. + ATENTIE: Daca uitati parola, unica solutie de recuperare a portofelului va fi semnatura. + + + + newRecurringDialog + + + Edit Schedule + Editati Programul + + + + Payment Description + Descriptia Platii + + + + Schedule + Programa + + + + Next Payment + Urmatoarea Plata + + + + Amount + Valoare + + + + Memo + Memo + + + + To + Catre + + + + From + De la + + + + Number of payments + Numarul de plati + + + + diff --git a/silentdragon-lite.pro b/silentdragon-lite.pro index 762dab7..3dec433 100644 --- a/silentdragon-lite.pro +++ b/silentdragon-lite.pro @@ -14,6 +14,7 @@ QT += widgets QT += websockets + TARGET = SilentDragonLite TEMPLATE = app @@ -49,6 +50,7 @@ SOURCES += \ src/3rdparty/qrcode/BitBuffer.cpp \ src/3rdparty/qrcode/QrCode.cpp \ src/3rdparty/qrcode/QrSegment.cpp \ + src/3rdparty/json/json.hpp \ src/settings.cpp \ src/sendtab.cpp \ src/txtablemodel.cpp \ @@ -94,7 +96,6 @@ HEADERS += \ src/3rdparty/qrcode/BitBuffer.hpp \ src/3rdparty/qrcode/QrCode.hpp \ src/3rdparty/qrcode/QrSegment.hpp \ - src/3rdparty/json/json.hpp \ src/settings.h \ src/txtablemodel.h \ src/qrcodelabel.h \ @@ -122,6 +123,7 @@ HEADERS += \ FORMS += \ src/contactrequest.ui \ src/deposithush.ui \ + src/emoji.ui \ src/encryption.ui \ src/hushrequest.ui \ src/mainwindow.ui \ @@ -130,6 +132,8 @@ FORMS += \ src/newwallet.ui \ src/recurringpayments.ui \ src/restoreseed.ui \ + src/seedrestore.ui \ + src/sendHushTransactionChat.ui \ src/settings.ui \ src/about.ui \ src/confirm.ui \ @@ -162,6 +166,7 @@ TRANSLATIONS = res/silentdragonlite_es.ts \ res/silentdragonlite_fa.ts \ res/silentdragonlite_id.ts \ res/silentdragonlite_ar.ts \ + res/silentdragonlite_ro.ts \ res/silentdragonlite_tr.ts include(singleapplication/singleapplication.pri) diff --git a/src/Chat/Chat.cpp b/src/Chat/Chat.cpp index 672808c..3c68837 100644 --- a/src/Chat/Chat.cpp +++ b/src/Chat/Chat.cpp @@ -46,6 +46,45 @@ void ChatMemoEdit::setLenDisplayLabelChat(QLabel* label) { this->lenDisplayLabelchat = label; } +ChatMemoEditRequest::ChatMemoEditRequest(QWidget* parent) : QTextEdit(parent) { + QObject::connect(this, &QTextEdit::textChanged, this, &ChatMemoEditRequest::updateDisplayChatRequest); +} + +void ChatMemoEditRequest::updateDisplayChatRequest() { + QString txt = this->toPlainText(); + if (lenDisplayLabelchatRequest) + lenDisplayLabelchatRequest->setText(QString::number(txt.toUtf8().size()) + "/" + QString::number(maxlenchatrequest)); + + if (txt.toUtf8().size() <= maxlenchatrequest) { + // Everything is fine + if (sendRequestButton) + sendRequestButton->setEnabled(true); + + if (lenDisplayLabelchatRequest) + lenDisplayLabelchatRequest->setStyleSheet(""); + } + else { + // Overweight + if (sendRequestButton) + sendRequestButton->setEnabled(false); + + if (lenDisplayLabelchatRequest) + lenDisplayLabelchatRequest->setStyleSheet("color: red;"); + } +} + +void ChatMemoEditRequest::setMaxLenChatRequest(int len) { + this->maxlenchatrequest = len; + updateDisplayChatRequest(); +} + +void ChatMemoEditRequest::SetSendRequestButton(QPushButton* button) { + this->sendRequestButton = button; +} + +void ChatMemoEditRequest::setLenDisplayLabelChatRequest(QLabel* label) { + this->lenDisplayLabelchatRequest = label; +} void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label) { @@ -59,7 +98,8 @@ void Chat::renderChatBox(Ui::MainWindow *ui, QListView *view, QLabel *label) if ( (p.getName() == ui->contactNameMemo->text().trimmed()) && (p.getPartnerAddress() == c.second.getAddress()) && - (c.second.isOutgoing() == true)) + (c.second.isOutgoing() == true)) + { QStandardItem *Items = new QStandardItem(c.second.toChatLine()); diff --git a/src/Chat/Helper/ChatDelegator.h b/src/Chat/Helper/ChatDelegator.h index e4474a8..36a856c 100644 --- a/src/Chat/Helper/ChatDelegator.h +++ b/src/Chat/Helper/ChatDelegator.h @@ -37,7 +37,7 @@ class ListViewDelegate : public QAbstractItemDelegate inline QSize sizeHint(QStyleOptionViewItem const &option, QModelIndex const &index) const; }; -inline ListViewDelegate::ListViewDelegate(QObject *parent): QAbstractItemDelegate(parent), d_radius(5), d_toppadding(5), d_bottompadding(3), d_leftpadding(5), d_rightpadding(5), d_verticalmargin(5), d_horizontalmargin(10), d_pointerwidth(4), d_pointerheight(17), d_widthfraction(.6) +inline ListViewDelegate::ListViewDelegate(QObject *parent): QAbstractItemDelegate(parent), d_radius(15), d_toppadding(15), d_bottompadding(3), d_leftpadding(5), d_rightpadding(5), d_verticalmargin(5), d_horizontalmargin(10), d_pointerwidth(4), d_pointerheight(25), d_widthfraction(.6) { } @@ -50,7 +50,28 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons bodydoc.setDefaultTextOption(textOption); bodydoc.setDefaultFont(QFont("Roboto", 12)); QString bodytext(index.data(Qt::DisplayRole).toString()); - bodydoc.setHtml(bodytext); + bodydoc.setHtml(bodytext.replace("\n", "
")); + bodydoc.setHtml(bodytext.replace(":smiley:", "")); + bodydoc.setHtml(bodytext.replace(":-)", "")); + bodydoc.setHtml(bodytext.replace(":money_mouth:", "")); + bodydoc.setHtml(bodytext.replace(":laughing:", "")); + bodydoc.setHtml(bodytext.replace(":sweet_smile:", "")); + bodydoc.setHtml(bodytext.replace(":joy:", "")); + bodydoc.setHtml(bodytext.replace(":innocent:", "")); + bodydoc.setHtml(bodytext.replace(":partying_face:", "")); + bodydoc.setHtml(bodytext.replace(":fire:", "")); + bodydoc.setHtml(bodytext.replace(":rolling_eyes:", "")); + bodydoc.setHtml(bodytext.replace(":stuck_out_tongue:", "")); + bodydoc.setHtml(bodytext.replace(":face_with_3hearts:", "")); + bodydoc.setHtml(bodytext.replace(":heart_eyes:", "")); + bodydoc.setHtml(bodytext.replace(":nauseated:", "")); + bodydoc.setHtml(bodytext.replace(":poop:", "")); + bodydoc.setHtml(bodytext.replace(":symbols_mouth:", "")); + bodydoc.setHtml(bodytext.replace(":sunglass:", "")); + bodydoc.setHtml(bodytext.replace(":stuck_out:", "")); + bodydoc.setHtml(bodytext.replace(";p", "")); + bodydoc.setHtml(bodytext.replace(":hush_white:", "")); + bodydoc.setHtml(bodytext.replace(":sd:", "")); qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding; bodydoc.setTextWidth(contentswidth); qreal bodyheight = bodydoc.size().height(); @@ -173,7 +194,28 @@ inline QSize ListViewDelegate::sizeHint(QStyleOptionViewItem const &option, QMod bodydoc.setDefaultTextOption(textOption); bodydoc.setDefaultFont(QFont("Roboto", 12)); QString bodytext(index.data(Qt::DisplayRole).toString()); - bodydoc.setHtml(bodytext); + bodydoc.setHtml(bodytext.replace("\n", "
")); + bodydoc.setHtml(bodytext.replace(":smiley:", "")); + bodydoc.setHtml(bodytext.replace(":-)", "")); + bodydoc.setHtml(bodytext.replace(":money_mouth:", "")); + bodydoc.setHtml(bodytext.replace(":laughing:", "")); + bodydoc.setHtml(bodytext.replace(":sweet_smile:", "")); + bodydoc.setHtml(bodytext.replace(":joy:", "")); + bodydoc.setHtml(bodytext.replace(":innocent:", "")); + bodydoc.setHtml(bodytext.replace(":partying_face:", "")); + bodydoc.setHtml(bodytext.replace(":fire:", "")); + bodydoc.setHtml(bodytext.replace(":rolling_eyes:", "")); + bodydoc.setHtml(bodytext.replace(":stuck_out_tongue:", "")); + bodydoc.setHtml(bodytext.replace(":face_with_3hearts:", "")); + bodydoc.setHtml(bodytext.replace(":heart_eyes:", "")); + bodydoc.setHtml(bodytext.replace(":nauseated:", "")); + bodydoc.setHtml(bodytext.replace(":poop:", "")); + bodydoc.setHtml(bodytext.replace(":symbols_mouth:", "")); + bodydoc.setHtml(bodytext.replace(":sunglass:", "")); + bodydoc.setHtml(bodytext.replace(":stuck_out:", "")); + bodydoc.setHtml(bodytext.replace(";p", "")); + bodydoc.setHtml(bodytext.replace(":hush_white:", "")); + bodydoc.setHtml(bodytext.replace(":sd:", "")); // the width of the contents are the (a fraction of the window width) minus (margins + padding + width of the bubble's tail) qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding; @@ -190,4 +232,4 @@ inline QSize ListViewDelegate::sizeHint(QStyleOptionViewItem const &option, QMod return size; } -#endif \ No newline at end of file +#endif diff --git a/src/DataStore/ChatDataStore.cpp b/src/DataStore/ChatDataStore.cpp index 82f9db3..4e54e1e 100644 --- a/src/DataStore/ChatDataStore.cpp +++ b/src/DataStore/ChatDataStore.cpp @@ -39,6 +39,18 @@ QString ChatDataStore::getPassword() return _password; } +QString ChatDataStore::getSendZaddr() +{ + + return _zaddr; +} + +void ChatDataStore::setSendZaddr(QString zaddr) +{ + + _zaddr = zaddr; +} + void ChatDataStore::setPassword(QString password) { @@ -47,7 +59,7 @@ void ChatDataStore::setPassword(QString password) QString ChatDataStore::dump() { - json chats; + json chats; chats["count"] = this->data.size(); json j = {}; for (auto &c: this->data) @@ -55,7 +67,7 @@ QString ChatDataStore::dump() j.push_back(c.second.toJson()); } chats["chatitems"] = j; - return QString::fromStdString(chats.dump()); + return QString::fromStdString(chats.dump()); } std::map ChatDataStore::getAllRawChatItems() @@ -103,6 +115,46 @@ std::map ChatDataStore::getAllOldContactRequests() return filteredItems; } +std::map ChatDataStore::getAllCashMemosIncoming() +{ + std::map filteredItems; + + for(auto &c: this->data) + { + if ( + (c.second.isOutgoing() == false) && + (c.second.getType() == "Money") && + (c.second.getMemo().startsWith("{")) + + ) + + { + filteredItems[c.first] = c.second; + } + } + return filteredItems; +} + +std::map ChatDataStore::getAllCashMemosOutgoing() +{ + std::map filteredItems; + + for(auto &c: this->data) + { + if ( + (c.second.isOutgoing() == true) && + (c.second.getType() == "Money") && + (c.second.getMemo().startsWith("{")) + + ) + + { + filteredItems[c.first] = c.second; + } + } + return filteredItems; +} + std::map ChatDataStore::getAllMemos() { std::map filteredItems; @@ -124,4 +176,4 @@ std::map ChatDataStore::getAllMemos() ChatDataStore* ChatDataStore::instance = nullptr; -bool ChatDataStore::instanced = false; \ No newline at end of file +bool ChatDataStore::instanced = false; diff --git a/src/DataStore/ChatDataStore.h b/src/DataStore/ChatDataStore.h index c1233b6..350ac91 100644 --- a/src/DataStore/ChatDataStore.h +++ b/src/DataStore/ChatDataStore.h @@ -23,12 +23,18 @@ class ChatDataStore ChatItem getData(QString key); std::map getAllRawChatItems(); std::map getAllNewContactRequests(); + std::map getAllCashMemosOutgoing(); + std::map getAllCashMemosIncoming(); std::map getAllOldContactRequests(); std::map getAllMemos(); QString getPassword(); + QString getSendZaddr(); - void setPassword(QString Password); + void setSendZaddr(QString Password); QString _password; + + void setPassword(QString zaddr); + QString _zaddr; QString dump(); @@ -41,4 +47,4 @@ class ChatDataStore -#endif \ No newline at end of file +#endif diff --git a/src/DataStore/ContactDataStore.cpp b/src/DataStore/ContactDataStore.cpp index e853770..61d58bd 100644 --- a/src/DataStore/ContactDataStore.cpp +++ b/src/DataStore/ContactDataStore.cpp @@ -43,8 +43,8 @@ QString ContactDataStore::dump() j.push_back(c.second.toJson()); } contacts["contacts"] = j; - return QString::fromStdString(contacts.dump(4)); + return QString::fromStdString(contacts.dump(4)); } ContactDataStore* ContactDataStore::instance = nullptr; -bool ContactDataStore::instanced = false; \ No newline at end of file +bool ContactDataStore::instanced = false; diff --git a/src/DataStore/ContactDataStore.h b/src/DataStore/ContactDataStore.h index 009657e..5abfe00 100644 --- a/src/DataStore/ContactDataStore.h +++ b/src/DataStore/ContactDataStore.h @@ -31,4 +31,4 @@ class ContactDataStore -#endif \ No newline at end of file +#endif diff --git a/src/DataStore/SietchDataStore.h b/src/DataStore/SietchDataStore.h index 5b5b498..b69e0ca 100644 --- a/src/DataStore/SietchDataStore.h +++ b/src/DataStore/SietchDataStore.h @@ -28,4 +28,4 @@ class SietchDataStore } }; -#endif \ No newline at end of file +#endif diff --git a/src/FileSystem/FileSystem.h b/src/FileSystem/FileSystem.h index 34fc5fc..6ee40cd 100644 --- a/src/FileSystem/FileSystem.h +++ b/src/FileSystem/FileSystem.h @@ -9,6 +9,7 @@ #include "../Crypto/FileEncryption.h" #include using json = nlohmann::json; + class FileSystem { private: @@ -28,4 +29,4 @@ class FileSystem }; -#endif \ No newline at end of file +#endif diff --git a/src/Model/ChatItem.cpp b/src/Model/ChatItem.cpp index 66b5176..06d3ef7 100644 --- a/src/Model/ChatItem.cpp +++ b/src/Model/ChatItem.cpp @@ -158,6 +158,9 @@ QString ChatItem::toChatLine() { QDateTime myDateTime; QString lock; + QString money; + QString moneyText; + QString moneyTextRequest; myDateTime.setTime_t(_timestamp); if (_notarize == true) @@ -175,15 +178,48 @@ QString ChatItem::toChatLine() { lock = " "; - } + }else{} + + if (_memo.startsWith("Money transaction of :")) + { + if (_outgoing == true) + { + + moneyText = QString("
") + QString("
") + QString(" Outgoing Money Transaction ") + QString(" "); + }else{ + + + moneyText = QString("
") + QString("
") + QString(" Incoming Money Transaction ") + QString(" "); + + } + }else{money = ""; + moneyText = ""; } + + if (_memo.startsWith("Request of :")) + { + if (_outgoing == true) + { + + moneyTextRequest = QString("
") + QString("
") + QString(" Outgoing Hush Request ") + QString(" "); + }else{ + + + moneyTextRequest = QString("
") + QString("
") + QString(" Incoming Hush Request ") + QString(" "); + + } + }else{moneyTextRequest = ""; + moneyTextRequest = ""; } + + QString line = QString("") + myDateTime.toString("yyyy-MM-dd hh:mm"); - line += QString(lock) + QString(""); + line += QString(lock) + QString(moneyText) + QString(moneyTextRequest) + QString(""); line +=QString("

") + _memo.toHtmlEscaped() + QString("

"); return line; } + json ChatItem::toJson() { json j; @@ -203,4 +239,4 @@ json ChatItem::toJson() ChatItem::~ChatItem() { -} \ No newline at end of file +} diff --git a/src/Model/ChatItem.h b/src/Model/ChatItem.h index 900c994..991868a 100644 --- a/src/Model/ChatItem.h +++ b/src/Model/ChatItem.h @@ -57,4 +57,4 @@ class ChatItem ~ChatItem(); }; -#endif \ No newline at end of file +#endif diff --git a/src/Model/ContactItem.cpp b/src/Model/ContactItem.cpp index b542270..2188d05 100644 --- a/src/Model/ContactItem.cpp +++ b/src/Model/ContactItem.cpp @@ -95,4 +95,4 @@ json ContactItem::toJson() j["_cid"] = _cid.toStdString(); j["_avatar"] = _avatar.toStdString(); return j; -} \ No newline at end of file +} diff --git a/src/Model/ContactItem.h b/src/Model/ContactItem.h index e5e313d..9fdd7a4 100644 --- a/src/Model/ContactItem.h +++ b/src/Model/ContactItem.h @@ -37,4 +37,4 @@ public: json toJson(); }; -#endif \ No newline at end of file +#endif diff --git a/src/Model/ContactRequest.cpp b/src/Model/ContactRequest.cpp index 3ad804f..28f1d17 100644 --- a/src/Model/ContactRequest.cpp +++ b/src/Model/ContactRequest.cpp @@ -93,4 +93,4 @@ void ContactRequest::clear() ContactRequest::~ContactRequest() { clear(); -} \ No newline at end of file +} diff --git a/src/Model/ContactRequest.h b/src/Model/ContactRequest.h index 930ad56..5fe5fa3 100644 --- a/src/Model/ContactRequest.h +++ b/src/Model/ContactRequest.h @@ -37,4 +37,4 @@ class ContactRequest ~ContactRequest(); }; -#endif \ No newline at end of file +#endif diff --git a/src/addressbook.cpp b/src/addressbook.cpp index e2f481d..eb23258 100644 --- a/src/addressbook.cpp +++ b/src/addressbook.cpp @@ -250,6 +250,9 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target) ); + parent->ui->listChat->verticalScrollBar()->setValue( + parent->ui->listChat->verticalScrollBar()->maximum()); + }); // AddressBook::getInstance()->addAddressLabel(newLabel, ab.addr->text(), cid); @@ -386,25 +389,56 @@ AddressBook::AddressBook() void AddressBook::readFromStorage() { - QFile file(AddressBook::writeableFile()); + auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + QString target_decaddr_file = dir.filePath("addresslabels.dat"); + QString target_encaddr_file = dir.filePath("addresslabels.dat.enc"); + QFile file(target_encaddr_file); + QFile file1(target_decaddr_file); if (file.exists()) { + + // Decrypt first + + QString passphraseHash = DataStore::getChatDataStore()->getPassword(); + int length = passphraseHash.length(); + + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); + + #define PassphraseHashEnd ((const unsigned char *) sequence1) + #define MESSAGE_LEN length + + #define PASSWORD sequence + #define KEY_LEN crypto_box_SEEDBYTES + + const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1()); + const unsigned char *pwHash= reinterpret_cast(ba.constData()); + + + + + FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, pwHash); + + allLabels.clear(); - file.open(QIODevice::ReadOnly); - QDataStream in(&file); // read the data serialized from the file + file1.open(QIODevice::ReadOnly); + QDataStream in(&file1); // read the data serialized from the file QString version; in >> version; QList> stuff; in >> stuff; //////////////found old addrbook, and rename it to .bak - if (version != "v2") + if (version == "v1") { auto filename = QStringLiteral("addresslabels.dat"); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); QFile address(dir.filePath(filename)); + qDebug() << "is v1"; + address.rename(dir.filePath("addresslabels.bak")); }else{ @@ -419,21 +453,16 @@ void AddressBook::readFromStorage() // qDebug() << "Read " << version << " Hush contacts from disk..."; - file.close(); + file1.close(); + + FileEncryption::encrypt(target_encaddr_file, target_decaddr_file, pwHash); + file1.remove(); } else { qDebug() << "No Hush contacts found on disk!"; } - // Special. - // Add the default silentdragon donation address if it isn't already present - // QList allAddresses; - // std::transform(allLabels.begin(), allLabels.end(), - // std::back_inserter(allAddresses), [=] (auto i) { return i.getPartnerAddress(); }); - // if (!allAddresses.contains(Settings::getDonationAddr(true))) { - // allLabels.append(QPair("silentdragon donation", Settings::getDonationAddr(true))); - // } } @@ -442,12 +471,36 @@ void AddressBook::writeToStorage() //FileSystem::getInstance()->writeContacts(AddressBook::writeableFile(), DataStore::getContactDataStore()->dump()); // FileSystem::getInstance()->writeContactsOldFormat(AddressBook::writeableFile(), allLabels); + + QString passphraseHash = DataStore::getChatDataStore()->getPassword(); + int length = passphraseHash.length(); + + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); + + #define PassphraseHashEnd ((const unsigned char *) sequence1) + #define MESSAGE_LEN length + + #define PASSWORD sequence + #define KEY_LEN crypto_box_SEEDBYTES + + const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1()); + const unsigned char *pwHash= reinterpret_cast(ba.constData()); + + - - QFile file(AddressBook::writeableFile()); + auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + QString target_encaddr_file = dir.filePath("addresslabels.dat.enc"); + QString target_decaddr_file = dir.filePath("addresslabels.dat"); + + FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, pwHash); + + QFile file(target_decaddr_file); file.open(QIODevice::ReadWrite | QIODevice::Truncate); QDataStream out(&file); // we will serialize the data into the file QList> contacts; + for(auto &item: allLabels) { QList c; @@ -456,10 +509,20 @@ void AddressBook::writeToStorage() c.push_back(item.getMyAddress()); c.push_back(item.getCid()); c.push_back(item.getAvatar()); - contacts.push_back(c); + contacts.push_back(c); + } out << QString("v2") << contacts; + qDebug()<<"schreibe in Datei: "; file.close(); + + + FileEncryption::encrypt(target_encaddr_file, target_decaddr_file , pwHash); + QFile file1(target_decaddr_file); + file1.remove(); + + qDebug()<<"encrypt Addrbook writeToStorage"; + } QString AddressBook::writeableFile() diff --git a/src/chatmodel.cpp b/src/chatmodel.cpp index f5bf1b6..63146fc 100644 --- a/src/chatmodel.cpp +++ b/src/chatmodel.cpp @@ -163,7 +163,7 @@ void MainWindow::renderContactRequest(){ - if ((c.second.isOutgoing() == false) && (label_contact == c.second.getRequestZaddr())) + if ((c.second.isOutgoing() == false) && (label_contact == c.second.getRequestZaddr() && (c.second.getMemo().startsWith("{") == false))) { @@ -194,12 +194,12 @@ void MainWindow::renderContactRequest(){ QString label_contactold = index.data(Qt::DisplayRole).toString(); QStandardItemModel* contactMemo = new QStandardItemModel(); - if ((c.second.isOutgoing() == false) && (label_contactold == c.second.getContact())) + if ((c.second.isOutgoing() == false) && (label_contactold == c.second.getContact()) && (c.second.getMemo().startsWith("{") == false)) { QStandardItem* Items = new QStandardItem(c.second.getMemo()); - contactMemo->appendRow(Items); + contactMemo->appendRow(Items); requestContact.requestMemo->setModel(contactMemo); requestContact.requestMemo->show(); @@ -255,7 +255,7 @@ void MainWindow::renderContactRequest(){ ui->listContactWidget); QMessageBox::information(this, "Added Contact","successfully added your new contact. You can now Chat with this contact"); - + dialog.close(); }); dialog.exec(); @@ -433,8 +433,6 @@ Tx MainWindow::createTxFromChatPage() { QString myAddr = c.getMyAddress(); QString type = "Memo"; QString addr = c.getPartnerAddress(); - - /////////User input for chatmemos QString memoplain = ui->memoTxtChat->toPlainText().trimmed(); @@ -443,43 +441,31 @@ Tx MainWindow::createTxFromChatPage() { int lengthmemo = memoplain.length(); char *memoplainchar = NULL; - memoplainchar = new char[lengthmemo+1]; - strncpy(memoplainchar, memoplain.toLocal8Bit(), lengthmemo +1); - - /////////We convert the CID from QString to unsigned char*, so we can encrypt it later - int lengthcid = cid.length(); - - char *cidchar = NULL; - cidchar = new char[lengthcid+1]; - strncpy(cidchar, cid.toLocal8Bit(), lengthcid +1); - - - - QString pubkey = this->getPubkeyByAddress(addr); - QString passphrase = DataStore::getChatDataStore()->getPassword(); - QString hashEncryptionKey = passphrase; - int length = hashEncryptionKey.length(); + memoplainchar = new char[lengthmemo+2]; + strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1); + QString pubkey = this->getPubkeyByAddress(addr); + QString passphraseHash = DataStore::getChatDataStore()->getPassword(); + int length = passphraseHash.length(); ////////////////Generate the secretkey for our message encryption - char *hashEncryptionKeyraw = NULL; - hashEncryptionKeyraw = new char[length+1]; - strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1); + char *hashEncryptionKeyraw = NULL; + hashEncryptionKeyraw = new char[length+1]; + strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1); #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) #define MESSAGEAS1_LEN length - unsigned char hash[crypto_kx_SEEDBYTES]; - - crypto_hash_sha256(hash,MESSAGEAS1, MESSAGEAS1_LEN); - + unsigned char sk[crypto_kx_SECRETKEYBYTES]; unsigned char pk[crypto_kx_PUBLICKEYBYTES]; unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; if (crypto_kx_seed_keypair(pk,sk, - hash) !=0) { + MESSAGEAS1) !=0) { + + this->logger->write("Suspicious keypair, bail out "); } ////////////////Get the pubkey from Bob, so we can create the share key @@ -489,14 +475,21 @@ Tx MainWindow::createTxFromChatPage() { if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) { - /* Suspicious client public key, bail out */ + this->logger->write("Suspicious client public send key, bail out "); } + // Let's try to preserve Unicode characters + QByteArray ba_memo = memoplain.toUtf8(); + int ba_memo_length = ba_memo.size(); + + #define MESSAGE (const unsigned char *) ba_memo.data() + #define MESSAGE_LEN ba_memo_length + ////////////Now lets encrypt the message Alice send to Bob////////////////////////////// - #define MESSAGE (const unsigned char *) memoplainchar - #define MESSAGE_LEN lengthmemo + //#define MESSAGE (const unsigned char *) memoplainchar + //#define MESSAGE_LEN lengthmemo #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LEN) unsigned char ciphertext[CIPHERTEXT_LEN]; unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; @@ -521,8 +514,7 @@ Tx MainWindow::createTxFromChatPage() { /////Ciphertext Memo QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex(); - - + tx.toAddrs.push_back(ToFields{addr, amt, hmemo}); tx.toAddrs.push_back(ToFields{addr, amt, memo}); @@ -549,6 +541,7 @@ void MainWindow::sendChat() { QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"), tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"), QMessageBox::Ok, this); + ui->memoTxtChat->setEnabled(true); msg.exec(); return; @@ -578,6 +571,7 @@ void MainWindow::sendChat() { QMessageBox::Ok, this); msg.exec(); + ui->memoTxtChat->setEnabled(true); // abort the Tx return; @@ -597,6 +591,7 @@ void MainWindow::sendChat() { movie->start(); ui->sendChatButton->show(); ui->sendChatButton->setEnabled(false); + ui->memoTxtChat->setEnabled(true); } else { @@ -606,6 +601,8 @@ void MainWindow::sendChat() { movie1->start(); ui->sendChatButton->show(); ui->sendChatButton->setEnabled(false); + ui->memoTxtChat->setEnabled(true); + } ui->memoTxtChat->clear(); @@ -624,6 +621,8 @@ void MainWindow::sendChat() { ui->sendChatButton->setIcon(sendIcon); movie->stop(); ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); + }else{ QPixmap send(":/icons/res/sendBlack.png"); @@ -631,6 +630,7 @@ void MainWindow::sendChat() { ui->sendChatButton->setIcon(sendIcon); movie1->stop(); ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); } }); @@ -643,6 +643,7 @@ void MainWindow::sendChat() { // Errored out [=] (QString opid, QString errStr) { ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000); + ui->memoTxtChat->setEnabled(true); if (!opid.isEmpty()) errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr; @@ -657,6 +658,7 @@ void MainWindow::sendChat() { ui->sendChatButton->setIcon(sendIcon); movie->stop(); ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); }else{ QPixmap send(":/icons/res/sendBlack.png"); @@ -664,6 +666,7 @@ void MainWindow::sendChat() { ui->sendChatButton->setIcon(sendIcon); movie1->stop(); ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); } @@ -681,6 +684,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) { if (!Settings::isValidAddress(toAddr.addr)) { QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr); return QString(tr("Recipient Address ")) % addr % tr(" is Invalid"); + ui->memoTxtChat->setEnabled(true); } // This technically shouldn't be possible, but issue #62 seems to have discovered a bug @@ -698,6 +702,7 @@ QString MainWindow::doSendChatTxValidations(Tx tx) { if (available < total) { return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent") .arg(available.toDecimalhushString(), total.toDecimalhushString()); + ui->memoTxtChat->setEnabled(true); } return ""; @@ -710,9 +715,11 @@ void::MainWindow::addContact() request.setupUi(&dialog); Settings::saveRestore(&dialog); -QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () { - try + request.memorequest->setLenDisplayLabelChatRequest(request.memoSizeChatRequest); + + try { + bool sapling = true; rpc->createNewZaddr(sapling, [=] (json reply) { QString myAddr = QString::fromStdString(reply.get()[0]); @@ -720,6 +727,10 @@ QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () { request.myzaddr->setText(myAddr); ui->listReceiveAddresses->insertItem(0, myAddr); ui->listReceiveAddresses->setCurrentIndex(0); + DataStore::getChatDataStore()->setSendZaddr(myAddr); + + + qDebug()<<"Zaddr: "<text(); @@ -748,78 +758,67 @@ QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () { contactRequest.setAvatar(avatar); contactRequest.setLabel(label); - }); - - QObject::connect(request.sendRequestButton, &QPushButton::clicked, this, &MainWindow::saveandsendContact); - // QObject::connect(request.onlyAdd, &QPushButton::clicked, this, &MainWindow::saveContact); + }); + + + QObject::connect(request.sendRequestButton, &QPushButton::clicked, this, &MainWindow::saveandsendContact); + + // QObject::connect(request.onlyAdd, &QPushButton::clicked, this, &MainWindow::saveContact); dialog.exec(); - rpc->refreshContacts(ui->listContactWidget); - } void MainWindow::saveandsendContact() { - this->ContactRequest(); - + this->ContactRequest(); } // Create a Tx for a contact Request Tx MainWindow::createTxForSafeContactRequest() { Tx tx; -{ - CAmount totalAmt; - QString amtStr = "0"; - CAmount amt; - QString headerbytes = ""; - amt = CAmount::fromDecimalString("0"); - totalAmt = totalAmt + amt; + { + CAmount totalAmt; + QString amtStr = "0"; + CAmount amt; + QString headerbytes = ""; + amt = CAmount::fromDecimalString("0"); + totalAmt = totalAmt + amt; - QString cid = contactRequest.getCid(); - QString myAddr = contactRequest.getSenderAddress(); - QString type = "Cont"; - QString addr = contactRequest.getReceiverAddress(); + QString cid = contactRequest.getCid(); + QString myAddr = DataStore::getChatDataStore()->getSendZaddr(); + QString type = "Cont"; + QString addr = contactRequest.getReceiverAddress(); - - QString memo = contactRequest.getMemo(); - // QString privkey = rpc->fetchPrivKey(myAddr); - QString passphrase = DataStore::getChatDataStore()->getPassword(); - QString hashEncryptionKey = passphrase; - int length = hashEncryptionKey.length(); - ////////////////Generate the secretkey for our message encryption - char *hashEncryptionKeyraw = NULL; - hashEncryptionKeyraw = new char[length+1]; - strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1); - #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) - #define MESSAGEAS1_LEN length + QString memo = contactRequest.getMemo(); + QString passphrase = DataStore::getChatDataStore()->getPassword(); + int length = passphrase.length(); - - unsigned char hash[crypto_kx_SEEDBYTES]; +////////////////Generate the secretkey for our message encryption + char *hashEncryptionKeyraw = NULL; + hashEncryptionKeyraw = new char[length+1]; + strncpy(hashEncryptionKeyraw, passphrase.toUtf8(), length +1); - crypto_hash_sha256(hash,MESSAGEAS1, MESSAGEAS1_LEN); + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) + #define MESSAGEAS1_LEN length + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; - unsigned char sk[crypto_kx_SECRETKEYBYTES]; - unsigned char pk[crypto_kx_PUBLICKEYBYTES]; - - if (crypto_kx_seed_keypair(pk,sk, - hash) !=0) { - } + if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) { + this->logger->write("Suspicious client public contact request key, bail out "); + } - QString publicKey = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex(); + QString publicKey = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex(); + QString hmemo= createHeaderMemo(type,cid,myAddr,"", publicKey); - QString hmemo= createHeaderMemo(type,cid,myAddr,"", publicKey); + tx.toAddrs.push_back(ToFields{addr, amt, hmemo}); + tx.toAddrs.push_back(ToFields{addr, amt, memo}); + tx.fee = Settings::getMinerFee(); + } - - tx.toAddrs.push_back(ToFields{addr, amt, hmemo}); - tx.toAddrs.push_back(ToFields{addr, amt, memo}); - tx.fee = Settings::getMinerFee(); - -} - return tx; } @@ -835,26 +834,14 @@ void MainWindow::ContactRequest() { return; } - if (contactRequest.getSenderAddress().size() > 80) { - - QMessageBox msg(QMessageBox::Critical, tr("Missing HushChat Address"), - tr("You have to create your HushChat address to send a contact request,\n"), - QMessageBox::Ok, this); - - msg.exec(); - return; - } - - int max = 235; + int max = 512; QString chattext = contactRequest.getMemo();; int size = chattext.size(); if (size > max){ - // auto addr = ""; - // if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) { QMessageBox msg(QMessageBox::Critical, tr("Your Message is too long"), - tr("You can only write messages with 235 character maximum \n") + tr("\n Please reduce your message to 235 character."), + tr("You can only write messages with 512 character maximum \n") + tr("\n Please reduce your message to 235 character."), QMessageBox::Ok, this); msg.exec(); diff --git a/src/connection.cpp b/src/connection.cpp index 569ebed..163be4b 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -10,6 +10,16 @@ using json = nlohmann::json; +#ifdef Q_OS_WIN +auto dirwalletconnection = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat"); +#endif +#ifdef Q_OS_MACOS +auto dirwalletconnection = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat"); +#endif +#ifdef Q_OS_LINUX +auto dirwalletconnection = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)).filePath(".silentdragonlite/silentdragonlite-wallet.dat"); +#endif + ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc) { this->main = main; @@ -59,7 +69,6 @@ void ConnectionLoader::doAutoConnect() { qDebug() << "Doing autoconnect"; auto config = std::shared_ptr(new ConnectionConfig()); - config->dangerous = false; config->server = Settings::getInstance()->getSettings().server; // Initialize the library @@ -70,7 +79,6 @@ void ConnectionLoader::doAutoConnect() { main->logger->write(QObject::tr("Using existing wallet.")); char* resp = litelib_initialize_existing( - config->dangerous, config->server.toStdString().c_str() ); QString response = litelib_process_response(resp); @@ -85,7 +93,7 @@ void ConnectionLoader::doAutoConnect() else { main->logger->write(QObject::tr("Create/restore wallet.")); - createOrRestore(config->dangerous, config->server); + createOrRestore(config->server); d->show(); } @@ -97,13 +105,16 @@ void ConnectionLoader::doAutoConnect() // If success, set the connection main->logger->write("Connection is online."); connection->setInfo(reply); + main->logger->write("getting Connection reply"); isSyncing = new QAtomicInteger(); - isSyncing->store(true); + isSyncing->storeRelaxed(true); + main->logger->write("isSyncing"); // Do a sync at startup syncTimer = new QTimer(main); + main->logger->write("Beginning sync"); connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) { - isSyncing->store(false); + isSyncing->storeRelaxed(false); // Cancel the timer syncTimer->deleteLater(); // When sync is done, set the connection @@ -113,10 +124,13 @@ void ConnectionLoader::doAutoConnect() // While it is syncing, we'll show the status updates while it is alive. QObject::connect(syncTimer, &QTimer::timeout, [=]() { // Check the sync status - if (isSyncing != nullptr && isSyncing->load()) { + if (isSyncing != nullptr && isSyncing->loadRelaxed()) { // Get the sync status + + try { connection->doRPC("syncstatus", "", [=](json reply) { if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end()) + { qint64 synced = reply["synced_blocks"].get(); qint64 total = reply["total_blocks"].get(); @@ -128,32 +142,56 @@ void ConnectionLoader::doAutoConnect() [=](QString err) { qDebug() << "Sync error" << err; }); + }catch (...) + { + main->logger->write("catch sync progress reply"); + + } + } }); syncTimer->setInterval(1* 1000); syncTimer->start(); + main->logger->write("Start sync timer"); }, [=](QString err) { showError(err); }); } -void ConnectionLoader::createOrRestore(bool dangerous, QString server) +void ConnectionLoader::createOrRestore(QString server) { // Close the startup dialog, since we'll be showing the wizard d->hide(); // Create a wizard - FirstTimeWizard wizard(dangerous, server); + FirstTimeWizard wizard(server); + main->logger->write("Start new Wallet with FirstimeWizard"); wizard.exec(); } void ConnectionLoader::doRPCSetConnection(Connection* conn) { qDebug() << "Connectionloader finished, setting connection"; + main->logger->write("Connectionloader finished, setting connection"); rpc->setConnection(conn); d->accept(); QTimer::singleShot(1, [=]() { delete this; }); + +try +{ + + QFile plaintextWallet(dirwalletconnection); + main->logger->write("Path to Wallet.dat : " ); + plaintextWallet.remove(); + +}catch (...) + +{ + + main->logger->write("no Plaintext wallet.dat"); +} + } Connection* ConnectionLoader::makeConnection(std::shared_ptr config) @@ -202,7 +240,6 @@ void Executor::run() { char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str()); QString reply = litelib_process_response(resp); - //qDebug() << "RPC Reply=" << reply; auto parsed = json::parse( reply.toStdString().c_str(), nullptr, @@ -212,7 +249,8 @@ void Executor::run() emit handleError(reply); else - emit responseReady(parsed); + + emit responseReady(parsed); } diff --git a/src/connection.h b/src/connection.h index 7130710..715fd1d 100644 --- a/src/connection.h +++ b/src/connection.h @@ -5,14 +5,12 @@ #include "ui_connection.h" #include "precompiled.h" - using json = nlohmann::json; class Controller; struct ConnectionConfig { QString server; - bool dangerous; QString proxy; }; @@ -34,7 +32,7 @@ private: void doAutoConnect(); - void createOrRestore(bool dangerous, QString server); + void createOrRestore(QString server); void showError(QString explanation); void showInformation(QString info, QString detail = ""); @@ -64,7 +62,7 @@ public slots: void processRPCCallback(json resp); void processError(QString error); -private: +private: std::function cb; std::function errCb; @@ -73,14 +71,14 @@ private: /** * A runnable that runs some lightclient Command in a non-UI thread. * It emits the "responseReady" signal, which should be processed in a GUI thread. - * + * * Since the autoDelete flag is ON, the runnable should be destroyed automatically - * by the threadpool. + * by the threadpool. */ class Executor : public QObject, public QRunnable { Q_OBJECT -public: +public: Executor(QString cmd, QString args) { this->cmd = cmd; this->args = args; @@ -97,7 +95,7 @@ signals: private: QString cmd; - QString args; + QString args; }; /** @@ -116,8 +114,8 @@ public: void shutdown(); - - void doRPC(const QString cmd, const QString args, const std::function& cb, + + void doRPC(const QString cmd, const QString args, const std::function& cb, const std::function& errCb); void doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function& cb); void doRPCIgnoreError(const QString cmd, const QString args, const std::function& cb) ; diff --git a/src/contactrequest.ui b/src/contactrequest.ui index d187eb1..62699d3 100644 --- a/src/contactrequest.ui +++ b/src/contactrequest.ui @@ -122,22 +122,6 @@ - - - - - 0 - 0 - - - - Create New Address - - - false - - - @@ -394,7 +378,7 @@ - + 0 @@ -407,7 +391,7 @@ - + Add a memo to your request @@ -453,6 +437,13 @@ + + + ChatMemoEditRequest + QTextEdit +
mainwindow.h
+
+
diff --git a/src/controller.cpp b/src/controller.cpp index 7ce4c2d..e14e32d 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -17,6 +17,7 @@ ContactModel *contactModel = new ContactModel(); using json = nlohmann::json; + Controller::Controller(MainWindow* main) { auto cl = new ConnectionLoader(main, this); @@ -102,6 +103,9 @@ void Controller::setConnection(Connection* c) ui->listContactWidget ); + + ui->listChat->verticalScrollBar()->setValue( + ui->listChat->verticalScrollBar()->maximum()); } std::string Controller::encryptDecrypt(std::string toEncrypt) @@ -121,7 +125,7 @@ std::string Controller::encryptDecrypt(std::string toEncrypt) } // Build the RPC JSON Parameters for this tx -void Controller::fillTxJsonParams(json& allRecepients, Tx tx) +void Controller::fillTxJsonParams(json& allRecepients, Tx tx) { Q_ASSERT(allRecepients.is_array()); @@ -141,12 +145,11 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) DataStore::getSietchDataStore()->setData(QString("Sietch") + QString(i), zdust.toUtf8()); } ); } - // Set sietch zdust addr to json. - // Using DataStore singelton, to store the data into the dusts, bing bada boom :D + // Using DataStore singelton, to store the data into the dust. for(uint8_t i = 0; i < 6; i++) { - dust.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString(); + dust.at(i)["address"] = DataStore::getSietchDataStore()->getData(QString("Sietch" + QString(i))).toStdString(); } DataStore::getSietchDataStore()->clear(); // clears the datastore @@ -157,42 +160,41 @@ void Controller::fillTxJsonParams(json& allRecepients, Tx tx) const int randomStringLength = sizerandomString; QString randomString; + QRandomGenerator *gen = QRandomGenerator::system(); for(int i=0; ibounded(0, possibleCharacters.length() - 1); QChar nextChar = possibleCharacters.at(index); randomString.append(nextChar); } - - for(uint8_t i = 0; i < 6; i++) + + for(uint8_t i = 0; i < 6; i++) { int length = randomString.length(); int randomSize = rand() % 120 +10; - char *randomHash = NULL; randomHash = new char[length+1]; strncpy(randomHash, randomString.toLocal8Bit(), length +1); - #define MESSAGE ((const unsigned char *) randomHash) #define MESSAGE_LEN length #define MESSAGE_LEN1 length + randomSize + + unsigned char hash[crypto_secretstream_xchacha20poly1305_ABYTES]; -unsigned char hash[crypto_secretstream_xchacha20poly1305_ABYTES]; - -crypto_generichash(hash, sizeof hash, + crypto_generichash(hash, sizeof hash, MESSAGE, MESSAGE_LEN1, NULL, 0); -std::string decryptedMemo(reinterpret_cast(hash),MESSAGE_LEN1); -std::string encrypt = this->encryptDecrypt(decryptedMemo); -QString randomHashafter1 = QByteArray(reinterpret_cast(encrypt.c_str()),encrypt.size()).toHex(); -dust.at(i)["memo"] = randomHashafter1.toStdString(); - - } + std::string decryptedMemo(reinterpret_cast(hash),MESSAGE_LEN1); + std::string encrypt = this->encryptDecrypt(decryptedMemo); + QString randomHashafter1 = QByteArray(reinterpret_cast(encrypt.c_str()),encrypt.size()).toHex(); + dust.at(i)["memo"] = randomHashafter1.toStdString(); + } - for(uint8_t i = 0; i < 6; i++) + for(auto &it: dust) { - dust.at(i)["amount"] = 0; + it["amount"] = 0; } @@ -205,18 +207,20 @@ dust.at(i)["memo"] = randomHashafter1.toStdString(); if (Settings::isZAddress(toAddr.addr) && !toAddr.memo.trimmed().isEmpty()) rec["memo"] = toAddr.memo.toStdString(); - allRecepients.push_back(rec) ; + allRecepients.push_back(rec); } - allRecepients.insert(std::begin(allRecepients), { + allRecepients.insert(std::begin(allRecepients), { dust.at(0), dust.at(1), dust.at(2), dust.at(3), dust.at(4), dust.at(5) - + }) ; + + qDebug()<<"ADDR DUST"; } void Controller::noConnection() @@ -257,11 +261,11 @@ void Controller::refresh(bool force) getInfoThenRefresh(force); } -void Controller::processInfo(const json& info) +void Controller::processInfo(const json& info) { // Testnet? QString chainName; - if (!info["chain_name"].is_null()) + if (!info["chain_name"].is_null()) { chainName = QString::fromStdString(info["chain_name"].get()); Settings::getInstance()->setTestnet(chainName == "test"); @@ -282,18 +286,16 @@ void Controller::getInfoThenRefresh(bool force) static bool prevCallSucceeded = false; - zrpc->fetchInfo([=] (const json& reply) { + zrpc->fetchInfo([=] (const json& reply) { prevCallSucceeded = true; int curBlock = reply["latest_block_height"].get(); bool doUpdate = force || (model->getLatestBlock() != curBlock); int difficulty = reply["difficulty"].get(); int blocks_until_halving= 340000 - curBlock; - int halving_days = (blocks_until_halving * 150) / (60*60*24) ; + int halving_days = (blocks_until_halving * 150) / (60 * 60 * 24) ; int longestchain = reply["longestchain"].get(); int notarized = reply["notarized"].get(); - - model->setLatestBlock(curBlock); if ( Settings::getInstance()->get_currency_name() == "EUR" || @@ -309,11 +311,7 @@ void Controller::getInfoThenRefresh(bool force) ); ui->longestchain->setText( "Block: " + QLocale(QLocale::German).toString(longestchain) - ); - - - ui->difficulty->setText( QLocale(QLocale::German).toString(difficulty) ); @@ -342,12 +340,9 @@ void Controller::getInfoThenRefresh(bool force) ); } - ui->Version->setText( - QString::fromStdString(reply["version"].get()) - ); - ui->Vendor->setText( - QString::fromStdString(reply["vendor"].get()) - ); + ui->Version->setText(QString::fromStdString(reply["version"].get())); + ui->Vendor->setText(QString::fromStdString(reply["vendor"].get())); + main->logger->write( QString("Refresh. curblock ") % QString::number(curBlock) % ", update=" % (doUpdate ? "true" : "false") ); @@ -359,7 +354,6 @@ void Controller::getInfoThenRefresh(bool force) QString chainName = Settings::getInstance()->isTestnet() ? "test" : "main"; main->statusLabel->setText(chainName + "(" + QString::number(curBlock) + ")"); - // use currency ComboBox as input if (Settings::getInstance()->get_currency_name() == "USD") @@ -377,8 +371,6 @@ void Controller::getInfoThenRefresh(bool force) " $ " + (QLocale(QLocale::English).toString(cap,'f', 2)) ); - - } else if (Settings::getInstance()->get_currency_name() == "EUR") { @@ -568,7 +560,7 @@ void Controller::getInfoThenRefresh(bool force) zrpc->fetchSupply([=] (const json& reply) { int supply = reply["supply"].get(); int zfunds = reply["zfunds"].get(); - int total = reply["total"].get(); + int total = reply["total"].get();; if ( Settings::getInstance()->get_currency_name() == "EUR" || Settings::getInstance()->get_currency_name() == "CHF" || @@ -595,7 +587,7 @@ void Controller::getInfoThenRefresh(bool force) refreshAddresses(); // This calls refreshZSentTransactions() and refreshReceivedZTrans() refreshTransactions(); } - + refreshBalances(); int lag = longestchain - notarized ; this->setLag(lag); }, [=](QString err) { @@ -652,7 +644,7 @@ void Controller::refreshAddresses() model->replaceZaddresses(newzaddresses); auto taddrs = reply["t_addresses"].get(); - for (auto& it : taddrs) + for (auto& it : taddrs) { auto addr = QString::fromStdString(it.get()); if (Settings::isTAddress(addr)) @@ -690,7 +682,7 @@ void Controller::processUnspent(const json& reply, QMap* balan CAmount amount = CAmount::fromqint64(it["value"].get()); bool spendable = it["unconfirmed_spent"].is_null() && it["spent"].is_null(); // TODO: Wait for 1 confirmations - bool pending = !it["unconfirmed_spent"].is_null(); + bool pending = !it["unconfirmed_spent"].is_null();; unspentOutputs->push_back( UnspentOutput{ qsAddr, txid, amount, block, spendable, pending } @@ -878,7 +870,6 @@ void Controller::refreshBalances() CAmount balAvailable = balT + balVerified; model->setAvailableBalance(balAvailable); updateUIBalances(); - }); // 2. Get the UTXOs @@ -916,7 +907,8 @@ void Controller::refreshTransactions() { zrpc->fetchTransactions([=] (json reply) { QList txdata; - for (auto& it : reply.get()) { + for (auto& it : reply.get()) { + { QString address; CAmount total_amount; QList items; @@ -924,204 +916,195 @@ void Controller::refreshTransactions() { long confirmations; if (it.find("unconfirmed") != it.end() && it["unconfirmed"].get()) { confirmations = 0; - } else { + }else{ confirmations = model->getLatestBlock() - it["block_height"].get() + 1; } + auto txid = QString::fromStdString(it["txid"]); auto datetime = it["datetime"].get(); - + // First, check if there's outgoing metadata if (!it["outgoing_metadata"].is_null()) { for (auto o: it["outgoing_metadata"].get()) - { - // if (chatModel->getCidByTx(txid) == QString("0xdeadbeef")){ - QString address; + + { + // if (chatModel->getCidByTx(txid) == QString("0xdeadbeef")){ + QString address; address = QString::fromStdString(o["address"]); - + // Sent items are -ve - CAmount amount = CAmount::fromqint64(-1* o["value"].get()); + CAmount amount = CAmount::fromqint64(-1* o["value"].get()); - // Check for Memos - - if (confirmations == 0) { - chatModel->addconfirmations(txid, confirmations); - } - - if ((confirmations == 1) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))){ - DataStore::getChatDataStore()->clear(); - chatModel->killConfirmationCache(); - chatModel->killMemoCache(); - this->refresh(true); - } + // Check for Memos + if (confirmations == 0) { + chatModel->addconfirmations(txid, confirmations); + } + + if ((confirmations > 0) && (chatModel->getConfirmationByTx(txid) != QString("0xdeadbeef"))) { + DataStore::getChatDataStore()->clear(); + chatModel->killConfirmationCache(); + chatModel->killMemoCache(); + this->refresh(true); + } + QString memo; QString cid; QString headerbytes; QString publickey; if (!o["memo"].is_null()) { - memo = QString::fromStdString(o["memo"].get()); + memo = QString::fromStdString(o["memo"].get()); - if (memo.startsWith("{")) { - try - { - QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8()); - - cid = headermemo["cid"].toString(); - headerbytes = headermemo["e"].toString(); - - chatModel->addCid(txid, cid); - chatModel->addHeader(txid, headerbytes); - - } catch(...) - - { - - } - } + if (memo.startsWith("{")) { + try + { + QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8()); + + cid = headermemo["cid"].toString(); + headerbytes = headermemo["e"].toString(); + + chatModel->addCid(txid, cid); + chatModel->addHeader(txid, headerbytes); + + } + catch (...) + { + // on any exception caught + } + } bool isNotarized; if (confirmations > getLag()) { isNotarized = true; - }else{ - - isNotarized = false; } + else + { + isNotarized = false; + } - if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")){ - - cid = chatModel->getCidByTx(txid); - - }else{ - cid = ""; - } - - - if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){ - - headerbytes = chatModel->getHeaderByTx(txid); - - - }else{ - headerbytes = ""; - } - - if (main->getPubkeyByAddress(address) != QString("0xdeadbeef")){ + if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")) + { + cid = chatModel->getCidByTx(txid); + } + else + { + cid = ""; + } - publickey = main->getPubkeyByAddress(address); - + if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")) + { + headerbytes = chatModel->getHeaderByTx(txid); + } + else + { + headerbytes = ""; + } - }else{ - publickey = ""; - } + if (main->getPubkeyByAddress(address) != QString("0xdeadbeef")) + { + publickey = main->getPubkeyByAddress(address); + } + else + { + publickey = ""; + } - /////We need to filter out Memos smaller then the ciphertext size, or it will dump - - if ((memo.startsWith("{") == false) && (headerbytes.length() > 20)) - { - - QString passphrase = DataStore::getChatDataStore()->getPassword(); - QString hashEncryptionKey = passphrase; - int length = hashEncryptionKey.length(); + /////We need to filter out Memos smaller then the ciphertext size, or it will dump + if ((memo.startsWith("{") == false) && (headerbytes.length() > 20)) + { + QString passphrase = DataStore::getChatDataStore()->getPassword(); + int length = passphrase.length(); - ////////////////Generate the secretkey for our message encryption + ////////////////Generate the secretkey for our message encryption + char *hashEncryptionKeyraw = NULL; + hashEncryptionKeyraw = new char[length+1]; + strncpy(hashEncryptionKeyraw, passphrase.toUtf8(), length +1); - char *hashEncryptionKeyraw = NULL; - hashEncryptionKeyraw = new char[length+1]; - strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1); - const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1()); - const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); + const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1()); + const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) /////////// + #define MESSAGEAS1_LEN length - - - #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)/////////// - #define MESSAGEAS1_LEN length - - - unsigned char hash1[crypto_kx_SEEDBYTES]; - - crypto_hash_sha256(hash1,MESSAGEAS1, MESSAGEAS1_LEN); - unsigned char sk[crypto_kx_SECRETKEYBYTES]; - unsigned char pk[crypto_kx_PUBLICKEYBYTES]; + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; - if (crypto_kx_seed_keypair(pk,sk, - hash1) !=0) { - } - - unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; + if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) + { + main->logger->write("Keypair outgoing error"); + } + + unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; - ////////////////Get the pubkey from Bob, so we can create the share key - - - /////Create the shared key for sending the message - - if (crypto_kx_server_session_keys(server_rx, server_tx, - pk, sk, pubkeyBob) != 0) { - /* Suspicious client public key, bail out */ - } - - - const QByteArray ba = QByteArray::fromHex(memo.toLatin1()); - const unsigned char *encryptedMemo = reinterpret_cast(ba.constData()); + ////////////////Get the pubkey from Bob, so we can create the share key - const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1()); - const unsigned char *header = reinterpret_cast(ba1.constData()); - - int encryptedMemoSize1 = ba.length(); + /////Create the shared key for sending the message - QString memodecrypt; + if (crypto_kx_server_session_keys(server_rx, server_tx, pk, sk, pubkeyBob) != 0) + { + main->logger->write("Suspicious client public outgoing key, bail out "); + } + + const QByteArray ba = QByteArray::fromHex(memo.toUtf8()); + const unsigned char *encryptedMemo = reinterpret_cast(ba.constData()); - if (encryptedMemoSize1 > 15) - { - //////unsigned char* as message from QString - #define MESSAGE2 (const unsigned char *) encryptedMemo + const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1()); + const unsigned char *header = reinterpret_cast(ba1.constData()); - ///////// length of the encrypted message - #define CIPHERTEXT1_LEN encryptedMemoSize1 + int encryptedMemoSize1 = ba.length(); - ///////Message length is smaller then the encrypted message - #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES + QString memodecrypt; - //////Set the length of the decrypted message + if ((encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES) > 0) + { + //////unsigned char* as message from QString + #define MESSAGE2 (const unsigned char *) encryptedMemo - unsigned char decrypted[MESSAGE1_LEN]; - unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL]; - crypto_secretstream_xchacha20poly1305_state state; + ///////// length of the encrypted message + #define CIPHERTEXT1_LEN encryptedMemoSize1 - /////Our decrypted message is now in decrypted. We need it as QString to render it - /////Only the QString gives weird data, so convert first to std::string - // crypto_secretstream_xchacha20poly1305_keygen(client_rx); - if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) { - /* Invalid header, no need to go any further */ - } + ///////Message length is smaller then the encrypted message + #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES - if (crypto_secretstream_xchacha20poly1305_pull - (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { - /* Invalid/incomplete/corrupted ciphertext - abort */ - } + //////Set the length of the decrypted message - std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN); - - memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); + unsigned char decrypted[MESSAGE1_LEN]; + unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL]; + crypto_secretstream_xchacha20poly1305_state state; - }else{ - memodecrypt = ""; + /////Our decrypted message is now in decrypted. We need it as QString to render it + /////Only the QString gives weird data, so convert first to std::string + // crypto_secretstream_xchacha20poly1305_keygen(client_rx); + if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, server_tx) != 0) { + /* Invalid header, no need to go any further */ + } + + if (crypto_secretstream_xchacha20poly1305_pull + (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { + /* Invalid/incomplete/corrupted ciphertext - abort */ + } - } - /////Now we can convert it to QString + std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN); - - - //////////////Give us the output of the decrypted message as debug to see if it was successfully - - ChatItem item = ChatItem( + memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); + } + else + { + + memodecrypt = ""; + } + + /////Now we can convert it to QString + //////////////Give us the output of the decrypted message as debug to see if it was successfully + + ChatItem item = ChatItem( datetime, address, QString(""), @@ -1135,49 +1118,46 @@ void Controller::refreshTransactions() { isNotarized, false ); - DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); - updateUIBalances(); - + DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); + // updateUIBalances(); } - - } + } items.push_back(TransactionItemDetail{address, amount, memo}); total_amount = total_amount + amount; - } + } { - QList addresses; + QList addresses; for (auto item : items) { - // Concat all the addresses - - - addresses.push_back(item.address); - address = addresses.join(","); + // Concat all the addresses + addresses.push_back(item.address); + address = addresses.join(","); } - - } + } txdata.push_back(TransactionItem{ "send", datetime, address, txid,confirmations, items }); - } else { - // Incoming Transaction + } + else + { + + { // Incoming Transaction address = (it["address"].is_null() ? "" : QString::fromStdString(it["address"])); model->markAddressUsed(address); QString memo; if (!it["memo"].is_null()) { memo = QString::fromStdString(it["memo"]); - } items.push_back(TransactionItemDetail{ - address, + address, CAmount::fromqint64(it["amount"].get()), - memo + memo }); TransactionItem tx{ @@ -1185,7 +1165,9 @@ void Controller::refreshTransactions() { }; txdata.push_back(tx); - + } + + QString type; QString publickey; QString headerbytes; @@ -1197,8 +1179,8 @@ void Controller::refreshTransactions() { if (!it["memo"].is_null()) { if (memo.startsWith("{")) { - try - { + try + { QJsonDocument headermemo = QJsonDocument::fromJson(memo.toUtf8()); cid = headermemo["cid"].toString(); @@ -1210,225 +1192,220 @@ void Controller::refreshTransactions() { chatModel->addCid(txid, cid); chatModel->addrequestZaddr(txid, requestZaddr); chatModel->addHeader(txid, headerbytes); - + if (publickey.length() > 10){ main->addPubkey(requestZaddr, publickey); } - } catch(...) - { - - } - } + } + catch (...) + { + // on any exception + } + } - if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")){ - + if (chatModel->getCidByTx(txid) != QString("0xdeadbeef")) + { cid = chatModel->getCidByTx(txid); - - }else{ - cid = ""; + } + else + { + cid = ""; } - if (chatModel->getrequestZaddrByTx(txid) != QString("0xdeadbeef")){ - + if (chatModel->getrequestZaddrByTx(txid) != QString("0xdeadbeef")) + { requestZaddr = chatModel->getrequestZaddrByTx(txid); - }else{ - requestZaddr = ""; - } - - - if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")){ + } + else + { + requestZaddr = ""; + } + if (chatModel->getHeaderByTx(txid) != QString("0xdeadbeef")) + { headerbytes = chatModel->getHeaderByTx(txid); - - - }else{ - headerbytes = ""; - } - - if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef")){ + } + else + { + headerbytes = ""; + } + if (main->getPubkeyByAddress(requestZaddr) != QString("0xdeadbeef")) + { publickey = main->getPubkeyByAddress(requestZaddr); - - - }else{ - publickey = ""; - } - - if (contactModel->getContactbyAddress(requestZaddr) != QString("0xdeadbeef")){ + } + else + { + publickey = ""; + } - isContact = true; - contactname = contactModel->getContactbyAddress(requestZaddr); + if (contactModel->getContactbyAddress(requestZaddr) != QString("0xdeadbeef")) + { + isContact = true; + contactname = contactModel->getContactbyAddress(requestZaddr); + } + else + { + isContact = false; + contactname = ""; + } - }else{ + bool isNotarized; - isContact = false; - contactname = ""; + if (confirmations > getLag()) + { + isNotarized = true; + } + else + { + isNotarized = false; + } - } + int position = it["position"].get(); - bool isNotarized; + int ciphercheck = memo.length() - crypto_secretstream_xchacha20poly1305_ABYTES; - if (confirmations > getLag()) + if ((memo.startsWith("{") == false) && (headerbytes > 0) && (ciphercheck > 0)) + { + if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef")) { - isNotarized = true; - }else{ - - isNotarized = false; - } - - int position = it["position"].get(); - - if ((memo.startsWith("{") == false) && (headerbytes > 0)) - { - - if (chatModel->getMemoByTx(txid) == QString("0xdeadbeef")){ - - - if (position == 1) - { - - chatModel->addMemo(txid, headerbytes); - }else{} - - QString passphrase = DataStore::getChatDataStore()->getPassword(); - QString hashEncryptionKey = passphrase; - int length = hashEncryptionKey.length(); - - char *hashEncryptionKeyraw = NULL; - hashEncryptionKeyraw = new char[length+1]; - strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1); - - //const QByteArray ba2 = QByteArray::fromHex(hashEncryptionKey.toLatin1()); - // const unsigned char *hashEncryptionKeyraw = reinterpret_cast(ba2.constData()); - - const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1()); - const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); + if (position == 1) + { + chatModel->addMemo(txid, headerbytes); + } + else + { + // + } + QString passphrase = DataStore::getChatDataStore()->getPassword(); + int length = passphrase.length(); - #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)/////////// - #define MESSAGEAS1_LEN length + char *hashEncryptionKeyraw = NULL; + hashEncryptionKeyraw = new char[length+1]; + strncpy(hashEncryptionKeyraw, passphrase.toUtf8(), length +1); - - unsigned char hash1[crypto_kx_SEEDBYTES]; + const QByteArray pubkeyBobArray = QByteArray::fromHex(publickey.toLatin1()); + const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); - crypto_hash_sha256(hash1,MESSAGEAS1, MESSAGEAS1_LEN); - unsigned char sk[crypto_kx_SECRETKEYBYTES]; - unsigned char pk[crypto_kx_PUBLICKEYBYTES]; - - if (crypto_kx_seed_keypair(pk,sk, - hash1) !=0) { + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)/////////// + #define MESSAGEAS1_LEN length + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; - } - unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES]; + if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) + { + main->logger->write("Suspicious outgoing key pair, bail out "); + } - - ////////////////Get the pubkey from Bob, so we can create the share key + unsigned char client_rx[crypto_kx_SESSIONKEYBYTES], client_tx[crypto_kx_SESSIONKEYBYTES]; - - /////Create the shared key for sending the message + ////////////////Get the pubkey from Bob, so we can create the share key - if (crypto_kx_client_session_keys(client_rx, client_tx, - pk, sk, pubkeyBob) != 0) { - /* Suspicious client public key, bail out */ - } - - + /////Create the shared key for sending the message - const QByteArray ba = QByteArray::fromHex(memo.toLatin1()); - const unsigned char *encryptedMemo = reinterpret_cast(ba.constData()); + if (crypto_kx_client_session_keys(client_rx, client_tx, pk, sk, pubkeyBob) != 0) + { + main->logger->write("Suspicious client public incoming key, bail out "); + } - const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1()); - const unsigned char *header = reinterpret_cast(ba1.constData()); + const QByteArray ba = QByteArray::fromHex(memo.toUtf8()); + const unsigned char *encryptedMemo = reinterpret_cast(ba.constData()); - int encryptedMemoSize1 = ba.length(); - int headersize = ba1.length(); + const QByteArray ba1 = QByteArray::fromHex(headerbytes.toLatin1()); + const unsigned char *header = reinterpret_cast(ba1.constData()); - //////unsigned char* as message from QString - #define MESSAGE2 (const unsigned char *) encryptedMemo + int encryptedMemoSize1 = ba.length(); + int headersize = ba1.length(); - ///////// length of the encrypted message - #define CIPHERTEXT1_LEN encryptedMemoSize1 + //////unsigned char* as message from QString + #define MESSAGE2 (const unsigned char *) encryptedMemo - ///////Message length is smaller then the encrypted message - #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES + ///////// length of the encrypted message + #define CIPHERTEXT1_LEN encryptedMemoSize1 - //////Set the length of the decrypted message + ///////Message length is smaller then the encrypted message + #define MESSAGE1_LEN encryptedMemoSize1 - crypto_secretstream_xchacha20poly1305_ABYTES - unsigned char decrypted[MESSAGE1_LEN]; - unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL]; - crypto_secretstream_xchacha20poly1305_state state; + //////Set the length of the decrypted message - /////Our decrypted message is now in decrypted. We need it as QString to render it - /////Only the QString gives weird data, so convert first to std::string - // crypto_secretstream_xchacha20poly1305_keygen(client_rx); - if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) { - /* Invalid header, no need to go any further */ - } + unsigned char decrypted[MESSAGE1_LEN+1]; + unsigned char tag[crypto_secretstream_xchacha20poly1305_TAG_FINAL]; + crypto_secretstream_xchacha20poly1305_state state; - if (crypto_secretstream_xchacha20poly1305_pull - (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { - /* Invalid/incomplete/corrupted ciphertext - abort */ - } + /////Our decrypted message is now in decrypted. We need it as QString to render it + /////Only the QString gives weird data, so convert first to std::string + // crypto_secretstream_xchacha20poly1305_keygen(client_rx); + if (crypto_secretstream_xchacha20poly1305_init_pull(&state, header, client_rx) != 0) { + main->logger->write("Invalid header incoming, no need to go any further "); + } - std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN); + if (crypto_secretstream_xchacha20poly1305_pull + (&state, decrypted, NULL, tag, MESSAGE2, CIPHERTEXT1_LEN, NULL, 0) != 0) { + main->logger->write("Invalid/incomplete/corrupted ciphertext - abort"); + } - /////Now we can convert it to QString - QString memodecrypt; - - memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); - + std::string decryptedMemo(reinterpret_cast(decrypted),MESSAGE1_LEN); + /////Now we can convert it to QString + QString memodecrypt; - // } - //////////////Give us the output of the decrypted message as debug to see if it was successfully - + memodecrypt = QString::fromUtf8( decryptedMemo.data(), decryptedMemo.size()); + // } + //////////////Give us the output of the decrypted message as debug to see if it was successfully - ChatItem item = ChatItem( + ChatItem item = ChatItem( datetime, address, contactname, memodecrypt, requestZaddr, type, - cid, + cid, txid, confirmations, false, isNotarized, isContact ); - DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); - - }else{ - - } - - }else{ - ChatItem item = ChatItem( - datetime, - address, - contactname, - memo, - requestZaddr, - type, - cid, - txid, - confirmations, - false, - isNotarized, - isContact - ); - DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); + DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); + + } + else + { + // + } + + } + else + { + ChatItem item = ChatItem( + datetime, + address, + contactname, + memo, + requestZaddr, + type, + cid, + txid, + confirmations, + false, + isNotarized, + isContact + ); + DataStore::getChatDataStore()->setData(ChatIDGenerator::getInstance()->generateID(item), item); } } + } + } } - } + } - // Calculate the total unspent amount that's pending. This will need to be + // Calculate the total unspent amount that's pending. This will need to be // shown in the UI so the user can keep track of pending funds CAmount totalPending; for (auto txitem : txdata) { @@ -1444,13 +1421,14 @@ void Controller::refreshTransactions() { // Update UI Balance updateUIBalances(); - // Update model data, which updates the table view - transactionsTableModel->replaceData(txdata); - chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat); + // Update model data, which updates the table view + transactionsTableModel->replaceData(txdata); + chat->renderChatBox(ui, ui->listChat,ui->memoSizeChat); ui->listChat->verticalScrollBar()->setValue( ui->listChat->verticalScrollBar()->maximum()); - - }); + + }); + } void Controller::refreshChat(QListView *listWidget, QLabel *label) @@ -1464,6 +1442,8 @@ void Controller::refreshChat(QListView *listWidget, QLabel *label) void Controller::refreshContacts(QListView *listWidget) { contactModel->renderContactList(listWidget); + ui->listChat->verticalScrollBar()->setValue( + ui->listChat->verticalScrollBar()->maximum()); } // If the wallet is encrpyted and locked, we need to unlock it @@ -1560,11 +1540,11 @@ void Controller::executeTransaction(Tx tx, std::cout << std::setw(2) << params << std::endl; zrpc->sendTransaction(QString::fromStdString(params.dump()), [=](const json& reply) { - if (reply.find("txid") == reply.end()) + if (reply.find("txid") == reply.end()) { error("", "Couldn't understand Response: " + QString::fromStdString(reply.dump())); - } - else + } + else { QString txid = QString::fromStdString(reply["txid"].get()); submitted(txid); @@ -1773,7 +1753,7 @@ void Controller::refreshZECPrice() const json& item = parsed.get(); const json& hush = item["hush"].get(); - if (hush["usd"] >= 0) + if (hush["usd"] >= 0) { qDebug() << "Found hush key in price json"; qDebug() << "HUSH = $" << QString::number((double)hush["usd"]); @@ -1804,7 +1784,7 @@ void Controller::refreshZECPrice() Settings::getInstance()->setRUBPrice( hush["rub"]); } - if (hush["cad"] >= 0) + if (hush["cad"] >= 0) { qDebug() << "HUSH = CAD" << QString::number((double)hush["cad"]); Settings::getInstance()->setCADPrice( hush["cad"]); @@ -1858,7 +1838,7 @@ void Controller::refreshZECPrice() Settings::getInstance()->setBTCVolume( hush["btc_24h_vol"]); } - if (hush["cny_24h_vol"] >= 0) + if (hush["cny_24h_vol"] >= 0) { qDebug() << "HUSH = cny_24h_vol" << QString::number((double)hush["cny_24h_vol"]); Settings::getInstance()->setCNYVolume( hush["cny_24h_vol"]); @@ -2049,7 +2029,7 @@ void Controller::shutdownhushd() } bool finished = false; - zrpc->saveWallet([&] (json) { + zrpc->saveWallet([&] (json) { if (!finished) d.accept(); finished = true; diff --git a/src/controller.h b/src/controller.h index 195827c..bbf3cc7 100644 --- a/src/controller.h +++ b/src/controller.h @@ -19,6 +19,7 @@ #include "Model/ContactRequestChatItem.h" #include "Model/ContactItem.h" #include "contactmodel.h" + using json = nlohmann::json; struct WatchedTx { @@ -40,7 +41,7 @@ public: Connection* getConnection() { return zrpc->getConnection(); } void setConnection(Connection* c); void refresh(bool force = false); - void refreshAddresses(); + void refreshAddresses(); int getLag(); void setLag(int lag); int _lag; @@ -99,35 +100,35 @@ public: void noConnection(); bool isEmbedded() { return ehushd != nullptr; } - void encryptWallet(QString password, const std::function& cb) { + void encryptWallet(QString password, const std::function& cb) { zrpc->encryptWallet(password, cb); } - void removeWalletEncryption(QString password, const std::function& cb) { + void removeWalletEncryption(QString password, const std::function& cb) { zrpc->removeWalletEncryption(password, cb); } void saveWallet(const std::function& cb) { zrpc->saveWallet(cb); } void clearWallet(const std::function& cb) { zrpc->clearWallet(cb); } - void createNewZaddr(bool sapling, const std::function& cb) { + void createNewZaddr(bool sapling, const std::function& cb) { unlockIfEncrypted([=] () { zrpc->createNewZaddr(sapling, cb); }, [=](){}); } - void createNewTaddr(const std::function& cb) { + void createNewTaddr(const std::function& cb) { unlockIfEncrypted([=] () { zrpc->createNewTaddr(cb); }, [=](){}); } - void createNewSietchZaddr(const std::function& cb) { + void createNewSietchZaddr(const std::function& cb) { unlockIfEncrypted([=] () { zrpc->createNewSietchZaddr(cb); }, [=](){}); } - void fetchPrivKey(QString addr, const std::function& cb) { + void fetchPrivKey(QString addr, const std::function& cb) { unlockIfEncrypted([=] () { zrpc->fetchPrivKey(addr, cb); }, @@ -136,7 +137,7 @@ public: }); } - void fetchAllPrivKeys(const std::function cb) { + void fetchAllPrivKeys(const std::function cb) { unlockIfEncrypted([=] () { zrpc->fetchAllPrivKeys(cb); }, diff --git a/src/emoji.ui b/src/emoji.ui new file mode 100644 index 0000000..8118466 --- /dev/null +++ b/src/emoji.ui @@ -0,0 +1,339 @@ + + + emojiDialog + + + + 0 + 0 + 261 + 150 + + + + Emoji + + + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + + :/emoji/res/emoji/emoji1.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/laughing.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/sweet_smile.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/joy.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/innocent.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/partying_face.png + + + + true + + + + + + + + + + + :/icons/res/money-mouth.png + + + + true + + + + + + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + + :/emoji/res/emoji/face-with-rolling-eyes.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/face-with-tongue.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/face_with_3hearts.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/heart_shaped_eyes.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/nauseated-face.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/pile-of-poo.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/serious-face-with-symbols-covering-mouth.png + + + + true + + + + + + + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + + + + :/emoji/res/emoji/smiling-face-with-sunglasses.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/stuck-out.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/hush-money-white.png + + + + true + + + + + + + + + + + :/emoji/res/emoji/SD.png + + + + true + + + + + + + + + + diff --git a/src/firsttimewizard.cpp b/src/firsttimewizard.cpp index 5ef96bb..47941ea 100644 --- a/src/firsttimewizard.cpp +++ b/src/firsttimewizard.cpp @@ -8,14 +8,24 @@ #include "../lib/silentdragonlitelib.h" -using json = nlohmann::json; -FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server) +FirstTimeWizard::FirstTimeWizard(QString server) { setWindowTitle("New wallet wizard"); - this->dangerous = dangerous; this->server = server; + ////backup addresslabels.dat if there is one, to restore it later + + auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + QString addressbook = dir.filePath("addresslabels.dat.enc"); + QFile file(addressbook); + + if (file.exists()) + { + file.rename(dir.filePath("addresslabels.dat.enc-backup")); + + } + // Create the pages setPage(Page_NewOrRestore, new NewOrRestorePage(this)); setPage(Page_New, new NewSeedPage(this)); @@ -40,34 +50,86 @@ int FirstTimeWizard::nextId() const { NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent) { setTitle("Create or Restore wallet."); - - QWidget* pageWidget = new QWidget(); Ui_CreateWalletForm form; form.setupUi(pageWidget); - + + QGraphicsScene* scene = new QGraphicsScene(); + QGraphicsView* view = new QGraphicsView(scene); + form.Logo->setScene(scene); + QPixmap pixmap(":/icons/res/dark-01.png"); + scene->addPixmap(pixmap); + form.Logo->show(); + + + parent->button(QWizard::CommitButton)->setEnabled(false); + setButtonText(QWizard::CommitButton, "Next"); + form.txtPassword->setEnabled(false); + form.txtConfirmPassword->setEnabled(false); + + QObject::connect(form.TOS, &QRadioButton::clicked, [=](bool checked) { + if (checked) { + + form.txtPassword->setEnabled(true); + form.txtConfirmPassword->setEnabled(true); + + } + }); + auto fnPasswordEdited = [=](const QString&) { // Enable the Finish button if the passwords match. - QString Password = form.txtPassword->text(); + QString passphraseBlank = form.txtPassword->text(); + + QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL"); + if (!form.txtPassword->text().isEmpty() && - form.txtPassword->text() == form.txtConfirmPassword->text() && Password.size() >= 16) { + form.txtPassword->text() == form.txtConfirmPassword->text() && passphraseBlank.size() >= 16 ){ form.lblPasswordMatch->setText(""); - parent->button(QWizard::CommitButton)->setEnabled(true); - setButtonText(QWizard::CommitButton, "Next"); + + form.radioRestoreWallet->setEnabled(true); form.radioNewWallet->setEnabled(true); form.radioNewWallet->setChecked(true); + parent->button(QWizard::CommitButton)->setEnabled(true); - -DataStore::getChatDataStore()->setPassword(Password); + int length = passphrase.length(); + + char *sequence = NULL; + sequence = new char[length+1]; + strncpy(sequence, passphrase.toUtf8(), length +1); + + QString passphraseHash = blake3_PW(sequence); + + + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); + + #define MESSAGE ((const unsigned char *) sequence) + #define MESSAGE_LEN length + #define hash ((const unsigned char *) sequence1) + + #define PASSWORD sequence + #define KEY_LEN crypto_box_SEEDBYTES + + unsigned char key[KEY_LEN]; + + if (crypto_pwhash + (key, sizeof key, PASSWORD, strlen(PASSWORD), hash, + crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { + /* out of memory */ +} + QString passphraseHash1 = QByteArray(reinterpret_cast(key), KEY_LEN).toHex(); + DataStore::getChatDataStore()->setPassword(passphraseHash1); //main->setPassword(Password); //qDebug()<<"Objekt gesetzt"; - + // Exclusive buttons QObject::connect(form.radioNewWallet, &QRadioButton::clicked, [=](bool checked) { if (checked) { @@ -82,6 +144,8 @@ DataStore::getChatDataStore()->setPassword(Password); } }); + + @@ -106,6 +170,8 @@ DataStore::getChatDataStore()->setPassword(Password); form.radioRestoreWallet->setEnabled(false); form.radioNewWallet->setEnabled(false); setCommitPage(true); + + } @@ -127,7 +193,7 @@ NewSeedPage::NewSeedPage(FirstTimeWizard *parent) : QWizardPage(parent) { void NewSeedPage::initializePage() { // Call the library to create a new wallet. - char* resp = litelib_initialize_new(parent->dangerous, parent->server.toStdString().c_str()); + char* resp = litelib_initialize_new(parent->server.toStdString().c_str()); QString reply = litelib_process_response(resp); auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); @@ -136,8 +202,6 @@ void NewSeedPage::initializePage() { } else { QString seed = QString::fromStdString(parsed["seed"].get()); form.txtSeed->setPlainText(seed); - - } @@ -151,6 +215,7 @@ bool NewSeedPage::validatePage() { auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) { + QMessageBox::warning(this, tr("Failed to save wallet"), tr("Couldn't save the wallet") + "\n" + reply, QMessageBox::Ok); @@ -196,10 +261,14 @@ bool RestoreSeedPage::validatePage() { return false; } +///Number + +QString number_str = form.number->text(); +qint64 number = number_str.toUInt(); // 3. Attempt to restore wallet with the seed phrase { - char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(), - seed.toStdString().c_str(), birthday); + char* resp = litelib_initialize_new_from_phrase(parent->server.toStdString().c_str(), + seed.toStdString().c_str(), birthday, number); QString reply = litelib_process_response(resp); if (reply.toUpper().trimmed() != "OK") { diff --git a/src/firsttimewizard.h b/src/firsttimewizard.h index 8d84b61..8b6de40 100644 --- a/src/firsttimewizard.h +++ b/src/firsttimewizard.h @@ -5,6 +5,7 @@ #include "ui_newseed.h" #include "ui_restoreseed.h" +#include "ui_newwallet.h" #include "mainwindow.h" @@ -15,7 +16,7 @@ class FirstTimeWizard: public QWizard public: - FirstTimeWizard(bool dangerous, QString server); + FirstTimeWizard(QString server); protected: @@ -28,7 +29,6 @@ private: Page_Restore }; - bool dangerous; QString server; friend class NewOrRestorePage; diff --git a/src/liteinterface.cpp b/src/liteinterface.cpp index e17bb71..3d7a4a1 100644 --- a/src/liteinterface.cpp +++ b/src/liteinterface.cpp @@ -129,7 +129,7 @@ void LiteInterface::removeWalletEncryption(QString password, const std::function } -void LiteInterface::sendTransaction(QString params, const std::function& cb, +void LiteInterface::sendTransaction(QString params, const std::function& cb, const std::function& err) { if (conn == nullptr) return; @@ -137,7 +137,7 @@ void LiteInterface::sendTransaction(QString params, const std::functiondoRPC("send", params, cb, err); } -void LiteInterface::fetchInfo(const std::function& cb, +void LiteInterface::fetchInfo(const std::function& cb, const std::function& err) { if (conn == nullptr) return; @@ -153,7 +153,7 @@ void LiteInterface::fetchSupply(const std::function& cb) { } -void LiteInterface::fetchLatestBlock(const std::function& cb, +void LiteInterface::fetchLatestBlock(const std::function& cb, const std::function& err) { if (conn == nullptr) return; diff --git a/src/liteinterface.h b/src/liteinterface.h index 4f9c13c..b8309bd 100644 --- a/src/liteinterface.h +++ b/src/liteinterface.h @@ -42,12 +42,12 @@ public: void fetchTransactions (const std::function& cb); void fetchAddresses (const std::function& cb); - void fetchInfo(const std::function& cb, + void fetchInfo(const std::function& cb, const std::function& err); - void fetchLatestBlock(const std::function& cb, + void fetchLatestBlock(const std::function& cb, const std::function& err); void fetchBalance(const std::function& cb); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 338c8b2..64a3148 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -17,13 +17,16 @@ #include "settings.h" #include "version.h" #include "connection.h" +#include "ui_sendHushTransactionChat.h" #include "ui_contactrequest.h" #include "ui_deposithush.h" +#include "ui_emoji.h" #include "ui_requestContactDialog.h" #include "chatmodel.h" #include "requestdialog.h" #include "ui_startupencryption.h" #include "ui_removeencryption.h" +#include "ui_seedrestore.h" #include "websockets.h" #include "sodium.h" #include "sodium/crypto_generichash_blake2b.h" @@ -33,11 +36,14 @@ #include "Crypto/FileEncryption.h" #include "DataStore/DataStore.h" #include "firsttimewizard.h" +#include "../lib/silentdragonlitelib.h" +#include +#include +#include using json = nlohmann::json; - #ifdef Q_OS_WIN auto dirwallet = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet.dat"); auto dirwalletenc = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)).filePath("silentdragonlite/silentdragonlite-wallet-enc.dat"); @@ -159,17 +165,124 @@ MainWindow::MainWindow(QWidget *parent) : // Rescan QObject::connect(ui->actionRescan, &QAction::triggered, [=]() { - // To rescan, we clear the wallet state, and then reload the connection + + QFile file(dirwalletenc); + QFile file1(dirwallet); + + if(fileExists(dirwalletenc)) + + { + file.remove(); + file1.remove(); + } + + + Ui_Restore restoreSeed; + QDialog dialog(this); + restoreSeed.setupUi(&dialog); + Settings::saveRestore(&dialog); + + + rpc->fetchSeed([=](json reply) { + if (isJsonError(reply)) { + return; + } + + restoreSeed.seed->setReadOnly(true); + restoreSeed.seed->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap); + QString seedJson = QString::fromStdString(reply.get()); + int startPos = seedJson.indexOf("seed") +7; + int endPos = seedJson.indexOf("}") -1; + int length = endPos - startPos; + QString seed = seedJson.mid(startPos, length); + restoreSeed.seed->setPlainText(seed); + + int startPosB = seedJson.indexOf("birthday") +10; + int endPosB = seedJson.indexOf("seed") -2; + int lengthB = endPosB - startPosB; + QString birthday = seedJson.mid(startPosB, lengthB); + restoreSeed.birthday->setPlainText(birthday); + }); + + QObject::connect(restoreSeed.restore, &QPushButton::clicked, [&](){ + + QString seed = restoreSeed.seed->toPlainText(); + if (seed.trimmed().split(" ").length() != 24) { + QMessageBox::warning(this, tr("Failed to restore wallet"), + tr("SilentDragonLite needs 24 words to restore wallet"), + QMessageBox::Ok); + return false; + } + + + // 2. Validate birthday + QString birthday_str = restoreSeed.birthday->toPlainText(); + bool ok; + qint64 birthday = birthday_str.toUInt(&ok); + if (!ok) { + QMessageBox::warning(this, tr("Failed to parse wallet birthday"), + tr("Couldn't understand wallet birthday. This should be a block height from where to rescan the wallet. You can leave it as '0' if you don't know what it should be."), + QMessageBox::Ok); + return false; + } + + + QString number_str = restoreSeed.quantity->text(); + qint64 number = number_str.toUInt(); + + auto config = std::shared_ptr(new ConnectionConfig()); + config->server = Settings::getInstance()->getSettings().server; + // 3. Attempt to restore wallet with the seed phrase + { + char* resp = litelib_initialize_new_from_phrase(config->server.toStdString().c_str(), + seed.toStdString().c_str(), birthday, number); + QString reply = litelib_process_response(resp); + + if (reply.toUpper().trimmed() != "OK") { + QMessageBox::warning(this, tr("Failed to restore wallet"), + tr("Couldn't restore the wallet") + "\n" + reply, + QMessageBox::Ok); + + } + } + + // 4. Finally attempt to save the wallet + { + char* resp = litelib_execute("save", ""); + QString reply = litelib_process_response(resp); + + QByteArray ba_reply = reply.toUtf8(); + QJsonDocument jd_reply = QJsonDocument::fromJson(ba_reply); + QJsonObject parsed = jd_reply.object(); + + if (parsed.isEmpty() || parsed["result"].isNull()) { + QMessageBox::warning(this, tr("Failed to save wallet"), + tr("Couldn't save the wallet") + "\n" + reply, + QMessageBox::Ok); + + } else {} + + dialog.close(); + // To rescan, we clear the wallet state, and then reload the connection // This will start a sync, and show the scanning status. this->getRPC()->clearWallet([=] (auto) { // Save the wallet this->getRPC()->saveWallet([=] (auto) { // Then reload the connection. The ConnectionLoader deletes itself. - auto cl = new ConnectionLoader(this, rpc); + auto cl = new ConnectionLoader(this, rpc); cl->loadConnection(); - }); - }); - }); + }); + }); + + + } + + }); + + // }); + + dialog.exec(); +}); // Address Book QObject::connect(ui->action_Address_Book, &QAction::triggered, this, &MainWindow::addressBook); @@ -305,53 +418,31 @@ void MainWindow::closeEvent(QCloseEvent* event) { fileoldencryption.remove(); // Encrypt our wallet.dat - QString str = DataStore::getChatDataStore()->getPassword(); - // QString str = ed.txtPassword->text(); // data comes from user inputs - int length = str.length(); - - char *sequence = NULL; - sequence = new char[length+1]; - strncpy(sequence, str.toLocal8Bit(), length +1); + QString passphraseHash = DataStore::getChatDataStore()->getPassword(); + int length = passphraseHash.length(); - #define MESSAGE ((const unsigned char *) sequence) - #define MESSAGE_LEN length - - unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES]; - - crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN); - - #define PASSWORD sequence - #define KEY_LEN crypto_box_SEEDBYTES - - + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); - /////////we use the Hash of the Password as Salt, not perfect but still a good solution. + #define PassphraseHashEnd ((const unsigned char *) sequence1) + #define MESSAGE_LEN length - unsigned char key[KEY_LEN]; + #define PASSWORD sequence + #define KEY_LEN crypto_box_SEEDBYTES - if (crypto_pwhash - (key, sizeof key, PASSWORD, strlen(PASSWORD), hash, - crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, - crypto_pwhash_ALG_DEFAULT) != 0) { - /* out of memory */ -} - + const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1()); + const unsigned char *encryptedMemo1 = reinterpret_cast(ba.constData()); + auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); - // auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); - QString source_file = dir.filePath("addresslabels.dat"); - QString target_enc_file = dir.filePath("addresslabels.dat.enc"); QString sourceWallet_file = dirwallet; QString target_encWallet_file = dirwalletenc; - FileEncryption::encrypt(target_enc_file, source_file, key); - FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key); - - ///////////////// we rename the plaintext wallet.dat to Backup, for testing. + // FileEncryption::encrypt(target_enc_file, source_file, key); + FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, encryptedMemo1); QFile wallet(dirwallet); - QFile address(dir.filePath("addresslabels.dat")); wallet.remove(); - address.remove(); } @@ -399,51 +490,49 @@ void MainWindow::encryptWallet() { if (d.exec() == QDialog::Accepted) { - QString passphrase = ed.txtPassword->text(); // data comes from user inputs + QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs + QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL"); int length = passphrase.length(); - DataStore::getChatDataStore()->setPassword(passphrase); - - char *sequence = NULL; - sequence = new char[length+1]; - strncpy(sequence, passphrase.toLocal8Bit(), length +1); - - #define MESSAGE ((const unsigned char *) sequence) - #define MESSAGE_LEN length - - unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES]; + - crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN); + char *sequence = NULL; + sequence = new char[length+1]; + strncpy(sequence, passphrase.toUtf8(), length +1); + + QString passphraseHash = blake3_PW(sequence); + DataStore::getChatDataStore()->setPassword(passphraseHash); - #define PASSWORD sequence - #define KEY_LEN crypto_box_SEEDBYTES + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); - + #define MESSAGE ((const unsigned char *) sequence) + #define MESSAGE_LEN length + #define hash ((const unsigned char *) sequence1) - /////////we use the Hash of the Password as Salt, not perfect but still a good solution. + #define PASSWORD sequence + #define KEY_LEN crypto_box_SEEDBYTES - unsigned char key[KEY_LEN]; + unsigned char key[KEY_LEN]; - if (crypto_pwhash - (key, sizeof key, PASSWORD, strlen(PASSWORD), hash, - crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, - crypto_pwhash_ALG_DEFAULT) != 0) { - /* out of memory */ + if (crypto_pwhash + (key, sizeof key, PASSWORD, strlen(PASSWORD), hash, + crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { + /* out of memory */ } + QString passphraseHash1 = QByteArray(reinterpret_cast(key), KEY_LEN).toHex(); + DataStore::getChatDataStore()->setPassword(passphraseHash1); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); - QString source_file = dir.filePath("addresslabels.dat"); - QString target_enc_file = dir.filePath("addresslabels.dat.enc"); QString sourceWallet_file = dirwallet; QString target_encWallet_file = dirwalletenc; - - FileEncryption::encrypt(target_enc_file, source_file, key); + FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key); QFile wallet(dirwallet); - QFile address(dir.filePath("addresslabels.dat")); wallet.rename(dirwalletbackup); - address.rename(dir.filePath("addresslabels.datBackup")); QMessageBox::information(this, tr("Wallet Encryption Success"), QString("Successfully encrypted your wallet"), @@ -484,27 +573,28 @@ void MainWindow::removeWalletEncryption() { if (d.exec() == QDialog::Accepted) { - QString str = ed.txtPassword->text(); // data comes from user inputs - int length = str.length(); + QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs + + QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL"); + + int length = passphrase.length(); char *sequence = NULL; sequence = new char[length+1]; - strncpy(sequence, str.toLocal8Bit(), length +1); + strncpy(sequence, passphrase.toUtf8(), length +1); - #define MESSAGE ((const unsigned char *) sequence) - #define MESSAGE_LEN length + QString passphraseHash = blake3_PW(sequence); - unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES]; + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); - crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN); + + #define hash ((const unsigned char *) sequence1) #define PASSWORD sequence #define KEY_LEN crypto_box_SEEDBYTES - - - /////////we use the Hash of the Password as Salt, not perfect but still a good solution. - unsigned char key[KEY_LEN]; if (crypto_pwhash @@ -513,18 +603,14 @@ void MainWindow::removeWalletEncryption() { crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ } - - auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); QString target_encwallet_file = dirwalletenc; QString target_decwallet_file = dirwallet; - QString target_encaddr_file = dir.filePath("addresslabels.dat.enc"); - QString target_decaddr_file = dir.filePath("addresslabels.dat"); FileEncryption::decrypt(target_decwallet_file, target_encwallet_file, key); - FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key); + QFile filencrypted(dirwalletenc); QFile wallet(dirwallet); @@ -556,85 +642,64 @@ void MainWindow::removeWalletEncryptionStartUp() { QDialog d(this); Ui_startup ed; ed.setupUi(&d); - + if (d.exec() == QDialog::Accepted) { - QString password = ed.txtPassword->text(); // data comes from user inputs - int length = password.length(); - DataStore::getChatDataStore()->setPassword(password); + QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs + + QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL"); + int length = passphrase.length(); + char *sequence = NULL; sequence = new char[length+1]; - strncpy(sequence, password.toLocal8Bit(), length +1); + strncpy(sequence, passphrase.toUtf8(), length +1); + + QString passphraseHash = blake3_PW(sequence); + + + char *sequence1 = NULL; + sequence1 = new char[length+1]; + strncpy(sequence1, passphraseHash.toUtf8(), length+1); #define MESSAGE ((const unsigned char *) sequence) #define MESSAGE_LEN length - - unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES]; - - crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN); + #define hash ((const unsigned char *) sequence1) #define PASSWORD sequence - #define KEY_LEN crypto_box_SEEDBYTES + #define KEY_LEN crypto_box_SEEDBYTES - - - /////////we use the Hash of the Password as Salt, not perfect but still a good solution. - - unsigned char key[KEY_LEN]; + unsigned char key[KEY_LEN]; - if (crypto_pwhash - (key, sizeof key, PASSWORD, strlen(PASSWORD), hash, - crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, - crypto_pwhash_ALG_DEFAULT) != 0) { + if (crypto_pwhash + (key, sizeof key, PASSWORD, strlen(PASSWORD), hash, + crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, + crypto_pwhash_ALG_DEFAULT) != 0) { /* out of memory */ - } +} + QString passphraseHash1 = QByteArray(reinterpret_cast(key), KEY_LEN).toHex(); + DataStore::getChatDataStore()->setPassword(passphraseHash1); - - { auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); - auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); + QString target_encwallet_file = dirwalletenc; QString target_decwallet_file = dirwallet; - QString target_encaddr_file = dir.filePath("addresslabels.dat.enc"); - QString target_decaddr_file = dir.filePath("addresslabels.dat"); FileEncryption::decrypt(target_decwallet_file, target_encwallet_file, key); - FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key); - } + auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); QFile wallet(dirwallet); - //QFile backup(dirHome.filePath(".silentdragonlite/silentdragonlite-wallet.datBACKUP"));*/ - if (wallet.size() > 0) + if (wallet.size() == 0) { - if (fileExists(dirwalletbackup)) - - { - - QMessageBox::information(this, tr("You still have plaintext data on your disk!"), - QString("WARNING: Delete it only if you have a backup of your Wallet Seed."), - QMessageBox::Ok - ); - // backup.remove(); - - } - - QMessageBox::information(this, tr("Wallet Encryption Success"), - QString("SDL is ready to Rock"), - QMessageBox::Ok - ); - - - }else{ - + QMessageBox::critical(this, tr("Wallet Encryption Failed"), QString("false password please try again"), QMessageBox::Ok ); this->removeWalletEncryptionStartUp(); - } + }else{} }else{ @@ -655,6 +720,30 @@ void MainWindow::setPassword(QString password) _password = password; } +QString MainWindow::getAmt() +{ + + return _amt; +} + +void MainWindow::setAmt(QString amt) +{ + + _amt = amt; +} + +QString MainWindow::getMoneyMemo() +{ + + return _moneymemo; +} + +void MainWindow::setMoneyMemo(QString moneymemo) +{ + + _moneymemo = moneymemo; +} + void MainWindow::setupStatusBar() { // Status Bar loadingLabel = new QLabel(); @@ -731,8 +820,6 @@ void MainWindow::setupSettingsModal() { QObject::connect(settings.comboBoxTheme, &QComboBox::currentTextChanged, [=] (QString theme_name) { this->slot_change_theme(theme_name); - // Tell the user to restart - QMessageBox::information(this, tr("Restart"), tr("Please restart Silentdragonlite to have the theme apply"), QMessageBox::Ok); }); // Get Currency Data @@ -756,7 +843,7 @@ void MainWindow::setupSettingsModal() { // List of default servers settings.cmbServer->addItem("https://lite.myhush.org"); - settings.cmbServer->addItem("rnhk4pwlsbaqzx7wcqfy47lijf2opklstaukq35reiz5rn76crfqpjqd.onion:9067"); + settings.cmbServer->addItem("6onaaujm4ozaokzu.onion:80"); // Load current values into the dialog @@ -1169,7 +1256,7 @@ void MainWindow::setupBalancesTab() { QList allAddresses; allAddresses = getRPC()->getModel()->getAllZAddresses(); - QString depositzaddr = allAddresses[1]; + QString depositzaddr = allAddresses[0]; deposithush.qrcodeDisplayDeposit->setQrcodeString(depositzaddr); deposithush.zaddr->setText(depositzaddr); @@ -1245,9 +1332,9 @@ void MainWindow::setupTransactionsTab() { // Set up context menu on transactions tab auto theme = Settings::getInstance()->get_theme_name(); if (theme == "Dark" || theme == "Midnight") { - ui->listChat->setStyleSheet("background-image: url(:/icons/res/sdlogo.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat;background-size: cover"); + ui->listChat->setStyleSheet("background-image: url(:/icons/res/SDLogo.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat"); } - if (theme == "Default") {ui->listChat->setStyleSheet("background-image: url(:/icons/res/sdlogo2.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat;background-size: cover");} + if (theme == "Default") {ui->listChat->setStyleSheet("background-image: url(:/icons/res/sdlogo2.png) ;background-attachment: fixed ;background-position: center center ;background-repeat: no-repeat");} ui->listChat->setResizeMode(QListView::Adjust); ui->listChat->setWordWrap(true); @@ -1344,6 +1431,8 @@ void MainWindow::setupTransactionsTab() { void MainWindow::setupchatTab() { + ui->memoTxtChat->setEnabled(false); + /////////////Setting Icons for Chattab and different themes auto theme = Settings::getInstance()->get_theme_name(); @@ -1388,6 +1477,11 @@ void MainWindow::setupchatTab() { } QObject::connect(ui->sendChatButton, &QPushButton::clicked, this, &MainWindow::sendChat); + QObject::connect(ui->sendChatButton, &QPushButton::clicked, [&] () { + + ui->memoTxtChat->setEnabled(false); + + }); QObject::connect(ui->safeContactRequest, &QPushButton::clicked, this, &MainWindow::addContact); QObject::connect(ui->pushContact, &QPushButton::clicked, this , &MainWindow::renderContactRequest); @@ -1411,6 +1505,8 @@ void MainWindow::setupchatTab() { ui->listChat->addAction(viewexplorer); ui->listChat->addAction(copytxid); + }); + QObject::connect(copymessage, &QAction::triggered, [=] { @@ -1503,7 +1599,7 @@ void MainWindow::setupchatTab() { } }); -}); + ///////// Add contextmenu QMenu* contextMenu; @@ -1513,10 +1609,8 @@ void MainWindow::setupchatTab() { QAction* requestHushAction; QAction* subatomicAction; contextMenu = new QMenu(ui->listContactWidget); - requestAction = new QAction("Send a contact request - coming soon",contextMenu); + HushAction = new QAction("Send or Request Hush ",contextMenu); editAction = new QAction("Delete this contact",contextMenu); - HushAction = new QAction("Send a friend some Hush - coming soon",contextMenu); - requestHushAction = new QAction("Request some Hush - coming soon",contextMenu); subatomicAction = new QAction("Make a subatomic swap with a friend- coming soon",contextMenu); @@ -1525,25 +1619,86 @@ void MainWindow::setupchatTab() { QObject::connect(ui->listContactWidget, &QTableView::clicked, [=] () { ui->listContactWidget->setContextMenuPolicy(Qt::ActionsContextMenu); - ui->listContactWidget->addAction(requestAction); - ui->listContactWidget->addAction(editAction); ui->listContactWidget->addAction(HushAction); - ui->listContactWidget->addAction(requestHushAction); + ui->listContactWidget->addAction(editAction); ui->listContactWidget->addAction(subatomicAction); + ui->memoTxtChat->setEnabled(true); - /*QObject::connect(requestHushAction, &QAction::triggered, [=]() { QModelIndex index = ui->listContactWidget->currentIndex(); - QString label_contact = index.data(Qt::DisplayRole).toString(); + QString label_contact = index.data(Qt::DisplayRole).toString(); for(auto &p : AddressBook::getInstance()->getAllAddressLabels()) if (label_contact == p.getName()) { ui->contactNameMemo->setText(p.getName()); rpc->refresh(true); + + } + }); + + QObject::connect(HushAction, &QAction::triggered, [=]() { + + QModelIndex index = ui->listContactWidget->currentIndex(); + QString label_contact = index.data(Qt::DisplayRole).toString(); + + Ui_transactionHush transaction; + QDialog transactionDialog(this); + transaction.setupUi(&transactionDialog); + Settings::saveRestore(&transactionDialog); + // transaction.requestHush->setEnabled(false); + // transaction.requestHush->setVisible(false); + transaction.amountChat->setValidator(this->getAmountValidator()); + QString icon = ":icons/res/hush-money-white.png"; + QPixmap hush(icon); + transaction.label_3->setPixmap(hush); + + + + for(auto &p : AddressBook::getInstance()->getAllAddressLabels()) + if (label_contact == p.getName()) { + + QStandardItemModel* contact = new QStandardItemModel(); + QString avatar = p.getAvatar(); + QStandardItem* Items1 = new QStandardItem(p.getName()); + Items1->setData(QIcon(avatar),Qt::DecorationRole); + contact->appendRow(Items1); + transaction.contactName->setModel(contact); + transaction.contactName->setIconSize(QSize(60,70)); + transaction.contactName->setUniformItemSizes(true); + transaction.contactName->setDragDropMode(QAbstractItemView::DropOnly); + transaction.contactName->show(); + } - MainWindow::showRequesthush(); - - }); */ + + QObject::connect(transaction.sendHush, &QPushButton::clicked, [&] (){ + + QString amt = transaction.amountChat->text(); + QString memo = transaction.MemoMoney->text(); + this->setAmt(amt); + this->setMoneyMemo(memo); + transactionDialog.close(); + }); + + QObject::connect(transaction.sendHush, &QPushButton::clicked, this , &MainWindow::sendMoneyChat); + + + + QObject::connect(transaction.requestHush, &QPushButton::clicked, [&] (){ + + QString amt = transaction.amountChat->text(); + QString memo = transaction.MemoMoney->text(); + this->setAmt(amt); + this->setMoneyMemo(memo); + transactionDialog.close(); + }); + + QObject::connect(transaction.requestHush, &QPushButton::clicked, this , &MainWindow::sendMoneyRequestChat); + + + + transactionDialog.exec(); + + }); QObject::connect(editAction, &QAction::triggered, [=]() { QModelIndex index = ui->listContactWidget->currentIndex(); @@ -1566,20 +1721,579 @@ void MainWindow::setupchatTab() { } }); + + +ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat); + +} + +// Create a Tx from the current state of the Chat page. +Tx MainWindow::createTxFromSendChatPage() { + Tx tx; + CAmount totalAmt; + // For each addr/amt in the Chat tab + { + + QString amtStr = this->getAmt(); + CAmount amt; + CAmount amtHm; + + amt = CAmount::fromDecimalString(amtStr); + amtHm = CAmount::fromDecimalString("0"); + totalAmt = totalAmt + amt; + QModelIndex index = ui->listContactWidget->currentIndex(); QString label_contact = index.data(Qt::DisplayRole).toString(); - - for(auto &p : AddressBook::getInstance()->getAllAddressLabels()) - if (label_contact == p.getName()) { - ui->contactNameMemo->setText(p.getName()); - rpc->refresh(true); + + for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) + + if (label_contact == c.getName()) { + + QString cid = c.getCid(); + QString myAddr = c.getMyAddress(); + QString type = "Money"; + QString addr = c.getPartnerAddress(); + QString moneymemo = this->getMoneyMemo(); + + /////////User input for chatmemos + QString memoplain = QString("Money transaction of : ") + amtStr + QString(" HUSH") + QString("\n") + QString("\n") + moneymemo; + + /////////We convert the user input from QString to unsigned char*, so we can encrypt it later + int lengthmemo = memoplain.length(); + + char *memoplainchar = NULL; + memoplainchar = new char[lengthmemo+2]; + strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1); + + QString pubkey = this->getPubkeyByAddress(addr); + QString passphraseHash = DataStore::getChatDataStore()->getPassword(); + int length = passphraseHash.length(); + + ////////////////Generate the secretkey for our message encryption + + char *hashEncryptionKeyraw = NULL; + hashEncryptionKeyraw = new char[length+1]; + strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1); + + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) + #define MESSAGEAS1_LEN length + + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; + unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; + + if (crypto_kx_seed_keypair(pk,sk, + MESSAGEAS1) !=0) { + + this->logger->write("Suspicious keypair, bail out "); + } + ////////////////Get the pubkey from Bob, so we can create the share key + + const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1()); + const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); + /////Create the shared key for sending the message + + if (crypto_kx_server_session_keys(server_rx, server_tx, + pk, sk, pubkeyBob) != 0) { + this->logger->write("Suspicious client public send key, bail out "); + } + + + // Let's try to preserve Unicode characters + QByteArray ba_memo = memoplain.toUtf8(); + int ba_memo_length = ba_memo.size(); + + #define MESSAGEMoney (const unsigned char *) ba_memo.data() + #define MESSAGE_LENMoney ba_memo_length + + + ////////////Now lets encrypt the message Alice send to Bob////////////////////////////// + //#define MESSAGE (const unsigned char *) memoplainchar + //#define MESSAGE_LEN lengthmemo + #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LENMoney) + unsigned char ciphertext[CIPHERTEXT_LEN]; + unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; + + crypto_secretstream_xchacha20poly1305_state state; + + /* Set up a new stream: initialize the state and create the header */ + crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx); + + + /* Now, encrypt the first chunk. `c1` will contain an encrypted, + * authenticated representation of `MESSAGE_PART1`. */ + crypto_secretstream_xchacha20poly1305_push + (&state, ciphertext, NULL, MESSAGEMoney, MESSAGE_LENMoney, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL); + + ////Create the HM for this message + QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex(); + QString publickeyAlice = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex(); + + + QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice,1,0); + + /////Ciphertext Memo + QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex(); + + + tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo}); + tx.toAddrs.push_back(ToFields{addr, amt, memo}); + + } + } + + tx.fee = Settings::getMinerFee(); + + return tx; + +} + +void MainWindow::sendMoneyChat() { + +////////////////////////////Todo: Check if a Contact is selected////////// + + // Create a Tx from the values on the send tab. Note that this Tx object + // might not be valid yet. + + /* QString Name = ui->contactNameMemo->text(); + + if ((ui->contactNameMemo->text().isEmpty()) || (ui->memoTxtChat->toPlainText().trimmed().isEmpty())) { + + QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"), + tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"), + QMessageBox::Ok, this); + + msg.exec(); + return; + }*/ + + + Tx tx = createTxFromSendChatPage(); + + QString error = doSendChatMoneyTxValidations(tx); + + if (!error.isEmpty()) { + // Something went wrong, so show an error and exit + QMessageBox msg(QMessageBox::Critical, tr("Message Error"), error, + QMessageBox::Ok, this); + + msg.exec(); + ui->memoTxtChat->setEnabled(true); + + // abort the Tx + return; + } + + auto movie = new QMovie(this); + auto movie1 = new QMovie(this); + movie->setFileName(":/img/res/loaderblack.gif"); + movie1->setFileName(":/img/res/loaderwhite.gif"); + + auto theme = Settings::getInstance()->get_theme_name(); + if (theme == "Dark" || theme == "Midnight") { + + connect(movie, &QMovie::frameChanged, [=]{ + ui->sendChatButton->setIcon(movie->currentPixmap()); + }); + movie->start(); + ui->sendChatButton->show(); + ui->sendChatButton->setEnabled(false); + + } else { + + connect(movie1, &QMovie::frameChanged, [=]{ + ui->sendChatButton->setIcon(movie1->currentPixmap()); + }); + movie1->start(); + ui->sendChatButton->show(); + ui->sendChatButton->setEnabled(false); + ui->memoTxtChat->setEnabled(false); } - }); + + ui->memoTxtChat->clear(); + + // And send the Tx + rpc->executeTransaction(tx, + [=] (QString txid) { + ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid); + + + QTimer::singleShot(1000, [=]() { + + if (theme == "Dark" || theme == "Midnight") { + QPixmap send(":/icons/res/send-white.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie->stop(); + ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); + }else{ + + QPixmap send(":/icons/res/sendBlack.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie1->stop(); + ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); + } + + }); + + // Force a UI update so we get the unconfirmed Tx + rpc->refresh(true); + ui->memoTxtChat->clear(); + // ui->memoTxtChat->setEnabled(true); + + }, + // Errored out + [=] (QString opid, QString errStr) { + ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000); + ui->memoTxtChat->setEnabled(true); + + if (!opid.isEmpty()) + errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr; + + QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok); + movie->stop(); + ui->memoTxtChat->setEnabled(true); + + + if (theme == "Dark" || theme == "Midnight") { + QPixmap send(":/icons/res/send-white.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie->stop(); + ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); + }else{ + + QPixmap send(":/icons/res/sendBlack.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie1->stop(); + ui->sendChatButton->setEnabled(true); + ui->memoTxtChat->setEnabled(true); + } + + + } + ); + + } + +QString MainWindow::doSendChatMoneyTxValidations(Tx tx) { + // Check to see if we have enough verified funds to send the Tx. + + CAmount total; + for (auto toAddr : tx.toAddrs) { + if (!Settings::isValidAddress(toAddr.addr)) { + QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr); + return QString(tr("Recipient Address ")) % addr % tr(" is Invalid"); + ui->memoTxtChat->setEnabled(true); + } + + // This technically shouldn't be possible, but issue #62 seems to have discovered a bug + // somewhere, so just add a check to make sure. + if (toAddr.amount.toqint64() < 0) { + return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr)); + ui->memoTxtChat->setEnabled(true); + } + + total = total + toAddr.amount; + } + total = total + tx.fee; + + auto available = rpc->getModel()->getAvailableBalance(); + + if (available < total) { + return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent") + .arg(available.toDecimalhushString(), total.toDecimalhushString()); + ui->memoTxtChat->setEnabled(true); + + } + + return ""; +} + +// Create a Tx from the current state of the Chat page. +Tx MainWindow::createTxFromSendRequestChatPage() { + Tx tx; + CAmount totalAmt; + // For each addr/amt in the Chat tab + { + + QString amtStr = this->getAmt(); + CAmount amt; + CAmount amtHm; + + amt = CAmount::fromDecimalString("0"); + amtHm = CAmount::fromDecimalString("0"); + totalAmt = totalAmt + amt; + + QModelIndex index = ui->listContactWidget->currentIndex(); + QString label_contact = index.data(Qt::DisplayRole).toString(); + + for(auto &c : AddressBook::getInstance()->getAllAddressLabels()) + + if (label_contact == c.getName()) { + + QString cid = c.getCid(); + QString myAddr = c.getMyAddress(); + QString type = "Money"; + QString addr = c.getPartnerAddress(); + QString moneymemo = this->getMoneyMemo(); + + /////////User input for chatmemos + QString memoplain = QString("Request of : ") + amtStr + QString(" HUSH ") + QString("\n") + QString("\n") + moneymemo; + + /////////We convert the user input from QString to unsigned char*, so we can encrypt it later + int lengthmemo = memoplain.length(); + + char *memoplainchar = NULL; + memoplainchar = new char[lengthmemo+2]; + strncpy(memoplainchar, memoplain.toUtf8(), lengthmemo +1); + + QString pubkey = this->getPubkeyByAddress(addr); + QString passphraseHash = DataStore::getChatDataStore()->getPassword(); + int length = passphraseHash.length(); + + ////////////////Generate the secretkey for our message encryption + + char *hashEncryptionKeyraw = NULL; + hashEncryptionKeyraw = new char[length+1]; + strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1); + + #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) + #define MESSAGEAS1_LEN length + + + unsigned char sk[crypto_kx_SECRETKEYBYTES]; + unsigned char pk[crypto_kx_PUBLICKEYBYTES]; + unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; + + if (crypto_kx_seed_keypair(pk,sk, + MESSAGEAS1) !=0) { + + this->logger->write("Suspicious keypair, bail out "); + } + ////////////////Get the pubkey from Bob, so we can create the share key + + const QByteArray pubkeyBobArray = QByteArray::fromHex(pubkey.toLatin1()); + const unsigned char *pubkeyBob = reinterpret_cast(pubkeyBobArray.constData()); + /////Create the shared key for sending the message + + if (crypto_kx_server_session_keys(server_rx, server_tx, + pk, sk, pubkeyBob) != 0) { + this->logger->write("Suspicious client public send key, bail out "); + } + + + // Let's try to preserve Unicode characters + QByteArray ba_memo = memoplain.toUtf8(); + int ba_memo_length = ba_memo.size(); + + #define MESSAGEMoney (const unsigned char *) ba_memo.data() + #define MESSAGE_LENMoney ba_memo_length + + + ////////////Now lets encrypt the message Alice send to Bob////////////////////////////// + //#define MESSAGE (const unsigned char *) memoplainchar + //#define MESSAGE_LEN lengthmemo + #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LENMoney) + unsigned char ciphertext[CIPHERTEXT_LEN]; + unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; + + crypto_secretstream_xchacha20poly1305_state state; + + /* Set up a new stream: initialize the state and create the header */ + crypto_secretstream_xchacha20poly1305_init_push(&state, header, server_tx); + + + /* Now, encrypt the first chunk. `c1` will contain an encrypted, + * authenticated representation of `MESSAGE_PART1`. */ + crypto_secretstream_xchacha20poly1305_push + (&state, ciphertext, NULL, MESSAGEMoney, MESSAGE_LENMoney, NULL, 0, crypto_secretstream_xchacha20poly1305_TAG_FINAL); + + ////Create the HM for this message + QString headerbytes = QByteArray(reinterpret_cast(header), crypto_secretstream_xchacha20poly1305_HEADERBYTES).toHex(); + QString publickeyAlice = QByteArray(reinterpret_cast(pk), crypto_kx_PUBLICKEYBYTES).toHex(); + + + QString hmemo= createHeaderMemo(type,cid,myAddr,headerbytes,publickeyAlice,1,0); + + /////Ciphertext Memo + QString memo = QByteArray(reinterpret_cast(ciphertext), CIPHERTEXT_LEN).toHex(); + -ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat); + tx.toAddrs.push_back(ToFields{addr, amtHm, hmemo}); + tx.toAddrs.push_back(ToFields{addr, amt, memo}); + + } + } + + tx.fee = Settings::getMinerFee(); + + return tx; + +} + +void MainWindow::sendMoneyRequestChat() { + +////////////////////////////Todo: Check if a Contact is selected////////// + + // Create a Tx from the values on the send tab. Note that this Tx object + // might not be valid yet. + + /* QString Name = ui->contactNameMemo->text(); + + if ((ui->contactNameMemo->text().isEmpty()) || (ui->memoTxtChat->toPlainText().trimmed().isEmpty())) { + + QMessageBox msg(QMessageBox::Critical, tr("You have to select a contact and insert a Memo"), + tr("You have selected no Contact from Contactlist,\n") + tr("\nor your Memo is empty"), + QMessageBox::Ok, this); + + msg.exec(); + return; + }*/ + + + Tx tx = createTxFromSendRequestChatPage(); + + QString error = doSendChatMoneyRequestTxValidations(tx); + + if (!error.isEmpty()) { + // Something went wrong, so show an error and exit + QMessageBox msg(QMessageBox::Critical, tr("Message Error"), error, + QMessageBox::Ok, this); + + msg.exec(); + + // abort the Tx + return; + } + + auto movie = new QMovie(this); + auto movie1 = new QMovie(this); + movie->setFileName(":/img/res/loaderblack.gif"); + movie1->setFileName(":/img/res/loaderwhite.gif"); + + auto theme = Settings::getInstance()->get_theme_name(); + if (theme == "Dark" || theme == "Midnight") { + + connect(movie, &QMovie::frameChanged, [=]{ + ui->sendChatButton->setIcon(movie->currentPixmap()); + }); + movie->start(); + ui->sendChatButton->show(); + ui->sendChatButton->setEnabled(false); + + } else { + + connect(movie1, &QMovie::frameChanged, [=]{ + ui->sendChatButton->setIcon(movie1->currentPixmap()); + }); + movie1->start(); + ui->sendChatButton->show(); + ui->sendChatButton->setEnabled(false); + } + + ui->memoTxtChat->clear(); + + // And send the Tx + rpc->executeTransaction(tx, + [=] (QString txid) { + ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid); + + + QTimer::singleShot(1000, [=]() { + + if (theme == "Dark" || theme == "Midnight") { + QPixmap send(":/icons/res/send-white.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie->stop(); + ui->sendChatButton->setEnabled(true); + }else{ + + QPixmap send(":/icons/res/sendBlack.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie1->stop(); + ui->sendChatButton->setEnabled(true); + } + + }); + + // Force a UI update so we get the unconfirmed Tx + rpc->refresh(true); + ui->memoTxtChat->clear(); + + }, + // Errored out + [=] (QString opid, QString errStr) { + ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000); + + if (!opid.isEmpty()) + errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr; + + QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok); + movie->stop(); + + + if (theme == "Dark" || theme == "Midnight") { + QPixmap send(":/icons/res/send-white.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie->stop(); + ui->sendChatButton->setEnabled(true); + }else{ + + QPixmap send(":/icons/res/sendBlack.png"); + QIcon sendIcon(send); + ui->sendChatButton->setIcon(sendIcon); + movie1->stop(); + ui->sendChatButton->setEnabled(true); + } + + + + } + ); + + } + +QString MainWindow::doSendChatMoneyRequestTxValidations(Tx tx) { + // Check to see if we have enough verified funds to send the Tx. + + CAmount total; + for (auto toAddr : tx.toAddrs) { + if (!Settings::isValidAddress(toAddr.addr)) { + QString addr = (toAddr.addr.length() > 100 ? toAddr.addr.left(100) + "..." : toAddr.addr); + return QString(tr("Recipient Address ")) % addr % tr(" is Invalid"); + } + + // This technically shouldn't be possible, but issue #62 seems to have discovered a bug + // somewhere, so just add a check to make sure. + if (toAddr.amount.toqint64() < 0) { + return QString(tr("Amount for address '%1' is invalid!").arg(toAddr.addr)); + } + + total = total + toAddr.amount; + } + total = total + tx.fee; + + auto available = rpc->getModel()->getAvailableBalance(); + + if (available < total) { + return tr("Not enough available funds to send this transaction\n\nHave: %1\nNeed: %2\n\nNote: Funds need 1 confirmations before they can be spent") + .arg(available.toDecimalhushString(), total.toDecimalhushString()); + } + + return ""; } + void MainWindow::updateChat() { rpc->refreshChat(ui->listChat,ui->memoSizeChat); @@ -1993,7 +2707,7 @@ void MainWindow::slot_change_theme(const QString& theme_name) if (qFile.open(QFile::ReadOnly)) { QString styleSheet = QLatin1String(qFile.readAll()); - this->setStyleSheet(""); // reset styles + this->setStyleSheet(""); // resets styles, makes app restart unnecessary this->setStyleSheet(styleSheet); } @@ -2029,3 +2743,125 @@ void MainWindow::on_givemeZaddr_clicked() }); } + +void MainWindow::on_emojiButton_clicked() +{ + + QDialog emojiDialog(this); + Ui_emojiDialog emoji; + emoji.setupUi(&emojiDialog); + Settings::saveRestore(&emojiDialog); + +QObject::connect(emoji.smiley, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":smiley:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.money, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":money_mouth:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.laughing, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":laughing:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.sweet_smile, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":sweet_smile:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.joy, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":joy:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.innocent, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":innocent:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.partying_face, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":partying_face:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.rolling_eyes, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":rolling_eyes:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.tongue, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":stuck_out_tongue:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.hearts3, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":face_with_3hearts:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.heart_eyes, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":heart_eyes:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.nauseated, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":nauseated:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.poop, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":poop:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.symbols_mouth, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":symbols_mouth:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.sunglass, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":sunglass:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.stuck_out, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":stuck_out:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.hush_white, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":hush_white:"); + + emojiDialog.close(); +}); + +QObject::connect(emoji.sd, &QPushButton::clicked, [&] () { + ui->memoTxtChat->insertHtml(":sd:"); + + emojiDialog.close(); +}); + + + + emojiDialog.exec(); +} + diff --git a/src/mainwindow.h b/src/mainwindow.h index 62ff3f3..09edc6e 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -7,6 +7,8 @@ #include "recurring.h" #include "firsttimewizard.h" +using json = nlohmann::json; + // Forward declare to break circular dependency. class Controller; class Settings; @@ -14,7 +16,6 @@ class WSServer; class WormholeClient; class ChatModel; -using json = nlohmann::json; // Struct used to hold destination info when sending a Tx. struct ToFields { @@ -50,12 +51,18 @@ public: QString doSendTxValidations(Tx tx); QString doSendChatTxValidations(Tx tx); + QString doSendChatMoneyTxValidations(Tx tx); QString doSendRequestTxValidations(Tx tx); + QString doSendChatMoneyRequestTxValidations(Tx tx); QString getCid(); + QString getAmt(); + QString getMoneyMemo(); QString getPassword(); std::map pubkeyMap; QString getPubkeyByAddress(QString requestZaddr); void setPassword(QString Password); + void setAmt(QString Amt); + void setMoneyMemo(QString MoneyMemo); void addPubkey(QString requestZaddr, QString pubkey); @@ -106,12 +113,15 @@ private slots: void on_givemeZaddr_clicked(); + void on_emojiButton_clicked(); private: bool fileExists(QString path); void closeEvent(QCloseEvent* event); void closeEventpw(QCloseEvent* event); QString _password; + QString _amt; + QString _moneymemo; void setupSendTab(); @@ -136,7 +146,8 @@ private: Tx createTxFromChatPage(); Tx createTxForSafeContactRequest(); - + Tx createTxFromSendChatPage(); + Tx createTxFromSendRequestChatPage(); void encryptWallet(); void removeWalletEncryption(); @@ -145,6 +156,8 @@ private: void cancelButton(); void sendButton(); void sendChat(); + void sendMoneyChat(); + void sendMoneyRequestChat(); void addContact(); void ContactRequest(); @@ -215,5 +228,21 @@ private: QPushButton* sendChatButton = nullptr; }; +class ChatMemoEditRequest : public QTextEdit +{ +public: + ChatMemoEditRequest(QWidget* parent); + + void setMaxLenChatRequest(int len); + void setLenDisplayLabelChatRequest(QLabel* label); + void SetSendRequestButton(QPushButton* button); + void updateDisplayChatRequest(); + +private: + int maxlenchatrequest = 512; + QLabel* lenDisplayLabelchatRequest = nullptr; + QPushButton* sendRequestButton = nullptr; +}; + #endif // MAINWINDOW_H diff --git a/src/mainwindow.ui b/src/mainwindow.ui index 8471227..4e62995 100644 --- a/src/mainwindow.ui +++ b/src/mainwindow.ui @@ -6,7 +6,7 @@ 0 0 - 1274 + 1308 779 @@ -59,7 +59,7 @@ - 2 + 0 @@ -428,8 +428,8 @@ 0 0 - 1226 - 493 + 1260 + 509 @@ -1341,8 +1341,8 @@ HushChat - - + + @@ -1546,7 +1546,7 @@ - + QLayout::SetDefaultConstraint @@ -1683,6 +1683,12 @@ 0 + + + 850 + 0 + + false @@ -1706,9 +1712,48 @@ + + + + + 20 + 0 + + + + + + + + :/emoji/res/emoji/emoji1.png + + + + + 17 + 17 + + + + true + + + - + + 6 + + + 6 + + + 6 + + + 6 + + @@ -1716,6 +1761,12 @@ 0 + + + 16777215 + 50 + + 100 @@ -1747,7 +1798,7 @@ - + @@ -1783,7 +1834,7 @@ 0 0 - 1274 + 1308 22 diff --git a/src/newwallet.ui b/src/newwallet.ui index 9f1e76c..a307069 100644 --- a/src/newwallet.ui +++ b/src/newwallet.ui @@ -6,114 +6,129 @@ 0 0 - 437 - 381 + 950 + 717 + + + 0 + 0 + + + + + 950 + 734 + + Create New SDL Wallet - - - - Confirm Passphrase: - - - - - - - QLineEdit::Password - - - - - + + - + 0 0 - - - - - - - - Restore wallet from seed - - - - - - - Restore an existing wallet, using the 24-word seed. - - - true - - - - - - - - - - QLineEdit::Password + + + 931 + 192 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContentsOnFirstShow - - - - - 0 - 0 - + + + + Qt::Vertical - - - - - - - - Create a new wallet - - - - - - - Create a new wallet with a randomly generated seed. - - - true - - - - - + + + 20 + 50 + + + - - - Qt::Horizontal + + + + 931 + 150 + + + + + 949 + 16777215 + + + + false + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<h1 align="center" style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:xx-large; font-weight:600;">Hush + HushChat Terms of Service</span></h1> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">All users of this platform agree to not use it for initiating or threatening any forceful interference or violence on an individual or their property, aka, the <a href="https://en.wikipedia.org/wiki/Non-aggression_principle"><span style=" text-decoration: underline; color:#0000ff;">Non-Aggression Principle</span></a>.</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">THE SERVICE IS PROVIDED “AS IS” AND The Hush Developers DO NOT MAKE ANY SPECIFIC COMMITMENTS OR WARRANTIES ABOUT THE SERVICE.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">By clicking OK, you agree to use Hush, the SilentDragon family of wallets, HushChat, and any software developed by The Hush Developers in accordance with your local laws, that all liabilities related to using this service are your own, and The Hush Developers WILL NOT BE RESPONSIBLE FOR any losses related to using this software.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + true - - + + + + + 251 + 16777215 + + - Encryption Passphrase: + I accept the Terms of Service - + + + + Qt::Vertical + + + + 20 + 49 + + + + + @@ -121,6 +136,12 @@ 0 + + + 711 + 0 + + color: red; @@ -132,7 +153,7 @@ - + @@ -145,6 +166,125 @@ + + + + Encryption Passphrase: + + + + + + + + 611 + 0 + + + + QLineEdit::Password + + + + + + + Confirm Passphrase: + + + + + + + + 611 + 0 + + + + QLineEdit::Password + + + + + + + Qt::Horizontal + + + + + + + + + + 0 + 0 + + + + + 431 + 90 + + + + + 431 + 90 + + + + + + + + + + Restore wallet from seed + + + + + + + + + + + 0 + 0 + + + + + 431 + 0 + + + + + 431 + 90 + + + + + + + + + + Create a new wallet + + + + + + + + diff --git a/src/precompiled.h b/src/precompiled.h index 1826cda..80905dc 100644 --- a/src/precompiled.h +++ b/src/precompiled.h @@ -71,9 +71,10 @@ #include #include #include +#include -#include "3rdparty/json/json.hpp" #include "3rdparty/qrcode/QrCode.hpp" +#include "3rdparty/json/json.hpp" #define SODIUM_STATIC #include "3rdparty/sodium.h" diff --git a/src/recurring.cpp b/src/recurring.cpp index 471cd90..dd10f70 100644 --- a/src/recurring.cpp +++ b/src/recurring.cpp @@ -319,7 +319,7 @@ QString Recurring::writeableFile() { auto filename = QStringLiteral("recurringpayments.json"); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); - if (!dir.exists()) + if (dir.exists()) QDir().mkpath(dir.absolutePath()); if (Settings::getInstance()->isTestnet()) { @@ -353,6 +353,9 @@ void Recurring::removeRecurringInfo(QString hash) { void Recurring::readFromStorage() { + + if (writeableFile().isEmpty()) + { QFile file(writeableFile()); file.open(QIODevice::ReadOnly); @@ -365,10 +368,14 @@ void Recurring::readFromStorage() { auto p = RecurringPaymentInfo::fromJson(k.toObject()); payments.insert(p.getHash(), p); } + }else{} } void Recurring::writeToStorage() { + + if (writeableFile().isEmpty()) + { QFile file(writeableFile()); file.open(QIODevice::ReadWrite | QIODevice::Truncate); @@ -381,6 +388,7 @@ void Recurring::writeToStorage() { out << QJsonDocument(arr).toJson(); file.close(); +}else{} } /** diff --git a/src/restoreSeed.ui b/src/restoreSeed.ui new file mode 100644 index 0000000..fb923db --- /dev/null +++ b/src/restoreSeed.ui @@ -0,0 +1,72 @@ + + + + + Dialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + 30 + 240 + 341 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + buttonBox + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + + diff --git a/src/restoreseed.ui b/src/restoreseed.ui index 64bd43f..fb549dc 100644 --- a/src/restoreseed.ui +++ b/src/restoreseed.ui @@ -6,24 +6,14 @@ 0 0 - 400 - 300 + 498 + 575 Restore Wallet Seed - - - - Please enter your 24-word seed below - - - true - - - @@ -35,36 +25,36 @@ - - + + Wallet Seed - + false - + Wallet Birthday - + 0 - + @@ -79,9 +69,48 @@ + + + + Quantity + + + + + + + 10 + + + + + + + + 9 + + + + The quantity of shielded addresses that gets recreated during the restore process + + + true + + + + + + + Please enter your 24-word seed below + + + true + + + diff --git a/src/scripts/mkrelease.sh b/src/scripts/mkrelease.sh index 15e22ac..1a965df 100755 --- a/src/scripts/mkrelease.sh +++ b/src/scripts/mkrelease.sh @@ -35,6 +35,15 @@ rm -rf bin/SilentDragonLite* > /dev/null # Build the lib first cd lib && make release && cd .. make -j$(nproc) > /dev/null +make install INSTALL_ROOT=AppDir + +# now, build AppImage using linuxdeploy and linuxdeploy-plugin-qt +# download linuxdeploy and its Qt plugin +wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage +wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage + +# make them executable +chmod +x linuxdeploy*.AppImage echo "[OK]" diff --git a/src/seedrestore.ui b/src/seedrestore.ui new file mode 100644 index 0000000..697c2c2 --- /dev/null +++ b/src/seedrestore.ui @@ -0,0 +1,114 @@ + + + Restore + + + + 0 + 0 + 637 + 429 + + + + Restore your Wallet + + + + + + + 0 + 284 + + + + + + + + + + Birthday : + + + + + + + Quantity : + + + + + + + + + + + + 529 + 0 + + + + + 16777215 + 25 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + + + + + + 529 + 0 + + + + + + + + + + + + + Qt::Horizontal + + + + 521 + 20 + + + + + + + + + 89 + 16777215 + + + + Restore + + + + + + + + diff --git a/src/sendHushTransactionChat.ui b/src/sendHushTransactionChat.ui new file mode 100644 index 0000000..94bc851 --- /dev/null +++ b/src/sendHushTransactionChat.ui @@ -0,0 +1,276 @@ + + + transactionHush + + + + 0 + 0 + 212 + 405 + + + + Send or Request Hush + + + + + + To : + + + + + + + QLayout::SetFixedSize + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 16777215 + 70 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + QAbstractItemView::NoEditTriggers + + + false + + + + + + + + + QLayout::SetFixedSize + + + 6 + + + 6 + + + 6 + + + 6 + + + + + + 80 + 16777215 + + + + Amount: + + + + + + + + 80 + 16777215 + + + + + 200 + 0 + + + + 9 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Amount + + + + + + + + 35 + 16777215 + + + + Hush + + + + + + + + + Memo : + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 41 + + + + + 16777215 + 41 + + + + 100 + + + + + + + Qt::Vertical + + + + 20 + 39 + + + + + + + + QLayout::SetFixedSize + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Request Hush + + + + + + + + 16777215 + 25 + + + + Send Hush + + + + + + + + + QLayout::SetFixedSize + + + 6 + + + 6 + + + 6 + + + 6 + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel + + + + + + + + + + + buttonBox + rejected() + transactionHush + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/sendtab.cpp b/src/sendtab.cpp index 7e21261..4d125dd 100644 --- a/src/sendtab.cpp +++ b/src/sendtab.cpp @@ -8,9 +8,9 @@ #include "controller.h" #include "recurring.h" - using json = nlohmann::json; + void MainWindow::setupSendTab() { // Create the validator for send to/amount fields amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); diff --git a/src/settings.h b/src/settings.h index c598369..a917d67 100644 --- a/src/settings.h +++ b/src/settings.h @@ -67,8 +67,6 @@ public: void set_currency_name(QString currency_name); - - bool isSaplingActive(); void setZECPrice(double p) { ZECPrice = p; } diff --git a/src/settings.ui b/src/settings.ui index 57620e5..e9b5c22 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -138,6 +138,11 @@ Default + + + test + + diff --git a/src/version.h b/src/version.h index 927bb5b..06e80b4 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define APP_VERSION "1.3.3" +#define APP_VERSION "1.3.8" diff --git a/src/websockets.cpp b/src/websockets.cpp index 852a553..3f75e59 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -923,7 +923,7 @@ void AppDataServer::processGetTransactions(MainWindow* mainWindow, std::shared_p {"amount", model->getAmt(i)}, {"txid", model->getTxId(i)}, {"address", model->getAddr(i)}, - {"memo", model->getMemo(i)}, + // {"memo", model->getMemo(i)}, {"confirmations", model->getConfirmations(i)} }); }