pull/248/head
larteyoh 2 months ago
parent 2ffc105beb
commit 511d4a0446

@ -242,6 +242,7 @@ Page {
}
if(button.text == restoreFromSeedButton.text) {
walletRestoreStack.currentIndex = 1
seedInput.forceActiveFocus()
}
if(button.text == restoreFromKeysButton.text) {
walletRestoreStack.currentIndex = 2
@ -587,12 +588,34 @@ Page {
messageBox.open()
return;
}
Wallet.restoreFromSeed(seedInput.text, User)
// Process login credentials
// ...
let loginError = Backend.loginWithMnemonic(Wallet, seedInput.text, User)
if(loginError != Enum.LoginError.Ok) {
console.log("loginError", loginError)
if(loginError == Enum.LoginError.WalletBadNetworkType) {
messageBox.text = qsTr("Bad network type")
messageBox.open()
} else if(loginError == Enum.LoginError.WalletInvalidMnemonic) {
messageBox.text = qsTr("Invalid mnemonic")
messageBox.open()
} else if(loginError == Enum.LoginError.WalletBadWalletType) {
messageBox.text = qsTr("Bad wallet type")
messageBox.open()
} else if(loginError == Enum.LoginError.DaemonIsNotConnected) {
messageBox.text = qsTr("Daemon (neromon) is not connected")
messageBox.open()
} else if(loginError == Enum.LoginError.UserNotFound) {
messageBox.text = qsTr("User not found. Please try again or register")
messageBox.open()
} else {
messageBox.text = qsTr("Login error")
messageBox.open()
}
return;
}
onAutoSync();
// Switch to HomePage
////pageStack.pushPage("qrc:/qml/pages/HomePage.qml", StackView.Immediate)//stack.push(home_page)
pageStack.pushPage("qrc:/qml/pages/HomePage.qml", StackView.Immediate)//stack.push(home_page)
}
}

@ -451,7 +451,6 @@ void neroshop::Node::persist_routing_table(const std::string& address, int port)
db::Sqlite3 * database = neroshop::get_database();
if(!database) throw std::runtime_error("database is NULL");
database->execute("BEGIN;");
if(!database->table_exists("routing_table")) { // or simply "nodes"
database->execute("CREATE TABLE routing_table("
@ -459,8 +458,6 @@ void neroshop::Node::persist_routing_table(const std::string& address, int port)
}
database->execute_params("INSERT INTO routing_table (ip_address, port) VALUES (?1, ?2);", { address, std::to_string(port) });
database->execute("COMMIT;");
}
void neroshop::Node::rebuild_routing_table() {

@ -96,7 +96,15 @@ int neroshop::MoneroWallet::restore_from_seed(const std::string& seed)
wallet_config_obj.m_seed = seed;
wallet_config_obj.m_restore_height = 0;
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet (wallet_config_obj, nullptr));
try {
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet (wallet_config_obj, nullptr));
} catch (const std::exception& e) {
std::string error_msg = e.what();
std::cerr << "\033[1;91m" << error_msg << "\033[0m\n";
if(neroshop::string::contains(error_msg, "Invalid mnemonic")) {
return static_cast<int>(WalletError::InvalidMnemonic);
}
}
if(!monero_wallet_obj.get()) return static_cast<int>(WalletError::IsNotOpened);
std::cout << "\033[1;35m" << "restored in-memory wallet (from seed)" << "\033[0m" << std::endl;

