From 3ac7a7af50343512bcd6e9e28bfcb5ea18cdfcc0 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 6 Jun 2019 11:50:25 -0400 Subject: [PATCH] compiling except missing height and isOutgoing fields which require accessors --- src/daemon/MoneroDaemon.h | 118 +++++++++++++------------- src/utils/MoneroUtils.cpp | 144 +++++++++++++++---------------- src/wallet/MoneroWallet.cpp | 165 +++++++++++++++++++----------------- src/wallet/MoneroWallet.h | 123 +++++++++++++++------------ 4 files changed, 286 insertions(+), 264 deletions(-) diff --git a/src/daemon/MoneroDaemon.h b/src/daemon/MoneroDaemon.h index 7719db5..9621765 100644 --- a/src/daemon/MoneroDaemon.h +++ b/src/daemon/MoneroDaemon.h @@ -21,7 +21,7 @@ namespace monero { /** * Models a connection to a daemon. * - * TODO: shared_ptr? + * TODO: boost::optional? */ struct MoneroRpcConnection { string uri; @@ -39,43 +39,43 @@ namespace monero { * Models a Monero transaction on the blockchain. */ struct MoneroTx { - shared_ptr block; - shared_ptr id; - shared_ptr version; - shared_ptr isCoinbase; - shared_ptr paymentId; - shared_ptr fee; - shared_ptr mixin; - shared_ptr doNotRelay; - shared_ptr isRelayed; - shared_ptr isConfirmed; - shared_ptr inTxPool; - shared_ptr numConfirmations; - shared_ptr unlockTime; - shared_ptr lastRelayedTimestamp; - shared_ptr receivedTimestamp; - shared_ptr isDoubleSpend; - shared_ptr key; - shared_ptr fullHex; - shared_ptr prunedHex; - shared_ptr prunableHex; - shared_ptr prunableHash; - shared_ptr size; - shared_ptr weight; + boost::optional> block; + boost::optional id; + boost::optional version; + boost::optional isCoinbase; + boost::optional paymentId; + boost::optional fee; + boost::optional mixin; + boost::optional doNotRelay; + boost::optional isRelayed; + boost::optional isConfirmed; + boost::optional inTxPool; + boost::optional numConfirmations; + boost::optional unlockTime; + boost::optional lastRelayedTimestamp; + boost::optional receivedTimestamp; + boost::optional isDoubleSpend; + boost::optional key; + boost::optional fullHex; + boost::optional prunedHex; + boost::optional prunableHex; + boost::optional prunableHash; + boost::optional size; + boost::optional weight; vector vins; vector vouts; vector outputIndices; - shared_ptr metadata; - shared_ptr commonTxSets; + boost::optional metadata; + boost::optional commonTxSets; vector extra; - shared_ptr rctSignatures; // TODO: implement - shared_ptr rctSigPrunable; // TODO: implement - shared_ptr isKeptByBlock; - shared_ptr isFailed; - shared_ptr lastFailedHeight; - shared_ptr lastFailedId; - shared_ptr maxUsedBlockHeight; - shared_ptr maxUsedBlockId; + boost::optional rctSignatures; // TODO: implement + boost::optional rctSigPrunable; // TODO: implement + boost::optional isKeptByBlock; + boost::optional isFailed; + boost::optional lastFailedHeight; + boost::optional lastFailedId; + boost::optional maxUsedBlockHeight; + boost::optional maxUsedBlockId; vector signatures; }; @@ -83,31 +83,31 @@ namespace monero { * Models a Monero block header which contains information about the block. */ struct MoneroBlockHeader { - shared_ptr id; - shared_ptr height; - shared_ptr timestamp; - shared_ptr size; - shared_ptr weight; - shared_ptr longTermWeight; - shared_ptr depth; - shared_ptr difficulty; - shared_ptr cumulativeDifficulty; - shared_ptr majorVersion; - shared_ptr minorVersion; - shared_ptr nonce; - shared_ptr coinbaseTxId; - shared_ptr numTxs; - shared_ptr orphanStatus; - shared_ptr prevId; - shared_ptr reward; + boost::optional id; + boost::optional height; + boost::optional timestamp; + boost::optional size; + boost::optional weight; + boost::optional longTermWeight; + boost::optional depth; + boost::optional difficulty; + boost::optional cumulativeDifficulty; + boost::optional majorVersion; + boost::optional minorVersion; + boost::optional nonce; + boost::optional coinbaseTxId; + boost::optional numTxs; + boost::optional orphanStatus; + boost::optional prevId; + boost::optional reward; }; /** * Models a Monero block in the blockchain. */ struct MoneroBlock : public MoneroBlockHeader { - shared_ptr hex; - shared_ptr coinbaseTx; + boost::optional hex; + boost::optional coinbaseTx; vector txs; vector txIds; }; @@ -116,8 +116,8 @@ namespace monero { * Models a Monero key image. */ struct MoneroKeyImage { - shared_ptr hex; - shared_ptr signature; + boost::optional hex; + boost::optional signature; }; /** @@ -125,11 +125,11 @@ namespace monero { */ struct MoneroOutput { shared_ptr tx; - shared_ptr keyImage; - shared_ptr amount; - shared_ptr index; + boost::optional keyImage; + boost::optional amount; + boost::optional index; vector ringOutputIndices; - shared_ptr stealthPublicKey; + boost::optional stealthPublicKey; }; } diff --git a/src/utils/MoneroUtils.cpp b/src/utils/MoneroUtils.cpp index 7ec0fbb..7f91de0 100644 --- a/src/utils/MoneroUtils.cpp +++ b/src/utils/MoneroUtils.cpp @@ -117,32 +117,32 @@ void MoneroUtils::binaryBlocksToJson(const std::string &bin, std::string &json) boost::property_tree::ptree MoneroUtils::toPropertyTree(const MoneroAccount& account) { cout << "toPropertyTree(account)" << endl; boost::property_tree::ptree accountNode; - if (account.index != nullptr) accountNode.put("index", *account.index); - if (account.primaryAddress != nullptr) accountNode.put("primaryAddress", *account.primaryAddress); - if (account.balance != nullptr) accountNode.put("balance", *account.balance); - if (account.unlockedBalance != nullptr) accountNode.put("unlockedBalance", *account.unlockedBalance); - if (!account.subaddresses.empty()) { - boost::property_tree::ptree subaddressesNode; - for (const auto& subaddress : account.subaddresses) { - subaddressesNode.push_back(std::make_pair("", toPropertyTree(subaddress))); - } - accountNode.add_child("subaddresses", subaddressesNode); - } +// if (account.index != nullptr) accountNode.put("index", *account.index); +// if (account.primaryAddress != nullptr) accountNode.put("primaryAddress", *account.primaryAddress); +// if (account.balance != nullptr) accountNode.put("balance", *account.balance); +// if (account.unlockedBalance != nullptr) accountNode.put("unlockedBalance", *account.unlockedBalance); +// if (!account.subaddresses.empty()) { +// boost::property_tree::ptree subaddressesNode; +// for (const auto& subaddress : account.subaddresses) { +// subaddressesNode.push_back(std::make_pair("", toPropertyTree(subaddress))); +// } +// accountNode.add_child("subaddresses", subaddressesNode); +// } return accountNode; } boost::property_tree::ptree MoneroUtils::toPropertyTree(const MoneroSubaddress& subaddress) { cout << "toPropertyTree(subaddress)" << endl; boost::property_tree::ptree subaddressNode; - if (subaddress.accountIndex != nullptr) subaddressNode.put("accountIndex", *subaddress.accountIndex); - if (subaddress.index != nullptr) subaddressNode.put("index", *subaddress.index); - if (subaddress.address != nullptr) subaddressNode.put("address", *subaddress.address); - if (subaddress.label != nullptr) subaddressNode.put("label", *subaddress.label); - if (subaddress.balance != nullptr) subaddressNode.put("balance", *subaddress.balance); - if (subaddress.unlockedBalance != nullptr) subaddressNode.put("unlockedBalance", *subaddress.unlockedBalance); - if (subaddress.numUnspentOutputs != nullptr) subaddressNode.put("numUnspentOutputs", *subaddress.numUnspentOutputs); - if (subaddress.isUsed != nullptr) subaddressNode.put("isUsed", *subaddress.isUsed); - if (subaddress.numBlocksToUnlock != nullptr) subaddressNode.put("numBlocksToUnlock", *subaddress.numBlocksToUnlock); +// if (subaddress.accountIndex != nullptr) subaddressNode.put("accountIndex", *subaddress.accountIndex); +// if (subaddress.index != nullptr) subaddressNode.put("index", *subaddress.index); +// if (subaddress.address != nullptr) subaddressNode.put("address", *subaddress.address); +// if (subaddress.label != nullptr) subaddressNode.put("label", *subaddress.label); +// if (subaddress.balance != nullptr) subaddressNode.put("balance", *subaddress.balance); +// if (subaddress.unlockedBalance != nullptr) subaddressNode.put("unlockedBalance", *subaddress.unlockedBalance); +// if (subaddress.numUnspentOutputs != nullptr) subaddressNode.put("numUnspentOutputs", *subaddress.numUnspentOutputs); +// if (subaddress.isUsed != nullptr) subaddressNode.put("isUsed", *subaddress.isUsed); +// if (subaddress.numBlocksToUnlock != nullptr) subaddressNode.put("numBlocksToUnlock", *subaddress.numBlocksToUnlock); return subaddressNode; } @@ -151,69 +151,69 @@ boost::property_tree::ptree MoneroUtils::toPropertyTree(const MoneroSubaddress& boost::property_tree::ptree MoneroUtils::txToPropertyTree(const MoneroTx& tx) { cout << "txToPropertyTree(tx)" << endl; boost::property_tree::ptree txNode; - if (tx.block != nullptr) throw runtime_error("not implemented"); // this should be ignored since we only serialize down the tree - if (tx.id != nullptr) txNode.put("id", *tx.id); - if (tx.version != nullptr) txNode.put("version", *tx.version); - if (tx.isCoinbase != nullptr) txNode.put("isCoinbase", *tx.isCoinbase); - if (tx.paymentId != nullptr) txNode.put("paymentId", *tx.paymentId); - if (tx.fee != nullptr) txNode.put("fee", *tx.fee); - if (tx.mixin != nullptr) txNode.put("mixin", *tx.mixin); - if (tx.doNotRelay != nullptr) txNode.put("doNotRelay", *tx.doNotRelay); - if (tx.isRelayed != nullptr) txNode.put("isRelayed", *tx.isRelayed); - if (tx.isConfirmed != nullptr) txNode.put("isConfirmed", *tx.isConfirmed); - if (tx.inTxPool != nullptr) txNode.put("inTxPool", *tx.inTxPool); - if (tx.numConfirmations != nullptr) txNode.put("numConfirmations", *tx.numConfirmations); - if (tx.unlockTime != nullptr) txNode.put("unlockTime", *tx.unlockTime); - if (tx.lastRelayedTimestamp != nullptr) txNode.put("lastRelayedTimestamp", *tx.lastRelayedTimestamp); - if (tx.receivedTimestamp != nullptr) txNode.put("receivedTimestamp", *tx.receivedTimestamp); - if (tx.isDoubleSpend != nullptr) txNode.put("isDoubleSpend", *tx.isDoubleSpend); - if (tx.key != nullptr) txNode.put("key", *tx.key); - if (tx.fullHex != nullptr) txNode.put("fullHex", *tx.fullHex); - if (tx.prunedHex != nullptr) txNode.put("prunedHex", *tx.prunedHex); - if (tx.prunableHex != nullptr) txNode.put("prunableHex", *tx.prunableHex); - if (tx.prunableHash != nullptr) txNode.put("prunableHash", *tx.prunableHash); - if (tx.size != nullptr) txNode.put("size", *tx.size); - if (tx.weight != nullptr) txNode.put("weight", *tx.weight); - if (!tx.vins.empty()) throw runtime_error("not implemented"); - if (!tx.vouts.empty()) throw runtime_error("not implemented"); - if (!tx.outputIndices.empty()) throw runtime_error("not implemented"); - if (tx.metadata != nullptr) txNode.put("metadata", *tx.metadata); - if (tx.commonTxSets != nullptr) throw runtime_error("not implemented"); - if (!tx.extra.empty()) throw runtime_error("not implemented"); - if (tx.rctSignatures != nullptr) throw runtime_error("not implemented"); - if (tx.rctSigPrunable != nullptr) throw runtime_error("not implemented"); - if (tx.isKeptByBlock != nullptr) txNode.put("isKeptByBlock", *tx.isKeptByBlock); - if (tx.isFailed != nullptr) txNode.put("isFailed", *tx.isFailed); - if (tx.lastFailedHeight != nullptr) txNode.put("lastFailedHeight", *tx.lastFailedHeight); - if (tx.lastFailedId != nullptr) txNode.put("lastFailedId", *tx.lastFailedId); - if (tx.maxUsedBlockHeight != nullptr) txNode.put("maxUsedBlockHeight", *tx.maxUsedBlockHeight); - if (tx.maxUsedBlockId != nullptr) txNode.put("maxUsedBlockId", *tx.maxUsedBlockId); - if (!tx.signatures.empty()) throw runtime_error("not implemented"); +// if (tx.block != nullptr) throw runtime_error("not implemented"); // this should be ignored since we only serialize down the tree +// if (tx.id != nullptr) txNode.put("id", *tx.id); +// if (tx.version != nullptr) txNode.put("version", *tx.version); +// if (tx.isCoinbase != nullptr) txNode.put("isCoinbase", *tx.isCoinbase); +// if (tx.paymentId != nullptr) txNode.put("paymentId", *tx.paymentId); +// if (tx.fee != nullptr) txNode.put("fee", *tx.fee); +// if (tx.mixin != nullptr) txNode.put("mixin", *tx.mixin); +// if (tx.doNotRelay != nullptr) txNode.put("doNotRelay", *tx.doNotRelay); +// if (tx.isRelayed != nullptr) txNode.put("isRelayed", *tx.isRelayed); +// if (tx.isConfirmed != nullptr) txNode.put("isConfirmed", *tx.isConfirmed); +// if (tx.inTxPool != nullptr) txNode.put("inTxPool", *tx.inTxPool); +// if (tx.numConfirmations != nullptr) txNode.put("numConfirmations", *tx.numConfirmations); +// if (tx.unlockTime != nullptr) txNode.put("unlockTime", *tx.unlockTime); +// if (tx.lastRelayedTimestamp != nullptr) txNode.put("lastRelayedTimestamp", *tx.lastRelayedTimestamp); +// if (tx.receivedTimestamp != nullptr) txNode.put("receivedTimestamp", *tx.receivedTimestamp); +// if (tx.isDoubleSpend != nullptr) txNode.put("isDoubleSpend", *tx.isDoubleSpend); +// if (tx.key != nullptr) txNode.put("key", *tx.key); +// if (tx.fullHex != nullptr) txNode.put("fullHex", *tx.fullHex); +// if (tx.prunedHex != nullptr) txNode.put("prunedHex", *tx.prunedHex); +// if (tx.prunableHex != nullptr) txNode.put("prunableHex", *tx.prunableHex); +// if (tx.prunableHash != nullptr) txNode.put("prunableHash", *tx.prunableHash); +// if (tx.size != nullptr) txNode.put("size", *tx.size); +// if (tx.weight != nullptr) txNode.put("weight", *tx.weight); +// if (!tx.vins.empty()) throw runtime_error("not implemented"); +// if (!tx.vouts.empty()) throw runtime_error("not implemented"); +// if (!tx.outputIndices.empty()) throw runtime_error("not implemented"); +// if (tx.metadata != nullptr) txNode.put("metadata", *tx.metadata); +// if (tx.commonTxSets != nullptr) throw runtime_error("not implemented"); +// if (!tx.extra.empty()) throw runtime_error("not implemented"); +// if (tx.rctSignatures != nullptr) throw runtime_error("not implemented"); +// if (tx.rctSigPrunable != nullptr) throw runtime_error("not implemented"); +// if (tx.isKeptByBlock != nullptr) txNode.put("isKeptByBlock", *tx.isKeptByBlock); +// if (tx.isFailed != nullptr) txNode.put("isFailed", *tx.isFailed); +// if (tx.lastFailedHeight != nullptr) txNode.put("lastFailedHeight", *tx.lastFailedHeight); +// if (tx.lastFailedId != nullptr) txNode.put("lastFailedId", *tx.lastFailedId); +// if (tx.maxUsedBlockHeight != nullptr) txNode.put("maxUsedBlockHeight", *tx.maxUsedBlockHeight); +// if (tx.maxUsedBlockId != nullptr) txNode.put("maxUsedBlockId", *tx.maxUsedBlockId); +// if (!tx.signatures.empty()) throw runtime_error("not implemented"); return txNode; } boost::property_tree::ptree MoneroUtils::txWalletToPropertyTree(const MoneroTxWallet& tx) { cout << "txWalletToPropertyTree(tx)" << endl; boost::property_tree::ptree txNode = txToPropertyTree(tx); - if (!tx.vouts.empty()) throw runtime_error("not implemented"); - if (!tx.incomingTransfers.empty()) throw runtime_error("not implemented"); - if (tx.outgoingTransfer != nullptr) throw runtime_error("not implemented"); - if (tx.numSuggestedConfirmations != nullptr) txNode.put("numSuggestedConfirmations", *tx.numSuggestedConfirmations); - if (tx.note != nullptr) txNode.put("note", *tx.note); +// if (!tx.vouts.empty()) throw runtime_error("not implemented"); +// if (!tx.incomingTransfers.empty()) throw runtime_error("not implemented"); +// if (tx.outgoingTransfer != nullptr) throw runtime_error("not implemented"); +// if (tx.numSuggestedConfirmations != nullptr) txNode.put("numSuggestedConfirmations", *tx.numSuggestedConfirmations); +// if (tx.note != nullptr) txNode.put("note", *tx.note); return txNode; } boost::property_tree::ptree MoneroUtils::txRequestToPropertyTree(const MoneroTxRequest& tx) { cout << "txWalletToPropertyTree(tx)" << endl; boost::property_tree::ptree txNode = txWalletToPropertyTree(tx); - if (tx.isOutgoing != nullptr) txNode.put("isOutgoing", *tx.isOutgoing); - if (tx.isIncoming != nullptr) txNode.put("isIncoming", *tx.isIncoming); - if (!tx.txIds.empty()) throw runtime_error("not implemented"); - if (tx.hasPaymentId != nullptr) txNode.put("hasPaymentId", *tx.hasPaymentId); - if (!tx.paymentIds.empty()) throw runtime_error("not implemented"); - if (tx.minHeight != nullptr) txNode.put("minHeight", *tx.minHeight); - if (tx.maxHeight != nullptr) txNode.put("maxHeight", *tx.maxHeight); - if (tx.includeOutputs != nullptr) txNode.put("includeOutputs", *tx.includeOutputs); - if (tx.transferRequest != nullptr) throw runtime_error("not implemented"); +// if (tx.isOutgoing != nullptr) txNode.put("isOutgoing", *tx.isOutgoing); +// if (tx.isIncoming != nullptr) txNode.put("isIncoming", *tx.isIncoming); +// if (!tx.txIds.empty()) throw runtime_error("not implemented"); +// if (tx.hasPaymentId != nullptr) txNode.put("hasPaymentId", *tx.hasPaymentId); +// if (!tx.paymentIds.empty()) throw runtime_error("not implemented"); +// if (tx.minHeight != nullptr) txNode.put("minHeight", *tx.minHeight); +// if (tx.maxHeight != nullptr) txNode.put("maxHeight", *tx.maxHeight); +// if (tx.includeOutputs != nullptr) txNode.put("includeOutputs", *tx.includeOutputs); +// if (tx.transferRequest != nullptr) throw runtime_error("not implemented"); return txNode; } diff --git a/src/wallet/MoneroWallet.cpp b/src/wallet/MoneroWallet.cpp index b4c0aaa..97ee482 100644 --- a/src/wallet/MoneroWallet.cpp +++ b/src/wallet/MoneroWallet.cpp @@ -14,8 +14,8 @@ namespace monero { // ---------------------------- PRIVATE HELPERS ----------------------------- - bool boolEquals(bool val, shared_ptr ptr) { - return ptr == nullptr ? false : val == *ptr; + bool boolEquals(bool val, boost::optional optVal) { + return optVal == boost::none ? false : val == *optVal; } MoneroTransfer wallet2ToTransfer(const crypto::hash &txid, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd) { @@ -32,30 +32,26 @@ namespace monero { public: - Wallet2Listener(MoneroWallet* wallet, shared_ptr wallet2) { - this->wallet = wallet; - this->wallet2 = wallet2; - this->listener = nullptr; - this->syncStartHeight = nullptr; - this->syncEndHeight = nullptr; - this->syncListener = nullptr; + Wallet2Listener(MoneroWallet& wallet, tools::wallet2& wallet2) : wallet(wallet), wallet2(wallet2) { + this->listener = boost::none; + this->syncStartHeight = boost::none; + this->syncEndHeight = boost::none; + this->syncListener = boost::none; } ~Wallet2Listener() { cout << "~Wallet2Listener()" << endl; - delete syncStartHeight; - delete syncEndHeight; } - void setWalletListener(MoneroWalletListener* listener) { + void setWalletListener(boost::optional listener) { this->listener = listener; updateListening(); } - void onSyncStart(uint64_t startHeight, MoneroSyncListener* syncListener) { - if (syncStartHeight != nullptr || syncEndHeight != nullptr) throw runtime_error("Sync start or end height should not already be allocated"); - syncStartHeight = new uint64_t(startHeight); - syncEndHeight = new uint64_t(wallet->getChainHeight() - 1); + void onSyncStart(uint64_t startHeight, boost::optional syncListener) { + if (syncStartHeight != boost::none || syncEndHeight != boost::none) throw runtime_error("Sync start or end height should not already be allocated, is previous sync in progress?"); + syncStartHeight = startHeight; + syncEndHeight = wallet.getChainHeight() - 1; this->syncListener = syncListener; updateListening(); @@ -65,50 +61,48 @@ namespace monero { if (numBlocksTotal < 1) return; // don't report 0% progress if no subsequent progress to report double percentDone = numBlocksDone / (double) numBlocksTotal; string message = string("Synchronizing"); - if (listener != nullptr) listener->onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); - if (syncListener != nullptr) syncListener->onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); + if (listener != boost::none) listener.get().onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); + if (syncListener != boost::none) syncListener.get().onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); } void onSyncEnd() { - delete syncStartHeight; - syncStartHeight = nullptr; - delete syncEndHeight; - syncEndHeight = nullptr; - syncListener = nullptr; + syncStartHeight = boost::none; + syncEndHeight = boost::none; + syncListener = boost::none; updateListening(); } virtual void on_new_block(uint64_t height, const cryptonote::block& cnBlock) { // notify listener of block - if (this->listener != nullptr) { + if (listener != boost::none) { MoneroBlock block; - block.height = shared_ptr(make_shared(height)); - listener->onNewBlock(block); + block.height = height; + listener.get().onNewBlock(block); } // notify listeners of sync progress - if (syncStartHeight != nullptr && height > *syncStartHeight) { + if (syncStartHeight != boost::none && height > *syncStartHeight) { if (height > *syncEndHeight) *syncEndHeight = height; // increase end height if necessary uint64_t numBlocksDone = height - *syncStartHeight + 1; uint64_t numBlocksTotal = *syncEndHeight - *syncStartHeight + 1; double percentDone = numBlocksDone / (double) numBlocksTotal; string message = string("Synchronizing"); - if (this->listener != nullptr) this->listener->onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); - if (this->syncListener != nullptr) this->syncListener->onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); + if (listener != boost::none) listener.get().onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); + if (syncListener != boost::none) syncListener.get().onSyncProgress(*syncStartHeight, numBlocksDone, numBlocksTotal, percentDone, message); } } private: - MoneroWallet* wallet; - shared_ptr wallet2; - MoneroWalletListener* listener; - uint64_t* syncStartHeight; - uint64_t* syncEndHeight; - MoneroSyncListener* syncListener; + MoneroWallet& wallet; // wallet to inform notifications + tools::wallet2& wallet2; // internal wallet implementation to listen to + boost::optional listener; // listener to invoke with notifications + boost::optional syncStartHeight; + boost::optional syncEndHeight; + boost::optional syncListener; void updateListening() { - wallet2->callback(listener == nullptr && syncListener == nullptr ? nullptr : this); + wallet2.callback(listener == boost::none && syncListener == boost::none ? nullptr : this); } }; @@ -122,19 +116,19 @@ namespace monero { return walletFileExists; } - MoneroWallet::MoneroWallet(const string& path, const string&password) { + MoneroWallet::MoneroWallet(const string& path, const string& password) { cout << "MoneroWallet()" << endl; throw runtime_error("Not implemented"); } MoneroWallet::MoneroWallet(const string& path, const string&password, const MoneroNetworkType networkType, const MoneroRpcConnection& daemonConnection, const string& language) { cout << "MoneroWallet(3)" << endl; - wallet2 = shared_ptr(new tools::wallet2(static_cast(networkType), 1, true)); + wallet2 = unique_ptr(new tools::wallet2(static_cast(networkType), 1, true)); setDaemonConnection(daemonConnection.uri, daemonConnection.username, daemonConnection.password); wallet2->set_seed_language(language); crypto::secret_key recovery_val, secret_key; wallet2->generate(path, password, secret_key, false, false); - wallet2Listener = unique_ptr(new Wallet2Listener(this, wallet2)); + wallet2Listener = unique_ptr(new Wallet2Listener(*this, *wallet2)); } MoneroWallet::MoneroWallet(const string& path, const string& password, const string& mnemonic, const MoneroNetworkType networkType, const MoneroRpcConnection& daemonConnection, uint64_t restoreHeight) { @@ -147,11 +141,11 @@ namespace monero { if (language == crypto::ElectrumWords::old_language_name) language = Language::English().get_language_name(); // initialize wallet - wallet2 = shared_ptr(new tools::wallet2(static_cast(networkType), 1, true)); + wallet2 = unique_ptr(new tools::wallet2(static_cast(networkType), 1, true)); wallet2->set_seed_language(language); wallet2->generate(path, password, recoveryKey, true, false); wallet2->set_refresh_from_block_height(restoreHeight); - wallet2Listener = unique_ptr(new Wallet2Listener(this, wallet2)); + wallet2Listener = unique_ptr(new Wallet2Listener(*this, *wallet2)); // print the mnemonic epee::wipeable_string fetchedMnemonic; @@ -166,9 +160,9 @@ namespace monero { MoneroWallet::MoneroWallet(const string& path, const string& password, const MoneroNetworkType networkType) { cout << "MoneroWallet(3b)" << endl; - wallet2 = shared_ptr(new tools::wallet2(static_cast(networkType), 1, true)); + wallet2 = unique_ptr(new tools::wallet2(static_cast(networkType), 1, true)); wallet2->load(path, password); - wallet2Listener = unique_ptr(new Wallet2Listener(this, wallet2)); + wallet2Listener = unique_ptr(new Wallet2Listener(*this, *wallet2)); } MoneroWallet::~MoneroWallet() { @@ -177,6 +171,7 @@ namespace monero { } // TODO: switch this to setDaemonConnection(MoneroDaemonRpc& daemonConnection) + // TODO: actually setDaemonConnection(boost::optional& connection) void MoneroWallet::setDaemonConnection(const string& uri, const string& username, const string& password) { cout << "setDaemonConnection(" << uri << ", " << username << ", " << password << ")" << endl; @@ -237,8 +232,8 @@ namespace monero { // return indices in subaddress MoneroSubaddress subaddress; cryptonote::subaddress_index cnIndex = *index; - subaddress.accountIndex = shared_ptr(make_shared(cnIndex.major)); - subaddress.index = shared_ptr(make_shared(cnIndex.minor)); + subaddress.accountIndex = cnIndex.major; + subaddress.index = cnIndex.minor; return subaddress; } @@ -248,29 +243,29 @@ namespace monero { return string(wipeablePassword.data(), wipeablePassword.size()); } - void MoneroWallet::setListener(MoneroWalletListener* listener) { + void MoneroWallet::setListener(boost::optional listener) { cout << "setListener()" << endl; wallet2Listener->setWalletListener(listener); } MoneroSyncResult MoneroWallet::sync() { cout << "sync()" << endl; - return syncAux(nullptr, nullptr, nullptr); + return syncAux(boost::none, boost::none, boost::none); } MoneroSyncResult MoneroWallet::sync(MoneroSyncListener& listener) { cout << "sync(startHeight)" << endl; - return syncAux(nullptr, nullptr, &listener); + return syncAux(boost::none, boost::none, listener); } MoneroSyncResult MoneroWallet::sync(uint64_t startHeight) { cout << "sync(startHeight)" << endl; - return syncAux(&startHeight, nullptr, nullptr); + return syncAux(startHeight, boost::none, boost::none); } MoneroSyncResult MoneroWallet::sync(uint64_t startHeight, MoneroSyncListener& listener) { cout << "sync(startHeight, listener)" << endl; - return syncAux(&startHeight, nullptr, &listener); + return syncAux(startHeight, boost::none, listener); } // rescanBlockchain @@ -330,12 +325,12 @@ namespace monero { throw runtime_error("Not implemented"); } - vector MoneroWallet::getAccounts(const string tag) const { + vector MoneroWallet::getAccounts(const string& tag) const { cout << "getAccounts(" << tag << ")" << endl; throw runtime_error("Not implemented"); } - vector MoneroWallet::getAccounts(const bool includeSubaddresses, const string tag) const { + vector MoneroWallet::getAccounts(const bool includeSubaddresses, const string& tag) const { cout << "getAccounts(" << includeSubaddresses << ", " << tag << ")" << endl; // need transfers to inform if subaddresses used @@ -346,10 +341,10 @@ namespace monero { vector accounts; for (uint32_t accountIdx = 0; accountIdx < wallet2->get_num_subaddress_accounts(); accountIdx++) { MoneroAccount account; - account.index = shared_ptr(make_shared(accountIdx)); - account.primaryAddress = shared_ptr(make_shared(getAddress(accountIdx, 0))); - account.balance = shared_ptr(make_shared(wallet2->balance(accountIdx))); - account.unlockedBalance = shared_ptr(make_shared(wallet2->unlocked_balance(accountIdx))); + account.index = accountIdx; + account.primaryAddress = getAddress(accountIdx, 0); + account.balance = wallet2->balance(accountIdx); + account.unlockedBalance = wallet2->unlocked_balance(accountIdx); if (includeSubaddresses) account.subaddresses = getSubaddressesAux(accountIdx, vector(), transfers); accounts.push_back(account); } @@ -370,15 +365,19 @@ namespace monero { // build and return account MoneroAccount account; - account.index = shared_ptr(make_shared(accountIdx)); - account.primaryAddress = shared_ptr(make_shared(getAddress(accountIdx, 0))); - account.balance = shared_ptr(make_shared(wallet2->balance(accountIdx))); - account.unlockedBalance = shared_ptr(make_shared(wallet2->unlocked_balance(accountIdx))); + account.index = accountIdx; + account.primaryAddress = getAddress(accountIdx, 0); + account.balance = wallet2->balance(accountIdx); + account.unlockedBalance = wallet2->unlocked_balance(accountIdx); if (includeSubaddresses) account.subaddresses = getSubaddressesAux(accountIdx, vector(), transfers); return account; } - MoneroAccount MoneroWallet::createAccount(const string label) { + MoneroAccount MoneroWallet::createAccount() { + throw runtime_error("Not implemented"); + } + + MoneroAccount MoneroWallet::createAccount(const string& label) { throw runtime_error("Not implemented"); } @@ -418,18 +417,18 @@ namespace monero { // initialize subaddresses at indices for (uint32_t subaddressIndicesIdx = 0; subaddressIndicesIdx < subaddressIndices.size(); subaddressIndicesIdx++) { MoneroSubaddress subaddress; - subaddress.accountIndex = shared_ptr(make_shared(accountIdx)); + subaddress.accountIndex = accountIdx; uint32_t subaddressIdx = subaddressIndices.at(subaddressIndicesIdx); - subaddress.index = shared_ptr(make_shared(subaddressIdx)); - subaddress.address = shared_ptr(make_shared(getAddress(accountIdx, subaddressIdx))); + subaddress.index = subaddressIdx; + subaddress.address = getAddress(accountIdx, subaddressIdx); auto iter1 = balancePerSubaddress.find(subaddressIdx); - subaddress.balance = shared_ptr(make_shared(iter1 == balancePerSubaddress.end() ? 0 : iter1->second)); + subaddress.balance = iter1 == balancePerSubaddress.end() ? 0 : iter1->second; auto iter2 = unlockedBalancePerSubaddress.find(subaddressIdx); - subaddress.unlockedBalance = shared_ptr(make_shared(iter2 == unlockedBalancePerSubaddress.end() ? 0 : iter2->second.first)); - subaddress.numBlocksToUnlock = shared_ptr(make_shared(iter2 == unlockedBalancePerSubaddress.end() ? 0 : iter2->second.second)); + subaddress.unlockedBalance = iter2 == unlockedBalancePerSubaddress.end() ? 0 : iter2->second.first; + subaddress.numBlocksToUnlock = iter2 == unlockedBalancePerSubaddress.end() ? 0 : iter2->second.second; cryptonote::subaddress_index index = {accountIdx, subaddressIdx}; - subaddress.numUnspentOutputs = shared_ptr(make_shared(count_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == index; }))); - subaddress.isUsed = shared_ptr(make_shared(find_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return td.m_subaddr_index == index; }) != transfers.end())); + subaddress.numUnspentOutputs = count_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return !td.m_spent && td.m_subaddr_index == index; }); + subaddress.isUsed = find_if(transfers.begin(), transfers.end(), [&](const tools::wallet2::transfer_details& td) { return td.m_subaddr_index == index; }) != transfers.end(); subaddresses.push_back(subaddress); } @@ -440,7 +439,11 @@ namespace monero { throw runtime_error("Not implemented"); } - MoneroSubaddress MoneroWallet::createSubaddress(const uint32_t accountIdx, const string label) { + MoneroSubaddress MoneroWallet::createSubaddress(const uint32_t accountIdx) { + throw runtime_error("Not implemented"); + } + + MoneroSubaddress MoneroWallet::createSubaddress(const uint32_t accountIdx, const string& label) { throw runtime_error("Not implemented"); } @@ -470,15 +473,17 @@ namespace monero { vector MoneroWallet::getTransfers(const MoneroTransferRequest& request) const { cout << "getTransfers(request)" << endl; - // normalize transfer request - if (request.txRequest == nullptr) request.txRequest = shared_ptr(make_shared(MoneroTxRequest())); - MoneroTxRequest& txReq = *request.txRequest; + // normalize request + MoneroTxRequest txReq = *(request.txRequest != boost::none ? *request.txRequest : shared_ptr(make_shared(MoneroTxRequest()))); + + //MoneroTxRequest txReq = MoneroTxRequest(); + //if (request.txRequest != boost::none) txReq = **request.txRequest; // build parameters for wallet2->get_payments() - uint64_t minHeight = txReq.minHeight == nullptr ? 0 : *txReq.minHeight; - uint64_t maxHeight = txReq.maxHeight == nullptr ? CRYPTONOTE_MAX_BLOCK_NUMBER : min((uint64_t) CRYPTONOTE_MAX_BLOCK_NUMBER, *txReq.maxHeight); + uint64_t minHeight = txReq.minHeight == boost::none ? 0 : *txReq.minHeight; + uint64_t maxHeight = txReq.maxHeight == boost::none ? CRYPTONOTE_MAX_BLOCK_NUMBER : min((uint64_t) CRYPTONOTE_MAX_BLOCK_NUMBER, *txReq.maxHeight); boost::optional accountIndex = boost::none; - if (request.accountIndex != nullptr) accountIndex = *request.accountIndex; + if (request.accountIndex != boost::none) accountIndex = *request.accountIndex; std::set subaddressIndices; for (int i = 0; i < request.subaddressIndices.size(); i++) { subaddressIndices.insert(request.subaddressIndices[i]); @@ -489,7 +494,7 @@ namespace monero { // translate from MoneroTxRequest to in, out, pending, pool, failed terminology bool canBeConfirmed = !boolEquals(false, txReq.isConfirmed) && !boolEquals(true, txReq.inTxPool) && !boolEquals(true, txReq.isFailed) && !boolEquals(false, txReq.isRelayed); - bool canBeInTxPool = !boolEquals(true, txReq.isConfirmed) && !boolEquals(false, txReq.inTxPool) && !boolEquals(true, txReq.isFailed) && !boolEquals(false, txReq.isRelayed) && txReq.height == nullptr && txReq.minHeight == nullptr; + bool canBeInTxPool = !boolEquals(true, txReq.isConfirmed) && !boolEquals(false, txReq.inTxPool) && !boolEquals(true, txReq.isFailed) && !boolEquals(false, txReq.isRelayed) && txReq.height == boost::none && txReq.minHeight == boost::none; bool canBeIncoming = !boolEquals(false, request.isIncoming) && !boolEquals(true, request.isOutgoing) && !boolEquals(true, request.hasDestinations); bool canBeOutgoing = !boolEquals(false, request.isOutgoing) && !boolEquals(true, request.isIncoming); bool isIn = canBeIncoming && canBeConfirmed; @@ -557,14 +562,14 @@ namespace monero { // ------------------------------- PRIVATE HELPERS ---------------------------- - MoneroSyncResult MoneroWallet::syncAux(uint64_t* startHeight, uint64_t* endHeight, MoneroSyncListener* listener) { + MoneroSyncResult MoneroWallet::syncAux(boost::optional startHeight, boost::optional endHeight, boost::optional listener) { cout << "syncAux()" << endl; // validate inputs - if (endHeight != nullptr) throw runtime_error("Monero core wallet does not support syncing to an end height"); // TODO: custom exception type + if (endHeight != boost::none) throw runtime_error("Monero core wallet does not support syncing to an end height"); // TODO: custom exception type // determine sync start height - uint64_t syncStartHeight = startHeight == nullptr ? max(getHeight(), getRestoreHeight()) : *startHeight; + uint64_t syncStartHeight = startHeight == boost::none ? max(getHeight(), getRestoreHeight()) : *startHeight; // sync wallet wallet2Listener->onSyncStart(syncStartHeight, listener); diff --git a/src/wallet/MoneroWallet.h b/src/wallet/MoneroWallet.h index 57d1431..c620850 100644 --- a/src/wallet/MoneroWallet.h +++ b/src/wallet/MoneroWallet.h @@ -27,15 +27,15 @@ namespace monero { * Models a Monero subaddress. */ struct MoneroSubaddress { - shared_ptr accountIndex; - shared_ptr index; - shared_ptr address; - shared_ptr label; - shared_ptr balance; - shared_ptr unlockedBalance; - shared_ptr numUnspentOutputs; - shared_ptr isUsed; - shared_ptr numBlocksToUnlock; + boost::optional accountIndex; + boost::optional index; + boost::optional address; + boost::optional label; + boost::optional balance; + boost::optional unlockedBalance; + boost::optional numUnspentOutputs; + boost::optional isUsed; + boost::optional numBlocksToUnlock; // BEGIN_KV_SERIALIZE_MAP() // KV_SERIALIZE_OPT_N(accountIndex, "accountIndex", nullptr) // KV_SERIALIZE_OPT_N(index, "index", nullptr) @@ -53,12 +53,12 @@ namespace monero { * Models a Monero account. */ struct MoneroAccount { - shared_ptr index = nullptr; - shared_ptr primaryAddress = nullptr; - shared_ptr label; - shared_ptr balance; - shared_ptr unlockedBalance; - shared_ptr tag; + boost::optional index; + boost::optional primaryAddress; + boost::optional label; + boost::optional balance; + boost::optional unlockedBalance; + boost::optional tag; vector subaddresses; // BEGIN_KV_SERIALIZE_MAP() // KV_SERIALIZE_OPT_N(index, "index", nullptr) @@ -79,8 +79,8 @@ namespace monero { * Models an outgoing transfer destination. */ struct MoneroDestination { - shared_ptr address; - shared_ptr amount; + boost::optional address; + boost::optional amount; }; /** @@ -88,17 +88,17 @@ namespace monero { */ struct MoneroTransfer { shared_ptr tx; - shared_ptr amount; - shared_ptr accountIndex; - shared_ptr isIncoming; + boost::optional amount; + boost::optional accountIndex; + boost::optional isIncoming; }; /** * Models an incoming transfer of funds to the wallet. */ struct MoneroIncomingTransfer : public MoneroTransfer { - shared_ptr subaddressIndex; - shared_ptr address; + boost::optional subaddressIndex; + boost::optional address; }; /** @@ -114,11 +114,11 @@ namespace monero { * Models a Monero output with wallet extensions. */ struct MoneroOutputWallet : public MoneroOutput { - shared_ptr accountIndex; - shared_ptr subaddressIndex; - shared_ptr isSpent; - shared_ptr isUnlocked; - shared_ptr isFrozen; + boost::optional accountIndex; + boost::optional subaddressIndex; + boost::optional isSpent; + boost::optional isUnlocked; + boost::optional isFrozen; }; /** @@ -127,9 +127,9 @@ namespace monero { struct MoneroTxWallet : public MoneroTx { vector vouts; // TODO: override vouts with different type? vector incomingTransfers; - shared_ptr outgoingTransfer; - shared_ptr numSuggestedConfirmations; - shared_ptr note; + boost::optional outgoingTransfer; + boost::optional numSuggestedConfirmations; + boost::optional note; }; /** @@ -138,14 +138,14 @@ namespace monero { * All transfers are returned except those that do not meet the criteria defined in this request. */ struct MoneroTransferRequest : public MoneroTransfer { - shared_ptr isIncoming; - shared_ptr address; + boost::optional isIncoming; + boost::optional address; vector addresses; - shared_ptr subaddressIndex; + boost::optional subaddressIndex; vector subaddressIndices; vector destinations; - shared_ptr hasDestinations; - shared_ptr txRequest; + boost::optional hasDestinations; + boost::optional> txRequest; }; /** @@ -154,15 +154,15 @@ namespace monero { * All transactions are returned except those that do not meet the criteria defined in this request. */ struct MoneroTxRequest : public MoneroTxWallet { - shared_ptr isOutgoing; - shared_ptr isIncoming; + boost::optional isOutgoing; + boost::optional isIncoming; vector txIds; - shared_ptr hasPaymentId; + boost::optional hasPaymentId; vector paymentIds; - shared_ptr minHeight; - shared_ptr maxHeight; - shared_ptr includeOutputs; - shared_ptr transferRequest; + boost::optional minHeight; + boost::optional maxHeight; + boost::optional includeOutputs; + boost::optional transferRequest; }; /** @@ -173,7 +173,7 @@ namespace monero { */ struct MoneroOutputRequest : public MoneroOutput { vector subaddressIndices; - shared_ptr txRequest; + boost::optional txRequest; }; // --------------------------------- LISTENERS ------------------------------ @@ -213,6 +213,8 @@ namespace monero { /** * Invoked when sync progress is made. * + * TODO: const uint64_t& startHeight, etc...? + * * @param startHeight is the starting height of the sync request * @param numBlocksDone is the number of blocks synced * @param numBlocksTotal is the total number of blocks to sync @@ -421,7 +423,7 @@ namespace monero { // */ // virtual MoneroIntegratedAddress decodeIntegratedAddress(const string& integratedAddress = "") const; - void setListener(MoneroWalletListener* listener); + void setListener(boost::optional listener); MoneroSyncResult sync(); @@ -533,7 +535,7 @@ namespace monero { * @param tag is the tag for filtering accounts, all accounts if null * @return List are all accounts for the wallet with the given tag */ - vector getAccounts(const string tag) const; + vector getAccounts(const string& tag) const; /** * Get accounts with a given tag. @@ -542,7 +544,7 @@ namespace monero { * @param tag is the tag for filtering accounts, all accounts if null * @return List are all accounts for the wallet with the given tag */ - vector getAccounts(const bool includeSubaddresses, const string tag) const; + vector getAccounts(const bool includeSubaddresses, const string& tag) const; /** * Get an account without subaddress information. @@ -561,13 +563,20 @@ namespace monero { */ MoneroAccount getAccount(const uint32_t accountIdx, const bool includeSubaddresses) const; + /** + * Create a new account. + * + * @return the created account + */ + MoneroAccount createAccount(); + /** * Create a new account. * * @param label specifies the label for the account (optional) * @return the created account */ - MoneroAccount createAccount(const string label = ""); + MoneroAccount createAccount(const string& label); /** * Get all subaddresses in an account. @@ -599,10 +608,18 @@ namespace monero { * Create a subaddress within an account. * * @param accountIdx specifies the index of the account to create the subaddress within - * @param label specifies the the label for the subaddress (optional) * @return the created subaddress */ - MoneroSubaddress createSubaddress(uint32_t accountIdx, const string label = ""); + MoneroSubaddress createSubaddress(uint32_t accountIdx); + + /** + * Create a subaddress within an account. + * + * @param accountIdx specifies the index of the account to create the subaddress within + * @param label specifies the the label for the subaddress + * @return the created subaddress + */ + MoneroSubaddress createSubaddress(uint32_t accountIdx, const string& label); // /** // * Get a wallet transaction by id. @@ -1221,11 +1238,11 @@ namespace monero { private: friend struct Wallet2Listener; - shared_ptr wallet2; // internal wallet implementation - unique_ptr wallet2Listener; // listener for internal wallet implementation - MoneroWalletListener* listener; // wallet's external listener + unique_ptr wallet2; // internal wallet implementation + unique_ptr wallet2Listener; // listener for internal wallet implementation + boost::optional listener = boost::none; // wallet's external listener - MoneroSyncResult syncAux(uint64_t* startHeight, uint64_t* endHeight, MoneroSyncListener* listener); + MoneroSyncResult syncAux(boost::optional startHeight, boost::optional endHeight, boost::optional listener); vector getSubaddressesAux(uint32_t accountIdx, vector subaddressIndices, vector transfers) const; }; }