Browse Source

Merge pull request #167 from MyHush/dev

v1.3.6
pull/175/head v1.3.6
Denio 4 years ago
committed by GitHub
parent
commit
abb2d4de5b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      application.qrc
  2. 22
      lib/Cargo.lock
  3. 3
      lib/Cargo.toml
  4. 3
      lib/silentdragonlitelib.h
  5. 28
      lib/src/lib.rs
  6. BIN
      res/SilentDragonLite.png
  7. 239
      res/css/test.css
  8. BIN
      res/dark-01.png
  9. BIN
      res/images/tile.png
  10. BIN
      res/silentdragonlite_ar.qm
  11. 2151
      res/silentdragonlite_ar.ts
  12. BIN
      res/silentdragonlite_ro.qm
  13. 2001
      res/silentdragonlite_ro.ts
  14. 2
      silentdragon-lite.pro
  15. 18928
      src/3rdparty/json/json.hpp
  16. 42
      src/Chat/Chat.cpp
  17. 9
      src/Chat/Helper/ChatDelegator.h
  18. 23
      src/DataStore/ChatDataStore.cpp
  19. 9
      src/DataStore/ChatDataStore.h
  20. 13
      src/DataStore/ContactDataStore.cpp
  21. 3
      src/DataStore/ContactDataStore.h
  22. 4
      src/DataStore/SietchDataStore.h
  23. 4
      src/FileSystem/FileSystem.h
  24. 24
      src/Model/ChatItem.cpp
  25. 5
      src/Model/ChatItem.h
  26. 16
      src/Model/ContactItem.cpp
  27. 5
      src/Model/ContactItem.h
  28. 2
      src/Model/ContactRequest.cpp
  29. 3
      src/Model/ContactRequest.h
  30. 96
      src/addressbook.cpp
  31. 171
      src/chatmodel.cpp
  32. 62
      src/connection.cpp
  33. 34
      src/connection.h
  34. 27
      src/contactrequest.ui
  35. 1173
      src/controller.cpp
  36. 35
      src/controller.h
  37. 113
      src/firsttimewizard.cpp
  38. 1
      src/firsttimewizard.h
  39. 40
      src/liteinterface.cpp
  40. 42
      src/liteinterface.h
  41. 252
      src/mainwindow.cpp
  42. 17
      src/mainwindow.h
  43. 4
      src/mainwindow.ui
  44. 310
      src/newwallet.ui
  45. 2
      src/precompiled.h
  46. 65
      src/restoreseed.ui
  47. 2
      src/sendtab.cpp
  48. 13
      src/settings.h
  49. 5
      src/settings.ui
  50. 2
      src/version.h
  51. 10
      src/websockets.cpp

7
application.qrc

@ -47,6 +47,8 @@
<file>res/addContactBlack.png</file> <file>res/addContactBlack.png</file>
<file>res/unknownBlack.png</file> <file>res/unknownBlack.png</file>
<file>res/unknownWhite.png</file> <file>res/unknownWhite.png</file>
<file>res/hush-passion.png</file>
<file>res/dark-01.png</file>
</qresource> </qresource>
<qresource prefix="/img"> <qresource prefix="/img">
<file>res/hushdlogo.gif</file> <file>res/hushdlogo.gif</file>
@ -67,6 +69,7 @@
<file>res/silentdragonlite_fa.qm</file> <file>res/silentdragonlite_fa.qm</file>
<file>res/silentdragonlite_id.qm</file> <file>res/silentdragonlite_id.qm</file>
<file>res/silentdragonlite_ar.qm</file> <file>res/silentdragonlite_ar.qm</file>
<file>res/silentdragonlite_ro.qm</file>
</qresource> </qresource>
<qresource prefix="/css"> <qresource prefix="/css">
<file>res/css/Blue.css</file> <file>res/css/Blue.css</file>
@ -74,6 +77,7 @@
<file>res/css/Default.css</file> <file>res/css/Default.css</file>
<file>res/css/Light.css</file> <file>res/css/Light.css</file>
<file>res/css/Midnight.css</file> <file>res/css/Midnight.css</file>
<file>res/css/test.css</file>
</qresource> </qresource>
<qresource prefix="/images/blue"> <qresource prefix="/images/blue">
<file>res/images/blue/unchecked.png</file> <file>res/images/blue/unchecked.png</file>
@ -85,4 +89,7 @@
<file>res/images/blue/blue_rightArrow_small.png</file> <file>res/images/blue/blue_rightArrow_small.png</file>
<file>res/images/blue/blue_qtreeview_selected.png</file> <file>res/images/blue/blue_qtreeview_selected.png</file>
</qresource> </qresource>
<qresource prefix="/images">
<file>res/images/tile.png</file>
</qresource>
</RCC> </RCC>

22
lib/Cargo.lock