@ -131,9 +131,18 @@ int neroshop::Wallet::restore_from_seed(const std::string& seed)
wallet_config_obj.m_seed = seed;
wallet_config_obj.m_restore_height = 0;
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet (wallet_config_obj, nullptr));
try {
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero_wallet_full::create_wallet (wallet_config_obj, nullptr));
} catch (const std::exception& e) {
std::string error_msg = e.what();
std::cerr << "\033[1;91m" << error_msg << "\033[0m\n";
if(neroshop::string::contains(error_msg, "Invalid mnemonic")) {
return static_cast<int>(WalletError::InvalidMnemonic);
}
}
if(!monero_wallet_obj.get()) return static_cast<int>(WalletError::IsNotOpened);
std::cout << "\033[1;35;49m" << "restored in-memory wallet (from seed)" << "\033[0m" << std::endl;
return static_cast<int>(WalletError::Ok);
}
//-------------------------------------------------------
@ -168,7 +177,7 @@ int neroshop::Wallet::open(const std::string& path, const std::string& password)
monero_wallet_obj = std::unique_ptr<monero_wallet_full>(monero::monero_wallet_full::open_wallet(path, password, static_cast<monero::monero_network_type>(this->network_type)));
} catch (const std::exception& e) {
std::string error_msg = e.what();
neroshop::print(error_msg, 1);//tools::error::invalid_password
std::cerr << "\033[1;91m" << error_msg << "\033[0m\n";//tools::error::invalid_password
if(neroshop::string::contains(error_msg, "wallet cannot be opened as")) {
return static_cast<int>(WalletError::BadNetworkType);
} else if(neroshop::string::contains(error_msg, "invalid password")) {

@ -52,6 +52,7 @@ enum class WalletError {
BadNetworkType,
IsNotOpened, // monero_wallet_obj is nullptr
BadWalletType,
InvalidMnemonic,
};
class Wallet : public monero_wallet_listener {

@ -6,14 +6,13 @@
// neroshop
#include "../core/crypto/sha3.hpp"
#include "../core/protocol/p2p/node.hpp" // server.hpp included here (hopefully)
#include "../core/protocol/p2p/routing_table.hpp" // uncomment if using routing_table
#include "../core/protocol/p2p/routing_table.hpp"
#include "../core/protocol/transport/ip_address.hpp"
#include "../core/protocol/rpc/json_rpc.hpp"
#include "../core/protocol/messages/msgpack.hpp"
#include "../core/database/database.hpp"
#include "../core/tools/logger.hpp"
#include "../core/version.hpp"
#include "../core/tools/timer.hpp"
#include "../core/tools/filesystem.hpp"
#include <cxxopts.hpp>
@ -108,7 +107,7 @@ void rpc_server(const std::string& address) {
void ipc_server(Node& node) {
// Prevent bootstrap node from being accepted by IPC server
// since its only meant to act as an initial contact point for new nodes joining the network
if (node.is_bootstrap_node()) {
if (node.is_hardcoded()) {
std::cout << "Bootstrap node is not allowed to use the local IPC server. Please start another daemon instance to use the GUI\n";
return;
}
@ -163,12 +162,12 @@ void dht_server(Node& node) {
});
// Join the DHT network
if (!node.is_bootstrap_node()) {
if (!node.is_hardcoded()) {
//std::shared_lock<std::shared_mutex> read_lock(node_mutex);
node.join(); // A bootstrap node cannot join the network
}
if(node.is_bootstrap_node()) {
if(node.is_hardcoded()) {
node.rebuild_routing_table();
}

@ -1857,9 +1857,9 @@ int neroshop::Backend::loginWithWalletFile(WalletController* wallet_controller,
return static_cast<int>(EnumWrapper::LoginError::UserNotFound);
}
// Get the account DHT key
std::string account_key = database->get_text_params("SELECT key FROM mappings WHERE search_term = ?1 AND content = 'user'", { primary_address });
std::string user_key = database->get_text_params("SELECT key FROM mappings WHERE search_term = ?1 AND content = 'user'", { primary_address });
// Save user information in memory
std::string display_name = database->get_text_params("SELECT search_term FROM mappings WHERE key = ?1 AND LENGTH(search_term) <= 30 AND content = 'user'", { account_key });
std::string display_name = database->get_text_params("SELECT search_term FROM mappings WHERE key = ?1 AND LENGTH(search_term) <= 30 AND content = 'user'", { user_key });
std::unique_ptr<neroshop::User> seller(neroshop::Seller::on_login(*wallet_controller->getWallet()));
user_controller->_user = std::move(seller);
if(user_controller->getUser() == nullptr) {
@ -1900,28 +1900,88 @@ int neroshop::Backend::loginWithWalletFile(WalletController* wallet_controller,
int neroshop::Backend::loginWithMnemonic(WalletController* wallet_controller, const QString& mnemonic, UserController * user_controller) {
db::Sqlite3 * database = neroshop::get_database();
if(!database) throw std::runtime_error("database is NULL");
// Initialize monero wallet with existing wallet mnemonic
if(!wallet_controller->restoreFromSeed(mnemonic)) {
throw std::runtime_error("Invalid mnemonic or wallet network type");
return false;
// Make sure daemon is connected first
if(!DaemonManager::isDaemonServerBound()) {
neroshop::print("Please wait for the local daemon IPC server to connect first", 1);
return static_cast<int>(EnumWrapper::LoginError::DaemonIsNotConnected);
}
// Initialize monero wallet with existing wallet mnemonic
std::packaged_task<int(void)> restore_wallet_task([wallet_controller, mnemonic]() -> int {
int wallet_error = wallet_controller->restoreFromSeed(mnemonic);
if(wallet_error != 0) {
if(wallet_error == static_cast<int>(WalletError::IsOpenedByAnotherProgram))
return static_cast<int>(EnumWrapper::LoginError::WalletIsOpenedByAnotherProgram);
if(wallet_error == static_cast<int>(WalletError::InvalidMnemonic))
return static_cast<int>(EnumWrapper::LoginError::WalletInvalidMnemonic);
if(wallet_error == static_cast<int>(WalletError::BadNetworkType))
return static_cast<int>(EnumWrapper::LoginError::WalletBadNetworkType);
if(wallet_error == static_cast<int>(WalletError::IsNotOpened))
return static_cast<int>(EnumWrapper::LoginError::WalletIsNotOpened);
if(wallet_error == static_cast<int>(WalletError::BadWalletType))
return static_cast<int>(EnumWrapper::LoginError::WalletBadWalletType);
}
return static_cast<int>(EnumWrapper::LoginError::Ok);
});
std::future<int> future_result = restore_wallet_task.get_future();
// move the task (function) to a separate thread to prevent blocking of the main thread
std::thread worker(std::move(restore_wallet_task));
worker.detach();
int login_error = future_result.get();
if(login_error != 0) return login_error;
// Get the primary address
std::string primary_address = wallet_controller->getPrimaryAddress().toStdString();
// Check database to see if user key (hash of primary address) exists
bool user_key_found = database->get_integer_params("SELECT EXISTS(SELECT * FROM users WHERE monero_address = $1)", { primary_address });
bool user_found = database->get_integer_params("SELECT EXISTS(SELECT * FROM mappings WHERE search_term = ?1 AND content = 'user')", { primary_address });
// If user key is not found in the database, then create one. This is like registering for an account
if(!user_key_found) {
if(!user_found) {
// In reality, this function will return false if user key is not registered in the database
neroshop::print("user key not found in database. Please try again or register", 1);
wallet_controller->close();
return false;
return static_cast<int>(EnumWrapper::LoginError::UserNotFound);
}
// Get the account DHT key
std::string user_key = database->get_text_params("SELECT key FROM mappings WHERE search_term = ?1 AND content = 'user'", { primary_address });
// Save user information in memory
int user_id = database->get_integer_params("SELECT id FROM users WHERE monero_address = $1", { primary_address });
std::string display_name = database->get_text_params("SELECT search_term FROM mappings WHERE key = ?1 AND LENGTH(search_term) <= 30 AND content = 'user'", { user_key });
std::unique_ptr<neroshop::User> seller(neroshop::Seller::on_login(*wallet_controller->getWallet()));
user_controller->_user = std::move(seller);
if(user_controller->getUser() == nullptr) {
return static_cast<int>(EnumWrapper::LoginError::UserIsNullPointer);
}
// Load RSA keys from file
std::string config_path = NEROSHOP_DEFAULT_KEYS_PATH;
std::string public_key_path = config_path + "/" + (primary_address + ".pub");
std::string private_key_path = config_path + "/" + (primary_address + ".key");
// Load public_key (optional)
std::ifstream public_key_file(public_key_path);
if (public_key_file) {
std::ostringstream buffer;
buffer << public_key_file.rdbuf();
std::string public_key = buffer.str();
user_controller->_user->set_public_key(public_key);
}
// Load private_key (mandatory)
std::ifstream private_key_file(private_key_path);
if (!private_key_file) {
throw std::runtime_error("Failed to open private key file: " + private_key_path);
}
std::ostringstream buffer;
buffer << private_key_file.rdbuf();
std::string private_key = buffer.str();
user_controller->_user->set_private_key(private_key); // Set RSA private key
// Emit signals
emit user_controller->userChanged();
emit user_controller->userLogged();
// Display message
std::string display_name = database->get_text_params("SELECT name FROM users WHERE monero_address = $1", { primary_address });
neroshop::print("Welcome back, user " + ((!display_name.empty()) ? (display_name + " (id: " + primary_address + ")") : primary_address), 4);
return true;
return static_cast<int>(EnumWrapper::LoginError::Ok);
}
//----------------------------------------------------------------
int neroshop::Backend::loginWithKeys(WalletController* wallet_controller, UserController * user_controller) {

@ -22,6 +22,7 @@ public:
BadNetworkType,
IsNotOpened, // monero_wallet_obj is nullptr
BadWalletType,
InvalidMnemonic,
};
Q_ENUM(WalletError)
@ -45,10 +46,11 @@ public:
WalletBadNetworkType = static_cast<int>(WalletError::BadNetworkType),
WalletIsNotOpened = static_cast<int>(WalletError::IsNotOpened),
WalletBadWalletType = static_cast<int>(WalletError::BadWalletType),
WalletInvalidMnemonic = static_cast<int>(WalletError::InvalidMnemonic),
DaemonIsNotConnected = 10,
DaemonIsNotConnected = 100,
UserNotFound = 20,
UserNotFound = 200,
UserIsNullPointer,
};
Q_ENUM(LoginError)

Loading…
Cancel
Save