From fba4c61976583d203b2ceaf592269ab0731c4b83 Mon Sep 17 00:00:00 2001 From: Aditya Kulkarni Date: Fri, 18 Oct 2019 19:21:40 -0700 Subject: [PATCH] Wire up private key export --- src/controller.h | 5 +- src/liteinterface.cpp | 330 +----------------------------------------- src/liteinterface.h | 22 +-- src/main.cpp | 2 +- src/mainwindow.cpp | 28 ++-- 5 files changed, 24 insertions(+), 363 deletions(-) diff --git a/src/controller.h b/src/controller.h index fba66a1..811ac18 100644 --- a/src/controller.h +++ b/src/controller.h @@ -64,9 +64,8 @@ public: void createNewZaddr(bool sapling, const std::function& cb) { zrpc->createNewZaddr(sapling, cb); } void createNewTaddr(const std::function& cb) { zrpc->createNewTaddr(cb); } - void fetchZPrivKey(QString addr, const std::function& cb) { zrpc->fetchZPrivKey(addr, cb); } - void fetchTPrivKey(QString addr, const std::function& cb) { zrpc->fetchTPrivKey(addr, cb); } - void fetchAllPrivKeys(const std::function>)> cb) { zrpc->fetchAllPrivKeys(cb); } + void fetchPrivKey(QString addr, const std::function& cb) { zrpc->fetchPrivKey(addr, cb); } + void fetchAllPrivKeys(const std::function cb) { zrpc->fetchAllPrivKeys(cb); } // void importZPrivKey(QString addr, bool rescan, const std::function& cb) { zrpc->importZPrivKey(addr, rescan, cb); } // void importTPrivKey(QString addr, bool rescan, const std::function& cb) { zrpc->importTPrivKey(addr, rescan, cb); } diff --git a/src/liteinterface.cpp b/src/liteinterface.cpp index 261ee65..5f74074 100644 --- a/src/liteinterface.cpp +++ b/src/liteinterface.cpp @@ -33,15 +33,6 @@ void LiteInterface::fetchUnspent(const std::function& cb) { return; conn->doRPCWithDefaultErrorHandling("notes", "", cb); - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "listunspent"}, - // {"params", {0}} // Get UTXOs with 0 confirmations as well. - // }; - - // conn->doRPCWithDefaultErrorHandling(payload, cb); } void LiteInterface::createNewZaddr(bool, const std::function& cb) { @@ -58,32 +49,11 @@ void LiteInterface::createNewTaddr(const std::function& cb) { conn->doRPCWithDefaultErrorHandling("new", "t", cb); } -void LiteInterface::fetchZPrivKey(QString addr, const std::function& cb) { +void LiteInterface::fetchPrivKey(QString addr, const std::function& cb) { if (conn == nullptr) return; - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "z_exportkey"}, - // {"params", { addr.toStdString() }}, - // }; - - // conn->doRPCWithDefaultErrorHandling(payload, cb); -} - -void LiteInterface::fetchTPrivKey(QString addr, const std::function& cb) { - if (conn == nullptr) - return; - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "dumpprivkey"}, - // {"params", { addr.toStdString() }}, - // }; - - // conn->doRPCWithDefaultErrorHandling(payload, cb); + conn->doRPCWithDefaultErrorHandling("export", addr, cb); } // void LiteInterface::importZPrivKey(QString addr, bool rescan, const std::function& cb) { @@ -145,309 +115,17 @@ void LiteInterface::fetchInfo(const std::function& cb, conn->doRPC("info", "", cb, err); } -void LiteInterface::fetchBlockchainInfo(const std::function& cb) { - if (conn == nullptr) - return; - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "getblockchaininfo"} - // }; - - // conn->doRPCIgnoreError(payload, cb); -} - -void LiteInterface::fetchNetSolOps(const std::function cb) { - if (conn == nullptr) - return; - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "getnetworksolps"} - // }; - - // conn->doRPCIgnoreError(payload, [=](const json& reply) { - // qint64 solrate = reply.get(); - // cb(solrate); - // }); -} - -void LiteInterface::fetchMigrationStatus(const std::function& cb) { - if (conn == nullptr) - return; - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "z_getmigrationstatus"}, - // }; - - // conn->doRPCWithDefaultErrorHandling(payload, cb); -} - - -void LiteInterface::setMigrationStatus(bool enabled) { - if (conn == nullptr) - return; - - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "z_setmigration"}, - // {"params", {enabled}} - // }; - - // conn->doRPCWithDefaultErrorHandling(payload, [=](json) { - // // Ignore return value. - // }); -} - - /** * Method to get all the private keys for both z and t addresses. It will make 2 batch calls, * combine the result, and call the callback with a single list containing both the t-addr and z-addr * private keys */ -void LiteInterface::fetchAllPrivKeys(const std::function>)> cb) { +void LiteInterface::fetchAllPrivKeys(const std::function cb) { if (conn == nullptr) { // No connection, just return return; } - // // A special function that will call the callback when two lists have been added - // auto holder = new QPair>>(); - // holder->first = 0; // This is the number of times the callback has been called, initialized to 0 - // auto fnCombineTwoLists = [=] (QList> list) { - // // Increment the callback counter - // holder->first++; - - // // Add all - // std::copy(list.begin(), list.end(), std::back_inserter(holder->second)); - - // // And if the caller has been called twice, do the parent callback with the - // // collected list - // if (holder->first == 2) { - // // Sort so z addresses are on top - // std::sort(holder->second.begin(), holder->second.end(), - // [=] (auto a, auto b) { return a.first > b.first; }); - - // cb(holder->second); - // delete holder; - // } - // }; - - // // A utility fn to do the batch calling - // auto fnDoBatchGetPrivKeys = [=](json getAddressPayload, std::string privKeyDumpMethodName) { - // conn->doRPCWithDefaultErrorHandling(getAddressPayload, [=] (json resp) { - // QList addrs; - // for (auto addr : resp.get()) { - // addrs.push_back(QString::fromStdString(addr.get())); - // } - - // // Then, do a batch request to get all the private keys - // conn->doBatchRPC( - // addrs, - // [=] (auto addr) { - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", privKeyDumpMethodName}, - // {"params", { addr.toStdString() }}, - // }; - // return payload; - // }, - // [=] (QMap* privkeys) { - // QList> allTKeys; - // for (QString addr: privkeys->keys()) { - // allTKeys.push_back( - // QPair( - // addr, - // QString::fromStdString(privkeys->value(addr).get()))); - // } - - // fnCombineTwoLists(allTKeys); - // delete privkeys; - // } - // ); - // }); - // }; - - // // First get all the t and z addresses. - // json payloadT = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "getaddressesbyaccount"}, - // {"params", {""} } - // }; - - // json payloadZ = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "z_listaddresses"} - // }; - - // fnDoBatchGetPrivKeys(payloadT, "dumpprivkey"); - // fnDoBatchGetPrivKeys(payloadZ, "z_exportkey"); + conn->doRPCWithDefaultErrorHandling("export", "", cb); } -void LiteInterface::fetchOpStatus(const std::function& cb) { - if (conn == nullptr) - return; - - // Make an RPC to load pending operation statues - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "someid"}, - // {"method", "z_getoperationstatus"}, - // }; - - // conn->doRPCIgnoreError(payload, cb); -} - -void LiteInterface::fetchReceivedTTrans(QList txids, QList sentZTxs, - const std::function)> txdataFn) { - if (conn == nullptr) - return; - - // Look up all the txids to get the confirmation count for them. - // conn->doBatchRPC(txids, - // [=] (QString txid) { - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "senttxid"}, - // {"method", "gettransaction"}, - // {"params", {txid.toStdString()}} - // }; - - // return payload; - // }, - // [=] (QMap* txidList) { - // auto newSentZTxs = sentZTxs; - // // Update the original sent list with the confirmation count - // // TODO: This whole thing is kinda inefficient. We should probably just update the file - // // with the confirmed block number, so we don't have to keep calling gettransaction for the - // // sent items. - // for (TransactionItem& sentTx: newSentZTxs) { - // auto j = txidList->value(sentTx.txid); - // if (j.is_null()) - // continue; - // auto error = j["confirmations"].is_null(); - // if (!error) - // sentTx.confirmations = j["confirmations"].get(); - // } - - // txdataFn(newSentZTxs); - // delete txidList; - // } - // ); -} - - -// Refresh received z txs by calling z_listreceivedbyaddress/gettransaction -void LiteInterface::fetchReceivedZTrans(QList zaddrs, const std::function usedAddrFn, - const std::function)> txdataFn) { - if (conn == nullptr) - return; - - - // This method is complicated because z_listreceivedbyaddress only returns the txid, and - // we have to make a follow up call to gettransaction to get details of that transaction. - // Additionally, it has to be done in batches, because there are multiple z-Addresses, - // and each z-Addr can have multiple received txs. - - // 1. For each z-Addr, get list of received txs - // conn->doBatchRPC(zaddrs, - // [=] (QString zaddr) { - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "z_lrba"}, - // {"method", "z_listreceivedbyaddress"}, - // {"params", {zaddr.toStdString(), 0}} // Accept 0 conf as well. - // }; - - // return payload; - // }, - // [=] (QMap* zaddrTxids) { - // // Process all txids, removing duplicates. This can happen if the same address - // // appears multiple times in a single tx's outputs. - // QSet txids; - // QMap memos; - // for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { - // auto zaddr = it.key(); - // for (auto& i : it.value().get()) { - // // Mark the address as used - // usedAddrFn(zaddr); - - // // Filter out change txs - // if (! i["change"].get()) { - // auto txid = QString::fromStdString(i["txid"].get()); - // txids.insert(txid); - - // // Check for Memos - // QString memoBytes = QString::fromStdString(i["memo"].get()); - // if (!memoBytes.startsWith("f600")) { - // QString memo(QByteArray::fromHex( - // QByteArray::fromStdString(i["memo"].get()))); - // if (!memo.trimmed().isEmpty()) - // memos[zaddr + txid] = memo; - // } - // } - // } - // } - - // // 2. For all txids, go and get the details of that txid. - // conn->doBatchRPC(txids.toList(), - // [=] (QString txid) { - // json payload = { - // {"jsonrpc", "1.0"}, - // {"id", "gettx"}, - // {"method", "gettransaction"}, - // {"params", {txid.toStdString()}} - // }; - - // return payload; - // }, - // [=] (QMap* txidDetails) { - // QList txdata; - - // // Combine them both together. For every zAddr's txid, get the amount, fee, confirmations and time - // for (auto it = zaddrTxids->constBegin(); it != zaddrTxids->constEnd(); it++) { - // for (auto& i : it.value().get()) { - // // Filter out change txs - // if (i["change"].get()) - // continue; - - // auto zaddr = it.key(); - // auto txid = QString::fromStdString(i["txid"].get()); - - // // Lookup txid in the map - // auto txidInfo = txidDetails->value(txid); - - // qint64 timestamp; - // if (txidInfo.find("time") != txidInfo.end()) { - // timestamp = txidInfo["time"].get(); - // } else { - // timestamp = txidInfo["blocktime"].get(); - // } - - // auto amount = i["amount"].get(); - // auto confirmations = static_cast(txidInfo["confirmations"].get()); - - // TransactionItem tx{ QString("receive"), timestamp, zaddr, txid, amount, - // confirmations, "", memos.value(zaddr + txid, "") }; - // txdata.push_front(tx); - // } - // } - - // txdataFn(txdata); - - // // Cleanup both responses; - // delete zaddrTxids; - // delete txidDetails; - // } - // ); - // } - // ); -} diff --git a/src/liteinterface.h b/src/liteinterface.h index 29218cd..6df9662 100644 --- a/src/liteinterface.h +++ b/src/liteinterface.h @@ -39,34 +39,22 @@ public: void fetchUnspent (const std::function& cb); void fetchTransactions (const std::function& cb); - void fetchAddresses (const std::function& cb); - - void fetchReceivedZTrans(QList zaddrs, const std::function usedAddrFn, - const std::function)> txdataFn); - void fetchReceivedTTrans(QList txids, QList sentZtxs, - const std::function)> txdataFn); + void fetchAddresses (const std::function& cb); void fetchInfo(const std::function& cb, const std::function& err); - void fetchBlockchainInfo(const std::function& cb); - void fetchNetSolOps(const std::function cb); - void fetchOpStatus(const std::function& cb); - - void fetchMigrationStatus(const std::function& cb); - void setMigrationStatus(bool enabled); - + void fetchBalance(const std::function& cb); void createNewZaddr(bool sapling, const std::function& cb); void createNewTaddr(const std::function& cb); - void fetchZPrivKey(QString addr, const std::function& cb); - void fetchTPrivKey(QString addr, const std::function& cb); + void fetchPrivKey(QString addr, const std::function& cb); + void fetchAllPrivKeys(const std::function); + //void importZPrivKey(QString addr, bool rescan, const std::function& cb); //void importTPrivKey(QString addr, bool rescan, const std::function& cb); - void fetchAllPrivKeys(const std::function>)>); - void sendTransaction(QString params, const std::function& cb, const std::function& err); private: diff --git a/src/main.cpp b/src/main.cpp index a431736..bc93ab5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -214,7 +214,7 @@ public: } w = new MainWindow(); - w->setWindowTitle("ZecWallet v" + QString(APP_VERSION)); + w->setWindowTitle("Zecwallet v" + QString(APP_VERSION)); // If there was a payment URI on the command line, pay it if (parser.positionalArguments().length() > 0) { diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ccd9177..448e1d7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -695,13 +695,20 @@ void MainWindow::exportKeys(QString addr) { // Call the API auto isDialogAlive = std::make_shared(true); - auto fnUpdateUIWithKeys = [=](QList> privKeys) { + auto fnUpdateUIWithKeys = [=](json reply) { // Check to see if we are still showing. if (! *(isDialogAlive.get()) ) return; + if (reply.is_discarded() || !reply.is_array()) { + pui.privKeyTxt->setPlainText(tr("Error loading private keys")); + pui.buttonBox->button(QDialogButtonBox::Save)->setEnabled(false); + + return; + } + QString allKeysTxt; - for (auto keypair : privKeys) { - allKeysTxt = allKeysTxt % keypair.second % " # addr=" % keypair.first % "\n"; + for (auto i : reply.get()) { + allKeysTxt = allKeysTxt % QString::fromStdString(i["private_key"]) % " # addr=" % QString::fromStdString(i["address"]) % "\n"; } pui.privKeyTxt->setPlainText(allKeysTxt); @@ -711,19 +718,8 @@ void MainWindow::exportKeys(QString addr) { if (allKeys) { rpc->fetchAllPrivKeys(fnUpdateUIWithKeys); } - else { - auto fnAddKey = [=](json key) { - QList> singleAddrKey; - singleAddrKey.push_back(QPair(addr, QString::fromStdString(key.get()))); - fnUpdateUIWithKeys(singleAddrKey); - }; - - if (Settings::getInstance()->isZAddress(addr)) { - rpc->fetchZPrivKey(addr, fnAddKey); - } - else { - rpc->fetchTPrivKey(addr, fnAddKey); - } + else { + rpc->fetchPrivKey(addr, fnUpdateUIWithKeys); } d.exec();