[Dev] Documenting Feathercoin Specific Software settings - Part 6
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/forms/editaddressdialog.ui
+ <item row="2" column="0"> + <widget class="QCheckBox" name="stealthCB"> + <property name="text"> + <string>Stealth Address</string> + </property> + </widget> + </item>
Code added
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/receivecoinsdialog.cpp
- address = model ->getAddressTableModel() ->addRow(AddressTableModel::Receive, label, ""); + int typeInd = AddressTableModel::AT_Normal; + address = model ->getAddressTableModel() ->addRow(AddressTableModel::Receive, label, "",typeInd);
Code replaced
- ui->reqAmount->value(), ui->reqMessage->text()); + ui->reqAmount->value(), ui->reqMessage->text());
Code replaced
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/sendcoinsdialog.cpp
+ //QMessageBox::information(NULL, "Info1", "Click_SendButton", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
Code added
-
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/sendcoinsentry.cpp
+ #include "stealth.h" + #include <QDebug>
Code added
+ + if (recipient.address.length() > 75 + && IsStealthAddress(recipient.address.toStdString())) + recipient.typeInd = AddressTableModel::AT_Stealth; + else + recipient.typeInd = AddressTableModel::AT_Normal; + + qDebug() << "SendCoinsEntry::getValue,recipient.typeInd =" + QString::number(recipient.typeInd);
Code added
+ + if (recipient.address.length() > 75 + && IsStealthAddress(recipient.address.toStdString())) + recipient.typeInd = AddressTableModel::AT_Stealth; + else + recipient.typeInd = AddressTableModel::AT_Normal; + + qDebug() << "SendCoinsEntry::getValue,recipient.typeInd ="+ QString::number(recipient.typeInd);
Code added
-
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/transactiondesc.cpp
+ char cbuf[256]; + for (int k = 0; k < wtx.vout.size(); + + k) + { + snprintf(cbuf, sizeof(cbuf), "n_%d", k); + if (wtx.mapValue.count(cbuf) && !wtx.mapValue[cbuf].empty()) + strHTML + = "<br><b>" + tr(cbuf) + ":</b> " + GUIUtil::HtmlEscape(wtx.mapValue[cbuf], true) + "<br>"; + } +
Code added
-
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/walletmodel.cpp
+ #include <QMessageBox> + + #if defined(_MSC_VER) || defined(__MSVCRT__) + /* (s)size_t and ptrdiff_t have the same size specifier in MSVC: + http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.100%29.aspx + */ + #define PRIszx "Ix" + #define PRIszu "Iu" + #define PRIszd "Id" + #define PRIpdx "Ix" + #define PRIpdu "Iu" + #define PRIpdd "Id" + #else /* C99 standard */ + #define PRIszx "zx" + #define PRIszu "zu" + #define PRIszd "zd" + #define PRIpdx "tx" + #define PRIpdu "tu" + #define PRIpdd "td" + #endif
Additional code
- CBitcoinAddress addressParsed(address.toStdString());
Code removed
+ std::string sAddr = address.toStdString(); + + if (sAddr.length() > 75) + { + if (IsStealthAddress(sAddr)) + return true; + }; + + CBitcoinAddress addressParsed(sAddr);
Code replaced
-
{ // User-entered feathercoin address / amount:
Comment changed? name to Feathercoin
+ std::string sAddr = rcp.address.toStdString(); + if (rcp.typeInd == AddressTableModel::AT_Stealth) + { + CStealthAddress sxAddr; + if (sxAddr.SetEncoded(sAddr)) + { + ec_secret ephem_secret; + ec_secret secretShared; + ec_point pkSendTo; + ec_point ephem_pubkey; + + + if (GenerateRandomSecret(ephem_secret) != 0) + { + printf("GenerateRandomSecret failed.\n"); + return Aborted; + }; + + if (StealthSecret(ephem_secret, sxAddr.scan_pubkey, sxAddr.spend_pubkey, secretShared, pkSendTo) != 0) + { + printf("Could not generate receiving public key.\n"); + return Aborted; + }; + + CPubKey cpkTo(pkSendTo); + if (!cpkTo.IsValid()) + { + printf("Invalid public key generated.\n"); + return Aborted; + }; + + CKeyID ckidTo = cpkTo.GetID(); + + CBitcoinAddress addrTo(ckidTo); + + if (SecretToPublicKey(ephem_secret, ephem_pubkey) != 0) + { + printf("Could not generate ephem public key.\n"); + return Aborted; + }; + + //if (fDebug) + if (true) + { + LogPrintf("Stealth send to generated pubkey %"PRIszu": %s\n", pkSendTo.size(), HexStr(pkSendTo).c_str()); + LogPrintf("hash %s\n", addrTo.ToString().c_str()); + LogPrintf("ephem_pubkey %"PRIszu": %s\n", ephem_pubkey.size(), HexStr(ephem_pubkey).c_str()); + }; + + CScript scriptPubKey; + scriptPubKey.SetDestination(addrTo.Get()); + LogPrintf("scriptPubKey= %s \n", scriptPubKey.ToString()); + + vecSend.push_back(make_pair(scriptPubKey, rcp.amount)); + + CScript scriptP = CScript() << OP_RETURN << ephem_pubkey; + vecSend.push_back(make_pair(scriptP, 0)); + + continue; + }; // else drop through to normal + } +
Code added
- scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); + //scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); + scriptPubKey.SetDestination(CBitcoinAddress(sAddr).Get());
Code commented out?? review
+ int nChangePos = -1;
Code added
- bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl); + bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, nChangePos, strFailReason, coinControl);
Code replaced
+ else if (!rcp.message.isEmpty()) // Message from normal feathercoin:URI (feathercoin:123...?message=example)
Code replaced name
+ //Run//QMessageBox::information(NULL, "Info2", "Click_sendCoins", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes); CReserveKey *keyChange = transaction.getPossibleKeyChange(); + LogPrintf("sendCoins: newTx= \n%s", newTx->ToString()); +
Code commented out ? code added
+ //string strError =wallet->SendMoneyToDestination(rcp.label, transaction.GetValueOut(), *newTx);
Code added
+ //No Run//
Comment added
- std::map<CTxDestination, CAddressBookData>::iterator mi = wallet ->mapAddressBook.find(dest); - - // Check if we have a new address or an updated label - if (mi == wallet ->mapAddressBook.end()) - { - wallet ->SetAddressBook(dest, strLabel, "send"); - } - else if (mi ->second.name != strLabel) - { - wallet ->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose - } - }
Code removed
+ if (rcp.typeInd == AddressTableModel::AT_Stealth) + { + wallet->UpdateStealthAddress(strAddress, strLabel, true); + } else + { + std::map<CTxDestination, CAddressBookData>::iterator mi = wallet->mapAddressBook.find(dest); + // Check if we have a new address or an updated label + if (mi == wallet->mapAddressBook.end()) + { + wallet->SetAddressBook(dest, strLabel, "send"); + } + else if (mi->second.name != strLabel) + { + wallet->SetAddressBook(dest, strLabel, ""); // "" means don't change purpose + } + } + }
Code added
+ LogPrintf("sendCoins: updateAddressBook. \n");
Log interface message added
- static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, + /*static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
Commented out? should be deleted if not used…
+ }*/ + static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, + const CTxDestination &address, const std::string &label, bool isMine, + const std::string &purpose, ChangeType status) + { + QString strAddress = QString::fromStdString(CBitcoinAddress(address).ToString()); + QString strLabel = QString::fromStdString(label); + QString strPurpose = QString::fromStdString(purpose); + + if (address.type() == typeid(CStealthAddress)) + { + CStealthAddress sxAddr = boost::get<CStealthAddress>(address); + std::string enc = sxAddr.Encoded(); + //OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", enc.c_str(), label.c_str(), isMine, status); + qDebug() << "NotifyAddressBookChanged : " + QString::fromStdString(enc) + " " + QString::fromStdString(label) + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status); + QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(enc)), + Q_ARG(QString, QString::fromStdString(label)), + Q_ARG(bool, isMine), + Q_ARG(QString, strPurpose), + Q_ARG(int, status)); + } else { + //OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, status); + qDebug() << "NotifyAddressBookChanged : " + strAddress + " " + strLabel + " isMine=" + QString::number(isMine) + " purpose=" + strPurpose + " status=" + QString::number(status); + QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection, + Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())), + Q_ARG(QString, QString::fromStdString(label)), + Q_ARG(bool, isMine), + Q_ARG(QString, strPurpose), + Q_ARG(int, status)); + }
Code added
-
-
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/qt/walletmodel.h
+ int typeInd;
Code added
- TransactionCommitFailed + TransactionCommitFailed, + Aborted
?? code added?
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/rpcmisc.cpp
+ Object operator()(const CStealthAddress &stxAddr) const { + Object obj; + obj.push_back(Pair("todo", true)); + return obj; + }
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/rpcserver.cpp
+ + { "getnewstealthaddress", &getnewstealthaddress, false, false, true }, + { "liststealthaddresses", &liststealthaddresses, false, false, true }, + { "importstealthaddress", &importstealthaddress, false, false, true }, + { "sendtostealthaddress", &sendtostealthaddress, false, false, true }, + { "clearwallettransactions",&clearwallettransactions,false, false, true }, + { "scanforalltxns", &scanforalltxns, false, false, true }, + { "scanforstealthtxns", &scanforstealthtxns, false, false, true },
Code added
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/rpcserver.h
+ extern json_spirit::Value getnewstealthaddress(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value liststealthaddresses(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value importstealthaddress(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value sendtostealthaddress(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value clearwallettransactions(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value scanforalltxns(const json_spirit::Array& params, bool fHelp); + extern json_spirit::Value scanforstealthtxns(const json_spirit::Array& params, bool fHelp); +
Code added
src/rpcwallet.cpp
Large number of changes, could stealth code have been a seperate module? / file
+#include "stealth.h"
Code included
- if (fHelp || params.size() < 2 || params.size() > 4) + if (fHelp || params.size() < 2 || params.size() > 5)
Code replaced
- if (fHelp || params.size() < 3 || params.size() > 6) + if (fHelp || params.size() < 3 || params.size() > 7)
Code replaced
+ int nChangePos;
Code added
- bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason); + bool fCreated = pwalletMain->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired,nChangePos, strFailReason);
Code replaced
Main stealth function 1992 to line 2379
+ + Value getnewstealthaddress(const Array& params, bool fHelp) + { + if (fHelp || params.size() > 1) + throw runtime_error( + "getnewstealthaddress [label]\n" + "Returns a new ShadowCoin stealth address for receiving payments anonymously. "); + + if (pwalletMain->IsLocked()) + throw runtime_error("Failed: Wallet must be unlocked."); + + std::string sLabel; + if (params.size() > 0) + sLabel = params[0].get_str(); + + CStealthAddress sxAddr; + std::string sError; + if (!pwalletMain->NewStealthAddress(sError, sLabel, sxAddr)) + throw runtime_error(std::string("Could get new stealth address: ") + sError); + + if (!pwalletMain->AddStealthAddress(sxAddr)) + throw runtime_error("Could not save to wallet."); + + return sxAddr.Encoded(); + } + + Value liststealthaddresses(const Array& params, bool fHelp) + { + if (fHelp || params.size() > 1) + throw runtime_error( + "liststealthaddresses [show_secrets=0]\n" + "List owned stealth addresses."); + + bool fShowSecrets = false; + + if (params.size() > 0) + { + std::string str = params[0].get_str(); + + if (str == "0" || str == "n" || str == "no" || str == "-" || str == "false") + fShowSecrets = false; + else + fShowSecrets = true; + }; + + if (fShowSecrets) + { + if (pwalletMain->IsLocked()) + throw runtime_error("Failed: Wallet must be unlocked."); + }; + + Object result; + + std::set<CStealthAddress>::iterator it; + for (it = pwalletMain->stealthAddresses.begin(); it != pwalletMain->stealthAddresses.end(); + + it) + { + if (it->scan_secret.size() < 1) + continue; // stealth address is not owned + + if (fShowSecrets) + { + Object objA; + objA.push_back(Pair("Label ", it->label)); + objA.push_back(Pair("Address ", it->Encoded())); + objA.push_back(Pair("Scan Secret ", HexStr(it->scan_secret.begin(), it->scan_secret.end()))); + objA.push_back(Pair("Spend Secret ", HexStr(it->spend_secret.begin(), it->spend_secret.end()))); + result.push_back(Pair("Stealth Address", objA)); + } else + { + result.push_back(Pair("Stealth Address", it->Encoded() + " - " + it->label)); + }; + }; + + return result; + } + + Value importstealthaddress(const Array& params, bool fHelp) + { + if (fHelp || params.size() < 2) + throw runtime_error( + "importstealthaddress <scan_secret> <spend_secret> [label]\n" + "Import an owned stealth addresses."); + + std::string sScanSecret = params[0].get_str(); + std::string sSpendSecret = params[1].get_str(); + std::string sLabel; + + + if (params.size() > 2) + { + sLabel = params[2].get_str(); + }; + + std::vector<uint8_t> vchScanSecret; + std::vector<uint8_t> vchSpendSecret; + + if (IsHex(sScanSecret)) + { + vchScanSecret = ParseHex(sScanSecret); + } else + { + if (!DecodeBase58(sScanSecret, vchScanSecret)) + throw runtime_error("Could not decode scan secret as hex or base58."); + }; + + if (IsHex(sSpendSecret)) + { + vchSpendSecret = ParseHex(sSpendSecret); + } else + { + if (!DecodeBase58(sSpendSecret, vchSpendSecret)) + throw runtime_error("Could not decode spend secret as hex or base58."); + }; + + if (vchScanSecret.size() != 32) + throw runtime_error("Scan secret is not 32 bytes."); + if (vchSpendSecret.size() != 32) + throw runtime_error("Spend secret is not 32 bytes."); + + + ec_secret scan_secret; + ec_secret spend_secret; + + memcpy(&scan_secret.e[0], &vchScanSecret[0], 32); + memcpy(&spend_secret.e[0], &vchSpendSecret[0], 32); + + ec_point scan_pubkey, spend_pubkey; + if (SecretToPublicKey(scan_secret, scan_pubkey) != 0) + throw runtime_error("Could not get scan public key."); + + if (SecretToPublicKey(spend_secret, spend_pubkey) != 0) + throw runtime_error("Could not get spend public key."); + + + CStealthAddress sxAddr; + sxAddr.label = sLabel; + sxAddr.scan_pubkey = scan_pubkey; + sxAddr.spend_pubkey = spend_pubkey; + + sxAddr.scan_secret = vchScanSecret; + sxAddr.spend_secret = vchSpendSecret; + + Object result; + bool fFound = false; + // -- find if address already exists + std::set<CStealthAddress>::iterator it; + for (it = pwalletMain->stealthAddresses.begin(); it != pwalletMain->stealthAddresses.end(); + + it) + { + CStealthAddress &sxAddrIt = const_cast<CStealthAddress&>(*it); + if (sxAddrIt.scan_pubkey == sxAddr.scan_pubkey + && sxAddrIt.spend_pubkey == sxAddr.spend_pubkey) + { + if (sxAddrIt.scan_secret.size() < 1) + { + sxAddrIt.scan_secret = sxAddr.scan_secret; + sxAddrIt.spend_secret = sxAddr.spend_secret; + fFound = true; // update stealth address with secrets + break; + }; + + result.push_back(Pair("result", "Import failed - stealth address exists.")); + return result; + }; + }; + + if (fFound) + { + result.push_back(Pair("result", "Success, updated " + sxAddr.Encoded())); + } else + { + pwalletMain->stealthAddresses.insert(sxAddr); + result.push_back(Pair("result", "Success, imported " + sxAddr.Encoded())); + }; + + + if (!pwalletMain->AddStealthAddress(sxAddr)) + throw runtime_error("Could not save to wallet."); + + return result; + } + + + Value sendtostealthaddress(const Array& params, bool fHelp) + { + if (fHelp || params.size() < 2 || params.size() > 5) + throw runtime_error( + "sendtostealthaddress <stealth_address> <amount> [comment] [comment-to]\n" + "<amount> is a real and is rounded to the nearest 0.000001" + + HelpRequiringPassphrase()); + + if (pwalletMain->IsLocked()) + throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first."); + + std::string sEncoded = params[0].get_str(); + int64_t nAmount = AmountFromValue(params[1]); + + CStealthAddress sxAddr; + Object result; + + if (!sxAddr.SetEncoded(sEncoded)) + { + result.push_back(Pair("result", "Invalid Deepcoin stealth address.")); + return result; + }; + + + CWalletTx wtx; + if (params.size() > 2 && params[2].type() != null_type && !params[2].get_str().empty()) + wtx.mapValue["comment"] = params[2].get_str(); + if (params.size() > 3 && params[3].type() != null_type && !params[3].get_str().empty()) + wtx.mapValue["to"] = params[3].get_str(); + + std::string sError; + if (!pwalletMain->SendStealthMoneyToDestination(sxAddr, nAmount, wtx, sError)) + throw JSONRPCError(RPC_WALLET_ERROR, sError); + + return wtx.GetHash().GetHex(); + + result.push_back(Pair("result", "Not implemented yet.")); + + return result; + } + + Value clearwallettransactions(const Array& params, bool fHelp) + { + if (fHelp || params.size() > 0) + throw runtime_error( + "clearwallettransactions \n" + "delete all transactions from wallet - reload with scanforalltxns\n" + "Warning: Backup your wallet first!"); + + + + Object result; + + uint32_t nTransactions = 0; + + char cbuf[256]; + + { + LOCK2(cs_main, pwalletMain->cs_wallet); + + CWalletDB walletdb(pwalletMain->strWalletFile); + walletdb.TxnBegin(); + Dbc* pcursor = walletdb.GetTxnCursor(); + if (!pcursor) + throw runtime_error("Cannot get wallet DB cursor"); + + Dbt datKey; + Dbt datValue; + + datKey.set_flags(DB_DBT_USERMEM); + datValue.set_flags(DB_DBT_USERMEM); + + std::vector<unsigned char> vchKey; + std::vector<unsigned char> vchType; + std::vector<unsigned char> vchKeyData; + std::vector<unsigned char> vchValueData; + + vchKeyData.resize(100); + vchValueData.resize(100); + + datKey.set_ulen(vchKeyData.size()); + datKey.set_data(&vchKeyData[0]); + + datValue.set_ulen(vchValueData.size()); + datValue.set_data(&vchValueData[0]); + + unsigned int fFlags = DB_NEXT; // same as using DB_FIRST for new cursor + while (true) + { + int ret = pcursor->get(&datKey, &datValue, fFlags); + + if (ret == ENOMEM + || ret == DB_BUFFER_SMALL) + { + if (datKey.get_size() > datKey.get_ulen()) + { + vchKeyData.resize(datKey.get_size()); + datKey.set_ulen(vchKeyData.size()); + datKey.set_data(&vchKeyData[0]); + }; + + if (datValue.get_size() > datValue.get_ulen()) + { + vchValueData.resize(datValue.get_size()); + datValue.set_ulen(vchValueData.size()); + datValue.set_data(&vchValueData[0]); + }; + // -- try once more, when DB_BUFFER_SMALL cursor is not expected to move + ret = pcursor->get(&datKey, &datValue, fFlags); + }; + + if (ret == DB_NOTFOUND) + break; + else + if (datKey.get_data() == NULL || datValue.get_data() == NULL + || ret != 0) + { + snprintf(cbuf, sizeof(cbuf), "wallet DB error %d, %s", ret, db_strerror(ret)); + throw runtime_error(cbuf); + }; + + CDataStream ssValue(SER_DISK, CLIENT_VERSION); + ssValue.SetType(SER_DISK); + ssValue.clear(); + ssValue.write((char*)datKey.get_data(), datKey.get_size()); + + ssValue >> vchType; + + + std::string strType(vchType.begin(), vchType.end()); + + //printf("strType %s\n", strType.c_str()); + + if (strType == "tx") + { + uint256 hash; + ssValue >> hash; + + if ((ret = pcursor->del(0)) != 0) + { + printf("Delete transaction failed %d, %s\n", ret, db_strerror(ret)); + continue; + }; + + pwalletMain->mapWallet.erase(hash); + pwalletMain->NotifyTransactionChanged(pwalletMain, hash, CT_DELETED); + + nTransactions + + ; + }; + }; + pcursor->close(); + walletdb.TxnCommit(); + + + //pwalletMain->mapWallet.clear(); + } + + snprintf(cbuf, sizeof(cbuf), "Removed %u transactions.", nTransactions); + result.push_back(Pair("complete", std::string(cbuf))); + result.push_back(Pair("", "Reload with scanforstealthtxns or re-download blockchain.")); + + + return result; + } + + Value scanforalltxns(const Array& params, bool fHelp) + { + if (fHelp || params.size() > 1) + throw runtime_error( + "scanforalltxns [fromHeight]\n" + "Scan blockchain for owned transactions."); + + Object result; + int32_t nFromHeight = 0; + + CBlockIndex *pindex = chainActive.Genesis(); + + + if (params.size() > 0) + nFromHeight = params[0].get_int(); + + + if (nFromHeight > 0) + { + pindex = mapBlockIndex[hashBestChain]; + while (pindex->nHeight > nFromHeight + && pindex->pprev) + pindex = pindex->pprev; + }; + + if (pindex == NULL) + throw runtime_error("Genesis Block is not set."); + + { + LOCK2(cs_main, pwalletMain->cs_wallet); + + pwalletMain->MarkDirty(); + + pwalletMain->ScanForWalletTransactions(pindex, true); + pwalletMain->ReacceptWalletTransactions(); + } + + result.push_back(Pair("result", "Scan complete.")); + + return result; + } + + Value scanforstealthtxns(const Array& params, bool fHelp) + { + if (fHelp || params.size() > 1) + throw runtime_error( + "scanforstealthtxns [fromHeight]\n" + "Scan blockchain for owned stealth transactions."); + + Object result; + uint32_t nBlocks = 0; + uint32_t nTransactions = 0; + int32_t nFromHeight = 0; + + CBlockIndex *pindex = chainActive.Genesis(); + + + if (params.size() > 0) + nFromHeight = params[0].get_int(); + + + if (nFromHeight > 0) + { + pindex = mapBlockIndex[hashBestChain]; + while (pindex->nHeight > nFromHeight + && pindex->pprev) + pindex = pindex->pprev; + }; + + if (pindex == NULL) + throw runtime_error("Genesis Block is not set."); + + // -- locks in AddToWalletIfInvolvingMe + + bool fUpdate = true; // todo: option? + + pwalletMain->nStealth = 0; + pwalletMain->nFoundStealth = 0; + + while (pindex) + { + nBlocks + + ; + CBlock block; + ReadBlockFromDisk(block, pindex); //block.ReadFromDisk(pindex); + + BOOST_FOREACH(CTransaction& tx, block.vtx) + { + //if (!tx.IsStandard()) + string reason; + if (!IsStandardTx(tx, reason)) + continue; // leave out coinbase and others + nTransactions + + ; + + pwalletMain->AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate); + }; + + pindex = pindex->pnext; + }; + + printf("Scanned %u blocks, %u transactions\n", nBlocks, nTransactions); + printf("Found %u stealth transactions in blockchain.\n", pwalletMain->nStealth); + printf("Found %u new owned stealth transactions.\n", pwalletMain->nFoundStealth); + + char cbuf[256]; + snprintf(cbuf, sizeof(cbuf), "%u new stealth transactions.", pwalletMain->nFoundStealth); + + result.push_back(Pair("result", "Scan complete.")); + result.push_back(Pair("found", std::string(cbuf))); + + return result; + }
Code added stealth function
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/script.cpp
- typedef vector<unsigned char> valtype; + //typedef vector<unsigned char> valtype;
Code replaced, commented out?
+ bool operator()(const CStealthAddress &stxAddr) const + { + return stxAddr.scan_secret.size() == ec_secret_size; + }
Code added stealth address
+ + void operator()(const CStealthAddress &stxAddr) { + CScript script; + }
Code added
+ + bool operator()(const CStealthAddress &stxAddr) const { + script->clear(); + //*script << OP_HASH160 << scriptID << OP_EQUAL; + //printf("TODO\n"); + return false; + }
Code added
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/script.h
+#include "stealth.h"
Code added
- typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination; + typedef boost::variant<CNoDestination, CKeyID, CScriptID, CStealthAddress> CTxDestination; + //typedef boost::variant<CNoDestination, CKeyID, CScriptID> CTxDestination;
Code replaced commented out?
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/stealth.cpp
Large new file, with 683 lines of code
+ // Copyright (c) 2014 The ShadowCoin developers + // Distributed under the MIT/X11 software license, see the accompanying + // file license.txt or http://www.opensource.org/licenses/mit-license.php. + + #include "stealth.h" + #include "base58.h" + + + #include <openssl/rand.h> + #include <openssl/ec.h> + #include <openssl/ecdsa.h> + #include <openssl/obj_mac.h> + + //const uint8_t stealth_version_byte = 0x2a; + const uint8_t stealth_version_byte = 0x1d; + + + bool CStealthAddress::SetEncoded(const std::string& encodedAddress) + { + data_chunk raw;
Start of large new file from ShadowCoin developers ??
+ std::string CStealthAddress::Encoded() const + { + // https://wiki.unsystem.net/index.php/DarkWallet/Stealth#Address_format + // [version] [options] [scan_key] [N] ... [Nsigs] [prefix_length] ... + + data_chunk raw; + raw.push_back(stealth_version_byte); + + raw.push_back(options); + + raw.insert(raw.end(), scan_pubkey.begin(), scan_pubkey.end()); + raw.push_back(1); // number of spend pubkeys + raw.insert(raw.end(), spend_pubkey.begin(), spend_pubkey.end()); + raw.push_back(0); // number of signatures + raw.push_back(0); // ? + + AppendChecksum(raw); +
Referance to DarkWallet, original (DK) code, has it been updated for 0.11? plan for head pick, ssl etc.
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/stealth.h
Large new file, with 122 lines of code
+ // Copyright (c) 2014 The ShadowCoin developers + // Distributed under the MIT/X11 software license, see the accompanying + // file license.txt or http://www.opensource.org/licenses/mit-license.php. + + #ifndef BITCOIN_STEALTH_H + #define BITCOIN_STEALTH_H + + #include "util.h" + #include "serialize.h" + + #include <stdlib.h> + #include <stdio.h> + #include <vector> + #include <inttypes.h> + + + typedef std::vector<uint8_t> data_chunk; + + const size_t ec_secret_size = 32; + const size_t ec_compressed_size = 33; + const size_t ec_uncompressed_size = 65; + + typedef struct ec_secret { uint8_t e[ec_secret_size]; } ec_secret; + typedef data_chunk ec_point; + + typedef uint32_t stealth_bitfield; + + struct stealth_prefix + { + uint8_t number_bits; + stealth_bitfield bitfield; + }; + + template <typename T, typename Iterator> + T from_big_endian(Iterator in) + { + //VERIFY_UNSIGNED(T); + T out = 0; + size_t i = sizeof(T); + while (0 < i) + out |= static_cast<T>(*in + + ) << (8 * --i); + return out; + } + + template <typename T, typename Iterator> + T from_little_endian(Iterator in) + { + //VERIFY_UNSIGNED(T); + T out = 0; + size_t i = 0; + while (i < sizeof(T)) + out |= static_cast<T>(*in + + ) << (8 * i + + ); + return out; + } + + class CStealthAddress + { + public: + CStealthAddress() + { + options = 0; + } + + uint8_t options; + ec_point scan_pubkey; + ec_point spend_pubkey; + //std::vector<ec_point> spend_pubkeys; + size_t number_signatures; + stealth_prefix prefix; + + mutable std::string label; + data_chunk scan_secret; + data_chunk spend_secret; + + bool SetEncoded(const std::string& encodedAddress); + std::string Encoded() const; + + bool operator <(const CStealthAddress& y) const + { + return memcmp(&scan_pubkey[0], &y.scan_pubkey[0], ec_compressed_size) < 0; + } + + bool operator == (const CStealthAddress& y) const + { + return (scan_pubkey == y.scan_pubkey) && + (spend_pubkey == y.spend_pubkey) && + (scan_secret == y.scan_secret) && + (spend_secret == y.spend_secret); + } + + IMPLEMENT_SERIALIZE + ( + READWRITE(this->options); + READWRITE(this->scan_pubkey); + READWRITE(this->spend_pubkey); + READWRITE(this->label); + + READWRITE(this->scan_secret); + READWRITE(this->spend_secret); + ); + + + + }; + + void AppendChecksum(data_chunk& data); + + bool VerifyChecksum(const data_chunk& data); + + int GenerateRandomSecret(ec_secret& out); + + int SecretToPublicKey(const ec_secret& secret, ec_point& out); + + int StealthSecret(ec_secret& secret, ec_point& pubkey, const ec_point& pkSpend, ec_secret& sharedSOut, ec_point& pkOut); + int StealthSecretSpend(ec_secret& scanSecret, ec_point& ephemPubkey, ec_secret& spendSecret, ec_secret& secretOut); + int StealthSharedToSecretSpend(ec_secret& sharedS, ec_secret& spendSecret, ec_secret& secretOut); + + bool IsStealthAddress(const std::string& encodedAddress); + + + #endif // BITCOIN_STEALTH_H +
New file include, how to handle going forward?
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/ui_interface.h
+ /** Ask the user whether they want to pay a fee or not. */ + boost::signals2::signal<bool (int64_t nFeeRequired, const std::string& strCaption), boost::signals2::last_value<bool> > ThreadSafeAskFee; +
Code added
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/ui_interface.h
+ /** Ask the user whether they want to pay a fee or not. */ + boost::signals2::signal<bool (int64_t nFeeRequired, const std::string& strCaption), boost::signals2::last_value<bool> > ThreadSafeAskFee; +
Code added
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/wallet.cpp
Large number of changes
+ #if defined(_MSC_VER) || defined(__MSVCRT__) + /* (s)size_t and ptrdiff_t have the same size specifier in MSVC: + http://msdn.microsoft.com/en-us/library/tcxf1dw6%28v=vs.100%29.aspx + */ + #define PRIszx "Ix" + #define PRIszu "Iu" + #define PRIszd "Id" + #define PRIpdx "Ix" + #define PRIpdu "Iu" + #define PRIpdd "Id" + #else /* C99 standard */ + #define PRIszx "zx" + #define PRIszu "zu" + #define PRIszd "zd" + #define PRIpdx "tx" + #define PRIpdu "tu" + #define PRIpdd "td" + #endif +
Code added
+ bool CWallet::Lock() + { + if (IsLocked()) + return true; + + if (fDebug) + printf("Locking wallet.\n"); + + { + LOCK(cs_wallet); + CWalletDB wdb(strWalletFile); + + // -- load encrypted spend_secret of stealth addresses + CStealthAddress sxAddrTemp; + std::set<CStealthAddress>::iterator it; + for (it = stealthAddresses.begin(); it != stealthAddresses.end(); + + it) + { + if (it->scan_secret.size() < 32) + continue; // stealth address is not owned + // -- CStealthAddress are only sorted on spend_pubkey + CStealthAddress &sxAddr = const_cast<CStealthAddress&>(*it); + if (fDebug) + printf("Recrypting stealth key %s\n", sxAddr.Encoded().c_str()); + + sxAddrTemp.scan_pubkey = sxAddr.scan_pubkey; + if (!wdb.ReadStealthAddress(sxAddrTemp)) + { + printf("Error: Failed to read stealth key from db %s\n", sxAddr.Encoded().c_str()); + continue; + } + sxAddr.spend_secret = sxAddrTemp.spend_secret; + }; + } + return LockKeyStore(); + };
Code added
+ UnlockStealthAddresses(vMasterKey);
Code added
- if (CCryptoKeyStore::Unlock(vMasterKey)) + if (CCryptoKeyStore::Unlock(vMasterKey)&& UnlockStealthAddresses(vMasterKey))
Code replaced
+ std::set<CStealthAddress>::iterator it; + for (it = stealthAddresses.begin(); it != stealthAddresses.end(); + + it) + { + if (it->scan_secret.size() < 32) + continue; // stealth address is not owned + // -- CStealthAddress is only sorted on spend_pubkey + CStealthAddress &sxAddr = const_cast<CStealthAddress&>(*it); + + if (fDebug) + printf("Encrypting stealth key %s\n", sxAddr.Encoded().c_str()); + + std::vector<unsigned char> vchCryptedSecret; + + CSecret vchSecret; + vchSecret.resize(32); + memcpy(&vchSecret[0], &sxAddr.spend_secret[0], 32); + + uint256 iv = Hash(sxAddr.spend_pubkey.begin(), sxAddr.spend_pubkey.end()); + if (!EncryptSecret(vMasterKey, vchSecret, iv, vchCryptedSecret)) + { + printf("Error: Failed encrypting stealth key %s\n", sxAddr.Encoded().c_str()); + continue; + }; + + sxAddr.spend_secret = vchCryptedSecret; + pwalletdbEncryption->WriteStealthAddress(sxAddr); + }; + +
Code added
+ + FindStealthTransactions(tx); +
Code added
-bool CWallet::CreateTransaction(const vector<pair<CScript, int64_t> >& vecSend, + bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) + CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, int32_t& nChangePos, std::string& strFailReason, const CCoinControl* coinControl)
Code replaced
- vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size()+1);
Code removed
+ vector<CTxOut>::iterator position = wtxNew.vout.begin() + GetRandInt(wtxNew.vout.size() + 1); + + if (position > wtxNew.vout.begin() && position < wtxNew.vout.end()) + { + while (position > wtxNew.vout.begin()) + { + if (position->nValue != 0) + break; + position--; + }; + }; wtxNew.vout.insert(position, newTxOut); + nChangePos = std::distance(wtxNew.vout.begin(), position);
Code added
- bool CWallet::CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl) + bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason, const CCoinControl* coinControl)
Code replaced
- return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, strFailReason, coinControl);
Code removed
+ int nChangePos; + string strError; + bool rv = CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, nChangePos, strError, coinControl); + return rv; + } + + bool CWallet::NewStealthAddress(std::string& sError, std::string& sLabel, CStealthAddress& sxAddr) + { + ec_secret scan_secret; + ec_secret spend_secret; + + if (GenerateRandomSecret(scan_secret) != 0 + || GenerateRandomSecret(spend_secret) != 0) + { + sError = "GenerateRandomSecret failed."; + printf("Error CWallet::NewStealthAddress - %s\n", sError.c_str()); + return false; + }; + + ec_point scan_pubkey, spend_pubkey; + if (SecretToPublicKey(scan_secret, scan_pubkey) != 0) + { + sError = "Could not get scan public key."; + printf("Error CWallet::NewStealthAddress - %s\n", sError.c_str()); + return false; + }; + + if (SecretToPublicKey(spend_secret, spend_pubkey) != 0) + { + sError = "Could not get spend public key."; + printf("Error CWallet::NewStealthAddress - %s\n", sError.c_str()); + return false; + }; + + if (fDebug)
Start of large section of code added from lines 1500 to 2128
+ FindStealthTransactions(wtxNew); +
Code added
+ LogPrintf("CommitTransaction start................\n"); + LogPrintf("CommitTransaction Broadcast start.............\n"); + LogPrintf("CommitTransaction RelayWalletTransaction............\n");
Code added for LofPrintf
- string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew)
Code replaced
+ //string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew) + string CWallet::SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee)
Code replaced
+ //if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired)) + if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending..."))) + return "ABORTED"; + + LogPrintf("SendMoney, scriptPubKey=%s \n",scriptPubKey.ToString()); +
Code added
-string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew) + //string CWallet::SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew) + string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
Code replaced
- return SendMoney(scriptPubKey, nValue, wtxNew); + LogPrintf("SendMoneyToDestination.....................\n"); + + return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
Code replaced
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/wallet.h
Large number of updates
+ #include "stealth.h" + typedef std::map<CKeyID, CStealthKeyMetadata> StealthKeyMetaMap; + typedef std::map<std::string, std::string> mapValue_t; + std::set<CStealthAddress> stealthAddresses; + StealthKeyMetaMap mapStealthKeyMeta; + uint32_t nStealth, nFoundStealth; // for reporting, zero before use + + bool Lock();
Code added
- bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); - bool CreateTransaction(CScript scriptPubKey, int64_t nValue, - CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); - std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew); - std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew);
Code replaced
+ /*bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, + CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);*/ + bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, + CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, int32_t& nChangePos, std::string& strFailReason, const CCoinControl *coinControl=NULL); + /*bool CreateTransaction(CScript scriptPubKey, int64_t nValue, + CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);*/ + bool CreateTransaction(CScript scriptPubKey, int64 nValue, + CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL); + bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey); + //std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew); + std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false); + //std::string SendMoneyToDestination(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew); + std::string SendMoneyToDestination(const CTxDestination& address, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false); + + bool NewStealthAddress(std::string& sError, std::string& sLabel, CStealthAddress& sxAddr); + bool AddStealthAddress(CStealthAddress& sxAddr); + bool UnlockStealthAddresses(const CKeyingMaterial& vMasterKeyIn); + bool UpdateStealthAddress(std::string &addr, std::string &label, bool addIfNotExist); + + bool CreateStealthTransaction(CScript scriptPubKey, int64_t nValue, std::vector<uint8_t>& P, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl* coinControl=NULL); + std::string SendStealthMoney(CScript scriptPubKey, int64_t nValue, std::vector<uint8_t>& P, CWalletTx& wtxNew, bool fAskFee=false); + bool SendStealthMoneyToDestination(CStealthAddress& sxAddress, int64_t nValue, CWalletTx& wtxNew, std::string& sError, bool fAskFee=false); + bool FindStealthTransactions(const CTransaction& tx); +
Replace code added
- typedef std::map<std::string, std::string> mapValue_t; + //typedef std::map<std::string, std::string> mapValue_t;
Code commented out?
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/walletdb.cpp
- else if (strType == "acentry") + { + if (fDebug) + printf("WalletDB ReadKeyValue sxAddr\n"); + + CStealthAddress sxAddr; + ssValue >> sxAddr; + + pwallet->stealthAddresses.insert(sxAddr); + } else if (strType == "acentry")
Code replaced
+ } else if (strType == "sxKeyMeta") + { + if (fDebug) + printf("WalletDB ReadKeyValue sxKeyMeta\n"); + + CKeyID keyId; + ssKey >> keyId; + CStealthKeyMetadata sxKeyMeta; + ssValue >> sxKeyMeta; + + pwallet->mapStealthKeyMeta[keyId] = sxKeyMeta;
Code added
-
Feathercoin specific changes made to convert Bitcoin to FTC 0.9.6.*
Add stealth address : - commit
https://github.com/FeatherCoin/Feathercoin/commit/e993143a1688a6aa57c03da6f181f8bf2f375bf6
src/walletdb.h
+#include "stealth.h"
Code added
+ class CStealthKeyMetadata + { + // -- used to get secret for keys created by stealth transaction with wallet locked + public: + CStealthKeyMetadata() {}; + + CStealthKeyMetadata(CPubKey pkEphem_, CPubKey pkScan_) + { + pkEphem = pkEphem_; + pkScan = pkScan_; + }; + + CPubKey pkEphem; + CPubKey pkScan; + + IMPLEMENT_SERIALIZE + ( + READWRITE(pkEphem); + READWRITE(pkScan); + ) + + }; +
Stealth class added
+ Dbc* GetAtCursor() + { + return GetCursor(); + } + + Dbc* GetTxnCursor() + { + if (!pdb) + return NULL; + + DbTxn* ptxnid = activeTxn; // call TxnBegin first + + Dbc* pcursor = NULL; + int ret = pdb->cursor(ptxnid, &pcursor, 0); + if (ret != 0) + return NULL; + return pcursor; + } + + DbTxn* GetAtActiveTxn() + { + return activeTxn; + } +
Code added
+ bool WriteStealthKeyMeta(const CKeyID& keyId, const CStealthKeyMetadata& sxKeyMeta) + { + nWalletDBUpdated + + ; + return Write(std::make_pair(std::string("sxKeyMeta"), keyId), sxKeyMeta, true); + } + + bool EraseStealthKeyMeta(const CKeyID& keyId) + { + nWalletDBUpdated + + ; + return Erase(std::make_pair(std::string("sxKeyMeta"), keyId)); + } + + bool WriteStealthAddress(const CStealthAddress& sxAddr) + { + nWalletDBUpdated + + ; + + return Write(std::make_pair(std::string("sxAddr"), sxAddr.scan_pubkey), sxAddr, true); + } + + bool ReadStealthAddress(CStealthAddress& sxAddr) + { + // -- set scan_pubkey before reading + return Read(std::make_pair(std::string("sxAddr"), sxAddr.scan_pubkey), sxAddr); + } +
Code added