@ -194,6 +194,20 @@ dependencies = [
"constant_time_eq 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "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]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.7.3" version = "0.7.3"
@ -1175,9 +1189,10 @@ dependencies = [
name = "qtlib" name = "qtlib"
version = "0.1.0" version = "0.1.0"
dependencies = [ 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)", "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)", "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=07288de82d84b9bf35d1210ccc98eb1e4b757eb7)",
] ]
[[package]] [[package]]
@ -1640,7 +1655,7 @@ dependencies = [
[[package]] [[package]]
name = "silentdragonlitelib" name = "silentdragonlitelib"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/MyHush/silentdragonlite-cli?rev=d2887d07879a93bdd9b2c8bd12504bb977e82fe0#d2887d07879a93bdd9b2c8bd12504bb977e82fe0" source = "git+https://github.com/MyHush/silentdragonlite-cli?rev=07288de82d84b9bf35d1210ccc98eb1e4b757eb7#07288de82d84b9bf35d1210ccc98eb1e4b757eb7"
dependencies = [ dependencies = [
"base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "bellman 0.1.0 (git+https://github.com/MyHush/librustzcash.git?rev=1a0204113d487cdaaf183c2967010e5214ff9e37)",
@ -2461,6 +2476,7 @@ dependencies = [
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "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 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 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-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-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" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
@ -2631,7 +2647,7 @@ dependencies = [
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "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 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 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)" = "<none>" "checksum silentdragonlitelib 0.1.0 (git+https://github.com/MyHush/silentdragonlite-cli?rev=07288de82d84b9bf35d1210ccc98eb1e4b757eb7)" = "<none>"
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "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 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" "checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85"

3
lib/Cargo.toml

@ -11,4 +11,5 @@ crate-type = ["staticlib"]
[dependencies] [dependencies]
libc = "0.2.58" libc = "0.2.58"
lazy_static = "1.4.0" 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 = "07288de82d84b9bf35d1210ccc98eb1e4b757eb7" }

3
lib/silentdragonlitelib.h

@ -9,10 +9,11 @@ extern bool litelib_wallet_exists (const char* chain_name);
extern char * litelib_initialize_new (bool dangerous, const char* server); extern char * litelib_initialize_new (bool dangerous, const char* server);
extern char * litelib_initialize_new_from_phrase extern char * litelib_initialize_new_from_phrase
(bool dangerous, const char* server, const char* seed, (bool dangerous, const char* server, const char* seed,
unsigned long long birthday); unsigned long long birthday, unsigned long long number);
extern char * litelib_initialize_existing (bool dangerous, const char* server); extern char * litelib_initialize_existing (bool dangerous, const char* server);
extern char * litelib_execute (const char* s, const char* args); extern char * litelib_execute (const char* s, const char* args);
extern void litelib_rust_free_string (char* s); extern void litelib_rust_free_string (char* s);
extern char * blake3_PW (char* pw);
#ifdef __cplusplus #ifdef __cplusplus
} }

28
lib/src/lib.rs

@ -29,6 +29,30 @@ pub extern fn litelib_wallet_exists(chain_name: *const c_char) -> bool {
println!("Wallet exists: {}", config.wallet_exists()); println!("Wallet exists: {}", config.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. /// Create a new wallet and return the seed for the newly created wallet.
@ -78,7 +102,7 @@ pub extern fn litelib_initialize_new(dangerous: bool, server: *const c_char) ->
/// Restore a wallet from the seed phrase /// Restore a wallet from the seed phrase
#[no_mangle] #[no_mangle]
pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const c_char, pub extern fn litelib_initialize_new_from_phrase(dangerous: bool, server: *const c_char,
seed: *const c_char, birthday: u64) -> *mut c_char { seed: *const c_char, birthday: u64, number: u64) -> *mut c_char {
let server_str = unsafe { let server_str = unsafe {
assert!(!server.is_null()); assert!(!server.is_null());
@ -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, false) {
Ok(l) => l, Ok(l) => l,
Err(e) => { Err(e) => {
let e_str = CString::new(format!("Error: {}", e)).unwrap(); let e_str = CString::new(format!("Error: {}", e)).unwrap();

BIN
res/SilentDragonLite.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

239
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);
}

BIN
res/dark-01.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

BIN
res/images/tile.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

BIN
res/silentdragonlite_ar.qm

Binary file not shown.

2151
res/silentdragonlite_ar.ts

File diff suppressed because it is too large

BIN
res/silentdragonlite_ro.qm

Binary file not shown.

2001
res/silentdragonlite_ro.ts

File diff suppressed because it is too large

2
silentdragon-lite.pro

@ -94,7 +94,6 @@ HEADERS += \
src/3rdparty/qrcode/BitBuffer.hpp \ src/3rdparty/qrcode/BitBuffer.hpp \
src/3rdparty/qrcode/QrCode.hpp \ src/3rdparty/qrcode/QrCode.hpp \
src/3rdparty/qrcode/QrSegment.hpp \ src/3rdparty/qrcode/QrSegment.hpp \
src/3rdparty/json/json.hpp \
src/settings.h \ src/settings.h \
src/txtablemodel.h \ src/txtablemodel.h \
src/qrcodelabel.h \ src/qrcodelabel.h \
@ -162,6 +161,7 @@ TRANSLATIONS = res/silentdragonlite_es.ts \
res/silentdragonlite_fa.ts \ res/silentdragonlite_fa.ts \
res/silentdragonlite_id.ts \ res/silentdragonlite_id.ts \
res/silentdragonlite_ar.ts \ res/silentdragonlite_ar.ts \
res/silentdragonlite_ro.ts \
res/silentdragonlite_tr.ts res/silentdragonlite_tr.ts
include(singleapplication/singleapplication.pri) include(singleapplication/singleapplication.pri)

18928
src/3rdparty/json/json.hpp

File diff suppressed because it is too large

42
src/Chat/Chat.cpp

@ -46,6 +46,45 @@ void ChatMemoEdit::setLenDisplayLabelChat(QLabel* label) {
this->lenDisplayLabelchat = 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) 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 ( if (
(p.getName() == ui->contactNameMemo->text().trimmed()) && (p.getName() == ui->contactNameMemo->text().trimmed()) &&
(p.getPartnerAddress() == c.second.getAddress()) && (p.getPartnerAddress() == c.second.getAddress()) &&
(c.second.isOutgoing() == true)) (c.second.isOutgoing() == true))
{ {
QStandardItem *Items = new QStandardItem(c.second.toChatLine()); QStandardItem *Items = new QStandardItem(c.second.toChatLine());

9
src/Chat/Helper/ChatDelegator.h

@ -37,7 +37,7 @@ class ListViewDelegate : public QAbstractItemDelegate
inline QSize sizeHint(QStyleOptionViewItem const &option, QModelIndex const &index) const; 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,7 @@ inline void ListViewDelegate::paint(QPainter *painter, QStyleOptionViewItem cons
bodydoc.setDefaultTextOption(textOption); bodydoc.setDefaultTextOption(textOption);
bodydoc.setDefaultFont(QFont("Roboto", 12)); bodydoc.setDefaultFont(QFont("Roboto", 12));
QString bodytext(index.data(Qt::DisplayRole).toString()); QString bodytext(index.data(Qt::DisplayRole).toString());
bodydoc.setHtml(bodytext); bodydoc.setHtml(bodytext.replace("\n", "<br>"));
qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding; qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding;
bodydoc.setTextWidth(contentswidth); bodydoc.setTextWidth(contentswidth);
qreal bodyheight = bodydoc.size().height(); qreal bodyheight = bodydoc.size().height();
@ -173,7 +173,8 @@ inline QSize ListViewDelegate::sizeHint(QStyleOptionViewItem const &option, QMod
bodydoc.setDefaultTextOption(textOption); bodydoc.setDefaultTextOption(textOption);
bodydoc.setDefaultFont(QFont("Roboto", 12)); bodydoc.setDefaultFont(QFont("Roboto", 12));
QString bodytext(index.data(Qt::DisplayRole).toString()); QString bodytext(index.data(Qt::DisplayRole).toString());
bodydoc.setHtml(bodytext); bodydoc.setHtml(bodytext.replace("\n", "<br>"));
// the width of the contents are the (a fraction of the window width) minus (margins + padding + width of the bubble's tail) // 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; qreal contentswidth = option.rect.width() * d_widthfraction - d_horizontalmargin - d_pointerwidth - d_leftpadding - d_rightpadding;
@ -190,4 +191,4 @@ inline QSize ListViewDelegate::sizeHint(QStyleOptionViewItem const &option, QMod
return size; return size;
} }
#endif #endif

23
src/DataStore/ChatDataStore.cpp

@ -39,6 +39,18 @@ QString ChatDataStore::getPassword()
return _password; return _password;
} }
QString ChatDataStore::getSendZaddr()
{
return _zaddr;
}
void ChatDataStore::setSendZaddr(QString zaddr)
{
_zaddr = zaddr;
}
void ChatDataStore::setPassword(QString password) void ChatDataStore::setPassword(QString password)
{ {
@ -47,15 +59,16 @@ void ChatDataStore::setPassword(QString password)
QString ChatDataStore::dump() QString ChatDataStore::dump()
{ {
json chats; QJsonObject chats;
chats["count"] = this->data.size(); chats["count"] = (qint64)this->data.size();
json j = {}; QJsonArray j;
for (auto &c: this->data) for (auto &c: this->data)
{ {
j.push_back(c.second.toJson()); j.push_back(c.second.toJson());
} }
chats["chatitems"] = j; chats["chatitems"] = j;
return QString::fromStdString(chats.dump()); QJsonDocument jd_chats = QJsonDocument(chats);
return QLatin1String(jd_chats.toJson(QJsonDocument::Compact));
} }
std::map<QString, ChatItem> ChatDataStore::getAllRawChatItems() std::map<QString, ChatItem> ChatDataStore::getAllRawChatItems()
@ -124,4 +137,4 @@ std::map<QString, ChatItem> ChatDataStore::getAllMemos()
ChatDataStore* ChatDataStore::instance = nullptr; ChatDataStore* ChatDataStore::instance = nullptr;
bool ChatDataStore::instanced = false; bool ChatDataStore::instanced = false;

9
src/DataStore/ChatDataStore.h

@ -1,7 +1,6 @@
#ifndef CHATDATASTORE_H #ifndef CHATDATASTORE_H
#define CHATDATASTORE_H #define CHATDATASTORE_H
#include "../chatmodel.h" #include "../chatmodel.h"
using json = nlohmann::json;
class ChatDataStore class ChatDataStore
{ {
@ -26,9 +25,13 @@ class ChatDataStore
std::map<QString, ChatItem> getAllOldContactRequests(); std::map<QString, ChatItem> getAllOldContactRequests();
std::map<QString, ChatItem> getAllMemos(); std::map<QString, ChatItem> getAllMemos();
QString getPassword(); QString getPassword();
QString getSendZaddr();
void setPassword(QString Password); void setSendZaddr(QString Password);
QString _password; QString _password;
void setPassword(QString zaddr);
QString _zaddr;
QString dump(); QString dump();
@ -41,4 +44,4 @@ class ChatDataStore
#endif #endif

13
src/DataStore/ContactDataStore.cpp

@ -33,9 +33,9 @@ ContactItem ContactDataStore::getData(QString key)
QString ContactDataStore::dump() QString ContactDataStore::dump()
{ {
json contacts; QJsonObject contacts;
contacts["count"] = this->data.size(); contacts["count"] = (qint64)this->data.size();
json j = {}; QJsonArray j = {};
for (auto &c: this->data) for (auto &c: this->data)
{ {
qDebug() << c.second.toQTString(); qDebug() << c.second.toQTString();
@ -43,8 +43,11 @@ QString ContactDataStore::dump()
j.push_back(c.second.toJson()); j.push_back(c.second.toJson());
} }
contacts["contacts"] = j; contacts["contacts"] = j;
return QString::fromStdString(contacts.dump(4)); QJsonDocument jd_contacts = QJsonDocument(contacts);
return QLatin1String(jd_contacts.toJson(QJsonDocument::Compact));
// return QString::fromStdString(contacts.dump(4));
} }
ContactDataStore* ContactDataStore::instance = nullptr; ContactDataStore* ContactDataStore::instance = nullptr;
bool ContactDataStore::instanced = false; bool ContactDataStore::instanced = false;

3
src/DataStore/ContactDataStore.h

@ -2,7 +2,6 @@
#define CONTACTDATASTORE_H #define CONTACTDATASTORE_H
#include "../Model/ContactItem.h" #include "../Model/ContactItem.h"
#include <string> #include <string>
using json = nlohmann::json;
class ContactDataStore class ContactDataStore
{ {
@ -31,4 +30,4 @@ class ContactDataStore
#endif #endif

4
src/DataStore/SietchDataStore.h

@ -1,8 +1,6 @@
#ifndef SIETCHDATASTORE_H #ifndef SIETCHDATASTORE_H
#define SIETCHDATASTORE_H #define SIETCHDATASTORE_H
using json = nlohmann::json;
class SietchDataStore class SietchDataStore
{ {
private: private:
@ -28,4 +26,4 @@ class SietchDataStore
} }
}; };
#endif #endif

4
src/FileSystem/FileSystem.h

@ -8,7 +8,7 @@
#include "../Model/ContactItem.h" #include "../Model/ContactItem.h"
#include "../Crypto/FileEncryption.h" #include "../Crypto/FileEncryption.h"
#include <fstream> #include <fstream>
using json = nlohmann::json;
class FileSystem class FileSystem
{ {
private: private:
@ -28,4 +28,4 @@ class FileSystem
}; };
#endif #endif

24
src/Model/ChatItem.cpp

@ -184,17 +184,17 @@ QString ChatItem::toChatLine()
return line; return line;
} }
json ChatItem::toJson() QJsonValue ChatItem::toJson()
{ {
json j; QJsonObject j;
j["_timestamp"] = _timestamp; j["_timestamp"] = (qint64)_timestamp;
j["_address"] = _address.toStdString(); j["_address"] = _address;
j["_contact"] = _contact.toStdString(); j["_contact"] = _contact;
j["_memo"] = _memo.toStdString(); j["_memo"] = _memo;
j["_requestZaddr"] = _requestZaddr.toStdString(); j["_requestZaddr"] = _requestZaddr;
j["_type"] = _type.toStdString(); j["_type"] = _type;
j["_cid"] = _cid.toStdString(); j["_cid"] = _cid;
j["_txid"] = _txid.toStdString(); j["_txid"] = _txid;
j["_confirmations"] = _confirmations; j["_confirmations"] = _confirmations;
j["_outgoing"] = _outgoing; j["_outgoing"] = _outgoing;
return j; return j;
@ -203,4 +203,4 @@ json ChatItem::toJson()
ChatItem::~ChatItem() ChatItem::~ChatItem()
{ {
} }

5
src/Model/ChatItem.h

@ -5,7 +5,6 @@
#define CHATITEM_H #define CHATITEM_H
#include <QString> #include <QString>
using json = nlohmann::json;
class ChatItem class ChatItem
{ {
@ -53,8 +52,8 @@ class ChatItem
void notarized(); void notarized();
void contact(bool iscontact); void contact(bool iscontact);
QString toChatLine(); QString toChatLine();
json toJson(); QJsonValue toJson();
~ChatItem(); ~ChatItem();
}; };
#endif #endif

16
src/Model/ContactItem.cpp

@ -86,13 +86,13 @@ QString ContactItem::toQTString()
return _name + "|" + _partnerAddress + "|" + _myAddress + "|" + _cid + "|" + _avatar; return _name + "|" + _partnerAddress + "|" + _myAddress + "|" + _cid + "|" + _avatar;
} }
json ContactItem::toJson() QJsonValue ContactItem::toJson()
{ {
json j; QJsonObject j;
j["_myAddress"] = _myAddress.toStdString(); j["_myAddress"] = _myAddress;
j["_partnerAddress"] = _partnerAddress.toStdString(); j["_partnerAddress"] = _partnerAddress;
j["_name"] = _name.toStdString(); j["_name"] = _name;
j["_cid"] = _cid.toStdString(); j["_cid"] = _cid;
j["_avatar"] = _avatar.toStdString(); j["_avatar"] = _avatar;
return j; return j;
} }

5
src/Model/ContactItem.h

@ -6,7 +6,6 @@
#include <vector> #include <vector>
#include <QString> #include <QString>
#include "mainwindow.h" #include "mainwindow.h"
using json = nlohmann::json;
class ContactItem class ContactItem
{ {
@ -34,7 +33,7 @@ public:
void setcid(QString cid); void setcid(QString cid);
void setAvatar(QString avatar); void setAvatar(QString avatar);
QString toQTString(); QString toQTString();
json toJson(); QJsonValue toJson();
}; };
#endif #endif

2
src/Model/ContactRequest.cpp

@ -93,4 +93,4 @@ void ContactRequest::clear()
ContactRequest::~ContactRequest() ContactRequest::~ContactRequest()
{ {
clear(); clear();
} }

3
src/Model/ContactRequest.h

@ -5,7 +5,6 @@
#define CONTACTREQUEST_H #define CONTACTREQUEST_H
#include <QString> #include <QString>
using json = nlohmann::json;
class ContactRequest class ContactRequest
{ {
@ -37,4 +36,4 @@ class ContactRequest
~ContactRequest(); ~ContactRequest();
}; };
#endif #endif

96
src/addressbook.cpp

@ -153,8 +153,8 @@ void AddressBook::open(MainWindow* parent, QLineEdit* target)
bool sapling = true; bool sapling = true;
try try
{ {
rpc->createNewZaddr(sapling, [=] (json reply) { rpc->createNewZaddr(sapling, [=] (QJsonValue reply) {
QString myAddr = QString::fromStdString(reply.get<json::array_t>()[0]); QString myAddr = reply.toArray()[0].toString();
QString message = QString("New Chat Address for your partner: ") + myAddr; QString message = QString("New Chat Address for your partner: ") + myAddr;
QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces); QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces);
@ -386,25 +386,56 @@ AddressBook::AddressBook()
void AddressBook::readFromStorage() 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()) 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<const unsigned char *>(ba.constData());
FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, pwHash);
allLabels.clear(); allLabels.clear();
file.open(QIODevice::ReadOnly); file1.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file QDataStream in(&file1); // read the data serialized from the file
QString version; QString version;
in >> version; in >> version;
QList<QList<QString>> stuff; QList<QList<QString>> stuff;
in >> stuff; in >> stuff;
//////////////found old addrbook, and rename it to .bak //////////////found old addrbook, and rename it to .bak
if (version != "v2") if (version == "v1")
{ {
auto filename = QStringLiteral("addresslabels.dat"); auto filename = QStringLiteral("addresslabels.dat");
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
QFile address(dir.filePath(filename)); QFile address(dir.filePath(filename));
qDebug() << "is v1";
address.rename(dir.filePath("addresslabels.bak")); address.rename(dir.filePath("addresslabels.bak"));
}else{ }else{
@ -419,21 +450,16 @@ void AddressBook::readFromStorage()
// qDebug() << "Read " << version << " Hush contacts from disk..."; // qDebug() << "Read " << version << " Hush contacts from disk...";
file.close(); file1.close();
FileEncryption::encrypt(target_encaddr_file, target_decaddr_file, pwHash);
file1.remove();
} }
else else
{ {
qDebug() << "No Hush contacts found on disk!"; qDebug() << "No Hush contacts found on disk!";
} }
// Special.
// Add the default silentdragon donation address if it isn't already present
// QList<QString> 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<QString, QString>("silentdragon donation", Settings::getDonationAddr(true)));
// }
} }
@ -442,12 +468,36 @@ void AddressBook::writeToStorage()
//FileSystem::getInstance()->writeContacts(AddressBook::writeableFile(), DataStore::getContactDataStore()->dump()); //FileSystem::getInstance()->writeContacts(AddressBook::writeableFile(), DataStore::getContactDataStore()->dump());
// FileSystem::getInstance()->writeContactsOldFormat(AddressBook::writeableFile(), allLabels); // 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<const unsigned char *>(ba.constData());
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
QFile file(AddressBook::writeableFile()); 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); file.open(QIODevice::ReadWrite | QIODevice::Truncate);
QDataStream out(&file); // we will serialize the data into the file QDataStream out(&file); // we will serialize the data into the file
QList<QList<QString>> contacts; QList<QList<QString>> contacts;
for(auto &item: allLabels) for(auto &item: allLabels)
{ {
QList<QString> c; QList<QString> c;
@ -456,10 +506,20 @@ void AddressBook::writeToStorage()
c.push_back(item.getMyAddress()); c.push_back(item.getMyAddress());
c.push_back(item.getCid()); c.push_back(item.getCid());
c.push_back(item.getAvatar()); c.push_back(item.getAvatar());
contacts.push_back(c); contacts.push_back(c);
} }
out << QString("v2") << contacts; out << QString("v2") << contacts;
qDebug()<<"schreibe in Datei: ";
file.close(); 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() QString AddressBook::writeableFile()

171
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(); QString label_contactold = index.data(Qt::DisplayRole).toString();
QStandardItemModel* contactMemo = new QStandardItemModel(); 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()); QStandardItem* Items = new QStandardItem(c.second.getMemo());
contactMemo->appendRow(Items); contactMemo->appendRow(Items);
requestContact.requestMemo->setModel(contactMemo); requestContact.requestMemo->setModel(contactMemo);
requestContact.requestMemo->show(); requestContact.requestMemo->show();
@ -255,7 +255,7 @@ void MainWindow::renderContactRequest(){
ui->listContactWidget); ui->listContactWidget);
QMessageBox::information(this, "Added Contact","successfully added your new contact. You can now Chat with this contact"); QMessageBox::information(this, "Added Contact","successfully added your new contact. You can now Chat with this contact");
dialog.close();
}); });
dialog.exec(); dialog.exec();
@ -443,43 +443,29 @@ Tx MainWindow::createTxFromChatPage() {
int lengthmemo = memoplain.length(); int lengthmemo = memoplain.length();
char *memoplainchar = NULL; char *memoplainchar = NULL;
memoplainchar = new char[lengthmemo+1]; memoplainchar = new char[lengthmemo+2];
strncpy(memoplainchar, memoplain.toLocal8Bit(), lengthmemo +1); strncpy(memoplainchar, memoplain.toUtf8(), 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();
QString pubkey = this->getPubkeyByAddress(addr);
QString passphraseHash = DataStore::getChatDataStore()->getPassword();
int length = passphraseHash.length();
////////////////Generate the secretkey for our message encryption ////////////////Generate the secretkey for our message encryption
char *hashEncryptionKeyraw = NULL; char *hashEncryptionKeyraw = NULL;
hashEncryptionKeyraw = new char[length+1]; hashEncryptionKeyraw = new char[length+1];
strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1); strncpy(hashEncryptionKeyraw, passphraseHash.toUtf8(), length+1);
#define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw) #define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
#define MESSAGEAS1_LEN length #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 sk[crypto_kx_SECRETKEYBYTES];
unsigned char pk[crypto_kx_PUBLICKEYBYTES]; unsigned char pk[crypto_kx_PUBLICKEYBYTES];
unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES]; unsigned char server_rx[crypto_kx_SESSIONKEYBYTES], server_tx[crypto_kx_SESSIONKEYBYTES];
if (crypto_kx_seed_keypair(pk,sk, if (crypto_kx_seed_keypair(pk,sk,
hash) !=0) { MESSAGEAS1) !=0) {
} }
////////////////Get the pubkey from Bob, so we can create the share key ////////////////Get the pubkey from Bob, so we can create the share key
@ -493,10 +479,17 @@ Tx MainWindow::createTxFromChatPage() {
} }
// 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////////////////////////////// ////////////Now lets encrypt the message Alice send to Bob//////////////////////////////
#define MESSAGE (const unsigned char *) memoplainchar //#define MESSAGE (const unsigned char *) memoplainchar
#define MESSAGE_LEN lengthmemo //#define MESSAGE_LEN lengthmemo
#define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LEN) #define CIPHERTEXT_LEN (crypto_secretstream_xchacha20poly1305_ABYTES + MESSAGE_LEN)
unsigned char ciphertext[CIPHERTEXT_LEN]; unsigned char ciphertext[CIPHERTEXT_LEN];
unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES]; unsigned char header[crypto_secretstream_xchacha20poly1305_HEADERBYTES];
@ -710,16 +703,22 @@ void::MainWindow::addContact()
request.setupUi(&dialog); request.setupUi(&dialog);
Settings::saveRestore(&dialog); Settings::saveRestore(&dialog);
QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () { request.memorequest->setLenDisplayLabelChatRequest(request.memoSizeChatRequest);
try
try
{ {
bool sapling = true; bool sapling = true;
rpc->createNewZaddr(sapling, [=] (json reply) { rpc->createNewZaddr(sapling, [=] (QJsonValue reply) {
QString myAddr = QString::fromStdString(reply.get<json::array_t>()[0]); QString myAddr = reply.toArray()[0].toString();
rpc->refreshAddresses(); rpc->refreshAddresses();
request.myzaddr->setText(myAddr); request.myzaddr->setText(myAddr);
ui->listReceiveAddresses->insertItem(0, myAddr); ui->listReceiveAddresses->insertItem(0, myAddr);
ui->listReceiveAddresses->setCurrentIndex(0); ui->listReceiveAddresses->setCurrentIndex(0);
DataStore::getChatDataStore()->setSendZaddr(myAddr);
qDebug()<<"Zaddr: "<<myAddr;
}); });
}catch(...) }catch(...)
@ -728,10 +727,9 @@ QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () {
qDebug() << QString("Caught something nasty with myZaddr Contact"); qDebug() << QString("Caught something nasty with myZaddr Contact");
} }
});
QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces); QString cid = QUuid::createUuid().toString(QUuid::WithoutBraces);
QObject::connect(request.sendRequestButton, &QPushButton::clicked, [&] () { QObject::connect(request.sendRequestButton, &QPushButton::clicked, [&] () {
QString addr = request.zaddr->text(); QString addr = request.zaddr->text();
@ -748,78 +746,67 @@ QObject::connect(request.newZaddr, &QPushButton::clicked, [&] () {
contactRequest.setAvatar(avatar); contactRequest.setAvatar(avatar);
contactRequest.setLabel(label); 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(); dialog.exec();
rpc->refreshContacts(ui->listContactWidget); rpc->refreshContacts(ui->listContactWidget);
} }
void MainWindow::saveandsendContact() void MainWindow::saveandsendContact()
{ {
this->ContactRequest(); this->ContactRequest();
} }
// Create a Tx for a contact Request // Create a Tx for a contact Request
Tx MainWindow::createTxForSafeContactRequest() Tx MainWindow::createTxForSafeContactRequest()
{ {
Tx tx; Tx tx;
{ {
CAmount totalAmt; CAmount totalAmt;
QString amtStr = "0"; QString amtStr = "0";
CAmount amt; CAmount amt;
QString headerbytes = ""; QString headerbytes = "";
amt = CAmount::fromDecimalString("0"); amt = CAmount::fromDecimalString("0");
totalAmt = totalAmt + amt; totalAmt = totalAmt + amt;
QString cid = contactRequest.getCid(); QString cid = contactRequest.getCid();
QString myAddr = contactRequest.getSenderAddress(); QString myAddr = DataStore::getChatDataStore()->getSendZaddr();
QString type = "Cont"; QString type = "Cont";
QString addr = contactRequest.getReceiverAddress(); 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 QString memo = contactRequest.getMemo();
char *hashEncryptionKeyraw = NULL; QString passphrase = DataStore::getChatDataStore()->getPassword();
hashEncryptionKeyraw = new char[length+1]; int length = passphrase.length();
strncpy(hashEncryptionKeyraw, hashEncryptionKey.toLocal8Bit(), length +1);
#define MESSAGEAS1 ((const unsigned char *) hashEncryptionKeyraw)
#define MESSAGEAS1_LEN length
////////////////Generate the secretkey for our message encryption
unsigned char hash[crypto_kx_SEEDBYTES]; 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]; if (crypto_kx_seed_keypair(pk, sk, MESSAGEAS1) !=0) {
unsigned char pk[crypto_kx_PUBLICKEYBYTES]; //
}
if (crypto_kx_seed_keypair(pk,sk,
hash) !=0) {
}
QString publicKey = QByteArray(reinterpret_cast<const char*>(pk), crypto_kx_PUBLICKEYBYTES).toHex(); QString publicKey = QByteArray(reinterpret_cast<const char*>(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; return tx;
} }
@ -835,17 +822,7 @@ void MainWindow::ContactRequest() {
return; return;
} }
if (contactRequest.getSenderAddress().size() > 80) { int max = 512;
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;
QString chattext = contactRequest.getMemo();; QString chattext = contactRequest.getMemo();;
int size = chattext.size(); int size = chattext.size();
@ -854,7 +831,7 @@ void MainWindow::ContactRequest() {
// auto addr = ""; // auto addr = "";
// if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) { // if (! Settings::isZAddress(AddressBook::addressFromAddressLabel(addr->text()))) {
QMessageBox msg(QMessageBox::Critical, tr("Your Message is too long"), 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); QMessageBox::Ok, this);
msg.exec(); msg.exec();

62
src/connection.cpp

@ -8,7 +8,15 @@
#include "../lib/silentdragonlitelib.h" #include "../lib/silentdragonlitelib.h"
#include "precompiled.h" #include "precompiled.h"
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) ConnectionLoader::ConnectionLoader(MainWindow* main, Controller* rpc)
{ {
@ -93,17 +101,17 @@ void ConnectionLoader::doAutoConnect()
auto me = this; auto me = this;
// After the lib is initialized, try to do get info // After the lib is initialized, try to do get info
connection->doRPC("info", "", [=](auto reply) { connection->doRPC("info", "", [=](QJsonValue reply) {
// If success, set the connection // If success, set the connection
main->logger->write("Connection is online."); main->logger->write("Connection is online.");
connection->setInfo(reply); connection->setInfo(reply);
isSyncing = new QAtomicInteger<bool>(); isSyncing = new QAtomicInteger<bool>();
isSyncing->store(true); isSyncing->storeRelaxed(true);
// Do a sync at startup // Do a sync at startup
syncTimer = new QTimer(main); syncTimer = new QTimer(main);
connection->doRPCWithDefaultErrorHandling("sync", "", [=](auto) { connection->doRPCWithDefaultErrorHandling("sync", "", [=](QJsonValue) {
isSyncing->store(false); isSyncing->storeRelaxed(false);
// Cancel the timer // Cancel the timer
syncTimer->deleteLater(); syncTimer->deleteLater();
// When sync is done, set the connection // When sync is done, set the connection
@ -113,13 +121,13 @@ void ConnectionLoader::doAutoConnect()
// While it is syncing, we'll show the status updates while it is alive. // While it is syncing, we'll show the status updates while it is alive.
QObject::connect(syncTimer, &QTimer::timeout, [=]() { QObject::connect(syncTimer, &QTimer::timeout, [=]() {
// Check the sync status // Check the sync status
if (isSyncing != nullptr && isSyncing->load()) { if (isSyncing != nullptr && isSyncing->loadRelaxed()) {
// Get the sync status // Get the sync status
connection->doRPC("syncstatus", "", [=](json reply) { connection->doRPC("syncstatus", "", [=](QJsonValue reply) {
if (isSyncing != nullptr && reply.find("synced_blocks") != reply.end()) if (isSyncing != nullptr && !reply.toObject()["synced_blocks"].isUndefined())
{ {
qint64 synced = reply["synced_blocks"].get<json::number_unsigned_t>(); qint64 synced = reply["synced_blocks"].toInt();
qint64 total = reply["total_blocks"].get<json::number_unsigned_t>(); qint64 total = reply["total_blocks"].toInt();
me->showInformation( me->showInformation(
"Synced " + QString::number(synced) + " / " + QString::number(total) "Synced " + QString::number(synced) + " / " + QString::number(total)
); );
@ -154,6 +162,9 @@ void ConnectionLoader::doRPCSetConnection(Connection* conn)
rpc->setConnection(conn); rpc->setConnection(conn);
d->accept(); d->accept();
QTimer::singleShot(1, [=]() { delete this; }); QTimer::singleShot(1, [=]() { delete this; });
QFile plaintextWallet(dirwalletconnection);
plaintextWallet.remove();
} }
Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config) Connection* ConnectionLoader::makeConnection(std::shared_ptr<ConnectionConfig> config)
@ -202,21 +213,26 @@ void Executor::run()
{ {
char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str()); char* resp = litelib_execute(this->cmd.toStdString().c_str(), this->args.toStdString().c_str());
QString reply = litelib_process_response(resp); QString reply = litelib_process_response(resp);
//qDebug() << "RPC Reply=" << reply; QJsonDocument parsed = QJsonDocument::fromJson(reply.toUtf8());
auto parsed = json::parse(
reply.toStdString().c_str(), if (parsed.isEmpty() || parsed.isNull())
nullptr,
false
);
if (parsed.is_discarded() || parsed.is_null())
emit handleError(reply); emit handleError(reply);
else else
emit responseReady(parsed); {
QJsonValue retval;
if (parsed.isObject())
retval = QJsonValue(parsed.object());
else if (parsed.isArray())
retval = QJsonValue(parsed.array());
emit responseReady(retval);
}
} }
void Callback::processRPCCallback(json resp) void Callback::processRPCCallback(QJsonValue resp)
{ {
this->cb(resp); this->cb(resp);
// Destroy self // Destroy self
@ -235,10 +251,10 @@ Connection::Connection(MainWindow* m, std::shared_ptr<ConnectionConfig> conf)
this->config = conf; this->config = conf;
this->main = m; this->main = m;
// Register the JSON type as a type that can be passed between signals and slots. // Register the JSON type as a type that can be passed between signals and slots.
qRegisterMetaType<json>("json"); qRegisterMetaType<QJsonValue>("QJsonValue");
} }
void Connection::doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb, const std::function<void(QString)>& errCb) void Connection::doRPC(const QString cmd, const QString args, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& errCb)
{ {
if (shutdownInProgress) if (shutdownInProgress)
// Ignoring RPC because shutdown in progress // Ignoring RPC because shutdown in progress
@ -257,14 +273,14 @@ void Connection::doRPC(const QString cmd, const QString args, const std::functio
QThreadPool::globalInstance()->start(runner); QThreadPool::globalInstance()->start(runner);
} }
void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb) void Connection::doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(QJsonValue)>& cb)
{ {
doRPC(cmd, args, cb, [=] (QString err) { doRPC(cmd, args, cb, [=] (QString err) {
this->showTxError(err); this->showTxError(err);
}); });
} }
void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb) void Connection::doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(QJsonValue)>& cb)
{ {
doRPC(cmd, args, cb, [=] (auto) { doRPC(cmd, args, cb, [=] (auto) {
// Ignored error handling // Ignored error handling

34
src/connection.h

@ -6,8 +6,6 @@
#include "precompiled.h" #include "precompiled.h"
using json = nlohmann::json;
class Controller; class Controller;
struct ConnectionConfig { struct ConnectionConfig {
@ -57,15 +55,15 @@ private:
class Callback: public QObject { class Callback: public QObject {
Q_OBJECT Q_OBJECT
public: public:
Callback(const std::function<void(json)> cb, const std::function<void(QString)> errCb) { this->cb = cb; this->errCb = errCb;} Callback(const std::function<void(QJsonValue)> cb, const std::function<void(QString)> errCb) { this->cb = cb; this->errCb = errCb;}
~Callback() = default; ~Callback() = default;
public slots: public slots:
void processRPCCallback(json resp); void processRPCCallback(QJsonValue resp);
void processError(QString error); void processError(QString error);
private: private:
std::function<void(json)> cb; std::function<void(QJsonValue)> cb;
std::function<void(QString)> errCb; std::function<void(QString)> errCb;
}; };
@ -73,14 +71,14 @@ private:
/** /**
* A runnable that runs some lightclient Command in a non-UI thread. * 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. * 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 * Since the autoDelete flag is ON, the runnable should be destroyed automatically
* by the threadpool. * by the threadpool.
*/ */
class Executor : public QObject, public QRunnable { class Executor : public QObject, public QRunnable {
Q_OBJECT Q_OBJECT
public: public:
Executor(QString cmd, QString args) { Executor(QString cmd, QString args) {
this->cmd = cmd; this->cmd = cmd;
this->args = args; this->args = args;
@ -92,12 +90,12 @@ public:
virtual void run(); virtual void run();
signals: signals:
void responseReady(json); void responseReady(QJsonValue);
void handleError(QString); void handleError(QString);
private: private:
QString cmd; QString cmd;
QString args; QString args;
}; };
/** /**
@ -116,20 +114,20 @@ public:
void shutdown(); void shutdown();
void doRPC(const QString cmd, const QString args, const std::function<void(json)>& cb, void doRPC(const QString cmd, const QString args, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& errCb); const std::function<void(QString)>& errCb);
void doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(json)>& cb); void doRPCWithDefaultErrorHandling(const QString cmd, const QString args, const std::function<void(QJsonValue)>& cb);
void doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(json)>& cb) ; void doRPCIgnoreError(const QString cmd, const QString args, const std::function<void(QJsonValue)>& cb) ;
void showTxError(const QString& error); void showTxError(const QString& error);
json getInfo() { return serverInfo; } QJsonValue getInfo() { return serverInfo; }
void setInfo(const json& info) { serverInfo = info; } void setInfo(const QJsonValue& info) { serverInfo = info; }
private: private:
bool shutdownInProgress = false; bool shutdownInProgress = false;
json serverInfo; QJsonValue serverInfo;
}; };
#endif #endif

27
src/contactrequest.ui

@ -122,22 +122,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="newZaddr">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Create New Address</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">
@ -394,7 +378,7 @@
</layout> </layout>
</item> </item>
<item row="11" column="0"> <item row="11" column="0">
<widget class="QLabel" name="memoSizeChat"> <widget class="QLabel" name="memoSizeChatRequest">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred"> <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch> <horstretch>0</horstretch>
@ -407,7 +391,7 @@
</widget> </widget>
</item> </item>
<item row="9" column="0" colspan="6"> <item row="9" column="0" colspan="6">
<widget class="QTextEdit" name="memorequest"> <widget class="ChatMemoEditRequest" name="memorequest">
<property name="placeholderText"> <property name="placeholderText">
<string>Add a memo to your request</string> <string>Add a memo to your request</string>
</property> </property>
@ -453,6 +437,13 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>ChatMemoEditRequest</class>
<extends>QTextEdit</extends>
<header>mainwindow.h</header>
</customwidget>
</customwidgets>
<resources/> <resources/>
<connections> <connections>
<connection> <connection>

1173
src/controller.cpp

File diff suppressed because it is too large

35
src/controller.h

@ -19,7 +19,6 @@
#include "Model/ContactRequestChatItem.h" #include "Model/ContactRequestChatItem.h"
#include "Model/ContactItem.h" #include "Model/ContactItem.h"
#include "contactmodel.h" #include "contactmodel.h"
using json = nlohmann::json;
struct WatchedTx { struct WatchedTx {
QString opid; QString opid;
@ -40,7 +39,7 @@ public:
Connection* getConnection() { return zrpc->getConnection(); } Connection* getConnection() { return zrpc->getConnection(); }
void setConnection(Connection* c); void setConnection(Connection* c);
void refresh(bool force = false); void refresh(bool force = false);
void refreshAddresses(); void refreshAddresses();
int getLag(); int getLag();
void setLag(int lag); void setLag(int lag);
int _lag; int _lag;
@ -91,7 +90,7 @@ public:
const std::function<void(QString txid)> submitted, const std::function<void(QString txid)> submitted,
const std::function<void(QString txid, QString errStr)> error); const std::function<void(QString txid, QString errStr)> error);
void fillTxJsonParams(json& params, Tx tx); void fillTxJsonParams(QJsonArray &params, Tx tx);
const TxTableModel* getTransactionsModel() { return transactionsTableModel; } const TxTableModel* getTransactionsModel() { return transactionsTableModel; }
@ -99,58 +98,58 @@ public:
void noConnection(); void noConnection();
bool isEmbedded() { return ehushd != nullptr; } bool isEmbedded() { return ehushd != nullptr; }
void encryptWallet(QString password, const std::function<void(json)>& cb) { void encryptWallet(QString password, const std::function<void(QJsonValue)>& cb) {
zrpc->encryptWallet(password, cb); zrpc->encryptWallet(password, cb);
} }
void removeWalletEncryption(QString password, const std::function<void(json)>& cb) { void removeWalletEncryption(QString password, const std::function<void(QJsonValue)>& cb) {
zrpc->removeWalletEncryption(password, cb); } zrpc->removeWalletEncryption(password, cb); }
void saveWallet(const std::function<void(json)>& cb) { zrpc->saveWallet(cb); } void saveWallet(const std::function<void(QJsonValue)>& cb) { zrpc->saveWallet(cb); }
void clearWallet(const std::function<void(json)>& cb) { zrpc->clearWallet(cb); } void clearWallet(const std::function<void(QJsonValue)>& cb) { zrpc->clearWallet(cb); }
void createNewZaddr(bool sapling, const std::function<void(json)>& cb) { void createNewZaddr(bool sapling, const std::function<void(QJsonValue)>& cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->createNewZaddr(sapling, cb); zrpc->createNewZaddr(sapling, cb);
}, [=](){}); }, [=](){});
} }
void createNewTaddr(const std::function<void(json)>& cb) { void createNewTaddr(const std::function<void(QJsonValue)>& cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->createNewTaddr(cb); zrpc->createNewTaddr(cb);
}, [=](){}); }, [=](){});
} }
void createNewSietchZaddr(const std::function<void(json)>& cb) { void createNewSietchZaddr(const std::function<void(QJsonValue)>& cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->createNewSietchZaddr(cb); zrpc->createNewSietchZaddr(cb);
}, [=](){}); }, [=](){});
} }
void fetchPrivKey(QString addr, const std::function<void(json)>& cb) { void fetchPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->fetchPrivKey(addr, cb); zrpc->fetchPrivKey(addr, cb);
}, },
[=]() { [=]() {
cb({ {"error", "Failed to unlock wallet"} }); cb(QJsonObject({ {"error", "Failed to unlock wallet"} }) );
}); });
} }
void fetchAllPrivKeys(const std::function<void(json)> cb) { void fetchAllPrivKeys(const std::function<void(QJsonValue)> cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->fetchAllPrivKeys(cb); zrpc->fetchAllPrivKeys(cb);
}, },
[=]() { [=]() {
cb({ {"error", "Failed to unlock wallet"} }); cb(QJsonObject({ {"error", "Failed to unlock wallet"} }));
}); });
} }
void fetchSeed(const std::function<void(json)> cb) { void fetchSeed(const std::function<void(QJsonValue)> cb) {
unlockIfEncrypted([=] () { unlockIfEncrypted([=] () {
zrpc->fetchSeed(cb); zrpc->fetchSeed(cb);
}, },
[=]() { [=]() {
cb({ {"error", "Failed to unlock wallet"} }); cb(QJsonObject({ {"error", "Failed to unlock wallet"} }));
}); });
} }
@ -163,12 +162,12 @@ public:
private: private:
void processInfo(const json&); void processInfo(const QJsonValue&);
void refreshBalances(); void refreshBalances();
void refreshTransactions(); void refreshTransactions();
void processUnspent (const json& reply, QMap<QString, CAmount>* newBalances, QList<UnspentOutput>* newUnspentOutputs); void processUnspent (const QJsonValue& reply, QMap<QString, CAmount>* newBalances, QList<UnspentOutput>* newUnspentOutputs);
void updateUI (bool anyUnconfirmed); void updateUI (bool anyUnconfirmed);
void updateUIBalances (); void updateUIBalances ();

113
src/firsttimewizard.cpp

@ -8,7 +8,6 @@
#include "../lib/silentdragonlitelib.h" #include "../lib/silentdragonlitelib.h"
using json = nlohmann::json;
FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server) FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server)
{ {
@ -16,6 +15,18 @@ FirstTimeWizard::FirstTimeWizard(bool dangerous, QString server)
this->dangerous = dangerous; this->dangerous = dangerous;
this->server = server; 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 // Create the pages
setPage(Page_NewOrRestore, new NewOrRestorePage(this)); setPage(Page_NewOrRestore, new NewOrRestorePage(this));
setPage(Page_New, new NewSeedPage(this)); setPage(Page_New, new NewSeedPage(this));
@ -40,34 +51,74 @@ int FirstTimeWizard::nextId() const {
NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent) { NewOrRestorePage::NewOrRestorePage(FirstTimeWizard *parent) : QWizardPage(parent) {
setTitle("Create or Restore wallet."); setTitle("Create or Restore wallet.");
QWidget* pageWidget = new QWidget(); QWidget* pageWidget = new QWidget();
Ui_CreateWalletForm form; Ui_CreateWalletForm form;
form.setupUi(pageWidget); 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");
auto fnPasswordEdited = [=](const QString&) { auto fnPasswordEdited = [=](const QString&) {
// Enable the Finish button if the passwords match. // 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() && 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(""); form.lblPasswordMatch->setText("");
parent->button(QWizard::CommitButton)->setEnabled(true);
setButtonText(QWizard::CommitButton, "Next");
form.radioRestoreWallet->setEnabled(true); form.radioRestoreWallet->setEnabled(true);
form.radioNewWallet->setEnabled(true); form.radioNewWallet->setEnabled(true);
form.radioNewWallet->setChecked(true); form.radioNewWallet->setChecked(true);
int length = passphrase.length();
DataStore::getChatDataStore()->setPassword(Password);
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<const char*>(key), KEY_LEN).toHex();
DataStore::getChatDataStore()->setPassword(passphraseHash1);
//main->setPassword(Password); //main->setPassword(Password);
//qDebug()<<"Objekt gesetzt"; //qDebug()<<"Objekt gesetzt";
// Exclusive buttons // Exclusive buttons
QObject::connect(form.radioNewWallet, &QRadioButton::clicked, [=](bool checked) { QObject::connect(form.radioNewWallet, &QRadioButton::clicked, [=](bool checked) {
if (checked) { if (checked) {
@ -82,6 +133,13 @@ DataStore::getChatDataStore()->setPassword(Password);
} }
}); });
QObject::connect(form.TOS, &QRadioButton::clicked, [=](bool checked) {
if (checked) {
parent->button(QWizard::CommitButton)->setEnabled(true);
}
});
@ -106,6 +164,8 @@ DataStore::getChatDataStore()->setPassword(Password);
form.radioRestoreWallet->setEnabled(false); form.radioRestoreWallet->setEnabled(false);
form.radioNewWallet->setEnabled(false); form.radioNewWallet->setEnabled(false);
setCommitPage(true); setCommitPage(true);
} }
@ -130,14 +190,15 @@ void NewSeedPage::initializePage() {
char* resp = litelib_initialize_new(parent->dangerous, parent->server.toStdString().c_str()); char* resp = litelib_initialize_new(parent->dangerous, parent->server.toStdString().c_str());
QString reply = litelib_process_response(resp); QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); QByteArray ba_reply = reply.toUtf8();
if (parsed.is_discarded() || parsed.is_null() || parsed.find("seed") == parsed.end()) { QJsonDocument jd_reply = QJsonDocument::fromJson(ba_reply);
QJsonObject parsed = jd_reply.object();
if (parsed.isEmpty() || parsed["seed"].isNull()) {
form.txtSeed->setPlainText(tr("Error creating a wallet") + "\n" + reply); form.txtSeed->setPlainText(tr("Error creating a wallet") + "\n" + reply);
} else { } else {
QString seed = QString::fromStdString(parsed["seed"].get<json::string_t>()); QString seed = parsed["seed"].toString();
form.txtSeed->setPlainText(seed); form.txtSeed->setPlainText(seed);
} }
@ -149,8 +210,11 @@ bool NewSeedPage::validatePage() {
char* resp = litelib_execute("save", ""); char* resp = litelib_execute("save", "");
QString reply = litelib_process_response(resp); QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); QByteArray ba_reply = reply.toUtf8();
if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) { 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"), QMessageBox::warning(this, tr("Failed to save wallet"),
tr("Couldn't save the wallet") + "\n" + reply, tr("Couldn't save the wallet") + "\n" + reply,
QMessageBox::Ok); QMessageBox::Ok);
@ -196,10 +260,14 @@ bool RestoreSeedPage::validatePage() {
return false; return false;
} }
///Number
QString number_str = form.number->text();
qint64 number = number_str.toUInt();
// 3. Attempt to restore wallet with the seed phrase // 3. Attempt to restore wallet with the seed phrase
{ {
char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(), char* resp = litelib_initialize_new_from_phrase(parent->dangerous, parent->server.toStdString().c_str(),
seed.toStdString().c_str(), birthday); seed.toStdString().c_str(), birthday, number);
QString reply = litelib_process_response(resp); QString reply = litelib_process_response(resp);
if (reply.toUpper().trimmed() != "OK") { if (reply.toUpper().trimmed() != "OK") {
@ -215,8 +283,11 @@ bool RestoreSeedPage::validatePage() {
char* resp = litelib_execute("save", ""); char* resp = litelib_execute("save", "");
QString reply = litelib_process_response(resp); QString reply = litelib_process_response(resp);
auto parsed = json::parse(reply.toStdString().c_str(), nullptr, false); QByteArray ba_reply = reply.toUtf8();
if (parsed.is_discarded() || parsed.is_null() || parsed.find("result") == parsed.end()) { 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"), QMessageBox::warning(this, tr("Failed to save wallet"),
tr("Couldn't save the wallet") + "\n" + reply, tr("Couldn't save the wallet") + "\n" + reply,
QMessageBox::Ok); QMessageBox::Ok);

1
src/firsttimewizard.h

@ -5,6 +5,7 @@
#include "ui_newseed.h" #include "ui_newseed.h"
#include "ui_restoreseed.h" #include "ui_restoreseed.h"
#include "ui_newwallet.h"
#include "mainwindow.h" #include "mainwindow.h"

40
src/liteinterface.cpp

@ -20,7 +20,7 @@ bool LiteInterface::haveConnection() {
return conn != nullptr; return conn != nullptr;
} }
void LiteInterface::fetchAddresses(const std::function<void(json)>& cb) { void LiteInterface::fetchAddresses(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -28,21 +28,21 @@ void LiteInterface::fetchAddresses(const std::function<void(json)>& cb) {
} }
void LiteInterface::fetchUnspent(const std::function<void(json)>& cb) { void LiteInterface::fetchUnspent(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("notes", "", cb); conn->doRPCWithDefaultErrorHandling("notes", "", cb);
} }
void LiteInterface::createNewZaddr(bool, const std::function<void(json)>& cb) { void LiteInterface::createNewZaddr(bool, const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("new", "zs", cb); conn->doRPCWithDefaultErrorHandling("new", "zs", cb);
} }
void LiteInterface::createNewSietchZaddr(const std::function<void(json)>& cb) { void LiteInterface::createNewSietchZaddr(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -50,70 +50,70 @@ void LiteInterface::createNewSietchZaddr(const std::function<void(json)>& cb) {
} }
void LiteInterface::createNewTaddr(const std::function<void(json)>& cb) { void LiteInterface::createNewTaddr(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("new", "R", cb); conn->doRPCWithDefaultErrorHandling("new", "R", cb);
} }
void LiteInterface::fetchPrivKey(QString addr, const std::function<void(json)>& cb) { void LiteInterface::fetchPrivKey(QString addr, const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("export", addr, cb); conn->doRPCWithDefaultErrorHandling("export", addr, cb);
} }
void LiteInterface::fetchSeed(const std::function<void(json)>& cb) { void LiteInterface::fetchSeed(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("seed", "", cb); conn->doRPCWithDefaultErrorHandling("seed", "", cb);
} }
void LiteInterface::fetchBalance(const std::function<void(json)>& cb) { void LiteInterface::fetchBalance(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("balance", "", cb); conn->doRPCWithDefaultErrorHandling("balance", "", cb);
} }
void LiteInterface::fetchTransactions(const std::function<void(json)>& cb) { void LiteInterface::fetchTransactions(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("list", "", cb); conn->doRPCWithDefaultErrorHandling("list", "", cb);
} }
void LiteInterface::saveWallet(const std::function<void(json)>& cb) { void LiteInterface::saveWallet(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("save", "", cb); conn->doRPCWithDefaultErrorHandling("save", "", cb);
} }
void LiteInterface::clearWallet(const std::function<void(json)>& cb) { void LiteInterface::clearWallet(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("clear", "", cb); conn->doRPCWithDefaultErrorHandling("clear", "", cb);
} }
void LiteInterface::unlockWallet(QString password, const std::function<void(json)>& cb) { void LiteInterface::unlockWallet(QString password, const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("unlock", password, cb); conn->doRPCWithDefaultErrorHandling("unlock", password, cb);
} }
void LiteInterface::fetchWalletEncryptionStatus(const std::function<void(json)>& cb) { void LiteInterface::fetchWalletEncryptionStatus(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
conn->doRPCWithDefaultErrorHandling("encryptionstatus", "", cb); conn->doRPCWithDefaultErrorHandling("encryptionstatus", "", cb);
} }
void LiteInterface::encryptWallet(QString password, const std::function<void(json)>& cb) { void LiteInterface::encryptWallet(QString password, const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -121,7 +121,7 @@ void LiteInterface::encryptWallet(QString password, const std::function<void(jso
} }
void LiteInterface::removeWalletEncryption(QString password, const std::function<void(json)>& cb) { void LiteInterface::removeWalletEncryption(QString password, const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -129,7 +129,7 @@ void LiteInterface::removeWalletEncryption(QString password, const std::function
} }
void LiteInterface::sendTransaction(QString params, const std::function<void(json)>& cb, void LiteInterface::sendTransaction(QString params, const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) { const std::function<void(QString)>& err) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -137,7 +137,7 @@ void LiteInterface::sendTransaction(QString params, const std::function<void(jso
conn->doRPC("send", params, cb, err); conn->doRPC("send", params, cb, err);
} }
void LiteInterface::fetchInfo(const std::function<void(json)>& cb, void LiteInterface::fetchInfo(const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) { const std::function<void(QString)>& err) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -145,7 +145,7 @@ void LiteInterface::fetchInfo(const std::function<void(json)>& cb,
conn->doRPC("info", "", cb, err); conn->doRPC("info", "", cb, err);
} }
void LiteInterface::fetchSupply(const std::function<void(json)>& cb) { void LiteInterface::fetchSupply(const std::function<void(QJsonValue)>& cb) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -153,7 +153,7 @@ void LiteInterface::fetchSupply(const std::function<void(json)>& cb) {
} }
void LiteInterface::fetchLatestBlock(const std::function<void(json)>& cb, void LiteInterface::fetchLatestBlock(const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err) { const std::function<void(QString)>& err) {
if (conn == nullptr) if (conn == nullptr)
return; return;
@ -166,7 +166,7 @@ void LiteInterface::fetchLatestBlock(const std::function<void(json)>& cb,
* combine the result, and call the callback with a single list containing both the t-addr and z-addr * combine the result, and call the callback with a single list containing both the t-addr and z-addr
* private keys * private keys
*/ */
void LiteInterface::fetchAllPrivKeys(const std::function<void(json)> cb) { void LiteInterface::fetchAllPrivKeys(const std::function<void(QJsonValue)> cb) {
if (conn == nullptr) { if (conn == nullptr) {
// No connection, just return // No connection, just return
return; return;

42
src/liteinterface.h

@ -6,8 +6,6 @@
#include "camount.h" #include "camount.h"
#include "connection.h" #include "connection.h"
using json = nlohmann::json;
// Since each transaction can contain multiple outputs, we separate them out individually // Since each transaction can contain multiple outputs, we separate them out individually
// into a struct with address, amount, memo // into a struct with address, amount, memo
struct TransactionItemDetail { struct TransactionItemDetail {
@ -38,43 +36,43 @@ public:
void setConnection(Connection* c); void setConnection(Connection* c);
Connection* getConnection() { return conn; } Connection* getConnection() { return conn; }
void fetchUnspent (const std::function<void(json)>& cb); void fetchUnspent (const std::function<void(QJsonValue)>& cb);
void fetchTransactions (const std::function<void(json)>& cb); void fetchTransactions (const std::function<void(QJsonValue)>& cb);
void fetchAddresses (const std::function<void(json)>& cb); void fetchAddresses (const std::function<void(QJsonValue)>& cb);
void fetchInfo(const std::function<void(json)>& cb, void fetchInfo(const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err); const std::function<void(QString)>& err);
void fetchLatestBlock(const std::function<void(json)>& cb, void fetchLatestBlock(const std::function<void(QJsonValue)>& cb,
const std::function<void(QString)>& err); const std::function<void(QString)>& err);
void fetchBalance(const std::function<void(json)>& cb); void fetchBalance(const std::function<void(QJsonValue)>& cb);
void createNewZaddr(bool sapling, const std::function<void(json)>& cb); void createNewZaddr(bool sapling, const std::function<void(QJsonValue)>& cb);
void createNewTaddr(const std::function<void(json)>& cb); void createNewTaddr(const std::function<void(QJsonValue)>& cb);
void createNewSietchZaddr(const std::function<void(json)>& cb); void createNewSietchZaddr(const std::function<void(QJsonValue)>& cb);
void fetchPrivKey(QString addr, const std::function<void(json)>& cb); void fetchPrivKey(QString addr, const std::function<void(QJsonValue)>& cb);
void fetchAllPrivKeys(const std::function<void(json)>); void fetchAllPrivKeys(const std::function<void(QJsonValue)>);
void fetchSeed(const std::function<void(json)>&); void fetchSeed(const std::function<void(QJsonValue)>&);
void saveWallet(const std::function<void(json)>& cb); void saveWallet(const std::function<void(QJsonValue)>& cb);
void clearWallet(const std::function<void(json)>& cb); void clearWallet(const std::function<void(QJsonValue)>& cb);
void fetchWalletEncryptionStatus(const std::function<void(json)>& cb); void fetchWalletEncryptionStatus(const std::function<void(QJsonValue)>& cb);
void fetchSupply(const std::function<void(json)>& cb); void fetchSupply(const std::function<void(QJsonValue)>& cb);
void encryptWallet(QString password, const std::function<void(json)>& cb); void encryptWallet(QString password, const std::function<void(QJsonValue)>& cb);
void unlockWallet(QString password, const std::function<void(json)>& cb); void unlockWallet(QString password, const std::function<void(QJsonValue)>& cb);
void removeWalletEncryption(QString password, const std::function<void(json)>& cb); void removeWalletEncryption(QString password, const std::function<void(QJsonValue)>& cb);
//void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb); //void importZPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
//void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb); //void importTPrivKey(QString addr, bool rescan, const std::function<void(json)>& cb);
void sendTransaction(QString params, const std::function<void(json)>& cb, const std::function<void(QString)>& err); void sendTransaction(QString params, const std::function<void(QJsonValue)>& cb, const std::function<void(QString)>& err);
private: private:
Connection* conn = nullptr; Connection* conn = nullptr;

252
src/mainwindow.cpp

@ -33,9 +33,7 @@
#include "Crypto/FileEncryption.h" #include "Crypto/FileEncryption.h"
#include "DataStore/DataStore.h" #include "DataStore/DataStore.h"
#include "firsttimewizard.h" #include "firsttimewizard.h"
#include "../lib/silentdragonlitelib.h"
using json = nlohmann::json;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
@ -305,53 +303,31 @@ void MainWindow::closeEvent(QCloseEvent* event) {
fileoldencryption.remove(); fileoldencryption.remove();
// Encrypt our wallet.dat // Encrypt our wallet.dat
QString str = DataStore::getChatDataStore()->getPassword(); QString passphraseHash = DataStore::getChatDataStore()->getPassword();
// QString str = ed.txtPassword->text(); // data comes from user inputs int length = passphraseHash.length();
int length = str.length();
char *sequence = NULL;
sequence = new char[length+1];
strncpy(sequence, str.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 *sequence1 = NULL;
sequence1 = new char[length+1];
strncpy(sequence1, passphraseHash.toUtf8(), length+1);
#define PASSWORD sequence #define PassphraseHashEnd ((const unsigned char *) sequence1)
#define KEY_LEN crypto_box_SEEDBYTES #define MESSAGE_LEN length
/////////we use the Hash of the Password as Salt, not perfect but still a good solution.
unsigned char key[KEY_LEN]; #define PASSWORD sequence
#define KEY_LEN crypto_box_SEEDBYTES
if (crypto_pwhash const QByteArray ba = QByteArray::fromHex(passphraseHash.toLatin1());
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash, const unsigned char *encryptedMemo1 = reinterpret_cast<const unsigned char *>(ba.constData());
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */
}
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); 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 sourceWallet_file = dirwallet;
QString target_encWallet_file = dirwalletenc; QString target_encWallet_file = dirwalletenc;
FileEncryption::encrypt(target_enc_file, source_file, key); // FileEncryption::encrypt(target_enc_file, source_file, key);
FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key); FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, encryptedMemo1);
///////////////// we rename the plaintext wallet.dat to Backup, for testing.
QFile wallet(dirwallet); QFile wallet(dirwallet);
QFile address(dir.filePath("addresslabels.dat"));
wallet.remove(); wallet.remove();
address.remove();
} }
@ -399,51 +375,49 @@ void MainWindow::encryptWallet() {
if (d.exec() == QDialog::Accepted) 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(); 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 char *sequence1 = NULL;
#define KEY_LEN crypto_box_SEEDBYTES 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 if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash, (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) { crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */ /* out of memory */
} }
QString passphraseHash1 = QByteArray(reinterpret_cast<const char*>(key), KEY_LEN).toHex();
DataStore::getChatDataStore()->setPassword(passphraseHash1);
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); 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 sourceWallet_file = dirwallet;
QString target_encWallet_file = dirwalletenc; QString target_encWallet_file = dirwalletenc;
FileEncryption::encrypt(target_enc_file, source_file, key);
FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key); FileEncryption::encrypt(target_encWallet_file, sourceWallet_file, key);
QFile wallet(dirwallet); QFile wallet(dirwallet);
QFile address(dir.filePath("addresslabels.dat"));
wallet.rename(dirwalletbackup); wallet.rename(dirwalletbackup);
address.rename(dir.filePath("addresslabels.datBackup"));
QMessageBox::information(this, tr("Wallet Encryption Success"), QMessageBox::information(this, tr("Wallet Encryption Success"),
QString("Successfully encrypted your wallet"), QString("Successfully encrypted your wallet"),
@ -484,27 +458,28 @@ void MainWindow::removeWalletEncryption() {
if (d.exec() == QDialog::Accepted) if (d.exec() == QDialog::Accepted)
{ {
QString str = ed.txtPassword->text(); // data comes from user inputs QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs
int length = str.length();
QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
int length = passphrase.length();
char *sequence = NULL; char *sequence = NULL;
sequence = new char[length+1]; sequence = new char[length+1];
strncpy(sequence, str.toLocal8Bit(), length +1); strncpy(sequence, passphrase.toUtf8(), length +1);
#define MESSAGE ((const unsigned char *) sequence) QString passphraseHash = blake3_PW(sequence);
#define MESSAGE_LEN length
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 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 if (crypto_pwhash
@ -513,18 +488,14 @@ void MainWindow::removeWalletEncryption() {
crypto_pwhash_ALG_DEFAULT) != 0) { crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */ /* out of memory */
} }
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString target_encwallet_file = dirwalletenc; QString target_encwallet_file = dirwalletenc;
QString target_decwallet_file = dirwallet; 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_decwallet_file, target_encwallet_file, key);
FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key);
QFile filencrypted(dirwalletenc); QFile filencrypted(dirwalletenc);
QFile wallet(dirwallet); QFile wallet(dirwallet);
@ -556,85 +527,64 @@ void MainWindow::removeWalletEncryptionStartUp() {
QDialog d(this); QDialog d(this);
Ui_startup ed; Ui_startup ed;
ed.setupUi(&d); ed.setupUi(&d);
if (d.exec() == QDialog::Accepted) if (d.exec() == QDialog::Accepted)
{ {
QString password = ed.txtPassword->text(); // data comes from user inputs QString passphraseBlank = ed.txtPassword->text(); // data comes from user inputs
int length = password.length();
DataStore::getChatDataStore()->setPassword(password); QString passphrase = QString("HUSH3") + passphraseBlank + QString("SDL");
int length = passphrase.length();
char *sequence = NULL; char *sequence = NULL;
sequence = new char[length+1]; 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 ((const unsigned char *) sequence)
#define MESSAGE_LEN length #define MESSAGE_LEN length
#define hash ((const unsigned char *) sequence1)
unsigned char hash[crypto_secretstream_xchacha20poly1305_KEYBYTES];
crypto_hash_sha256(hash,MESSAGE, MESSAGE_LEN);
#define PASSWORD sequence #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 if (crypto_pwhash
(key, sizeof key, PASSWORD, strlen(PASSWORD), hash, (key, sizeof key, PASSWORD, strlen(PASSWORD), hash,
crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE, crypto_pwhash_OPSLIMIT_SENSITIVE, crypto_pwhash_MEMLIMIT_SENSITIVE,
crypto_pwhash_ALG_DEFAULT) != 0) { crypto_pwhash_ALG_DEFAULT) != 0) {
/* out of memory */ /* out of memory */
} }
QString passphraseHash1 = QByteArray(reinterpret_cast<const char*>(key), KEY_LEN).toHex();
DataStore::getChatDataStore()->setPassword(passphraseHash1);
{
auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); auto dir = QDir(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation));
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QString target_encwallet_file = dirwalletenc; QString target_encwallet_file = dirwalletenc;
QString target_decwallet_file = dirwallet; 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_decwallet_file, target_encwallet_file, key);
FileEncryption::decrypt(target_decaddr_file, target_encaddr_file, key);
}
auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation)); auto dirHome = QDir(QStandardPaths::writableLocation(QStandardPaths::HomeLocation));
QFile wallet(dirwallet); 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"), QMessageBox::critical(this, tr("Wallet Encryption Failed"),
QString("false password please try again"), QString("false password please try again"),
QMessageBox::Ok QMessageBox::Ok
); );
this->removeWalletEncryptionStartUp(); this->removeWalletEncryptionStartUp();
} }else{}
}else{ }else{
@ -731,8 +681,6 @@ void MainWindow::setupSettingsModal() {
QObject::connect(settings.comboBoxTheme, &QComboBox::currentTextChanged, [=] (QString theme_name) { QObject::connect(settings.comboBoxTheme, &QComboBox::currentTextChanged, [=] (QString theme_name) {
this->slot_change_theme(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 // Get Currency Data
@ -1019,7 +967,7 @@ void MainWindow::exportSeed() {
rpc->fetchSeed([=](json reply) { rpc->fetchSeed([=](QJsonValue reply) {
if (isJsonError(reply)) { if (isJsonError(reply)) {
return; return;
} }
@ -1037,7 +985,7 @@ void MainWindow::exportSeed() {
pui.privKeyTxt->setReadOnly(true); pui.privKeyTxt->setReadOnly(true);
pui.privKeyTxt->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap); pui.privKeyTxt->setLineWrapMode(QPlainTextEdit::LineWrapMode::NoWrap);
pui.privKeyTxt->setPlainText(QString::fromStdString(reply.dump())); pui.privKeyTxt->setPlainText(QLatin1String(QJsonDocument(reply.toObject()).toJson(QJsonDocument::Compact)));
pui.helpLbl->setText(tr("This is your wallet seed. Please back it up carefully and safely.")); pui.helpLbl->setText(tr("This is your wallet seed. Please back it up carefully and safely."));
@ -1091,14 +1039,14 @@ void MainWindow::exportKeys(QString addr) {
bool allKeys = addr.isEmpty() ? true : false; bool allKeys = addr.isEmpty() ? true : false;
auto fnUpdateUIWithKeys = [=](json reply) { auto fnUpdateUIWithKeys = [=](QJsonValue reply) {
if (isJsonError(reply)) { if (isJsonError(reply)) {
return; return;
} }
if (reply.is_discarded() || !reply.is_array()) { if (reply.isNull() || !reply.isArray()) {
QMessageBox::critical(this, tr("Error getting private keys"), QMessageBox::critical(this, tr("Error getting private keys"),
tr("Error loading private keys: ") + QString::fromStdString(reply.dump()), tr("Error loading private keys: ") + QLatin1String(QJsonDocument(reply.toObject()).toJson(QJsonDocument::Compact)),
QMessageBox::Ok); QMessageBox::Ok);
return; return;
} }
@ -1137,8 +1085,8 @@ void MainWindow::exportKeys(QString addr) {
}); });
QString allKeysTxt; QString allKeysTxt;
for (auto i : reply.get<json::array_t>()) { for (auto i : reply.toArray()) {
allKeysTxt = allKeysTxt % QString::fromStdString(i["private_key"]) % " # addr=" % QString::fromStdString(i["address"]) % "\n"; allKeysTxt = allKeysTxt % i.toObject()["private_key"].toString() % " # addr=" % i.toObject()["address"].toString() % "\n";
} }
pui.privKeyTxt->setPlainText(allKeysTxt); pui.privKeyTxt->setPlainText(allKeysTxt);
@ -1169,7 +1117,7 @@ void MainWindow::setupBalancesTab() {
QList<QString> allAddresses; QList<QString> allAddresses;
allAddresses = getRPC()->getModel()->getAllZAddresses(); allAddresses = getRPC()->getModel()->getAllZAddresses();
QString depositzaddr = allAddresses[1]; QString depositzaddr = allAddresses[0];
deposithush.qrcodeDisplayDeposit->setQrcodeString(depositzaddr); deposithush.qrcodeDisplayDeposit->setQrcodeString(depositzaddr);
deposithush.zaddr->setText(depositzaddr); deposithush.zaddr->setText(depositzaddr);
@ -1344,6 +1292,8 @@ void MainWindow::setupTransactionsTab() {
void MainWindow::setupchatTab() { void MainWindow::setupchatTab() {
ui->memoTxtChat->setEnabled(false);
/////////////Setting Icons for Chattab and different themes /////////////Setting Icons for Chattab and different themes
auto theme = Settings::getInstance()->get_theme_name(); auto theme = Settings::getInstance()->get_theme_name();
@ -1530,6 +1480,7 @@ void MainWindow::setupchatTab() {
ui->listContactWidget->addAction(HushAction); ui->listContactWidget->addAction(HushAction);
ui->listContactWidget->addAction(requestHushAction); ui->listContactWidget->addAction(requestHushAction);
ui->listContactWidget->addAction(subatomicAction); ui->listContactWidget->addAction(subatomicAction);
ui->memoTxtChat->setEnabled(true);
/*QObject::connect(requestHushAction, &QAction::triggered, [=]() { /*QObject::connect(requestHushAction, &QAction::triggered, [=]() {
QModelIndex index = ui->listContactWidget->currentIndex(); QModelIndex index = ui->listContactWidget->currentIndex();
@ -1578,6 +1529,7 @@ void MainWindow::setupchatTab() {
}); });
ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat); ui->memoTxtChat->setLenDisplayLabelChat(ui->memoSizeChat);
} }
void MainWindow::updateChat() void MainWindow::updateChat()
@ -1592,8 +1544,8 @@ void MainWindow::updateContacts()
} }
void MainWindow::addNewZaddr(bool sapling) { void MainWindow::addNewZaddr(bool sapling) {
rpc->createNewZaddr(sapling, [=] (json reply) { rpc->createNewZaddr(sapling, [=] (QJsonValue reply) {
QString addr = QString::fromStdString(reply.get<json::array_t>()[0]); QString addr = reply.toArray()[0].toString();
// Make sure the RPC class reloads the z-addrs for future use // Make sure the RPC class reloads the z-addrs for future use
rpc->refreshAddresses(); rpc->refreshAddresses();
@ -1643,8 +1595,8 @@ std::function<void(bool)> MainWindow::addZAddrsToComboList(bool sapling) {
void MainWindow::setupReceiveTab() { void MainWindow::setupReceiveTab() {
auto addNewTAddr = [=] () { auto addNewTAddr = [=] () {
rpc->createNewTaddr([=] (json reply) { rpc->createNewTaddr([=] (QJsonValue reply) {
QString addr = QString::fromStdString(reply.get<json::array_t>()[0]); QString addr = reply.toArray()[0].toString();
// Make sure the RPC class reloads the t-addrs for future use // Make sure the RPC class reloads the t-addrs for future use
rpc->refreshAddresses(); rpc->refreshAddresses();
@ -1993,7 +1945,7 @@ void MainWindow::slot_change_theme(const QString& theme_name)
if (qFile.open(QFile::ReadOnly)) if (qFile.open(QFile::ReadOnly))
{ {
QString styleSheet = QLatin1String(qFile.readAll()); QString styleSheet = QLatin1String(qFile.readAll());
this->setStyleSheet(""); // reset styles this->setStyleSheet(""); // resets styles, makes app restart unnecessary
this->setStyleSheet(styleSheet); this->setStyleSheet(styleSheet);
} }
@ -2019,8 +1971,8 @@ void MainWindow::on_givemeZaddr_clicked()
{ {
bool sapling = true; bool sapling = true;
rpc->createNewZaddr(sapling, [=] (json reply) { rpc->createNewZaddr(sapling, [=] (QJsonValue reply) {
QString hushchataddr = QString::fromStdString(reply.get<json::array_t>()[0]); QString hushchataddr = reply.toArray()[0].toString();
QClipboard *zaddr_Clipboard = QApplication::clipboard(); QClipboard *zaddr_Clipboard = QApplication::clipboard();
zaddr_Clipboard ->setText(hushchataddr); zaddr_Clipboard ->setText(hushchataddr);
QMessageBox::information(this, "Your new HushChat address was copied to your clipboard!",hushchataddr); QMessageBox::information(this, "Your new HushChat address was copied to your clipboard!",hushchataddr);

17
src/mainwindow.h

@ -14,7 +14,6 @@ class WSServer;
class WormholeClient; class WormholeClient;
class ChatModel; class ChatModel;
using json = nlohmann::json;
// Struct used to hold destination info when sending a Tx. // Struct used to hold destination info when sending a Tx.
struct ToFields { struct ToFields {
@ -215,5 +214,21 @@ private:
QPushButton* sendChatButton = nullptr; 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 #endif // MAINWINDOW_H

4
src/mainwindow.ui

@ -59,7 +59,7 @@
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>2</number> <number>5</number>
</property> </property>
<widget class="QWidget" name="tab"> <widget class="QWidget" name="tab">
<attribute name="title"> <attribute name="title">
@ -429,7 +429,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1226</width> <width>1226</width>
<height>493</height> <height>509</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="sendToLayout"> <layout class="QVBoxLayout" name="sendToLayout">

310
src/newwallet.ui

@ -6,114 +6,129 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>437</width> <width>950</width>
<height>381</height> <height>717</height>
</rect> </rect>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>950</width>
<height>734</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Create New SDL Wallet</string> <string>Create New SDL Wallet</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="6" column="0"> <item row="0" column="0" colspan="3">
<widget class="QLabel" name="label_6"> <widget class="QGraphicsView" name="Logo">
<property name="text">
<string>Confirm Passphrase:</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="txtConfirmPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="title"> <property name="minimumSize">
<string/> <size>
</property> <width>931</width>
<layout class="QGridLayout" name="gridLayout_3"> <height>192</height>
<item row="0" column="0"> </size>
<widget class="QRadioButton" name="radioRestoreWallet"> </property>
<property name="text"> <property name="verticalScrollBarPolicy">
<string>Restore wallet from seed</string> <enum>Qt::ScrollBarAlwaysOff</enum>
</property> </property>
</widget> <property name="horizontalScrollBarPolicy">
</item> <enum>Qt::ScrollBarAlwaysOff</enum>
<item row="1" column="0"> </property>
<widget class="QLabel" name="label_3"> <property name="sizeAdjustPolicy">
<property name="text"> <enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
<string>Restore an existing wallet, using the 24-word seed. </string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QLineEdit" name="txtPassword">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0" colspan="3"> <item row="1" column="0">
<widget class="QGroupBox" name="groupBox"> <spacer name="verticalSpacer_2">
<property name="sizePolicy"> <property name="orientation">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding"> <enum>Qt::Vertical</enum>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="title"> <property name="sizeHint" stdset="0">
<string/> <size>
</property> <width>20</width>
<layout class="QGridLayout" name="gridLayout_2"> <height>50</height>
<item row="0" column="0"> </size>
<widget class="QRadioButton" name="radioNewWallet"> </property>
<property name="text"> </spacer>
<string>Create a new wallet</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Create a new wallet with a randomly generated seed.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item> </item>
<item row="2" column="0" colspan="3"> <item row="2" column="0" colspan="3">
<widget class="Line" name="line_2"> <widget class="QTextBrowser" name="textBrowser">
<property name="orientation"> <property name="minimumSize">
<enum>Qt::Horizontal</enum> <size>
<width>931</width>
<height>150</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>949</width>
<height>16777215</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="html">
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;h1 align=&quot;center&quot; style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:600;&quot;&gt;Hush + HushChat Terms of Service&lt;/span&gt;&lt;/h1&gt;
&lt;p style=&quot; margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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 &lt;a href=&quot;https://en.wikipedia.org/wiki/Non-aggression_principle&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;Non-Aggression Principle&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;THE SERVICE IS PROVIDED “AS IS” AND The Hush Developers DO NOT MAKE ANY SPECIFIC COMMITMENTS OR WARRANTIES ABOUT THE SERVICE.&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;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.&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_4"> <widget class="QRadioButton" name="TOS">
<property name="maximumSize">
<size>
<width>251</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>Encryption Passphrase:</string> <string>I accept the Terms of Service</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>49</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0" colspan="2">
<widget class="QLabel" name="lblPasswordMatch"> <widget class="QLabel" name="lblPasswordMatch">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred"> <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
@ -121,6 +136,12 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>711</width>
<height>0</height>
</size>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">color: red;</string> <string notr="true">color: red;</string>
</property> </property>
@ -132,7 +153,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="4" column="2">
<widget class="QLabel" name="label_5"> <widget class="QLabel" name="label_5">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred"> <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
@ -145,6 +166,125 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Encryption Passphrase:</string>
</property>
</widget>
</item>
<item row="5" column="1" colspan="2">
<widget class="QLineEdit" name="txtPassword">
<property name="minimumSize">
<size>
<width>611</width>
<height>0</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Confirm Passphrase:</string>
</property>
</widget>
</item>
<item row="6" column="1" colspan="2">
<widget class="QLineEdit" name="txtConfirmPassword">
<property name="minimumSize">
<size>
<width>611</width>
<height>0</height>
</size>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="7" column="0" colspan="3">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="8" column="0" colspan="3">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>431</width>
<height>90</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>431</width>
<height>90</height>
</size>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QRadioButton" name="radioRestoreWallet">
<property name="text">
<string>Restore wallet from seed</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>431</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>431</width>
<height>90</height>
</size>
</property>
<property name="title">
<string/>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QRadioButton" name="radioNewWallet">
<property name="text">
<string>Create a new wallet</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

2
src/precompiled.h

@ -71,8 +71,8 @@
#include <QObject> #include <QObject>
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QPainterPath>
#include "3rdparty/json/json.hpp"
#include "3rdparty/qrcode/QrCode.hpp" #include "3rdparty/qrcode/QrCode.hpp"
#define SODIUM_STATIC #define SODIUM_STATIC

65
src/restoreseed.ui

@ -6,24 +6,14 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>400</width> <width>498</width>
<height>300</height> <height>575</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Restore Wallet Seed</string> <string>Restore Wallet Seed</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Please enter your 24-word seed below</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="sizePolicy"> <property name="sizePolicy">
@ -35,36 +25,36 @@
<property name="title"> <property name="title">
<string/> <string/>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QGridLayout" name="gridLayout_2">
<item> <item row="0" column="0">
<widget class="QLabel" name="label_3"> <widget class="QLabel" name="label_3">
<property name="text"> <property name="text">
<string>Wallet Seed</string> <string>Wallet Seed</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="1" column="0">
<widget class="QPlainTextEdit" name="txtSeed"> <widget class="QPlainTextEdit" name="txtSeed">
<property name="readOnly"> <property name="readOnly">
<bool>false</bool> <bool>false</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="2" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="label_2">
<property name="text"> <property name="text">
<string>Wallet Birthday</string> <string>Wallet Birthday</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="3" column="0">
<widget class="QLineEdit" name="txtBirthday"> <widget class="QLineEdit" name="txtBirthday">
<property name="text"> <property name="text">
<string>0</string> <string>0</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="4" column="0">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="label_4">
<property name="font"> <property name="font">
<font> <font>
@ -79,9 +69,48 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Quantity </string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLineEdit" name="number">
<property name="text">
<string>10</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="font">
<font>
<pointsize>9</pointsize>
</font>
</property>
<property name="text">
<string>The quantity of shielded addresses that gets recreated during the restore process</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Please enter your 24-word seed below</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

2
src/sendtab.cpp

@ -9,8 +9,6 @@
#include "recurring.h" #include "recurring.h"
using json = nlohmann::json;
void MainWindow::setupSendTab() { void MainWindow::setupSendTab() {
// Create the validator for send to/amount fields // Create the validator for send to/amount fields
amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}")); amtValidator = new QRegExpValidator(QRegExp("[0-9]{0,8}\\.?[0-9]{0,8}"));

13
src/settings.h

@ -4,8 +4,6 @@
#include "precompiled.h" #include "precompiled.h"
#include "camount.h" #include "camount.h"
using json = nlohmann::json;
struct Config { struct Config {
QString server; QString server;
}; };
@ -67,8 +65,6 @@ public:
void set_currency_name(QString currency_name); void set_currency_name(QString currency_name);
bool isSaplingActive(); bool isSaplingActive();
void setZECPrice(double p) { ZECPrice = p; } void setZECPrice(double p) { ZECPrice = p; }
@ -225,13 +221,12 @@ private:
}; };
inline bool isJsonResultSuccess(const json& res) { inline bool isJsonResultSuccess(const QJsonValue& res) {
return res.find("result") != res.end() && return res.toObject()["result"].toString() == "success";
QString::fromStdString(res["result"].get<json::string_t>()) == "success";
} }
inline bool isJsonError(const json& res) { inline bool isJsonError(const QJsonValue& res) {
return res.find("error") != res.end(); return !res.toObject()["error"].isNull();
} }

5
src/settings.ui

@ -138,6 +138,11 @@
<string>Default</string> <string>Default</string>
</property> </property>
</item> </item>
<item>
<property name="text">
<string>test</string>
</property>
</item>
</widget> </widget>
<widget class="QCheckBox" name="chkFetchPrices"> <widget class="QCheckBox" name="chkFetchPrices">
<property name="geometry"> <property name="geometry">

2
src/version.h

@ -1 +1 @@
#define APP_VERSION "1.3.3" #define APP_VERSION "1.3.6"

10
src/websockets.cpp

@ -735,9 +735,9 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st
return; return;
} }
json params = json::array(); QJsonArray params;
mainwindow->getRPC()->fillTxJsonParams(params, tx); mainwindow->getRPC()->fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl; //std::cout << std::setw(2) << params << std::endl;
// And send the Tx // And send the Tx
mainwindow->getRPC()->executeTransaction(tx, mainwindow->getRPC()->executeTransaction(tx,
@ -835,9 +835,9 @@ void AppDataServer::processSendManyTx(QJsonObject sendmanyTx, MainWindow* mainwi
return; return;
} }
json params = json::array(); QJsonArray params;
mainwindow->getRPC()->fillTxJsonParams(params, tx); mainwindow->getRPC()->fillTxJsonParams(params, tx);
std::cout << std::setw(2) << params << std::endl; //std::cout << std::setw(2) << params << std::endl;
// And send the Tx // And send the Tx
mainwindow->getRPC()->executeTransaction(tx, mainwindow->getRPC()->executeTransaction(tx,
@ -923,7 +923,7 @@ void AppDataServer::processGetTransactions(MainWindow* mainWindow, std::shared_p
{"amount", model->getAmt(i)}, {"amount", model->getAmt(i)},
{"txid", model->getTxId(i)}, {"txid", model->getTxId(i)},
{"address", model->getAddr(i)}, {"address", model->getAddr(i)},
{"memo", model->getMemo(i)}, // {"memo", model->getMemo(i)},
{"confirmations", model->getConfirmations(i)} {"confirmations", model->getConfirmations(i)}
}); });
} }

Loading…
Cancel
Save