From dfc729784aab4bb07dd9e0ee58d0141f7f68ea92 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Thu, 14 Nov 2019 09:19:13 -0800 Subject: [PATCH 01/12] Log opid, creation time and execution time of z ops --- src/rpc.cpp | 25 ++++++++++++------------- src/sendtab.cpp | 14 ++++++++------ 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/rpc.cpp b/src/rpc.cpp index aeec65b..616aca8 100644 --- a/src/rpc.cpp +++ b/src/rpc.cpp @@ -108,7 +108,7 @@ json RPC::makePayload(std::string method, std::string params) { {"method", method }, {"params", {params}} }; - return payload; + return payload; } json RPC::makePayload(std::string method) { @@ -117,7 +117,7 @@ json RPC::makePayload(std::string method) { {"id", "42" }, {"method", method }, }; - return payload; + return payload; } void RPC::getTAddresses(const std::function& cb) { @@ -961,35 +961,34 @@ void RPC::watchTxStatus() { return noConnection(); // Make an RPC to load pending operation statues - json payload = { - {"jsonrpc", "1.0"}, - {"id", "someid"}, - {"method", "z_getoperationstatus"}, - }; - - conn->doRPCIgnoreError(payload, [=] (const json& reply) { + conn->doRPCIgnoreError(makePayload("z_getoperationstatus"), [=] (const json& reply) { + // conn->doRPCIgnoreError(payload, [=] (const json& reply) { // There's an array for each item in the status for (auto& it : reply.get()) { // If we were watching this Tx and its status became "success", then we'll show a status bar alert QString id = QString::fromStdString(it["id"]); if (watchingOps.contains(id)) { + // log any txs we are watching + // "creation_time": 1515969376, + // "execution_secs": 50.416337, // And if it ended up successful QString status = QString::fromStdString(it["status"]); main->loadingLabel->setVisible(false); if (status == "success") { auto txid = QString::fromStdString(it["result"]["txid"]); - SentTxStore::addToSentTx(watchingOps[id].tx, txid); auto wtx = watchingOps[id]; watchingOps.remove(id); wtx.completed(id, txid); - // Refresh balances to show unconfirmed balances + qDebug() << "opid "<< id << " started at "<loadingLabel->setVisible(false); } else { main->loadingLabel->setVisible(true); - main->loadingLabel->setToolTip(QString::number(watchingOps.size()) + QObject::tr(" tx computing. This can take several minutes.")); + main->loadingLabel->setToolTip(QString::number(watchingOps.size()) + QObject::tr(" transaction computing.")); } }); } diff --git a/src/sendtab.cpp b/src/sendtab.cpp index 99867b6..450d34f 100644 --- a/src/sendtab.cpp +++ b/src/sendtab.cpp @@ -1,3 +1,4 @@ +// Copyright 2019 The Hush developers #include "mainwindow.h" #include "ui_mainwindow.h" #include "addressbook.h" @@ -705,27 +706,28 @@ void MainWindow::sendButton() { // abort the Tx return; } - + // Show a dialog to confirm the Tx if (confirmTx(tx)) { // And send the Tx - rpc->executeTransaction(tx, + rpc->executeTransaction(tx, [=] (QString opid) { - ui->statusBar->showMessage(tr("Computing Tx: ") % opid); + ui->statusBar->showMessage(tr("Computing transaction: ") % opid); + qDebug() << "Computing opid: " << opid; }, [=] (QString, QString txid) { ui->statusBar->showMessage(Settings::txidStatusMessage + " " + txid); }, [=] (QString opid, QString errStr) { - ui->statusBar->showMessage(QObject::tr(" Tx ") % opid % QObject::tr(" failed"), 15 * 1000); + ui->statusBar->showMessage(QObject::tr(" Transaction ") % opid % QObject::tr(" failed"), 15 * 1000); if (!opid.isEmpty()) errStr = QObject::tr("The transaction with id ") % opid % QObject::tr(" failed. The error was") + ":\n\n" + errStr; - QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok); + QMessageBox::critical(this, QObject::tr("Transaction Error"), errStr, QMessageBox::Ok); } ); - } + } } QString MainWindow::doSendTxValidations(Tx tx) { From 9b64c4529fddf81c92d4cd8670ac6528c3dcf008 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Sun, 17 Nov 2019 06:41:01 -0800 Subject: [PATCH 02/12] Add some debugging and little things --- src/websockets.cpp | 30 ++++++++++++++++++++++-------- src/websockets.h | 8 +++----- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/websockets.cpp b/src/websockets.cpp index 689c326..b4735d2 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -1,3 +1,4 @@ +// Copyright 2019 The Hush developers #include "websockets.h" #include "rpc.h" @@ -5,7 +6,7 @@ #include "ui_mobileappconnector.h" #include "version.h" -// Weap the sendTextMessage to check if the connection is valid and that the parent WebServer didn't close this connection +// Wrap the sendTextMessage to check if the connection is valid and that the parent WebServer didn't close this connection // for some reason. void ClientWebSocket::sendTextMessage(QString m) { if (client) { @@ -101,23 +102,32 @@ WormholeClient::~WormholeClient() { if (timer) timer->stop(); - + + qDebug() << "Wormhole client destroyed"; delete timer; } +void ws_error() { + qDebug() << "websocket error!"; +} + void WormholeClient::connect() { delete m_webSocket; m_webSocket = new QWebSocket(); + QUrl wormhole = QUrl("wss://wormhole.myhush.org:443"); QObject::connect(m_webSocket, &QWebSocket::connected, this, &WormholeClient::onConnected); QObject::connect(m_webSocket, &QWebSocket::disconnected, this, &WormholeClient::closed); - m_webSocket->open(QUrl("wss://wormhole.myhush.org:443")); + qDebug() << "Opening connection to the SilentDragonWormhole"; + m_webSocket->open(wormhole); + qDebug() << "Opened connection to " << wormhole; //TODO: use env var to over-ride //m_webSocket->open(QUrl("ws://127.0.0.1:7070")); } -void WormholeClient::retryConnect() { + +void WormholeClient::retryConnect() { int max_retries = 10; qDebug() << "Websocket retryConnect, retryCount=" << retryCount; @@ -153,11 +163,11 @@ void WormholeClient::onConnected() QObject::connect(m_webSocket, &QWebSocket::textMessageReceived, this, &WormholeClient::onTextMessageReceived); - auto payload = QJsonDocument( QJsonObject { - {"register", code} - }).toJson(); + auto payload = QJsonDocument( QJsonObject { {"register", code} }).toJson(); + qDebug() << "Sending register"; m_webSocket->sendTextMessage(payload); + qDebug() << "Sent registration message with code=" << code; // On connected, we'll also create a timer to ping it every 4 minutes, since the websocket // will timeout after 5 minutes @@ -284,14 +294,17 @@ void AppDataServer::connectAppDialog(MainWindow* parent) { if (state == Qt::Checked) { } + qDebug() << "Updating QR"; updateUIWithNewQRCode(parent); }); // If we're not listening for the app, then start the websockets if (!parent->isWebsocketListening()) { QString wormholecode = ""; - if (getAllowInternetConnection()) + if (getAllowInternetConnection()) { wormholecode = AppDataServer::getInstance()->getWormholeCode(AppDataServer::getInstance()->getSecretHex()); + qDebug() << "Generated wormholecode=" << wormholecode; + } parent->createWebsocket(wormholecode); } @@ -681,6 +694,7 @@ void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, st if (Settings::getInstance()->isSproutAddress(i)) continue; // Filter out balances that don't have the requisite amount + // TODO: should this be amt+tx.fee? if (allBalances->value(i) < amt) continue; diff --git a/src/websockets.h b/src/websockets.h index 4758f1c..9456730 100644 --- a/src/websockets.h +++ b/src/websockets.h @@ -66,13 +66,11 @@ public: void retryConnect(); private: - MainWindow* parent = nullptr; + MainWindow* parent = nullptr; QWebSocket* m_webSocket = nullptr; - QTimer* timer = nullptr; - QString code; - int retryCount = 0; + unsigned int retryCount = 0; bool shuttingDown = false; }; @@ -175,4 +173,4 @@ private: -#endif // WEBSOCKETS_H \ No newline at end of file +#endif // WEBSOCKETS_H From bb09c5ac17c2e2a0188a32676030a33acfb09331 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Sun, 17 Nov 2019 19:17:21 -0800 Subject: [PATCH 03/12] add lots of websocket debugging and listen for ssl error signals --- src/mainwindow.cpp | 6 +++++- src/websockets.cpp | 43 +++++++++++++++++++++++++++++++++++-------- src/websockets.h | 1 + 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d75dec6..debd622 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -122,6 +122,7 @@ MainWindow::MainWindow(QWidget *parent) : setupZcashdTab(); rpc = new RPC(this); + qDebug() << "Created RPC"; restoreSavedStates(); @@ -132,6 +133,7 @@ MainWindow::MainWindow(QWidget *parent) : if (ads->getAllowInternetConnection()) wormholecode = ads->getWormholeCode(ads->getSecretHex()); + qDebug() << "MainWindow: createWebsocket with wormholcode=" << wormholecode; createWebsocket(wormholecode); } } @@ -142,10 +144,11 @@ void MainWindow::createWebsocket(QString wormholecode) { // TODO: env var bool msgDebug = true; wsserver = new WSServer(wsport, msgDebug, this); - qDebug() << "Listening for app connections on port " << wsport; + qDebug() << "createWebsocket: Listening for app connections on port " << wsport; if (!wormholecode.isEmpty()) { // Connect to the wormhole service + qDebug() << "Creating WormholeClient"; wormhole = new WormholeClient(this, wormholecode); } } @@ -165,6 +168,7 @@ bool MainWindow::isWebsocketListening() { } void MainWindow::replaceWormholeClient(WormholeClient* newClient) { + qDebug() << "replacing WormholeClient"; delete wormhole; wormhole = newClient; } diff --git a/src/websockets.cpp b/src/websockets.cpp index b4735d2..9a5ebc5 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -111,6 +111,13 @@ void ws_error() { qDebug() << "websocket error!"; } +void WormholeClient::sslerrors(const QList &) +{ + qDebug() << "SSL errors occurred!"; + m_webSocket->ignoreSslErrors(); + +} + void WormholeClient::connect() { delete m_webSocket; m_webSocket = new QWebSocket(); @@ -118,6 +125,7 @@ void WormholeClient::connect() { QObject::connect(m_webSocket, &QWebSocket::connected, this, &WormholeClient::onConnected); QObject::connect(m_webSocket, &QWebSocket::disconnected, this, &WormholeClient::closed); + QObject::connect(m_webSocket, QOverload&>::of(&QWebSocket::sslErrors), this, &WormholeClient::sslerrors); qDebug() << "Opening connection to the SilentDragonWormhole"; m_webSocket->open(wormhole); @@ -127,6 +135,20 @@ void WormholeClient::connect() { } +void WormholeClient::retryConnect() { + QTimer::singleShot(5 * 1000 * pow(2, retryCount), [=]() { + if (retryCount < 10) { + qDebug() << "Retrying websocket connection, count=" << this->retryCount; + this->retryCount++; + connect(); + } + else { + qDebug() << "Retry count exceeded, will not attempt retry any more"; + } + }); +} + +/* void WormholeClient::retryConnect() { int max_retries = 10; qDebug() << "Websocket retryConnect, retryCount=" << retryCount; @@ -145,6 +167,7 @@ void WormholeClient::retryConnect() { qDebug() << "Invalid retryCount=" << retryCount << " detected!"; } } +*/ // Called when the websocket is closed. If this was closed without our explicitly closing it, // then we need to try and reconnect @@ -193,11 +216,12 @@ void WormholeClient::onTextMessageReceived(QString message) // ============================== // AppDataServer // ============================== -AppDataServer* AppDataServer::instance = nullptr; +AppDataServer* AppDataServer::instance = nullptr; QString AppDataServer::getWormholeCode(QString secretHex) { + qDebug() << "AppDataServer::getWormholeCode"; unsigned char* secret = new unsigned char[crypto_secretbox_KEYBYTES]; - sodium_hex2bin(secret, crypto_secretbox_KEYBYTES, secretHex.toStdString().c_str(), crypto_secretbox_KEYBYTES*2, + sodium_hex2bin(secret, crypto_secretbox_KEYBYTES, secretHex.toStdString().c_str(), crypto_secretbox_KEYBYTES*2, NULL, NULL, NULL); unsigned char* out1 = new unsigned char[crypto_hash_sha256_BYTES]; @@ -207,7 +231,7 @@ QString AppDataServer::getWormholeCode(QString secretHex) { crypto_hash_sha256(out2, out1, crypto_hash_sha256_BYTES); char* wmcode = new char[crypto_hash_sha256_BYTES*2 + 1]; - sodium_bin2hex(wmcode, crypto_hash_sha256_BYTES*2 + 1, out2, crypto_hash_sha256_BYTES); + sodium_bin2hex(wmcode, crypto_hash_sha256_BYTES*2 + 1, out2, crypto_hash_sha256_BYTES); QString wmcodehex(wmcode); @@ -216,7 +240,7 @@ QString AppDataServer::getWormholeCode(QString secretHex) { delete[] out1; delete[] secret; - qDebug() << "Created wormhole secretHex"; + qDebug() << "Created wormhole secretHex=" << wmcodehex; return wmcodehex; } @@ -275,17 +299,18 @@ void AppDataServer::connectAppDialog(MainWindow* parent) { ui = new Ui_MobileAppConnector(); ui->setupUi(&d); Settings::saveRestore(&d); + qDebug() << "connectAppDialog"; updateUIWithNewQRCode(parent); updateConnectedUI(); QObject::connect(ui->btnDisconnect, &QPushButton::clicked, [=] () { + qDebug() << "Disconnecting"; QSettings().setValue("mobileapp/connectedname", ""); saveNewSecret(""); - updateConnectedUI(); }); - + QObject::connect(ui->txtConnStr, &QLineEdit::cursorPositionChanged, [=](int, int) { ui->txtConnStr->selectAll(); }); @@ -300,6 +325,7 @@ void AppDataServer::connectAppDialog(MainWindow* parent) { // If we're not listening for the app, then start the websockets if (!parent->isWebsocketListening()) { + qDebug() << "websocket not listening"; QString wormholecode = ""; if (getAllowInternetConnection()) { wormholecode = AppDataServer::getInstance()->getWormholeCode(AppDataServer::getInstance()->getSecretHex()); @@ -307,21 +333,22 @@ void AppDataServer::connectAppDialog(MainWindow* parent) { } parent->createWebsocket(wormholecode); + } else { + qDebug() << "no websocket not listening"; } d.exec(); // If there is nothing connected when the dialog exits, then shutdown the websockets if (!isAppConnected()) { + qDebug() << "no app connected, stopping websockets"; parent->stopWebsocket(); } // Cleanup tempSecret = ""; - delete tempWormholeClient; tempWormholeClient = nullptr; - delete ui; ui = nullptr; } diff --git a/src/websockets.h b/src/websockets.h index 9456730..1149a20 100644 --- a/src/websockets.h +++ b/src/websockets.h @@ -64,6 +64,7 @@ public: void connect(); void retryConnect(); + void sslerrors(const QList &); private: MainWindow* parent = nullptr; From f1f83c3ca2410b98dfe9e9924da96d953d007196 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Mon, 18 Nov 2019 15:26:01 -0800 Subject: [PATCH 04/12] copyright --- src/settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/settings.cpp b/src/settings.cpp index 540afab..442f2f2 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1,3 +1,4 @@ +// Copyright 2019 The Hush developers #include "mainwindow.h" #include "settings.h" From afa2eb6feba64c6f9e543833d3d610c474518c48 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Mon, 18 Nov 2019 15:26:53 -0800 Subject: [PATCH 05/12] bump version --- src/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version.h b/src/version.h index 3bf911d..37b696a 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define APP_VERSION "0.8.2" +#define APP_VERSION "0.8.3" From 8f6945b018f051cb509f1c9c6333b9424b7bc89d Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Tue, 19 Nov 2019 21:48:14 -0800 Subject: [PATCH 06/12] lots o debug --- src/websockets.cpp | 54 ++++++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/src/websockets.cpp b/src/websockets.cpp index 9a5ebc5..e0482e6 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -37,13 +37,15 @@ WSServer::WSServer(quint16 port, bool debug, QObject *parent) : WSServer::~WSServer() { - qDebug() << "Closing websocket"; + qDebug() << "Closing websocket server"; m_pWebSocketServer->close(); qDeleteAll(m_clients.begin(), m_clients.end()); + qDebug() << "Deleted all websocket clients"; } void WSServer::onNewConnection() { + qDebug() << "Websocket server: new connection"; QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection(); connect(pSocket, &QWebSocket::textMessageReceived, this, &WSServer::processTextMessage); @@ -91,20 +93,25 @@ WormholeClient::WormholeClient(MainWindow* p, QString wormholeCode) { this->parent = p; this->code = wormholeCode; connect(); + qDebug() << "New wormhole client after connect()"; } WormholeClient::~WormholeClient() { shuttingDown = true; if (m_webSocket->isValid()) { + qDebug() << "Wormhole closing!"; m_webSocket->close(); } - if (timer) + if (timer) { + qDebug() << "Wormhole timer stopping"; timer->stop(); + } qDebug() << "Wormhole client destroyed"; delete timer; + qDebug() << "Wormhole timer deleted"; } void ws_error() { @@ -114,11 +121,13 @@ void ws_error() { void WormholeClient::sslerrors(const QList &) { qDebug() << "SSL errors occurred!"; - m_webSocket->ignoreSslErrors(); + //TODO: don't do this in prod + //m_webSocket->ignoreSslErrors(); } void WormholeClient::connect() { + qDebug() << "Wormhole::connect"; delete m_webSocket; m_webSocket = new QWebSocket(); QUrl wormhole = QUrl("wss://wormhole.myhush.org:443"); @@ -180,11 +189,10 @@ void WormholeClient::closed() { void WormholeClient::onConnected() { - qDebug() << "WebSocket connected"; retryCount = 0; + qDebug() << "WebSocket connected, retryCount=" << retryCount; - QObject::connect(m_webSocket, &QWebSocket::textMessageReceived, - this, &WormholeClient::onTextMessageReceived); + QObject::connect(m_webSocket, &QWebSocket::textMessageReceived, this, &WormholeClient::onTextMessageReceived); auto payload = QJsonDocument( QJsonObject { {"register", code} }).toJson(); @@ -195,15 +203,18 @@ void WormholeClient::onConnected() // On connected, we'll also create a timer to ping it every 4 minutes, since the websocket // will timeout after 5 minutes timer = new QTimer(parent); + qDebug() << "Created QTimer"; QObject::connect(timer, &QTimer::timeout, [=]() { - if (!shuttingDown && m_webSocket->isValid()) { + qDebug() << "Timer timout!"; + if (!shuttingDown && m_webSocket && m_webSocket->isValid()) { auto payload = QJsonDocument(QJsonObject { {"ping", "ping"} }).toJson(); qint64 bytes = m_webSocket->sendTextMessage(payload); - qDebug() << "Sent ping, " << bytes << " bytes"; + qDebug() << "Sent ping, " << bytes << " bytes"; } }); - qDebug() << "Starting timer"; - timer->start(4 * 60 * 1000); // 4 minutes + unsigned int interval = 4*60*1000; + timer->start(interval); // 4 minutes + qDebug() << "Started timer with interval=" << interval; } void WormholeClient::onTextMessageReceived(QString message) @@ -351,6 +362,7 @@ void AppDataServer::connectAppDialog(MainWindow* parent) { tempWormholeClient = nullptr; delete ui; ui = nullptr; + qDebug() << "Destroyed tempWormholeClient and ui"; } void AppDataServer::updateUIWithNewQRCode(MainWindow* mainwindow) { @@ -369,9 +381,9 @@ void AppDataServer::updateUIWithNewQRCode(MainWindow* mainwindow) { if (ipv4Addr.isEmpty()) return; - + QString uri = "ws://" + ipv4Addr + ":8777"; - qDebug() << "Websocket URI: " << uri; + qDebug() << "Websocket URI: " << uri; // Get a new secret unsigned char* secretBin = new unsigned char[crypto_secretbox_KEYBYTES]; @@ -390,10 +402,11 @@ void AppDataServer::updateUIWithNewQRCode(MainWindow* mainwindow) { ui->qrcode->setQrcodeString(codeStr); ui->txtConnStr->setText(codeStr); + qDebug() << "New QR="< 0) { msg = msg + QString(" ").repeated(256 - (msg.length() % 256)); } @@ -494,7 +508,6 @@ QString AppDataServer::encryptOutgoing(QString msg) { {"payload", QString(encryptedHex)}, {"to", getWormholeCode(getSecretHex())} }); - delete[] noncebin; delete[] newLocalNonce; delete[] secret; @@ -510,6 +523,7 @@ QString AppDataServer::encryptOutgoing(QString msg) { unless the skipNonceCheck = true, which is used when attempting decrtption with a temp secret key. */ QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex, QString lastRemoteNonceHex) { + qDebug() << "Decrypting message"; // Decrypt and then process QString noncehex = msg.object().value("nonce").toString(); QString encryptedhex = msg.object().value("payload").toString(); @@ -571,12 +585,15 @@ QString AppDataServer::decryptMessage(QJsonDocument msg, QString secretHex, QStr delete[] noncebin; delete[] encrypted; delete[] decrypted; - + + qDebug() << "Returning decrypted payload="< pClient, AppConnectionType connType) { + qDebug() << "processMessage message"; + //qDebug() << "processMessage message=" << message; // this can log sensitive info auto replyWithError = [=]() { auto r = QJsonDocument(QJsonObject{ {"error", "Encryption error"}, @@ -660,6 +677,7 @@ void AppDataServer::processMessage(QString message, MainWindow* mainWindow, std: // Decrypted method will be executed here. void AppDataServer::processDecryptedMessage(QString message, MainWindow* mainWindow, std::shared_ptr pClient) { + //qDebug() << "processDecryptedMessage message=" << message; // First, extract the command from the message auto msg = QJsonDocument::fromJson(message.toUtf8()); @@ -692,7 +710,7 @@ void AppDataServer::processDecryptedMessage(QString message, MainWindow* mainWin // "sendTx" command. This method will actually send money, so be careful with everything void AppDataServer::processSendTx(QJsonObject sendTx, MainWindow* mainwindow, std::shared_ptr pClient) { - qDebug() << "processSendTx"; + qDebug() << "processSendTx with to=" << sendTx["to"].toString(); auto error = [=](QString reason) { auto r = QJsonDocument(QJsonObject{ {"errorCode", -1}, From 68e6d6964383426379f87d1ddfe241317dc52da4 Mon Sep 17 00:00:00 2001 From: heguli97 <38728905+heguli97@users.noreply.github.com> Date: Wed, 20 Nov 2019 18:09:42 +0200 Subject: [PATCH 07/12] Add Finnish translation --- res/zec_qt_wallet_fi.ts | 2069 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 2069 insertions(+) create mode 100644 res/zec_qt_wallet_fi.ts diff --git a/res/zec_qt_wallet_fi.ts b/res/zec_qt_wallet_fi.ts new file mode 100644 index 0000000..ae3c614 --- /dev/null +++ b/res/zec_qt_wallet_fi.ts @@ -0,0 +1,2069 @@ + + + + + AddressBookModel + + + Label + Osoitekirja + + + + Address + Osoite + + + + BalancesTableModel + + + Address + Osoite + + + + Amount + Määrä + + + + ConnectionDialog + + silentdragon + YOUR_TRANSLATION_HERE + + + Starting Up + YOUR_TRANSLATION_HERE + + + + SilentDragon + SilentDragon + + + + The Dragon Awakens... + Lohikäärme Herää... + + + + MainWindow + + silentdragon + YOUR_TRANSLATION_HERE + + + + Balance + Saldo + + + + Summary + Yhteenveto + + + + Shielded + Suojattu + + + + Transparent + Suojaamaton + + + + Total + Summa + + + + Some transactions are not yet confirmed + Joitakin tapahtumia ei ole vielä vahvistettu + + + + Address Balances + Osoitteiden Saldot + + + + + Send + Lähetä + + + + From + Mistä + + + + Address Balance + Osoitteen Saldo + + + + Send To + Minne + + + + Recipient + Vastaanottaja + + + + + + + + Address + Osoite + + + + + Address Book + Osoitekirja + + + + + + + Amount + Määrä + + + + Max Available + Enimmäismäärä Saatavilla + + + + Upload File + Lataa Tiedosto + + + + + + + Memo + Viesti + + + + Add Recipient + Lisää Vastaanottaja + + + + Recurring payment + Toistuva maksu + + + + Every month, starting 12-May-2012, for 6 payments + Joka kuukausi, Alkaen 12-Toukokuuta-2012, 6 maksua + + + + Edit Schedule + Muokkaa Aikataulua + + + + + Miner Fee + Siirtomaksu + + + + 0 + 0 + + + + Cancel + Peruuta + + + + Receive + Vastaanota + + + + Address Type + Osoitteen Tyyppi + + + + Local Services + Paikalliset Palvelut + + + + Longest Chain + Pisin Ketju + + + + &Send Duke Feedback + &Lähetä Dukelle Palautetta + + + + &Hush Discord + &Hush Discord + + + + &Hush Website + &Hush Verkkosivusto + + + + + Export transactions + Vie tapahtumat + + + + Pay HUSH &URI... + Maksa Hush &URI... + + + + Connect mobile &app + Yhdistä Älypuhelin &Sovellukseen + + + + Ctrl+M + Ctrl+M + + + + Request HUSH... + Pyydä Hush... + + + + Validate Address + Validoi Osoite + + + z-Addr(Sapling) + Suojattu Osoite (Sapling) + + + t-Addr + Suojaamaton Osoite + + + z-Addr(Sprout) + Suojattu Osoite (Sprout) + + + + New Address + Uusi Osoite + + + + View All Addresses + Näytä Kaikki Osoitteet + + + + Label + Nimeä + + + + Update Label + Päivitä Nimi + + + + Address balance + Osoiteen Saldo + + + + Optional + Vaihtoehtoinen + + + + + Export Private Key + Vie Salainen Avain + + + + Transactions + Tapahtumat + + + + hushd + hushd + + + + You are currently not mining + Tällä hetkellä et louhi + + + + + + + + + + + + + + + + + + + Loading... + Ladataan... + + + + Block height + Lohkokorkeus + + + + Notarized Hash + Notarisoitu Hash + + + + Notarized txid + Notarisoitu txid + + + + Notarized Lag + Notarisoitu Viive + + + + KMD Version + KMD Versio + + + + Protocol Version + Protokollan Versio + + + + Version + Versio + + + + P2P Port + P2P Portti + + + + RPC Port + RPC Portti + + + + Client Name + Asiakasohjelman Nimi + + + + Next Halving + Seuraava Puoliintuminen + + + + Network solution rate + Verkon Louhintanopeus + + + + Connections + Yhteydet + + + + + + + + + + + + + + + + + + | + | + + + + SilentDragon + SilentDragon + + + + Shielded Address (Private, Anonymous) + Suojattu Osoite (Yksityinen, Anonyymi) + + + + Transparent Address (Public, Metadata-Leaking) + Suojaamaton Osoite (Kaikille Näkyvä, Metadataa-Vuotava) + + + + &File + &Tiedosto + + + + &Help + &Apua + + + + &Apps + &Sovellukset + + + + &Edit + &Muokkaa + + + + E&xit + &Poistu + + + + &About + &Tietoja + + + + &Settings + &Asetukset + + + + Ctrl+P + Ctrl+P + + + &Donate + &Lahjoita + + + + Check github.com for &updates + Tarkista github.com &päivityksien varalta + + + + Sapling &turnstile + Sapling &turnstile + + + + Ctrl+A, Ctrl+T + Ctrl+A, Ctrl+T + + + + &Import private key + &Tuo salainen avain + + + + &Export all private keys + &Vie kaikki salaiset avaimet + + + + &z-board.net + &z-board.net + + + + Ctrl+A, Ctrl+Z + Ctrl+A, Ctrl+Z + + + + Address &book + &Osoitekirja + + + + Ctrl+B + Ctrl+B + + + + &Backup wallet.dat + &Varmuuskopioi wallet.dat + + + Thanks for supporting silentdragon! + Kiitos SilentDragonin tukemisesta! + + + Donate 0.01 + Lahjoita 0.01 + + + to support silentdragon + tukeaksesi silentdragonia + + + + You are on testnet, your post won't actually appear on z-board.net + Olet testiverkossa, viestisi ei näy z-board.netissä + + + + You need a sapling address with available balance to post + Tarvitset Suojatun osoitteen, jolla on käytettävissä oleva saldo lähettääksesi + + + + + Computing Tx: + Käsittelee Tapahtumaa: + + + The keys were imported. It may take several minutes to rescan the blockchain. Until then, functionality may be limited + YOUR_TRANSLATION_HERE + + + + Private key import rescan finished + Salaisen avaimen tuonnin uudelleenskannaus valmis + + + Please paste your private keys (z-Addr or t-Addr) here, one per line + YOUR_TRANSLATION_HERE + + + The keys will be imported into your connected hushd node + YOUR_TRANSLATION_HERE + + + + Tor configuration is available only when running an embedded hushd. + Tor-verkon konfigurointi on saatavilla vain kun integroitu hushd on käynnissä. + + + + You're using an external hushd. Please restart hushd with -rescan + Käytät ulkopuolista hushd:ia. Ole hyvä ja käynnistä hushd uudelleen -rescan:lla + + + + You're using an external hushd. Please restart hushd with -reindex + Käytät ulkopuolista hushd:ia. Ole hyvä ja käynnistä hushd uudelleen -reindex:lla + + + + Enable Tor + Ota Tor-verkko käyttöön + + + + Connection over Tor has been enabled. To use this feature, you need to restart SilentDragon. + Yhteys Tor-verkon kautta on otettu käyttöön. Jotta voit käyttää tätä ominaisuutta, sinun on käynnistettävä SilentDragon uudelleen. + + + + Disable Tor + Poista Tor-verkko käytöstä + + + + Connection over Tor has been disabled. To fully disconnect from Tor, you need to restart SilentDragon. + Yhteys Tor-verkon kautta on poistettu käytöstä. Katkaistaksesi Tor-verkon kokonaan, sinun on käynnistettävä SilentDragon uudelleen. + + + + SilentDragon needs to restart to rescan/reindex. SilentDragon will now close, please restart SilentDragon to continue + SilentDragon on käynnistettävä uudelleen, jotta voidaan uudelleenskannata/reindeksoida. SilentDragon sulkeutuu nyt, käynnistä SilentDragon uudelleen jatkaaksesi + + + + Restart SilentDragon + Käynnistä SilentDragon uudelleen + + + + Some feedback about SilentDragon or Hush... + Palautetta SilentDragonista tai Hushista... + + + + Send Duke some private and shielded feedback about + Lähetä Dukelle anonyymiä ja yksityistä palautetta + + + + or SilentDragon + tai SilentDragon + + + + Enter Address to validate + Syötä Osoite vahvistaakesi + + + + Transparent or Shielded Address: + Julkinen tai Suojattu Osoite: + + + + Paste HUSH URI + Liitä Hush URI + + + + Error paying Hush URI + Virhe maksaessa Hush URI + + + + URI should be of the form 'hush:<addr>?amt=x&memo=y + URI:n tulisi olla muodossa 'hush:<osoite>?määrä=x&muistio=y + + + + Please paste your private keys here, one per line + Liitä Salaiset Avaimesi tähän, yksi per rivi + + + + The keys will be imported into your connected Hush node + Avaimet tuodaan sinun yhdistettyyn Hush nodeen + + + + The keys were imported! It may take several minutes to rescan the blockchain. Until then, functionality may be limited + Avaimet tuotiin! Lohkoketjun uudelleenskannaus voi kestää useita minuutteja. Siihen asti toiminnallisuus voi olla rajoitettu + + + + Error + Virhe + + + + Error exporting transactions, file was not saved + Virhe tapahtumien viemisessä, tiedostoa ei tallennettu + + + + No wallet.dat + Ei wallet.dat tiedostoa + + + + Couldn't find the wallet.dat on this computer + Tästä tietokoneesta ei löytynyt wallet.dat-tiedostoa + + + + You need to back it up from the machine hushd is running on + Sinun on varmuuskopioitava se siitä koneesta, missä hushd on käynnissä + + + + Backup wallet.dat + Varmuuskopioi wallet.dat + + + + Couldn't backup + Varmuuskopiointi epäonnistui + + + + Couldn't backup the wallet.dat file. + wallet.dat-tiedostoa ei voitu varmuuskopioida. + + + + You need to back it up manually. + Sinun on varmuuskopioitava se manuaalisesti. + + + + These are all the private keys for all the addresses in your wallet + Tässä ovat kaikki lompakkosi osoitteiden salaiset avaimet + + + + Private key for + Salainen avain + + + + Save File + Tallenna Tiedosto + + + + Unable to open file + Tiedostoa ei voitu avata + + + + + Copy address + Kopioi osoite + + + + + + Copied to clipboard + Kopioitu leikepöydälle + + + + Get private key + Näe Salainen avain + + + + Shield balance to Sapling + Siirrä Saldo Suojattuun (Sapling) osoitteeseen + + + + + View on block explorer + Näytä lohkoketjussa + + + + Address Asset Viewer + Osoitteen Varojen Katselu + + + + Convert Address + Muunna Osoite + + + + Migrate to Sapling + Siirrä Saplingiin + + + + Copy txid + Kopioi Tapahtuman ID + + + + View Payment Request + Näytä Maksu Pyyntö + + + + View Memo + Näytä Viesti + + + + Reply to + Vastaa + + + + Created new t-Addr + Uusi Suojaamaton osoite luotu + + + + Copy Address + Kopioi Osoite + + + + Address has been previously used + Osoitetta on käytetty aiemmin + + + + Address is unused + Osoite on käyttämätön + + + + Recipient + Vastaanottaja + + + + + File Upload + Tiedoston Lataus + + + + Only z-addresses can have memos + Vain suojatut Zs-osoitteet voivat sisältää viestejä + + + + File size too large + Tiedoston koko on liian suuri + + + + The file size + Tiedoston koko + + + + bytes is greater than + tavua on suurempi kuin + + + + bytes + tavua + + + + Memos can only be used with z-addresses + Viestejä voidaan käyttää vain suojattujen Zs-osoitteiden kanssa + + + + The memo field can only be used with a z-address. + + Viestikenttää voidaan käyttää vain suojattujen Zs-osoitteiden kanssa. + + + + + +doesn't look like a z-address + +Ei näytä suojatulta Zs-osoitteelta + + + + Change from + Vaihda + + + + Current balance : + Tämänhetkinen saldo : + + + + Balance after this Tx: + Saldo tämän tapahtuman jälkeen: + + + + Transaction Error + Tapahtumavirhe + + + + From Address is Invalid + Lähettäjän Osoite on Virheellinen + + + + Recipient Address + Vastaanottajan Osoite + + + + is Invalid + on Virheellinen + + + + Amount '%1' is invalid! + Määrä '%1' on virheellinen! + + + + MemoDialog + + + + Memo + Viesti + + + + Include Reply Address + Sisällytä Vastausosoite + + + + MemoEdit + + + Reply to + Vastaa + + + + MobileAppConnector + + + Connect Mobile App + Yhdistä Älypuhelin Sovellukseen + + + + QR Code + QR Koodi + + + + Connection String + Yhteyden Tekstirivi + + + + Allow connections over the internet via SilentDragon wormhole + Salli yhteydet Internetin kautta SilentDragon-madonreiän kautta + + + + Scan this QRCode in SilentDragonAndroid to connect your device + Skannaa tämä QR-koodi SilentDragonAndroidissa laitteen kytkemiseksi + + + + SilentDragonAndroid + SilentDragonAndroid + + + + Disconnect + Katkaise Yhteys + + + + + TextLabel + TekstiMerkki + + + + Last seen: + Viimeksi nähty: + + + + Connection type: + Yhteyden tyyppi: + + + + PrivKey + + Private Key + Salainen Avain + + + + Private Keys + Salaiset Avaimet + + + + QObject + + + Attempting autoconnect + Yritetään automaattista yhteyttä + + + + Starting embedded hushd + Käynnistetään integroitu hushd + + + + hushd is set to run as daemon + hushd on asetettu toimimaan palveluprosessina + + + + Waiting for hushd + Odotetaan hushd:ia + + + You have hushd set to start as a daemon, which can cause problems with silentdragon + +.Please remove the following line from your zcash.conf and restart silentdragon +daemon=1 + YOUR_TRANSLATION_HERE + + + Couldn't start the embedded hushd. + +Please try restarting. + +If you previously started hushd with custom arguments, you might need to reset zcash.conf. + +If all else fails, please run hushd manually. + YOUR_TRANSLATION_HERE + + + Couldn't connect to hushd configured in zcash.conf. + +Not starting embedded hushd because --no-embedded was passed + YOUR_TRANSLATION_HERE + + + + All Downloads Finished Successfully! + Kaikki Lataukset Onnistui! + + + + Couldn't download params. Please check the help site for more info. + Paramereja ei voitu ladata. Tarkista lisätietoja ohjesivulta. + + + + The process returned + Prosessi palasi + + + + You have hushd set to start as a daemon, which can cause problems with SilentDragon + +.Please remove the following line from your HUSH3.conf and restart SilentDragon +daemon=1 + Olet asettanut hushd:n käynnistymään palveluprosessina, joka voi aiheuttaa ongelmia SilentDragonin kanssa + +.Poista seuraava rivi HUSH3.conf-tiedostosta ja käynnistä SilentDragon uudestaan +daemon=1 + + + + Couldn't start the embedded hushd. + +Please try restarting. + +If you previously started hushd with custom arguments, you might need to reset HUSH3.conf. + +If all else fails, please run hushd manually. + Integroitua hushdia ei voitu käynnistää. + +Yritä käynnistää uudelleen. + +Jos aloitit hushd:n aiemmin mukautetuilla argumenteilla, saatat joutua nollaamaan HUSH3.conf-tiedoston. + +Jos kaikki muu ei auta, suorita hushd manuaalisesti. + + + + Couldn't connect to hushd configured in HUSH3.conf. + +Not starting embedded hushd because --no-embedded was passed + HUSH3.conf:ssa määritettyyn hushdiin ei voitu muodostaa yhteyttä. + +Integroitua hushdia ei käynnistetä, koska --ei-integroitu ohitettiin + + + + Hide Advanced Config + Piilota Lisäasetukset + + + + Show Advanced Config + Näytä Lisäasetukset + + + + Choose data directory + Valitse tiedostohakemisto + + + + Could not create HUSH3.conf. + HUSH3.conf-tiedostoa ei voitu luoda. + + + + + Downloading + Ladataan + + + + more remaining ) + vielä jäljellä ) + + + + MB of + MT of + + + + MB at + MT at + + + + There was an error! : + Tapahtui virhe! : + + + + Downloading blocks + Lataa lohkoja + + + + Block height + Lohkokorkeus + + + + Syncing + Synkronoi + + + + Connected + Yhdistetty + + + + testnet: + testiverkko: + + + + Connected to hushd + Yhdistetty hushd + + + + hushd has no peer connections! Network issues? + hushd:lla ei ole vertaisverkko yhteyksiä! Verkko ongelmia? + + + + There was an error connecting to hushd. The error was + Yhdistettäessä hushd:iin tapahtui virhe. Virhe oli + + + + Update Available + Päivitys Saatavilla + + + + A new release v%1 is available! You have v%2. + +Would you like to visit the releases page? + Uusi versio v%1 on saatavilla! Sinulla on v%2. + +Haluaisitko vierailla lataus-sivulla? + + + + No updates available + Päivityksiä ei ole saatavilla + + + + You already have the latest release v%1 + Sinulla on jo uusin versio v%1 + + + + Please wait for SilentDragon to exit + Odotathan, että SilentDragon sulkeutuu + + + + + + The transaction with id + Tapahtuma tunnuksella + + + + + + failed. The error was + epäonnistui. Virhe oli + + + + + + failed + epäonnistui + + + + + + Tx + Tapahtuma + + + + tx computing. This can take several minutes. + käsittelee tapahtumaa. Tässä voi mennä useampi minuutti. + + + Please wait for silentdragon to exit + YOUR_TRANSLATION_HERE + + + + Waiting for hushd to exit + Odotetaan hushd:n poistumista + + + + failed. Please check the help site for more info + epäonnistui. Tarkista lisätietoja ohjesivulta + + + + hushd error + hushd virhe + + + + A manual connection was requested, but the settings are not configured. + +Please set the host/port and user/password in the Edit->Settings menu. + Manuaalista yhteyttä pyydettiin, mutta asetuksia ei ole määritetty. + +Aseta isäntä/portti ja käyttäjänimi/salasana Muokkaa-> Asetukset-valikossa. + + + + Could not connect to hushd configured in settings. + +Please set the host/port and user/password in the Edit->Settings menu. + Asetuksissa määritettyyn hushdiin ei voitu muodostaa yhteyttä. + +Aseta isäntä/portti ja käyttäjänimi/salasana Muokkaa-> Asetukset-valikossa. + + + + Authentication failed. The username / password you specified was not accepted by hushd. Try changing it in the Edit->Settings menu + Todennus epäonnistui. Hushd ei hyväksynyt määrittämääsi käyttäjänimeä / salasanaa. Yritä muuttaa niitä Muokkaa-> Asetukset-valikosta + + + + Your hushd is starting up. Please wait. + hushd on käynnistymässä. Ole hyvä ja odota. + + + + This may take several hours, grab some popcorn + Tämä voi viedä useita tunteja, nappaa Fazerin sinistä + + + + + Connection Error + Yhteysvirhe + + + + + + + Transaction Error + Tapahtumavirhe + + + There was an error sending the transaction. The error was: + YOUR_TRANSLATION_HERE + + + + + No Connection + Ei Yhteyttä + + + + Address Format Error + Osoitteen Formaatti Virhe + + + doesn't seem to be a valid Zcash address. + YOUR_TRANSLATION_HERE + + + + Pick + Valitse + + + + Address or Label Error + Osoite tai Nimi Virhe + + + + Address or Label cannot be empty + Osoite tai Nimi ei voi olla tyhjä + + + + %1 doesn't seem to be a valid Hush address. + %1 ei näytä olevan kelvollinen Hush-osoite. + + + + Label Error + Nimi Virhe + + + + The label '%1' already exists. Please remove the existing label. + Nimi '%1' on jo olemassa. Poista olemassa oleva nimike. + + + + Import Address Book + Tuo Osoitekirja + + + + Unable to open file + Tiedostoa ei voitu avata + + + + Address Book Import Done + Osoitekirjan Tuonti Valmis + + + + Imported %1 new Address book entries + Tuotu %1 uutta Osoitekirjamerkintää + + + + Copy address + Kopioi osoite + + + + Copied to clipboard + Kopioitu leikepöydälle + + + + Delete label + Poista nimi + + + + Tx submitted (right click to copy) txid: + Tapahtuma lähetetty (kopioi hiiren oikealla painikkeella) txid: + + + + Locked funds + Lukitut saldot + + + + Could not initiate migration. +You either have unconfirmed funds or the balance is too low for an automatic migration. + Siirtoa ei voitu aloittaa. +Sinulla on joko vahvistamattomia varoja tai saldo on liian pieni automaattiseen siirtoon. + + + + Computing Tx: + Käsitellään Tapahtumaa: + + + + Type + Tyyppi + + + + Address + Osoite + + + + Date/Time + Päivämäärä/Aika + + + + Amount + Määrä + + + + Connected directly + Yhdistetty suoraan + + + + Connected over the internet via SilentDragon wormhole service + Yhdistetty internetin kautta SilentDragon-madonreikäpalveluun + + + + Node is still syncing. + Nodea synkronoidaan edelleen. + + + + No sapling or transparent addresses with enough balance to spend. + Ei Sapling-suojattuja tai suojaamattomia osoitteita, joilla olisi tarpeeksi saldoa kulutettavana. + + + + RecurringDialog + + + Dialog + Dialogi + + + + Add + Lisää + + + + Edit + Muokkaa + + + + Delete + Poista + + + + RequestDialog + + + Payment Request + Maksupyyntö + + + + AddressBook + Osoitekirja + + + + Request From + Pyydä + + + + My Address + Oma Osoite + + + + Amount in + Määrä + + + + z address + Suojattu Zs-osoite + + + + Amount + Määrä + + + + The recipient will see this address in the "to" field when they pay your request. + Vastaanottaja näkee tämän osoitteen "minne" kentässä, kun hän maksaa pyyntösi. + + + + Amount USD + Määrä USD + + + + Memo + Viesti + + + + TextLabel + TextLabel + + + + Request payment from a Sapling address. You'll send a HUSH 0.0001 transaction to the address with a HUSH payment URI. The memo will be included in the transaction when the address pays you. + Pyydä maksua Sapling Zs-osoitteesta. Lähetä 0.0001 HUSH tapahtuma osoitteeseen HUSH URI-maksutunnuksen kanssa. Viesti sisällytetään tapahtumaan, kun osoite maksaa sinulle. + + + + Error paying HUSH URI + Virhe HUSH URI:n maksamisessa + + + + URI should be of the form 'hush:<addr>?amt=x&memo=y + URI:n pitäisi olla muodossa 'hush:<osoite>?Määrä=x&viesti=y + + + + Pay To + Maksa + + + + Pay + Maksa + + + + You are paying a payment request. Your address will not be visible to the person requesting this payment. + Olet maksamassa maksupyyntöä. Osoitteesi ei näy maksua pyytävälle henkilölle. + + + + Can only request from Sapling addresses + Voit pyytää vain Sapling osoitteista + + + + Settings + + + Settings + Asetukset + + + + hushd connection + hushd yhteys + + + + Host + Host + + + + Port + Portti + + + + RPC Username + RPC Käyttäjänimi + + + + RPC Password + RPC Salasana + + + + Options + Valinnat + + + + Check github for updates at startup + Tarkista päivitykset githubista käynnistyksen yhteydessä + + + + Connect to the Tor network via SOCKS proxy running on 127.0.0.1:9050. Please note that you'll have to install and run the Tor service externally. + Yhdistä Tor-verkkoon SOCKS-välityspalvelimen kautta, joka toimii 127.0.0.1:9050. Huomaa, että sinun on asennettava ja suoritettava Tor-palvelu ulkoisesti. + + + + Shielded transactions are saved locally and shown in the transactions tab. If you uncheck this, shielded transactions will not appear in the transactions tab. + Suojatut zs-tapahtumat tallennetaan paikallisesti ja ne näkyvät tapahtumat välilehdessä. Jos poistat tämän valinnan, suojatut tapahtumat eivät tule näkyviin Tapahtumat-välilehteen. + + + + Connect via Tor + Yhdistä Tor-verkon välityksellä + + + + Connect to github on startup to check for updates + Yhdistä githubiin käynnistäessä tarkistaaksesi päivitykset + + + + Connect to the internet to fetch HUSH prices + Yhdistä Internetiin hakeaksesi HUSH hinnat + + + + Fetch HUSH / USD prices + Hae HUSH / USD hinnat + + + + Troubleshooting + Vianetsintä + + + + Reindex + Reindeksoi + + + + Rescan the blockchain for any missing wallet transactions and to correct your wallet balance. This may take several hours. You need to restart SilentDragon for this to take effect + Uudelleenskannaa lohkoketju puuttuvien lompakkotapahtumien varalta ja lompakon saldon korjaamiseksi. Tämä voi viedä useita tunteja. Sinun on käynnistettävä SilentDragon uudelleen, jotta tämä muutos tulee voimaan + + + + Rescan + Uudelleenskannaa + + + + Rebuild the entire blockchain from the genesis block, by rescanning all the block files. This may take several hours to days, depending on your hardware. You need to restart SilentDragon for this to take effect + Rakenna koko lohkoketju uudelleen syntylohkosta alkaen skannaamalla kaikki lohkotiedostot. Tämä voi viedä useista tunneista päiviin laitteistosta riippuen. Sinun on käynnistettävä SilentDragon uudelleen, jotta tämä tulee voimaan + + + + Clear History + Tyhjennä Historia + + + + Remember shielded transactions + Muista suojatut tapahtumat + + + + Allow custom fees + Salli mukautetut siirtomaksut + + + + Allow overriding the default fees when sending transactions. Enabling this option may compromise your privacy since fees are transparent. + Salli oletusmaksujen muokkaaminen tapahtumia lähetettäessä. Tämän vaihtoehdon ottaminen käyttöön voi vaarantaa yksityisyytesi, koska siirtomaksut ovat suojaamattomia. + + + + Normally, change from t-Addresses goes to another t-Address. Checking this option will send the change to your shielded sapling address instead. Check this option to increase your privacy. + Normaalisti vaihtoraha siirtyy suojaamattomasta osoitteesta toiseen suojaamattomaan osoitteeseen. Jos valitset tämän vaihtoehdon, vaihtoraha lähetetään suojattuun Sapling-osoitteeseesi. Valitse tämä vaihtoehto lisätäksesi yksityisyyttäsi. + + + + Shield change from t-Addresses to your sapling address + Suojaa vaihtoraha suojaamattomasta osoitteesta suojattuun Sapling-osoitteeseen + + + + Turnstile + + + + Turnstile Migration + "Turnstile" Yhdistäminen + + + + Migrate over + Yhdistä + + + + From + Minne + + + + <html><head/><body><p>Funds from Sprout z-Addresses (which start with &quot;zc&quot;) need to be moved to the upgraded Sapling z-Addresses (which start with &quot;zs&quot;). The funds cannot be moved directly, but need to be sent through intermediate &quot;transparent&quot; addresses in privacy-preserving way.</p><p>This migration can be done automatically for you.</p></body></html> + <html><head/><body><p>Saldot Sprout z-Osoitteista (jotka alkavat &quot;zc&quot;) täytyy siirtää päivitettyihin Sapling z-Osoitteisiin (jotka alkavat &quot;zs&quot;). Saldoa ei voi siirtää suoraan, vaan on lähetettävä välivaiheiden &quot;suojaamattomien&quot; osoitteiden kautta yksityisyyttä suojaavalla tavalla.</p><p>Tämä siirto voidaan tehdä automaattisesti puolestasi.</p></body></html> + + + + To + Mistä + + + + Balance + Saldo + + + + Miner Fees + Siirtomaksut + + + + Total Balance + Kokonaissaldo + + + + TurnstileProgress + + + Turnstile Migration Progress + "Turnstile" Yhdistäminen Menossa + + + + From + Mistä + + + + To + Minne + + + + Please ensure you have your wallet.dat backed up! + Varmistathan, että olet varmuuskopioinut wallet.dat tiedoston! + + + + Next Transaction in 4 hours + Seuraava tapahtuma 4 tunnissa + + + + Migration Progress + Yhdistämisen Eteneminen + + + + ValidateAddress + + + Validate Address + Validoi Osoite + + + + TextLabel + TextLabel + + + + Address: + Osoite: + + + + ValidateAddressesModel + + + Property + Omaisuus + + + + Value + Arvo + + + + ViewAddressesDialog + + + All Addresses + Kaikki Osoitteet + + + + Export All Keys + Vie Kaikki Avaimet + + + + ViewAllAddressesModel + + + Address + Osoite + + + + Balance (%1) + Saldo (%1) + + + + about + + + About + Tietoa + + + + addressBook + + + Address Book + Osoitekirja + + + + Add New Address + Lisää Uusi Osoite + + + + Address (z-Addr or t-Addr) + Osoite (Suojattu tai Suojaamaton) + + + + Label + Nimeä + + + + Add to Address Book + Lisää Osoitekirjaan + + + + Import Address Book + Tuo osoitekirja + + + + confirm + + + Confirm Transaction + Vahvista Tapahtuma + + + + From + Mistä + + + + To + Minne + + + + hushd doesn't seem to have any peers. You might not be connected to the internet, so this Transaction might not work. + hushdilla ei näytä olevan vertaisia(P2P). Sinä et ehkä ole yhteydessä Internetiin, joten tämä tapahtuma ei ehkä toimi. + + + + You are sending a transaction while your node is still syncing. This may not work. + Olet lähettämässä tapahtumaa, kun node vielä synkronoi. Tämä ei välttämättä toimi. + + + + You are using a custom fee. Since fees are transparent, you are giving up some privacy. Please use this only if you know what you are doing! + Käytät mukautettua siirtomaksua. Koska siirtomaksut ovat suojaamattomia, luovut vähän yksityisyydestäsi. Käytä tätä vain, jos tiedät mitä teet! + + + + createZcashConf + + + Configure HUSH3.conf + Määritä HUSH3.conf + + + + Show Advanced Configuration + Näytä Lisäasetukset + + + + Your Hush node will be configured for you automatically + Sinun Hush node määritetään automaattisesti + + + + Use custom datadir + Käytä mukautettua hakemiston sijaintia + + + + Please choose a directory to store your wallet.dat and blockchain + Valitse hakemisto, johon haluat tallentaa wallet.dat- ja lohkoketjun tiedot + + + + Choose directory + Valitse Hakemisto + + + + Connect over Tor + Yhdistä Tor-verkon kautta + + + + Please note that you'll need to already have a Tor service configured on port 9050 + Ota Huomioon, että sinulla on jo oltava Tor-palvelu määritettynä porttiin 9050 + + + + newRecurringDialog + + + Edit Schedule + Muokkaa Aikataulua + + + + Schedule + Aikataulu + + + + Payment Description + Maksun Kuvaus + + + + TextLabel + TextLabel + + + + From + Mistä + + + + Number of payments + Maksujen Määrä + + + + Amount + Määrä + + + + Next Payment + Seuraava Maksu + + + + To + Minne + + + + Memo + Viesti + + + + zboard + + + Post to z-board.net + Lähetä z-board.netiin + + + + Total Fee + Kokonaissiirtomaksu + + + + Memo + Viesti + + + + (optional) + (vaihtoehtoinen) + + + + Send From + Mistä + + + + Post As: + Lähetä Nimellä: + + + + <html><head/><body><p>ZBoard: Fully anonymous and untraceable chat messages based on the ZCash blockchain. <a href="http://www.z-board.net/"><span style=" text-decoration: underline; color:#0000ff;">http://www.z-board.net/</span></a></p></body></html> + <html><head/><body><p>ZBoard: Täysin anonyymejä ja jäljittämätömiä chat-viestejä, jotka perustuvat ZCash-lohkoketjuun. <a href="http://www.z-board.net/"><span style=" text-decoration: underline; color:#0000ff;">http://www.z-board.net/</span></a></p></body></html> + + + + Warning + Varoitus + + + + Posting to Board + Lähetetään Aiheeseen + + + From 2ff8acbeaf0b87ac5a9bf31fe420b53692de3a26 Mon Sep 17 00:00:00 2001 From: heguli97 <38728905+heguli97@users.noreply.github.com> Date: Wed, 20 Nov 2019 18:10:36 +0200 Subject: [PATCH 08/12] Add Finnish translation to silentdragon.pro --- silentdragon.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/silentdragon.pro b/silentdragon.pro index b780e94..74bcf37 100644 --- a/silentdragon.pro +++ b/silentdragon.pro @@ -107,6 +107,7 @@ FORMS += \ TRANSLATIONS = res/zec_qt_wallet_es.ts \ + res/zec_qt_wallet_fi.ts \ res/zec_qt_wallet_fr.ts \ res/zec_qt_wallet_de.ts \ res/zec_qt_wallet_pt.ts \ From 88a7ea001327c10dce3f42024c0f95fe0014a1b0 Mon Sep 17 00:00:00 2001 From: heguli97 <38728905+heguli97@users.noreply.github.com> Date: Wed, 20 Nov 2019 18:11:46 +0200 Subject: [PATCH 09/12] Add Finnish translation to application.qrc --- application.qrc | 1 + 1 file changed, 1 insertion(+) diff --git a/application.qrc b/application.qrc index 543c220..eae82a1 100644 --- a/application.qrc +++ b/application.qrc @@ -15,6 +15,7 @@ res/zec_qt_wallet_de.qm res/zec_qt_wallet_es.qm + res/zec_qt_wallet_fi.qm res/zec_qt_wallet_fr.qm res/zec_qt_wallet_pt.qm res/zec_qt_wallet_it.qm From 2efc74bff67f178a864f1da54dfb6546f2159c5c Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Wed, 20 Nov 2019 09:15:39 -0800 Subject: [PATCH 10/12] Improve websocket bugs so we are less likely to coredump; syncedness bugs still exist --- src/websockets.cpp | 66 ++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/src/websockets.cpp b/src/websockets.cpp index e0482e6..fe86d8f 100644 --- a/src/websockets.cpp +++ b/src/websockets.cpp @@ -97,9 +97,10 @@ WormholeClient::WormholeClient(MainWindow* p, QString wormholeCode) { } WormholeClient::~WormholeClient() { + qDebug() << "WormholeClient destructor"; shuttingDown = true; - if (m_webSocket->isValid()) { + if (m_webSocket && m_webSocket->isValid()) { qDebug() << "Wormhole closing!"; m_webSocket->close(); } @@ -132,15 +133,19 @@ void WormholeClient::connect() { m_webSocket = new QWebSocket(); QUrl wormhole = QUrl("wss://wormhole.myhush.org:443"); - QObject::connect(m_webSocket, &QWebSocket::connected, this, &WormholeClient::onConnected); - QObject::connect(m_webSocket, &QWebSocket::disconnected, this, &WormholeClient::closed); - QObject::connect(m_webSocket, QOverload&>::of(&QWebSocket::sslErrors), this, &WormholeClient::sslerrors); + if (m_webSocket) { + QObject::connect(m_webSocket, &QWebSocket::connected, this, &WormholeClient::onConnected); + QObject::connect(m_webSocket, &QWebSocket::disconnected, this, &WormholeClient::closed); + QObject::connect(m_webSocket, QOverload&>::of(&QWebSocket::sslErrors), this, &WormholeClient::sslerrors); + qDebug() << "Opening connection to the SilentDragonWormhole"; + m_webSocket->open(wormhole); + qDebug() << "Opened connection to " << wormhole; + //TODO: use env var to over-ride + //m_webSocket->open(QUrl("ws://127.0.0.1:7070")); + } else { + qDebug() << "Invalid websocket object!"; + } - qDebug() << "Opening connection to the SilentDragonWormhole"; - m_webSocket->open(wormhole); - qDebug() << "Opened connection to " << wormhole; - //TODO: use env var to over-ride - //m_webSocket->open(QUrl("ws://127.0.0.1:7070")); } @@ -150,8 +155,7 @@ void WormholeClient::retryConnect() { qDebug() << "Retrying websocket connection, count=" << this->retryCount; this->retryCount++; connect(); - } - else { + } else { qDebug() << "Retry count exceeded, will not attempt retry any more"; } }); @@ -197,24 +201,28 @@ void WormholeClient::onConnected() auto payload = QJsonDocument( QJsonObject { {"register", code} }).toJson(); qDebug() << "Sending register"; - m_webSocket->sendTextMessage(payload); - qDebug() << "Sent registration message with code=" << code; - - // On connected, we'll also create a timer to ping it every 4 minutes, since the websocket - // will timeout after 5 minutes - timer = new QTimer(parent); - qDebug() << "Created QTimer"; - QObject::connect(timer, &QTimer::timeout, [=]() { - qDebug() << "Timer timout!"; - if (!shuttingDown && m_webSocket && m_webSocket->isValid()) { - auto payload = QJsonDocument(QJsonObject { {"ping", "ping"} }).toJson(); - qint64 bytes = m_webSocket->sendTextMessage(payload); - qDebug() << "Sent ping, " << bytes << " bytes"; - } - }); - unsigned int interval = 4*60*1000; - timer->start(interval); // 4 minutes - qDebug() << "Started timer with interval=" << interval; + if (m_webSocket && m_webSocket->isValid()) { + m_webSocket->sendTextMessage(payload); + qDebug() << "Sent registration message with code=" << code; + + // On connected, we'll also create a timer to ping it every 4 minutes, since the websocket + // will timeout after 5 minutes + timer = new QTimer(parent); + qDebug() << "Created QTimer"; + QObject::connect(timer, &QTimer::timeout, [=]() { + qDebug() << "Timer timeout!"; + if (!shuttingDown && m_webSocket && m_webSocket->isValid()) { + auto payload = QJsonDocument(QJsonObject { {"ping", "ping"} }).toJson(); + qint64 bytes = m_webSocket->sendTextMessage(payload); + qDebug() << "Sent ping, " << bytes << " bytes"; + } + }); + unsigned int interval = 4*60*1000; + timer->start(interval); // 4 minutes + qDebug() << "Started timer with interval=" << interval; + } else { + qDebug() << "Invalid websocket object onConnected!"; + } } void WormholeClient::onTextMessageReceived(QString message) From ae9d12e0a18c90241d8efdba1165728c00416680 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Tue, 12 Nov 2019 13:58:33 -0800 Subject: [PATCH 11/12] Notarization for macOS. Fixed #197 Conflicts: src/scripts/dounifiedbuild.ps1 src/scripts/mkmacdmg.sh --- src/scripts/dounifiedbuild.ps1 | 3 ++- src/scripts/mkmacdmg.sh | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/scripts/dounifiedbuild.ps1 b/src/scripts/dounifiedbuild.ps1 index 8ed14b6..a1704ef 100644 --- a/src/scripts/dounifiedbuild.ps1 +++ b/src/scripts/dounifiedbuild.ps1 @@ -2,6 +2,7 @@ param ( [Parameter(Mandatory=$true)][string]$version, [Parameter(Mandatory=$true)][string]$prev, + [Parameter(Mandatory=$true)][string]$certificate, [Parameter(Mandatory=$true)][string]$server, [Parameter(Mandatory=$true)][string]$winserver ) @@ -27,7 +28,7 @@ Write-Host "" Write-Host "[Building on Mac]" -bash src/scripts/mkmacdmg.sh --qt_path ~/Qt/5.11.1/clang_64/ --version $version --zcash_path ~/github/zcash +bash src/scripts/mkmacdmg.sh --qt_path ~/Qt/5.11.1/clang_64/ --version $version --zcash_path ~/gi/hush3 --certificate "$certificate" if (! $?) { Write-Output "[Error]" exit 1; diff --git a/src/scripts/mkmacdmg.sh b/src/scripts/mkmacdmg.sh index d163752..fbce40d 100755 --- a/src/scripts/mkmacdmg.sh +++ b/src/scripts/mkmacdmg.sh @@ -17,6 +17,11 @@ case $key in shift # past argument shift # past value ;; + -c|--certificate) + CERTIFICATE="$2" + shift # past argument + shift # past value + ;; -v|--version) APP_VERSION="$2" shift # past argument @@ -40,6 +45,11 @@ if [ -z $HUSH_DIR ]; then exit 1; fi +if [ -z "$CERTIFICATE" ]; then + echo "CERTIFICATE is not set. Please set it the name of the MacOS developer certificate to sign the binary with"; + exit 1; +fi + if [ -z $APP_VERSION ]; then echo "APP_VERSION is not set. Please set it to the current release version of the app"; exit 1; @@ -85,10 +95,18 @@ cp $HUSH_DIR/src/hush-cli silentdragon.app/Contents/MacOS/ cp $HUSH_DIR/src/komodod silentdragon.app/Contents/MacOS/ cp $HUSH_DIR/src/komodo-cli silentdragon.app/Contents/MacOS/ $QT_PATH/bin/macdeployqt silentdragon.app +codesign --deep --force --verify --verbose -s "$CERTIFICATE" --options runtime --timestamp silentdragon.app echo "[OK]" +# Code Signing Note: +# On MacOS, you still need to run these 3 commands: +# xcrun altool --notarize-app -t osx -f macOS-zecwallet-v0.8.0.dmg --primary-bundle-id="com.yourcompany.zecwallet" -u "apple developer id@email.com" -p "one time password" +# xcrun altool --notarization-info -u "apple developer id@email.com" -p "one time password" +#...wait for the notarization to finish... +# xcrun stapler staple macOS-zecwallet-v0.8.0.dmg echo -n "Building dmg..........." +<<<<<<< HEAD mv silentdragon.app silentdragon.app create-dmg --volname "silentdragon-v$APP_VERSION" --volicon "res/logo.icns" --window-pos 200 120 --icon "silentdragon.app" 200 190 --app-drop-link 600 185 --hide-extension "silentdragon.app" --window-size 800 400 --hdiutil-quiet --background res/dmgbg.png artifacts/macOS-silentdragon-v$APP_VERSION.dmg silentdragon.app >/dev/null 2>&1 From 3283ac403db541dcf2efc081815242124c40ba80 Mon Sep 17 00:00:00 2001 From: "Jonathan \"Duke\" Leto" Date: Thu, 21 Nov 2019 07:55:44 -0800 Subject: [PATCH 12/12] Try to find sapling params inside a DMG and fix bug where we did not verify spend param file exists --- src/connection.cpp | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index c6ad293..45b2ddb 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -1,3 +1,5 @@ +// Copyright 2019 The Hush developers +// GPLv3 #include "connection.h" #include "mainwindow.h" #include "settings.h" @@ -217,12 +219,13 @@ void ConnectionLoader::downloadParams(std::function cb) { main->logger->write("Adding params to download queue"); // Add all the files to the download queue downloadQueue = new QQueue(); - client = new QNetworkAccessManager(main); + client = new QNetworkAccessManager(main); + //TODO: we never execute this downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-output.params")); downloadQueue->enqueue(QUrl("https://z.cash/downloads/sapling-spend.params")); - doNextDownload(cb); + doNextDownload(cb); } void ConnectionLoader::doNextDownload(std::function cb) { @@ -586,24 +589,34 @@ QString ConnectionLoader::zcashParamsDir() { bool ConnectionLoader::verifyParams() { QDir paramsDir(zcashParamsDir()); + // TODO: better error reporting if only 1 file exists or is missing + // TODO: do a basic size check, to filter out partial downloads and corrupt + // files from full HD's and other weird stuff qDebug() << "Verifying sapling param files exist"; - if( QFile( QDir(".").filePath("sapling-output.params") ).exists() && QFile( QDir(".").filePath("sapling-output.params") ).exists() ) { + // This list of locations to look must be kept in sync with the list in hushd + if( QFile( QDir(".").filePath("sapling-output.params") ).exists() && QFile( QDir(".").filePath("sapling-spend.params") ).exists() ) { qDebug() << "Found params in ."; return true; } - if( QFile( QDir("..").filePath("sapling-output.params") ).exists() && QFile( QDir("..").filePath("sapling-output.params") ).exists() ) { + if( QFile( QDir("..").filePath("sapling-output.params") ).exists() && QFile( QDir("..").filePath("sapling-spend.params") ).exists() ) { qDebug() << "Found params in .."; return true; } - if( QFile( QDir("..").filePath("hush3/sapling-output.params") ).exists() && QFile( QDir("..").filePath("hush3/sapling-output.params") ).exists() ) { + if( QFile( QDir("..").filePath("hush3/sapling-output.params") ).exists() && QFile( QDir("..").filePath("hush3/sapling-spend.params") ).exists() ) { qDebug() << "Found params in ../hush3"; return true; } + // this is to support hushd inside a .dmg file, where the binaries are not at the root directory, but they are executed from the root dir of the .dmg + if( QFile( QDir("..").filePath("Contents/MacOS/sapling-output.params") ).exists() && QFile( QDir("..").filePath("Contents/MacOS/hush3/sapling-spend.params") ).exists() ) { + qDebug() << "Found params in ../Contents/MacOS"; + return true; + } + if (QFile(paramsDir.filePath("sapling-output.params")).exists() && QFile(paramsDir.filePath("sapling-spend.params")).exists()) { qDebug() << "Found params in " << paramsDir; return true;