From 240b454860b036d36da7c9a25e47b75bdc1f698f Mon Sep 17 00:00:00 2001 From: woodser Date: Mon, 18 Nov 2019 21:04:47 -0500 Subject: [PATCH 01/34] update to v15.x api; add randomx lib dependency --- CMakeLists.txt | 7 +++++++ src/utils/monero_utils.cpp | 2 +- src/wallet/monero_wallet.cpp | 36 +++++++++++++++++++++--------------- src/wallet/monero_wallet.h | 5 +++-- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe8804e..52e5063 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -221,6 +221,10 @@ set_target_properties(multisig PROPERTIES IMPORTED_LOCATION add_library(version STATIC IMPORTED) set_target_properties(version PROPERTIES IMPORTED_LOCATION ${EXTERNAL_LIBS_DIR}/monero-core/libversion.a) + +add_library(randomx STATIC IMPORTED) +set_target_properties(randomx PROPERTIES IMPORTED_LOCATION + ${EXTERNAL_LIBS_DIR}/monero-core/librandomx.a) ######################## # Build c++ library @@ -278,6 +282,7 @@ target_link_libraries(monero-cpp device_trezor multisig version + randomx ${EXTRA_LIBRARIES} ) @@ -335,6 +340,7 @@ target_link_libraries(sample_code device_trezor multisig version + randomx ${EXTRA_LIBRARIES} ) @@ -394,6 +400,7 @@ target_link_libraries(scratchpad device_trezor multisig version + randomx ${EXTRA_LIBRARIES} ) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index e977182..b1fc298 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -290,7 +290,7 @@ void monero_utils::binary_blocks_to_json(const std::string &bin, std::string &js boost::property_tree::ptree txsNode; for (int txIdx = 0; txIdx < resp_struct.blocks[blockIdx].txs.size(); txIdx++) { cryptonote::transaction tx; - if (cryptonote::parse_and_validate_tx_from_blob(resp_struct.blocks[blockIdx].txs[txIdx], tx)) { + if (cryptonote::parse_and_validate_tx_from_blob(resp_struct.blocks[blockIdx].txs[txIdx].blob, tx)) { // add tx node to txs node boost::property_tree::ptree txNode; diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index b7e99a9..91a223f 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -78,6 +78,7 @@ namespace monero { static const int DEFAULT_SYNC_INTERVAL_MILLIS = 1000 * 10; // default refresh interval 10 sec static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 30; // default connection timeout 30 sec + static const bool STRICT = false; // relies exclusively on blockchain data if true, includes local wallet data if false TODO: good use case to expose externally? // ----------------------- INTERNAL PRIVATE HELPERS ----------------------- @@ -1249,29 +1250,29 @@ namespace monero { // isMultisigImportNeeded uint64_t monero_wallet::get_balance() const { - return m_w2->balance_all(); + return m_w2->balance_all(STRICT); } uint64_t monero_wallet::get_balance(uint32_t account_idx) const { - return m_w2->balance(account_idx); + return m_w2->balance(account_idx, STRICT); } uint64_t monero_wallet::get_balance(uint32_t account_idx, uint32_t subaddress_idx) const { - map balance_per_subaddress = m_w2->balance_per_subaddress(account_idx); + map balance_per_subaddress = m_w2->balance_per_subaddress(account_idx, STRICT); auto iter = balance_per_subaddress.find(subaddress_idx); return iter == balance_per_subaddress.end() ? 0 : iter->second; } uint64_t monero_wallet::get_unlocked_balance() const { - return m_w2->unlocked_balance_all(); + return m_w2->unlocked_balance_all(STRICT); } uint64_t monero_wallet::get_unlocked_balance(uint32_t account_idx) const { - return m_w2->unlocked_balance(account_idx); + return m_w2->unlocked_balance(account_idx, STRICT); } uint64_t monero_wallet::get_unlocked_balance(uint32_t account_idx, uint32_t subaddress_idx) const { - map> unlocked_balance_per_subaddress = m_w2->unlocked_balance_per_subaddress(account_idx); + map> unlocked_balance_per_subaddress = m_w2->unlocked_balance_per_subaddress(account_idx, STRICT); auto iter = unlocked_balance_per_subaddress.find(subaddress_idx); return iter == unlocked_balance_per_subaddress.end() ? 0 : iter->second.first; } @@ -1304,8 +1305,8 @@ namespace monero { monero_account account; account.m_index = account_idx; account.m_primary_address = get_address(account_idx, 0); - account.m_balance = m_w2->balance(account_idx); - account.m_unlocked_balance = m_w2->unlocked_balance(account_idx); + account.m_balance = m_w2->balance(account_idx, STRICT); + account.m_unlocked_balance = m_w2->unlocked_balance(account_idx, STRICT); if (include_subaddresses) account.m_subaddresses = get_subaddresses_aux(account_idx, vector(), transfers); accounts.push_back(account); } @@ -1328,8 +1329,8 @@ namespace monero { monero_account account; account.m_index = account_idx; account.m_primary_address = get_address(account_idx, 0); - account.m_balance = m_w2->balance(account_idx); - account.m_unlocked_balance = m_w2->unlocked_balance(account_idx); + account.m_balance = m_w2->balance(account_idx, STRICT); + account.m_unlocked_balance = m_w2->unlocked_balance(account_idx, STRICT); if (include_subaddresses) account.m_subaddresses = get_subaddresses_aux(account_idx, vector(), transfers); return account; } @@ -1592,7 +1593,12 @@ namespace monero { // get unconfirmed incoming transfers if (is_pool) { - m_w2->update_pool_state(); // TODO monero-core: this should be encapsulated in wallet when unconfirmed transfers queried + + // update pool state TODO monero-core: this should be encapsulated in wallet when unconfirmed transfers queried + std::vector> process_txs; + m_w2->update_pool_state(process_txs); + if (!process_txs.empty()) m_w2->process_pool_state(process_txs); + std::list> payments; m_w2->get_unconfirmed_payments(payments, account_index, subaddress_indices); for (std::list>::const_iterator i = payments.begin(); i != payments.end(); ++i) { @@ -2669,8 +2675,8 @@ namespace monero { return send_request; } - string monero_wallet::get_attribute(const string& key) const { - return m_w2->get_attribute(key); + bool monero_wallet::get_attribute(const string& key, string& value) const { + return m_w2->get_attribute(key, value); } void monero_wallet::set_attribute(const string& key, const string& val) { @@ -2964,8 +2970,8 @@ namespace monero { vector subaddresses; // get balances per subaddress as maps - map balance_per_subaddress = m_w2->balance_per_subaddress(account_idx); - map> unlocked_balance_per_subaddress = m_w2->unlocked_balance_per_subaddress(account_idx); + map balance_per_subaddress = m_w2->balance_per_subaddress(account_idx, STRICT); + map> unlocked_balance_per_subaddress = m_w2->unlocked_balance_per_subaddress(account_idx, STRICT); // get all indices if no indices given vector subaddress_indices_req; diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 40b7e34..2dd6928 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1243,9 +1243,10 @@ namespace monero { * Get an attribute. * * @param key is the attribute to get the value of - * @return the attribute's value + * @param value is set to the key's value if set + * @return true if the key's value has been set, false otherwise */ - string get_attribute(const string& key) const; + bool get_attribute(const string& key, string& value) const; /** * Set an arbitrary attribute. From 6041e12be8f37c6047d97e484fa1466291e25d17 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 21 Nov 2019 12:02:03 -0500 Subject: [PATCH 02/34] set monero_tx_wallet.m_is_unlocked in monero_wallet --- src/wallet/monero_wallet.cpp | 4 ++++ src/wallet/monero_wallet_model.h | 1 + 2 files changed, 5 insertions(+) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 91a223f..b69308b 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -102,6 +102,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_unlock_time; + tx->m_is_unlocked = m_w2.is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); tx->m_fee = pd.m_fee; tx->m_note = m_w2.get_tx_note(pd.m_tx_hash); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -153,6 +154,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_unlock_time; + tx->m_is_unlocked = m_w2.is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); tx->m_fee = pd.m_amount_in - pd.m_amount_out; tx->m_note = m_w2.get_tx_note(txid); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -219,6 +221,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_unlock_time; + tx->m_is_unlocked = false; tx->m_fee = pd.m_fee; tx->m_note = m_w2.get_tx_note(pd.m_tx_hash); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -259,6 +262,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_tx.unlock_time; + tx->m_is_unlocked = false; tx->m_fee = pd.m_amount_in - pd.m_amount_out; tx->m_note = m_w2.get_tx_note(txid); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 3b473ba..0446524 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -261,6 +261,7 @@ namespace monero { vector> m_incoming_transfers; boost::optional> m_outgoing_transfer; boost::optional m_note; + boost::optional m_is_unlocked; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; From 0d392b96b9efed76d110e4c0c2724bf967b65584 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 21 Nov 2019 14:59:58 -0500 Subject: [PATCH 03/34] update handling payment id; set is_unlocked in sendd_split and sweep_output --- src/wallet/monero_wallet.cpp | 33 +++++++----------------------- src/wallet/monero_wallet_model.cpp | 1 + 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index b69308b..85a4e6a 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -190,7 +190,7 @@ namespace monero { for (const auto &d: pd.m_dests) { shared_ptr destination = make_shared(); destination->m_amount = d.amount; - destination->m_address = d.original.empty() ? cryptonote::get_account_address_as_str(m_w2.nettype(), d.is_subaddress, d.addr) : d.original; + destination->m_address = d.address(m_w2.nettype(), pd.m_payment_id); outgoing_transfer->m_destinations.push_back(destination); } @@ -293,7 +293,7 @@ namespace monero { for (const auto &d: pd.m_dests) { shared_ptr destination = make_shared(); destination->m_amount = d.amount; - destination->m_address = d.original.empty() ? cryptonote::get_account_address_as_str(m_w2.nettype(), d.is_subaddress, d.addr) : d.original; + destination->m_address = d.address(m_w2.nettype(), pd.m_payment_id); outgoing_transfer->m_destinations.push_back(destination); } @@ -538,30 +538,9 @@ namespace monero { if (!payment_id.empty()) { - - /* Just to clarify */ - const std::string& payment_id_str = payment_id; - - crypto::hash long_payment_id; - crypto::hash8 short_payment_id; - - /* Parse payment ID */ - if (wallet2::parse_long_payment_id(payment_id_str, long_payment_id)) { - cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, long_payment_id); - } - else { - er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; - er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 64 character string"; - return false; - } - - /* Append Payment ID data into extra */ - if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) { - er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; - er.message = "Something went wrong with payment_id. Please check its format: \"" + payment_id_str + "\", expected 64-character string"; - return false; - } - + er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID; + er.message = "Standalone payment IDs are obsolete. Use subaddresses or integrated addresses instead"; + return false; } return true; } @@ -1986,6 +1965,7 @@ namespace monero { tx->m_num_confirmations = 0; tx->m_mixin = request.m_mixin; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); + tx->m_is_unlocked = false; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 out_transfer->m_account_index = request.m_account_index; if (request.m_subaddress_indices.size() == 1) out_transfer->m_subaddress_indices.push_back(request.m_subaddress_indices[0]); // subaddress index is known iff 1 requested // TODO: get all known subaddress indices here @@ -2276,6 +2256,7 @@ namespace monero { tx->m_num_confirmations = 0; tx->m_mixin = request.m_mixin; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); + tx->m_is_unlocked = false; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 out_transfer->m_account_index = request.m_account_index; if (request.m_subaddress_indices.size() == 1) out_transfer->m_subaddress_indices.push_back(request.m_subaddress_indices[0]); // subaddress index is known iff 1 requested // TODO: get all known subaddress indices here diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 31f669a..5852791 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -142,6 +142,7 @@ namespace monero { if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); if (m_note != boost::none) node.put("note", *m_note); + if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); return node; } From 293ad48d63d5e037ec2963aa87bbd6b71e3e0124 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 21 Nov 2019 16:01:21 -0500 Subject: [PATCH 04/34] support is_unlocked in tx_query meets_criteria, node_to_tx_wallet, copy --- src/utils/monero_utils.cpp | 10 ++++++---- src/wallet/monero_wallet_model.cpp | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index b1fc298..ac16b8b 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -198,6 +198,8 @@ void node_to_tx_wallet(const boost::property_tree::ptree& node, shared_ptrfirst; //if (key == string("id")) tx->m_id = it->second.data(); + if (key == string("isUnlocked")) tx_wallet->m_is_unlocked = it->second.get_value(); + // TODO: deserialize other fields } } @@ -224,7 +226,7 @@ shared_ptr node_to_tx_query(const boost::property_tree::ptree& return m_tx_query; } -shared_ptr node_to_blockquery(const boost::property_tree::ptree& node) { +shared_ptr node_to_block_query(const boost::property_tree::ptree& node) { shared_ptr block = make_shared(); for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { string key = it->first; @@ -322,7 +324,7 @@ shared_ptr monero_utils::deserialize_tx_query(const string& tx_ boost::property_tree::read_json(iss, block_node); // convert query property tree to block - shared_ptr block = node_to_blockquery(block_node); + shared_ptr block = node_to_block_query(block_node); // get tx query shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); @@ -339,7 +341,7 @@ shared_ptr monero_utils::deserialize_transfer_query(const boost::property_tree::read_json(iss, blockNode); // convert query property tree to block - shared_ptr block = node_to_blockquery(blockNode); + shared_ptr block = node_to_block_query(blockNode); // return mpty query if no txs if (block->m_txs.empty()) return make_shared(); @@ -366,7 +368,7 @@ shared_ptr monero_utils::deserialize_output_query(const str boost::property_tree::read_json(iss, blockNode); // convert query property tree to block - shared_ptr block = node_to_blockquery(blockNode); + shared_ptr block = node_to_block_query(blockNode); // empty query if no txs if (block->m_txs.empty()) return make_shared(); diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 5852791..69f89d5 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -133,6 +133,7 @@ namespace monero { tgt->m_outgoing_transfer = transferCopy; } tgt->m_note = src->m_note; + tgt->m_is_unlocked = src->m_is_unlocked; return tgt; }; @@ -242,6 +243,7 @@ namespace monero { if (m_do_not_relay != boost::none && m_do_not_relay != tx->m_do_not_relay) return false; if (m_is_failed != boost::none && m_is_failed != tx->m_is_failed) return false; if (m_is_miner_tx != boost::none && m_is_miner_tx != tx->m_is_miner_tx) return false; + if (m_is_unlocked != boost::none && m_is_unlocked != tx->m_is_unlocked) return false; // at least one transfer must meet transfer query if defined if (m_transfer_query != boost::none) { From d7ef45b0fa648265b331ab3e6c0d3ab01f25284d Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 22 Nov 2019 09:21:10 -0500 Subject: [PATCH 05/34] handle validation error in send_split --- src/wallet/monero_wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 85a4e6a..a1dd6b6 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -1892,7 +1892,7 @@ namespace monero { std::vector extra; epee::json_rpc::error err; if (!validate_transfer(m_w2.get(), tr_destinations, payment_id, dsts, extra, true, err)) { - throw runtime_error("Need to handle send_split() validate_transfer error"); // TODO + throw runtime_error(err.message); } // prepare parameters for wallet2's create_transactions_2() From ff0f0574a767d4a65092846451b8879b63baa079 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 23 Nov 2019 13:13:19 -0500 Subject: [PATCH 06/34] add monero_version daemon model and wallet get_version() w/o impl --- src/daemon/monero_daemon_model.cpp | 9 +++++++++ src/daemon/monero_daemon_model.h | 9 +++++++++ src/wallet/monero_wallet.cpp | 4 ++++ src/wallet/monero_wallet.h | 7 +++++++ 4 files changed, 29 insertions(+) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index 5ccc271..cf5ca15 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -84,6 +84,15 @@ namespace monero { return monero_utils::serialize(to_property_tree()); } + // ----------------------------- MONERO VERSION ----------------------------- + + boost::property_tree::ptree monero_version::to_property_tree() const { + boost::property_tree::ptree node; + if (m_version_number != boost::none) node.put("versionNumber", *m_version_number); + if (m_is_release != boost::none) node.put("isRelease", *m_is_release); + return node; + } + // ------------------------- MONERO BLOCK HEADER ---------------------------- boost::property_tree::ptree monero_block_header::to_property_tree() const { diff --git a/src/daemon/monero_daemon_model.h b/src/daemon/monero_daemon_model.h index 21f793c..60a2ad0 100644 --- a/src/daemon/monero_daemon_model.h +++ b/src/daemon/monero_daemon_model.h @@ -91,6 +91,15 @@ namespace monero { STAGENET }; + /** + * Models a Monero version. + */ + struct monero_version : public serializable_struct { + boost::optional m_version_number; + boost::optional m_is_release; + boost::property_tree::ptree to_property_tree() const; + }; + /** * Models a connection to a daemon. * diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index a1dd6b6..50f2ddf 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -981,6 +981,10 @@ namespace monero { return m_is_synced; } + monero_version monero_wallet::get_version() const { + throw runtime_error("Not implemented"); + } + string monero_wallet::get_path() const { return m_w2->path(); } diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 2dd6928..1a47835 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -245,6 +245,13 @@ namespace monero { */ bool is_synced() const; + /** + * Get the wallet's version. + * + * @return the wallet's version + */ + monero_version get_version() const; + /** * Get the path of this wallet's file on disk. * From 8528c48a3369367f824ff27a77f420eda95606d2 Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 26 Nov 2019 10:52:49 -0500 Subject: [PATCH 07/34] fix private view key validation and error creating watch-only wallets --- src/wallet/monero_wallet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 50f2ddf..19b3bb3 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -882,7 +882,7 @@ namespace monero { // validate and parse private view key bool has_view_key = true; crypto::secret_key view_key_sk; - if (!view_key.empty()) { + if (view_key.empty()) { if (has_spend_key) has_view_key = false; else throw runtime_error("Neither view key nor spend key supplied, cancelled"); } From 246796c98f0df0ba5ac9158879da86de78d680eb Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 26 Nov 2019 13:51:32 -0500 Subject: [PATCH 08/34] implement deserialize_tx_set --- src/utils/monero_utils.cpp | 86 +++++++++++++++++++++++++----------- src/utils/monero_utils.h | 2 + src/wallet/monero_wallet.cpp | 10 +++-- src/wallet/monero_wallet.h | 8 ++++ 4 files changed, 77 insertions(+), 29 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index ac16b8b..2e37f9c 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -155,16 +155,16 @@ void node_to_tx(const boost::property_tree::ptree& node, shared_ptr t else if (key == string("version")) throw runtime_error("version deserializationn not implemented"); else if (key == string("isMinerTx")) tx->m_is_miner_tx = it->second.get_value(); else if (key == string("paymentId")) throw runtime_error("paymentId deserializationn not implemented"); - else if (key == string("fee")) throw runtime_error("fee deserialization not implemented"); + else if (key == string("fee")) tx->m_fee = it->second.get_value(); else if (key == string("mixin")) throw runtime_error("mixin deserialization not implemented"); else if (key == string("doNotRelay")) tx->m_do_not_relay = it->second.get_value(); else if (key == string("isRelayed")) tx->m_is_relayed = it->second.get_value(); else if (key == string("isConfirmed")) tx->m_is_confirmed = it->second.get_value(); else if (key == string("inTxPool")) tx->m_in_tx_pool = it->second.get_value(); - else if (key == string("numConfirmations")) throw runtime_error("numConfirmations deserialization not implemented"); - else if (key == string("unlockTime")) throw runtime_error("unlockTime deserialization not implemented"); - else if (key == string("lastRelayedTimestamp")) throw runtime_error("lastRelayedTimestamp deserialization not implemented"); - else if (key == string("receivedTimestamp")) throw runtime_error("receivedTimestamp deserializationn not implemented"); + else if (key == string("numConfirmations")) tx->m_num_confirmations = it->second.get_value(); + else if (key == string("unlockTime")) tx->m_unlock_time = it->second.get_value(); + else if (key == string("lastRelayedTimestamp")) tx->m_last_relayed_timestamp = it->second.get_value(); + else if (key == string("receivedTimestamp")) tx->m_received_timestamp = it->second.get_value(); else if (key == string("isDoubleSpendSeen")) tx->m_is_double_spend_seen = it->second.get_value(); else if (key == string("key")) tx->m_key = it->second.data(); else if (key == string("fullHex")) tx->m_full_hex = it->second.data(); @@ -176,7 +176,12 @@ void node_to_tx(const boost::property_tree::ptree& node, shared_ptr t else if (key == string("vins")) throw runtime_error("vins deserializationn not implemented"); else if (key == string("vouts")) throw runtime_error("vouts deserializationn not implemented"); else if (key == string("outputIndices")) throw runtime_error("m_output_indices deserialization not implemented"); - else if (key == string("metadata")) throw runtime_error("metadata deserialization not implemented"); + else if (key == string("metadata")) { + cout << "Assigning metadata" << endl; + tx->m_metadata = it->second.data(); + cout << "DONE ASSIGNING METADATA!" << endl; + //throw runtime_error("metadata deserialization not implemented"); + } else if (key == string("commonTxSets")) throw runtime_error("commonTxSets deserialization not implemented"); else if (key == string("extra")) throw runtime_error("extra deserialization not implemented"); else if (key == string("rctSignatures")) throw runtime_error("rctSignatures deserialization not implemented"); @@ -204,26 +209,26 @@ void node_to_tx_wallet(const boost::property_tree::ptree& node, shared_ptr node_to_tx_query(const boost::property_tree::ptree& node) { - shared_ptr m_tx_query = make_shared(); - node_to_tx_wallet(node, m_tx_query); + shared_ptr tx_query = make_shared(); + node_to_tx_wallet(node, tx_query); // initialize query from node for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { string key = it->first; - if (key == string("isOutgoing")) m_tx_query->m_is_outgoing = it->second.get_value(); - else if (key == string("isIncoming")) m_tx_query->m_is_incoming = it->second.get_value(); - else if (key == string("txIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) m_tx_query->m_tx_ids.push_back(it2->second.data()); - else if (key == string("hasPaymentId")) m_tx_query->m_has_payment_id = it->second.get_value(); - else if (key == string("paymentIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) m_tx_query->m_payment_ids.push_back(it2->second.data()); - else if (key == string("height")) m_tx_query->m_height = it->second.get_value(); - else if (key == string("minHeight")) m_tx_query->m_min_height = it->second.get_value(); - else if (key == string("maxHeight")) m_tx_query->m_max_height = it->second.get_value(); - else if (key == string("includeOutputs")) m_tx_query->m_include_outputs = it->second.get_value(); - else if (key == string("transferQuery")) m_tx_query->m_transfer_query = node_to_transfer_query(it->second); - else if (key == string("outputQuery")) m_tx_query->m_output_query = node_to_output_query(it->second); + if (key == string("isOutgoing")) tx_query->m_is_outgoing = it->second.get_value(); + else if (key == string("isIncoming")) tx_query->m_is_incoming = it->second.get_value(); + else if (key == string("txIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) tx_query->m_tx_ids.push_back(it2->second.data()); + else if (key == string("hasPaymentId")) tx_query->m_has_payment_id = it->second.get_value(); + else if (key == string("paymentIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) tx_query->m_payment_ids.push_back(it2->second.data()); + else if (key == string("height")) tx_query->m_height = it->second.get_value(); + else if (key == string("minHeight")) tx_query->m_min_height = it->second.get_value(); + else if (key == string("maxHeight")) tx_query->m_max_height = it->second.get_value(); + else if (key == string("includeOutputs")) tx_query->m_include_outputs = it->second.get_value(); + else if (key == string("transferQuery")) tx_query->m_transfer_query = node_to_transfer_query(it->second); + else if (key == string("outputQuery")) tx_query->m_output_query = node_to_output_query(it->second); } - return m_tx_query; + return tx_query; } shared_ptr node_to_block_query(const boost::property_tree::ptree& node) { @@ -231,8 +236,8 @@ shared_ptr node_to_block_query(const boost::property_tree::ptree& for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { string key = it->first; if (key == string("txs")) { - boost::property_tree::ptree txsNode = it->second; - for (boost::property_tree::ptree::const_iterator it2 = txsNode.begin(); it2 != txsNode.end(); ++it2) { + boost::property_tree::ptree txs_node = it->second; + for (boost::property_tree::ptree::const_iterator it2 = txs_node.begin(); it2 != txs_node.end(); ++it2) { block->m_txs.push_back(node_to_tx_query(it2->second)); } } @@ -289,7 +294,7 @@ void monero_utils::binary_blocks_to_json(const std::string &bin, std::string &js } // parse and validate txs - boost::property_tree::ptree txsNode; + boost::property_tree::ptree txs_node; for (int txIdx = 0; txIdx < resp_struct.blocks[blockIdx].txs.size(); txIdx++) { cryptonote::transaction tx; if (cryptonote::parse_and_validate_tx_from_blob(resp_struct.blocks[blockIdx].txs[txIdx].blob, tx)) { @@ -298,12 +303,12 @@ void monero_utils::binary_blocks_to_json(const std::string &bin, std::string &js boost::property_tree::ptree txNode; MTRACE("PRUNED:\n" << monero_utils::get_pruned_tx_json(tx)); txNode.put("", monero_utils::get_pruned_tx_json(tx)); // TODO: no pretty print - txsNode.push_back(std::make_pair("", txNode)); + txs_node.push_back(std::make_pair("", txNode)); } else { throw std::runtime_error("failed to parse tx blob at index " + std::to_string(txIdx)); } } - txsNodes.push_back(std::make_pair("", txsNode)); // array of array of transactions, one array per block + txsNodes.push_back(std::make_pair("", txs_node)); // array of array of transactions, one array per block } root.add_child("blocks", blocksNode); root.add_child("txs", txsNodes); @@ -316,6 +321,35 @@ void monero_utils::binary_blocks_to_json(const std::string &bin, std::string &js json = ss.str(); } +monero_tx_set monero_utils::deserialize_tx_set(const string& tx_set_str) { + cout << "monero_utils::deserialize_tx_set(...)" << endl; + cout << tx_set_str; + + // deserialize tx set to property + std::istringstream iss = tx_set_str.empty() ? std::istringstream() : std::istringstream(tx_set_str); + boost::property_tree::ptree tx_set_node; + boost::property_tree::read_json(iss, tx_set_node); + + // initialize tx_set from property node + monero_tx_set tx_set; + for (boost::property_tree::ptree::const_iterator it = tx_set_node.begin(); it != tx_set_node.end(); ++it) { + string key = it->first; + if (key == string("unsignedTxHex")) tx_set.m_unsigned_tx_hex = it->second.data(); + else if (key == string("multisigTxHex")) tx_set.m_multisig_tx_hex = it->second.data(); + else if (key == string("txs")) { + boost::property_tree::ptree txs_node = it->second; + for (boost::property_tree::ptree::const_iterator it2 = txs_node.begin(); it2 != txs_node.end(); ++it2) { + shared_ptr tx_wallet = make_shared(); + node_to_tx_wallet(it2->second, tx_wallet); + tx_set.m_txs.push_back(tx_wallet); + } + } + else throw runtime_error("monero_utils::deserialize_tx_set() field '" + key + "' not supported"); + } + + return tx_set; +} + shared_ptr monero_utils::deserialize_tx_query(const string& tx_query_str) { // deserialize tx query string to property rooted at block @@ -343,7 +377,7 @@ shared_ptr monero_utils::deserialize_transfer_query(const // convert query property tree to block shared_ptr block = node_to_block_query(blockNode); - // return mpty query if no txs + // return empty query if no txs if (block->m_txs.empty()) return make_shared(); // get tx query diff --git a/src/utils/monero_utils.h b/src/utils/monero_utils.h index 31b41aa..a9250b0 100644 --- a/src/utils/monero_utils.h +++ b/src/utils/monero_utils.h @@ -72,6 +72,8 @@ namespace monero_utils void binary_blocks_to_json(const std::string &bin, std::string &json); + monero_tx_set deserialize_tx_set(const string& tx_set_str); + shared_ptr deserialize_tx_query(const string& txQueryStr); shared_ptr deserialize_transfer_query(const string& transfer_query_str); diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 19b3bb3..4634284 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -1510,7 +1510,7 @@ namespace monero { if (query.m_tx_query.get()->m_transfer_query != boost::none && query.m_tx_query.get()->m_transfer_query.get().get() == &query) { _query = tx_query->m_transfer_query.get(); } else { - if (query.m_tx_query.get()->m_transfer_query != boost::none) throw new runtime_error("Transfer query's tx query must be a circular reference or null"); + if (query.m_tx_query.get()->m_transfer_query != boost::none) throw runtime_error("Transfer query's tx query must be a circular reference or null"); shared_ptr query_ptr = make_shared(query); // convert query to shared pointer for copy _query = query_ptr->copy(query_ptr, make_shared()); _query->m_tx_query = tx_query; @@ -1653,7 +1653,7 @@ namespace monero { if (query.m_tx_query.get()->m_output_query != boost::none && query.m_tx_query.get()->m_output_query.get().get() == &query) { _query = tx_query->m_output_query.get(); } else { - if (query.m_tx_query.get()->m_output_query != boost::none) throw new runtime_error("Output query's tx query must be a circular reference or null"); + if (query.m_tx_query.get()->m_output_query != boost::none) throw runtime_error("Output query's tx query must be a circular reference or null"); shared_ptr query_ptr = make_shared(query); // convert query to shared pointer for copy _query = query_ptr->copy(query_ptr, make_shared()); _query->m_tx_query = tx_query; @@ -2368,6 +2368,10 @@ namespace monero { return tx_set; } + monero_tx_set monero_wallet::parse_tx_set(const monero_tx_set& tx_set) { + throw runtime_error("Not implemented"); + } + string monero_wallet::sign(const string& msg) const { return m_w2->sign(msg); } @@ -2775,7 +2779,7 @@ namespace monero { // validate state and args bool ready; uint32_t threshold, total; - if (!m_w2->multisig(&ready, &threshold, &total)) throw new runtime_error("This wallet is not multisig"); + if (!m_w2->multisig(&ready, &threshold, &total)) throw runtime_error("This wallet is not multisig"); if (ready) throw runtime_error("This wallet is multisig, and already finalized"); if (multisig_hexes.size() < 1 || multisig_hexes.size() > total) throw runtime_error("Needs multisig info from more participants"); diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 1a47835..3f1e175 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1006,6 +1006,14 @@ namespace monero { */ monero_tx_set sweep_dust(bool do_not_relay = false); + /** + * Parses a tx set containing unsigned or multisig tx hex to a new tx set containing structured transactions. + * + * @param tx_set is a tx set containing unsigned or multisig tx hex + * @return the parsed tx set containing structured transactions + */ + monero_tx_set parse_tx_set(const monero_tx_set& tx_set); + /** * Sign a message. * From 453abdc74c6b59a6085405ff5cd935bf1754b3ba Mon Sep 17 00:00:00 2001 From: woodser Date: Tue, 26 Nov 2019 13:52:22 -0500 Subject: [PATCH 09/34] cleanup --- src/utils/monero_utils.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index 2e37f9c..4545bf2 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -176,12 +176,7 @@ void node_to_tx(const boost::property_tree::ptree& node, shared_ptr t else if (key == string("vins")) throw runtime_error("vins deserializationn not implemented"); else if (key == string("vouts")) throw runtime_error("vouts deserializationn not implemented"); else if (key == string("outputIndices")) throw runtime_error("m_output_indices deserialization not implemented"); - else if (key == string("metadata")) { - cout << "Assigning metadata" << endl; - tx->m_metadata = it->second.data(); - cout << "DONE ASSIGNING METADATA!" << endl; - //throw runtime_error("metadata deserialization not implemented"); - } + else if (key == string("metadata")) tx->m_metadata = it->second.data(); else if (key == string("commonTxSets")) throw runtime_error("commonTxSets deserialization not implemented"); else if (key == string("extra")) throw runtime_error("extra deserialization not implemented"); else if (key == string("rctSignatures")) throw runtime_error("rctSignatures deserialization not implemented"); From 3305a871ef844d55d487beef38e5d374ed05e772 Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 27 Nov 2019 10:47:34 -0500 Subject: [PATCH 10/34] implement parse_tx_set --- src/utils/monero_utils.cpp | 2 - src/wallet/monero_wallet.cpp | 158 ++++++++++++++++++++++++++++- src/wallet/monero_wallet_model.cpp | 42 +++++--- src/wallet/monero_wallet_model.h | 10 +- 4 files changed, 194 insertions(+), 18 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index 4545bf2..198cbd2 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -317,8 +317,6 @@ void monero_utils::binary_blocks_to_json(const std::string &bin, std::string &js } monero_tx_set monero_utils::deserialize_tx_set(const string& tx_set_str) { - cout << "monero_utils::deserialize_tx_set(...)" << endl; - cout << tx_set_str; // deserialize tx set to property std::istringstream iss = tx_set_str.empty() ? std::istringstream() : std::istringstream(tx_set_str); diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 4634284..372736b 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -1958,6 +1958,7 @@ namespace monero { out_transfer->m_amount = *tx_amounts_iter; // init other known fields + tx->m_is_outgoing = true; tx->m_payment_id = request.m_payment_id; tx->m_is_confirmed = false; tx->m_is_miner_tx = false; @@ -2369,7 +2370,162 @@ namespace monero { } monero_tx_set monero_wallet::parse_tx_set(const monero_tx_set& tx_set) { - throw runtime_error("Not implemented"); + + // get unsigned and multisig tx sets + string unsigned_tx_hex = tx_set.m_unsigned_tx_hex == boost::none ? "" : tx_set.m_unsigned_tx_hex.get(); + string multisig_tx_hex = tx_set.m_multisig_tx_hex == boost::none ? "" : tx_set.m_multisig_tx_hex.get(); + + // validate request + if (m_w2->key_on_device()) throw runtime_error("command not supported by HW wallet"); + if (m_w2->watch_only()) throw runtime_error("command not supported by watch-only wallet"); + if (unsigned_tx_hex.empty() && multisig_tx_hex.empty()) throw runtime_error("no txset provided"); + + std::vector tx_constructions; + if (!unsigned_tx_hex.empty()) { + try { + tools::wallet2::unsigned_tx_set exported_txs; + cryptonote::blobdata blob; + if (!epee::string_tools::parse_hexstr_to_binbuff(unsigned_tx_hex, blob)) throw runtime_error("Failed to parse hex."); + if (!m_w2->parse_unsigned_tx_from_str(blob, exported_txs)) throw runtime_error("cannot load unsigned_txset"); + tx_constructions = exported_txs.txes; + } + catch (const std::exception &e) { + throw runtime_error("failed to parse unsigned transfers: " + std::string(e.what())); + } + } else if (!multisig_tx_hex.empty()) { + try { + tools::wallet2::multisig_tx_set exported_txs; + cryptonote::blobdata blob; + if (!epee::string_tools::parse_hexstr_to_binbuff(multisig_tx_hex, blob)) throw runtime_error("Failed to parse hex."); + if (!m_w2->parse_multisig_tx_from_str(blob, exported_txs)) throw runtime_error("cannot load multisig_txset"); + for (size_t n = 0; n < exported_txs.m_ptx.size(); ++n) { + tx_constructions.push_back(exported_txs.m_ptx[n].construction_data); + } + } + catch (const std::exception &e) { + throw runtime_error("failed to parse multisig transfers: " + std::string(e.what())); + } + } + + std::vector ptx; // TODO wallet_rpc_server: unused variable + try + { + + // gather info for each tx + vector> txs; + std::unordered_map> dests; + int first_known_non_zero_change_index = -1; + for (size_t n = 0; n < tx_constructions.size(); ++n) + { + // pre-initialize tx + shared_ptr tx = make_shared(); + tx->m_is_outgoing = true; + tx->m_input_sum = 0; + tx->m_output_sum = 0; + tx->m_change_amount = 0; + tx->m_num_dummy_outputs = 0; + tx->m_mixin = std::numeric_limits::max() - 1; // smaller ring sizes will overwrite // TODO: remove - 1 when switched to ring size + + const tools::wallet2::tx_construction_data &cd = tx_constructions[n]; + std::vector tx_extra_fields; + bool has_encrypted_payment_id = false; + crypto::hash8 payment_id8 = crypto::null_hash8; + if (cryptonote::parse_tx_extra(cd.extra, tx_extra_fields)) + { + cryptonote::tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) + { + crypto::hash payment_id; + if(cryptonote::get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) + { + if (payment_id8 != crypto::null_hash8) + { + tx->m_payment_id = epee::string_tools::pod_to_hex(payment_id8); + has_encrypted_payment_id = true; + } + } + else if (cryptonote::get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id)) + { + tx->m_payment_id = epee::string_tools::pod_to_hex(payment_id); + } + } + } + + for (size_t s = 0; s < cd.sources.size(); ++s) + { + tx->m_input_sum = tx->m_input_sum.get() + cd.sources[s].amount; + size_t ring_size = cd.sources[s].outputs.size(); + if (ring_size < tx->m_mixin.get() + 1) + tx->m_mixin = ring_size - 1; // TODO: switch to m_ring_size + } + for (size_t d = 0; d < cd.splitted_dsts.size(); ++d) + { + const cryptonote::tx_destination_entry &entry = cd.splitted_dsts[d]; + std::string address = cryptonote::get_account_address_as_str(m_w2->nettype(), entry.is_subaddress, entry.addr); + if (has_encrypted_payment_id && !entry.is_subaddress && address != entry.original) + address = cryptonote::get_account_integrated_address_as_str(m_w2->nettype(), entry.addr, payment_id8); + auto i = dests.find(entry.addr); + if (i == dests.end()) + dests.insert(std::make_pair(entry.addr, std::make_pair(address, entry.amount))); + else + i->second.second += entry.amount; + tx->m_output_sum = tx->m_output_sum.get() + entry.amount; + } + if (cd.change_dts.amount > 0) + { + auto it = dests.find(cd.change_dts.addr); + if (it == dests.end()) throw runtime_error("Claimed change does not go to a paid address"); + if (it->second.second < cd.change_dts.amount) throw runtime_error("Claimed change is larger than payment to the change address"); + if (cd.change_dts.amount > 0) + { + if (first_known_non_zero_change_index == -1) + first_known_non_zero_change_index = n; + const tools::wallet2::tx_construction_data &cdn = tx_constructions[first_known_non_zero_change_index]; + if (memcmp(&cd.change_dts.addr, &cdn.change_dts.addr, sizeof(cd.change_dts.addr))) throw runtime_error("Change goes to more than one address"); + } + tx->m_change_amount = tx->m_change_amount.get() + cd.change_dts.amount; + it->second.second -= cd.change_dts.amount; + if (it->second.second == 0) + dests.erase(cd.change_dts.addr); + } + + tx->m_outgoing_transfer = make_shared(); + size_t n_dummy_outputs = 0; + for (auto i = dests.begin(); i != dests.end(); ) + { + if (i->second.second > 0) + { + shared_ptr destination = make_shared(); + destination->m_address = i->second.first; + destination->m_amount = i->second.second; + tx->m_outgoing_transfer.get()->m_destinations.push_back(destination); + } + else + tx->m_num_dummy_outputs = tx->m_num_dummy_outputs.get() + 1; + ++i; + } + + if (tx->m_change_amount.get() > 0) + { + const tools::wallet2::tx_construction_data &cd0 = tx_constructions[0]; + tx->m_change_address = get_account_address_as_str(m_w2->nettype(), cd0.subaddr_account > 0, cd0.change_dts.addr); + } + + tx->m_fee = tx->m_input_sum.get() - tx->m_output_sum.get(); + tx->m_unlock_time = cd.unlock_time; + tx->m_extra_hex = epee::to_hex::string({cd.extra.data(), cd.extra.size()}); + txs.push_back(tx); + } + + // build and return tx set + monero_tx_set tx_set; + tx_set.m_txs = txs; + return tx_set; + } + catch (const std::exception &e) + { + throw runtime_error("failed to parse unsigned transfers"); + } } string monero_wallet::sign(const string& msg) const { diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 69f89d5..6077376 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -119,6 +119,9 @@ namespace monero { monero_tx::copy(static_pointer_cast(src), static_pointer_cast(tgt)); // copy wallet extensions + tgt->m_tx_set = src->m_tx_set; + tgt->m_is_incoming = src->m_is_incoming; + tgt->m_is_outgoing = src->m_is_outgoing; if (!src->m_incoming_transfers.empty()) { tgt->m_incoming_transfers = vector>(); for (const shared_ptr& transfer : src->m_incoming_transfers) { @@ -134,27 +137,33 @@ namespace monero { } tgt->m_note = src->m_note; tgt->m_is_unlocked = src->m_is_unlocked; + tgt->m_input_sum = src->m_input_sum; + tgt->m_output_sum = src->m_output_sum; + tgt->m_change_address = src->m_change_address; + tgt->m_change_amount = src->m_change_amount; + tgt->m_num_dummy_outputs = src->m_num_dummy_outputs; + tgt->m_extra_hex = src->m_extra_hex; return tgt; }; boost::property_tree::ptree monero_tx_wallet::to_property_tree() const { boost::property_tree::ptree node = monero_tx::to_property_tree(); + if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); + if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); if (m_note != boost::none) node.put("note", *m_note); if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); + if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); + if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); + if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); + if (m_change_amount != boost::none) node.put("changeAmount", *m_change_amount); + if (m_num_dummy_outputs != boost::none) node.put("numDummyOutputs", *m_num_dummy_outputs); + if (m_extra_hex != boost::none) node.put("extraHex", *m_extra_hex); return node; } - bool monero_tx_wallet::is_outgoing() const { - return m_outgoing_transfer != boost::none; - } - - bool monero_tx_wallet::is_incoming() const { - return !m_incoming_transfers.empty(); - } - void monero_tx_wallet::merge(const shared_ptr& self, const shared_ptr& other) { merge(static_pointer_cast(self), static_pointer_cast(other)); } @@ -166,9 +175,6 @@ namespace monero { // merge base classes monero_tx::merge(self, other); - // merge wallet extensions - m_note = gen_utils::reconcile(m_note, other->m_note); - // merge incoming transfers if (!other->m_incoming_transfers.empty()) { for (const shared_ptr& transfer : other->m_incoming_transfers) { // NOTE: not using reference so shared_ptr is not deleted when tx is dereferenced @@ -183,6 +189,16 @@ namespace monero { if (self->m_outgoing_transfer == boost::none) self->m_outgoing_transfer = other->m_outgoing_transfer; else self->m_outgoing_transfer.get()->merge(self->m_outgoing_transfer.get(), other->m_outgoing_transfer.get()); } + + // merge simple extensions + m_note = gen_utils::reconcile(m_note, other->m_note); + m_is_unlocked = gen_utils::reconcile(m_is_unlocked, other->m_is_unlocked); + m_input_sum = gen_utils::reconcile(m_input_sum, other->m_input_sum); + m_output_sum = gen_utils::reconcile(m_output_sum, other->m_output_sum); + m_change_address = gen_utils::reconcile(m_change_address, other->m_change_address); + m_change_amount = gen_utils::reconcile(m_change_amount, other->m_change_amount); + m_num_dummy_outputs = gen_utils::reconcile(m_num_dummy_outputs, other->m_num_dummy_outputs); + m_extra_hex = gen_utils::reconcile(m_extra_hex, other->m_extra_hex); } // -------------------------- MONERO TX REQUEST ----------------------------- @@ -281,10 +297,10 @@ namespace monero { } // filter on incoming - if (m_is_incoming != boost::none && m_is_incoming != tx->is_incoming()) return false; + if (m_is_incoming != boost::none && m_is_incoming != tx->m_is_incoming) return false; // filter on outgoing - if (m_is_outgoing != boost::none && m_is_outgoing != tx->is_outgoing()) return false; + if (m_is_outgoing != boost::none && m_is_outgoing != tx->m_is_outgoing) return false; // filter on remaining fields boost::optional txHeight = tx->get_height(); diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 0446524..5169a63 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -258,15 +258,21 @@ namespace monero { */ struct monero_tx_wallet : public monero_tx { boost::optional> m_tx_set; + boost::optional m_is_incoming; + boost::optional m_is_outgoing; vector> m_incoming_transfers; boost::optional> m_outgoing_transfer; boost::optional m_note; boost::optional m_is_unlocked; + boost::optional m_input_sum; + boost::optional m_output_sum; + boost::optional m_change_address; + boost::optional m_change_amount; + boost::optional m_num_dummy_outputs; + boost::optional m_extra_hex; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - bool is_incoming() const; - bool is_outgoing() const; boost::property_tree::ptree to_property_tree() const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); From c1c19bb67e8ca83d3e6722f8a5c4e731f63d4b1c Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 27 Nov 2019 11:12:45 -0500 Subject: [PATCH 11/34] wallet jni sets tx m_is_incoming, m_is_outgoing --- src/wallet/monero_wallet.cpp | 8 ++++++++ src/wallet/monero_wallet_model.cpp | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 372736b..1ca4f08 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -98,6 +98,7 @@ namespace monero { tx->m_block = block; block->m_txs.push_back(tx); tx->m_id = string_tools::pod_to_hex(pd.m_tx_hash); + tx->m_is_incoming = true; tx->m_payment_id = string_tools::pod_to_hex(payment_id); if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id @@ -150,6 +151,7 @@ namespace monero { tx->m_block = block; block->m_txs.push_back(tx); tx->m_id = string_tools::pod_to_hex(txid); + tx->m_is_outgoing = true; tx->m_payment_id = string_tools::pod_to_hex(pd.m_payment_id); if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id @@ -217,6 +219,7 @@ namespace monero { const tools::wallet2::payment_details &pd = ppd.m_pd; shared_ptr tx = make_shared(); tx->m_id = string_tools::pod_to_hex(pd.m_tx_hash); + tx->m_is_incoming = true; tx->m_payment_id = string_tools::pod_to_hex(payment_id); if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id @@ -258,6 +261,7 @@ namespace monero { shared_ptr tx = make_shared(); tx->m_is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed; tx->m_id = string_tools::pod_to_hex(txid); + tx->m_is_outgoing = true; tx->m_payment_id = string_tools::pod_to_hex(pd.m_payment_id); if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id @@ -1605,6 +1609,10 @@ namespace monero { vector> transfers; for (const shared_ptr& tx : txs) { + // tx is not incoming/outgoing unless already set + if (tx->m_is_incoming == boost::none) tx->m_is_incoming = false; + if (tx->m_is_outgoing == boost::none) tx->m_is_outgoing = false; + // sort transfers sort(tx->m_incoming_transfers.begin(), tx->m_incoming_transfers.end(), incoming_transfer_before); diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 6077376..fce2261 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -191,6 +191,8 @@ namespace monero { } // merge simple extensions + m_is_incoming = gen_utils::reconcile(m_is_incoming, other->m_is_incoming); + m_is_outgoing = gen_utils::reconcile(m_is_outgoing, other->m_is_outgoing); m_note = gen_utils::reconcile(m_note, other->m_note); m_is_unlocked = gen_utils::reconcile(m_is_unlocked, other->m_is_unlocked); m_input_sum = gen_utils::reconcile(m_input_sum, other->m_input_sum); From 8e562047523abfb994a61aed1c547c64f1a69bf6 Mon Sep 17 00:00:00 2001 From: woodser Date: Wed, 27 Nov 2019 13:13:34 -0500 Subject: [PATCH 12/34] set tx->m_is_outgoing = true for sweeps --- src/wallet/monero_wallet.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 1ca4f08..0aaea16 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -2133,6 +2133,7 @@ namespace monero { shared_ptr tx = make_shared(); txs.push_back(tx); tx->m_id = *tx_ids_iter; + tx->m_is_outgoing = true; tx->m_key = *tx_keys_iter; tx->m_fee = *tx_fees_iter; tx->m_full_hex = *tx_blobs_iter; @@ -2249,6 +2250,7 @@ namespace monero { shared_ptr tx = make_shared(); txs.push_back(tx); tx->m_id = *tx_ids_iter; + tx->m_is_outgoing = true; tx->m_key = *tx_keys_iter; tx->m_fee = *tx_fees_iter; tx->m_full_hex = *tx_blobs_iter; @@ -2335,6 +2337,7 @@ namespace monero { shared_ptr tx = make_shared(); txs.push_back(tx); tx->m_id = *tx_ids_iter; + tx->m_is_outgoing = true; tx->m_key = *tx_keys_iter; tx->m_fee = *tx_fees_iter; tx->m_full_hex = *tx_blobs_iter; From 499218d75d3438a243080545efc59d033c0dfd05 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 08:14:29 -0500 Subject: [PATCH 13/34] sweep_account() and get_outputs() set tx->m_is_unlocked --- src/wallet/monero_wallet.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 0aaea16..9d105f3 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -335,6 +335,7 @@ namespace monero { tx->m_in_tx_pool = false; tx->m_do_not_relay = false; tx->m_is_double_spend_seen = false; + tx->m_is_unlocked = m_w2.is_transfer_unlocked(td); // construct vout shared_ptr vout = make_shared(); @@ -345,7 +346,7 @@ namespace monero { vout->m_account_index = td.m_subaddr_index.major; vout->m_subaddress_index = td.m_subaddr_index.minor; vout->m_is_spent = td.m_spent; - vout->m_is_unlocked = m_w2.is_transfer_unlocked(td); + vout->m_is_unlocked = m_w2.is_transfer_unlocked(td); // TODO: this is redundant with tx vout->m_is_frozen = td.m_frozen; if (td.m_key_image_known) { vout->m_key_image = make_shared(); @@ -2133,6 +2134,7 @@ namespace monero { shared_ptr tx = make_shared(); txs.push_back(tx); tx->m_id = *tx_ids_iter; + tx->m_is_unlocked = false; tx->m_is_outgoing = true; tx->m_key = *tx_keys_iter; tx->m_fee = *tx_fees_iter; From 86588678d0ce9bc95025dbf8bb66175f5d3f6449 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 09:18:20 -0500 Subject: [PATCH 14/34] implement get_version() --- src/wallet/monero_wallet.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 9d105f3..161f2b9 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -987,7 +987,10 @@ namespace monero { } monero_version monero_wallet::get_version() const { - throw runtime_error("Not implemented"); + monero_version version; + version.m_version_number = 65552; // same as monero-wallet-rpc v0.15.0.1 release + version.m_is_release = false; // TODO: could pull from MONERO_VERSION_IS_RELEASE in version.cpp + return version; } string monero_wallet::get_path() const { From 802958e8e765e2acf5a582539f0fce76d4587847 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 10:17:40 -0500 Subject: [PATCH 15/34] start address book definitions --- src/wallet/monero_wallet.h | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 3f1e175..2ac63d5 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1170,17 +1170,10 @@ namespace monero { // /** // * Get all address book entries. // * +// * @param indices are indices of the entries to get // * @return the address book entries // */ -// public List getAddressBookEntries(); -// -// /** -// * Get address book entries. -// * -// * @param entryIndices are indices of the entries to get -// * @return the address book entries -// */ -// public List getAddressBookEntries(Collection entryIndices); +// vector get_address_book_entries(const vector& indices) const; // // /** // * Add an address book entry. @@ -1189,17 +1182,7 @@ namespace monero { // * @param description is the entry description (optional) // * @return the index of the added entry // */ -// public int addAddressBookEntry(string address, string description); -// -// /** -// * Add an address book entry. -// * -// * @param address is the entry address -// * @param description is the entry description (optional) -// * @param payment_id is the entry paymet id (optional) -// * @return the index of the added entry -// */ -// public int addAddressBookEntry(string address, string description, string payment_id); +// uint32_t add_address_book_entry(const string& address, const string& description); // // /** // * Delete an address book entry. @@ -1207,7 +1190,7 @@ namespace monero { // * @param entryIdx is the index of the entry to delete // */ // public void deleteAddressBookEntry(int entryIdx); -// + // /** // * Tag accounts. // * From bc7e97563c11c22132336fd8765dc598ef17c4e7 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 12:53:19 -0500 Subject: [PATCH 16/34] add get_address_book_entries() stack w/o impl --- src/wallet/monero_wallet.cpp | 4 ++++ src/wallet/monero_wallet.h | 16 ++++++++-------- src/wallet/monero_wallet_model.cpp | 11 +++++++++++ src/wallet/monero_wallet_model.h | 12 ++++++++++++ 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 161f2b9..005025f 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -2790,6 +2790,10 @@ namespace monero { } } + vector monero_wallet::get_address_book_entries(const vector& indices) const { + throw runtime_error("get_address_book_entries() not implemented"); + } + string monero_wallet::create_payment_uri(const monero_send_request& request) const { MTRACE("create_payment_uri()"); diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 2ac63d5..3932bdc 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1167,14 +1167,14 @@ namespace monero { */ void set_tx_notes(const vector& tx_ids, const vector& notes); -// /** -// * Get all address book entries. -// * -// * @param indices are indices of the entries to get -// * @return the address book entries -// */ -// vector get_address_book_entries(const vector& indices) const; -// + /** + * Get all address book entries. + * + * @param indices are indices of the entries to get + * @return the address book entries + */ + vector get_address_book_entries(const vector& indices) const; + // /** // * Add an address book entry. // * diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index fce2261..e61c636 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -795,4 +795,15 @@ namespace monero { if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); return node; } + + // -------------------------- MONERO ADDRESS BOOK --------------------------- + + boost::property_tree::ptree monero_address_book_entry::to_property_tree() const { + boost::property_tree::ptree node; + if (m_index != boost::none) node.put("index", *m_index); + if (m_address != boost::none) node.put("address", *m_address); + if (m_description != boost::none) node.put("description", *m_description); + if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); + return node; + } } diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 5169a63..b14bb79 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -443,4 +443,16 @@ namespace monero { boost::property_tree::ptree to_property_tree() const; }; + + /** + * Monero address book entry model. + */ + struct monero_address_book_entry : serializable_struct { + boost::optional m_index; + boost::optional m_address; + boost::optional m_description; + boost::optional m_payment_id; + + boost::property_tree::ptree to_property_tree() const; + }; } From 8e404249edfda9c11ebafd8a036d94e8b18b11eb Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 13:10:31 -0500 Subject: [PATCH 17/34] define remaining address book functions --- src/wallet/monero_wallet.cpp | 12 ++++++++++ src/wallet/monero_wallet.h | 43 +++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 005025f..67920d3 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -2794,6 +2794,18 @@ namespace monero { throw runtime_error("get_address_book_entries() not implemented"); } + uint32_t monero_wallet::add_address_book_entry(const string& address, boost::optional description, boost::optional payment_id) { + throw runtime_error("add_address_book_entry() not implemented"); + } + + void monero_wallet::edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_paymenet_id, boost::optional payment_id) { + throw runtime_error("edit_address_book_entry() not implemented"); + } + + void monero_wallet::delete_address_book_entry(uint32_t entry_idx) { + throw runtime_error("delete_address_book_entry() not implemented"); + } + string monero_wallet::create_payment_uri(const monero_send_request& request) const { MTRACE("create_payment_uri()"); diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 3932bdc..2161914 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1175,21 +1175,34 @@ namespace monero { */ vector get_address_book_entries(const vector& indices) const; -// /** -// * Add an address book entry. -// * -// * @param address is the entry address -// * @param description is the entry description (optional) -// * @return the index of the added entry -// */ -// uint32_t add_address_book_entry(const string& address, const string& description); -// -// /** -// * Delete an address book entry. -// * -// * @param entryIdx is the index of the entry to delete -// */ -// public void deleteAddressBookEntry(int entryIdx); + /** + * Add an address book entry. + * + * @param address is the entry address + * @param description is the entry description (optional) + * @return the index of the added entry + */ + uint32_t add_address_book_entry(const string& address, boost::optional description = boost::none, boost::optional payment_id = boost::none); + + /** + * Edit an address book entry. + * + * @param index is the index of the address book entry to edit + * @param set_address specifies if the address should be updated + * @param address is the updated address + * @param set_description specifies if the description should be updated + * @param description is the updated description + * @param set_payment_id specifies if the payment id should be updated + * @param payment_id is the updated payment id + */ + void edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_paymenet_id, boost::optional payment_id); + + /** + * Delete an address book entry. + * + * @param entry_idx is the index of the entry to delete + */ + void delete_address_book_entry(uint32_t entry_idx); // /** // * Tag accounts. From d865dd56e09d4c8dbbd71a7a25968fb4f15f3776 Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 14:05:38 -0500 Subject: [PATCH 18/34] cleanup; ready to implement wallet address book methods --- src/wallet/monero_wallet.cpp | 4 ++-- src/wallet/monero_wallet.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 67920d3..8608844 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -2798,11 +2798,11 @@ namespace monero { throw runtime_error("add_address_book_entry() not implemented"); } - void monero_wallet::edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_paymenet_id, boost::optional payment_id) { + void monero_wallet::edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id) { throw runtime_error("edit_address_book_entry() not implemented"); } - void monero_wallet::delete_address_book_entry(uint32_t entry_idx) { + void monero_wallet::delete_address_book_entry(uint32_t index) { throw runtime_error("delete_address_book_entry() not implemented"); } diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 2161914..1eb95fa 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1195,14 +1195,14 @@ namespace monero { * @param set_payment_id specifies if the payment id should be updated * @param payment_id is the updated payment id */ - void edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_paymenet_id, boost::optional payment_id); + void edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id); /** * Delete an address book entry. * - * @param entry_idx is the index of the entry to delete + * @param index is the index of the entry to delete */ - void delete_address_book_entry(uint32_t entry_idx); + void delete_address_book_entry(uint32_t index); // /** // * Tag accounts. From ceea54988a99bc393f27a68e2d8000d65c2b4a5f Mon Sep 17 00:00:00 2001 From: woodser Date: Thu, 28 Nov 2019 21:06:10 -0500 Subject: [PATCH 19/34] implement get_address_book_entries() and delete_address_book_entry() --- src/wallet/monero_wallet.cpp | 32 ++++++++++++++++++++++++++++---- src/wallet/monero_wallet.h | 4 ++-- src/wallet/monero_wallet_model.h | 4 +++- todo.txt | 1 + 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 8608844..ddd052a 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -2791,19 +2791,43 @@ namespace monero { } vector monero_wallet::get_address_book_entries(const vector& indices) const { - throw runtime_error("get_address_book_entries() not implemented"); + MTRACE("monero_wallet::get_address_book_entries()"); + + // get wallet2 address book entries + const auto w2_entries = m_w2->get_address_book(); + + // build entries from wallet2 types + vector entries; + if (indices.empty()) { + uint64_t idx = 0; + for (const auto &w2_entry: w2_entries) { + monero_address_book_entry entry(idx++, cryptonote::get_account_address_as_str(m_w2->nettype(), w2_entry.m_is_subaddress, w2_entry.m_address), w2_entry.m_description, epee::string_tools::pod_to_hex(w2_entry.m_payment_id)); + entries.push_back(entry); + } + } else { + for (uint64_t idx : indices) { + if (idx >= w2_entries.size()) throw runtime_error("Index out of range: " + std::to_string(idx)); + const auto &w2_entry = w2_entries[idx]; + monero_address_book_entry entry(idx++, cryptonote::get_account_address_as_str(m_w2->nettype(), w2_entry.m_is_subaddress, w2_entry.m_address), w2_entry.m_description, epee::string_tools::pod_to_hex(w2_entry.m_payment_id)); + entries.push_back(entry); + } + } + + return entries; } uint32_t monero_wallet::add_address_book_entry(const string& address, boost::optional description, boost::optional payment_id) { throw runtime_error("add_address_book_entry() not implemented"); } - void monero_wallet::edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id) { + void monero_wallet::edit_address_book_entry(uint64_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id) { throw runtime_error("edit_address_book_entry() not implemented"); } - void monero_wallet::delete_address_book_entry(uint32_t index) { - throw runtime_error("delete_address_book_entry() not implemented"); + void monero_wallet::delete_address_book_entry(uint64_t index) { + const auto w2_entries = m_w2->get_address_book(); + if (index >= w2_entries.size()) throw runtime_error("Index out of range: " + std::to_string(index)); + if (!m_w2->delete_address_book_row(index)) throw runtime_error("Failed to delete address book entry"); } string monero_wallet::create_payment_uri(const monero_send_request& request) const { diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 1eb95fa..983dcb2 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1195,14 +1195,14 @@ namespace monero { * @param set_payment_id specifies if the payment id should be updated * @param payment_id is the updated payment id */ - void edit_address_book_entry(uint32_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id); + void edit_address_book_entry(uint64_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id); /** * Delete an address book entry. * * @param index is the index of the entry to delete */ - void delete_address_book_entry(uint32_t index); + void delete_address_book_entry(uint64_t index); // /** // * Tag accounts. diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index b14bb79..c388c23 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -448,11 +448,13 @@ namespace monero { * Monero address book entry model. */ struct monero_address_book_entry : serializable_struct { - boost::optional m_index; + boost::optional m_index; // TODO: not boost::optional boost::optional m_address; boost::optional m_description; boost::optional m_payment_id; + monero_address_book_entry() {} + monero_address_book_entry(uint64_t index, const string& address, const string& description, const string& payment_id) : m_index(index), m_address(address), m_description(description), m_payment_id(payment_id) {} boost::property_tree::ptree to_property_tree() const; }; } diff --git a/todo.txt b/todo.txt index c81d046..57b0e1b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,5 @@ TODO +preserve rpc error codes, just throwing runtime_error now gen_utils.h and monero_utils.h should not depend on monero_wallet.h add to ecosystem? monero_wallet.cpp move utilities in monero_namespace to be private From 5746fef3fea29bafba8005b2cf735b0bda6bb88c Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 08:56:35 -0500 Subject: [PATCH 20/34] add_address_book_entry(), edit_address_book_entry() impls --- src/wallet/monero_wallet.cpp | 83 +++++++++++++++++++++++++++++++++--- src/wallet/monero_wallet.h | 6 +-- 2 files changed, 81 insertions(+), 8 deletions(-) diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index ddd052a..f198965 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -2790,7 +2790,7 @@ namespace monero { } } - vector monero_wallet::get_address_book_entries(const vector& indices) const { + vector monero_wallet::get_address_book_entries(const vector& indices) const { MTRACE("monero_wallet::get_address_book_entries()"); // get wallet2 address book entries @@ -2816,12 +2816,85 @@ namespace monero { return entries; } - uint32_t monero_wallet::add_address_book_entry(const string& address, boost::optional description, boost::optional payment_id) { - throw runtime_error("add_address_book_entry() not implemented"); + uint64_t monero_wallet::add_address_book_entry(const string& address, const string& description, const string& payment_id) { + MTRACE("add_address_book_entry()"); + cryptonote::address_parse_info info; + crypto::hash payment_id_hash = crypto::null_hash; + epee::json_rpc::error er; + if(!get_account_address_from_str_or_url(info, m_w2->nettype(), address, + [&er](const std::string &url, const std::vector &addresses, bool dnssec_valid)->std::string { + if (!dnssec_valid) throw runtime_error(std::string("Invalid DNSSEC for ") + url); + if (addresses.empty()) throw runtime_error(std::string("No Monero address found at ") + url); + return addresses[0]; + })) + { + throw runtime_error(std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + address); + } + if (info.has_payment_id) { + memcpy(payment_id_hash.data, info.payment_id.data, 8); + memset(payment_id_hash.data + 8, 0, 24); + } + if (!payment_id.empty()) { + if (info.has_payment_id) throw runtime_error("Separate payment ID given with integrated address"); + crypto::hash long_payment_id; + if (!wallet2::parse_long_payment_id(payment_id, payment_id_hash)) { + if (!wallet2::parse_short_payment_id(payment_id, info.payment_id)) throw runtime_error("Payment id has invalid format: \"" + payment_id + "\", expected 64 character string"); + else throw runtime_error("Payment id has invalid format: standalone short payment IDs are forbidden, they must be part of an integrated address"); + } + } + if (!m_w2->add_address_book_row(info.address, payment_id_hash, description, info.is_subaddress)) throw runtime_error("Failed to add address book entry"); + return m_w2->get_address_book().size() - 1; } - void monero_wallet::edit_address_book_entry(uint64_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id) { - throw runtime_error("edit_address_book_entry() not implemented"); + void monero_wallet::edit_address_book_entry(uint64_t index, bool set_address, const string& address, bool set_description, const string& description, bool set_payment_id, const string& payment_id) { + MTRACE("edit_address_book_entry()"); + + const auto ab = m_w2->get_address_book(); + if (index >= ab.size()) throw runtime_error("Index out of range: " + std::to_string(index)); + + tools::wallet2::address_book_row entry = ab[index]; + + cryptonote::address_parse_info info; + crypto::hash payment_id_hash = crypto::null_hash; + epee::json_rpc::error er; + if (set_address) { + er.message = ""; + if(!get_account_address_from_str_or_url(info, m_w2->nettype(), address, + [&er](const std::string &url, const std::vector &addresses, bool dnssec_valid)->std::string { + if (!dnssec_valid) throw runtime_error(std::string("Invalid DNSSEC for ") + url); + if (addresses.empty()) throw runtime_error(std::string("No Monero address found at ") + url); + return addresses[0]; + })) + { + throw runtime_error("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: " + address); + } + entry.m_address = info.address; + entry.m_is_subaddress = info.is_subaddress; + if (info.has_payment_id) { + memcpy(entry.m_payment_id.data, info.payment_id.data, 8); + memset(entry.m_payment_id.data + 8, 0, 24); + } + } + + if (set_payment_id) { + if (payment_id.empty()) { + payment_id_hash = crypto::null_hash; + } else { + if (set_address && info.has_payment_id) throw runtime_error("Separate payment ID given with integrated address"); + if (!wallet2::parse_long_payment_id(payment_id, payment_id_hash)) { + crypto::hash8 spid; + if (!wallet2::parse_short_payment_id(payment_id, spid)) throw runtime_error("Payment id has invalid format: \"" + payment_id + "\", expected 64 character string"); + else throw runtime_error("Payment id has invalid format: standalone short payment IDs are forbidden, they must be part of an integrated address"); + } + } + entry.m_payment_id = payment_id_hash; + } + + if (set_description) entry.m_description = description; + + if (!m_w2->set_address_book_row(index, entry.m_address, entry.m_payment_id, entry.m_description, entry.m_is_subaddress)) { + throw runtime_error("Failed to edit address book entry"); + } } void monero_wallet::delete_address_book_entry(uint64_t index) { diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 983dcb2..40df6c0 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -1173,7 +1173,7 @@ namespace monero { * @param indices are indices of the entries to get * @return the address book entries */ - vector get_address_book_entries(const vector& indices) const; + vector get_address_book_entries(const vector& indices) const; /** * Add an address book entry. @@ -1182,7 +1182,7 @@ namespace monero { * @param description is the entry description (optional) * @return the index of the added entry */ - uint32_t add_address_book_entry(const string& address, boost::optional description = boost::none, boost::optional payment_id = boost::none); + uint64_t add_address_book_entry(const string& address, const string& description, const string& payment_id = ""); /** * Edit an address book entry. @@ -1195,7 +1195,7 @@ namespace monero { * @param set_payment_id specifies if the payment id should be updated * @param payment_id is the updated payment id */ - void edit_address_book_entry(uint64_t index, bool set_address, boost::optional address, bool set_description, boost::optional description, bool set_payment_id, boost::optional payment_id); + void edit_address_book_entry(uint64_t index, bool set_address, const string& address, bool set_description, const string& description, bool set_payment_id = false, const string& payment_id = ""); /** * Delete an address book entry. From 96301d1f9e171d4a46b22de09ef510fdcc3b5518 Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 09:15:21 -0500 Subject: [PATCH 21/34] indicate compatiblity with v0.15.0.1 in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 744a0e3..9424fef 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ In addition, this project conforms to an [API specification](http://moneroecosys This library may be used to build Monero-related applications, such as GUIs, libraries in other languages (e.g. [monero-java](https://github.com/monero-ecosystem/monero-java)), or a compliant REST/JSON-RPC API. +This library is compatible with [Monero Core v0.15.0.1 Carbon Chamaeleon](https://github.com/monero-project/monero/tree/v0.15.0.1). + ## Main Features - Manage Monero wallets which connect to a daemon From dab90215bfe6fafd78fa2a2cfdbe570649723d6c Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 09:42:13 -0500 Subject: [PATCH 22/34] refactor tx and output is_unlocked -> is_locked --- src/utils/monero_utils.cpp | 4 ++-- src/wallet/monero_wallet.cpp | 18 +++++++++--------- src/wallet/monero_wallet_model.cpp | 14 +++++++------- src/wallet/monero_wallet_model.h | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index 198cbd2..f33087b 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -127,7 +127,7 @@ void node_to_output_wallet(const boost::property_tree::ptree& node, shared_ptrm_account_index = it->second.get_value(); else if (key == string("subaddressIndex")) output_wallet->m_subaddress_index = it->second.get_value(); else if (key == string("isSpent")) output_wallet->m_is_spent = it->second.get_value(); - else if (key == string("isUnlocked")) output_wallet->m_is_unlocked = it->second.get_value(); + else if (key == string("isLocked")) output_wallet->m_is_locked = it->second.get_value(); else if (key == string("isFrozen")) output_wallet->m_is_frozen = it->second.get_value(); } } @@ -198,7 +198,7 @@ void node_to_tx_wallet(const boost::property_tree::ptree& node, shared_ptrfirst; //if (key == string("id")) tx->m_id = it->second.data(); - if (key == string("isUnlocked")) tx_wallet->m_is_unlocked = it->second.get_value(); + if (key == string("isLocked")) tx_wallet->m_is_locked = it->second.get_value(); // TODO: deserialize other fields } } diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index f198965..b2549f8 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -103,7 +103,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_unlock_time; - tx->m_is_unlocked = m_w2.is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); + tx->m_is_locked = !m_w2.is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); tx->m_fee = pd.m_fee; tx->m_note = m_w2.get_tx_note(pd.m_tx_hash); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -156,7 +156,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_unlock_time; - tx->m_is_unlocked = m_w2.is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); + tx->m_is_locked = !m_w2.is_transfer_unlocked(pd.m_unlock_time, pd.m_block_height); tx->m_fee = pd.m_amount_in - pd.m_amount_out; tx->m_note = m_w2.get_tx_note(txid); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -224,7 +224,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_unlock_time; - tx->m_is_unlocked = false; + tx->m_is_locked = true; tx->m_fee = pd.m_fee; tx->m_note = m_w2.get_tx_note(pd.m_tx_hash); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -266,7 +266,7 @@ namespace monero { if (tx->m_payment_id->substr(16).find_first_not_of('0') == std::string::npos) tx->m_payment_id = tx->m_payment_id->substr(0, 16); // TODO monero core: this should be part of core wallet if (tx->m_payment_id == monero_tx::DEFAULT_PAYMENT_ID) tx->m_payment_id = boost::none; // clear default payment id tx->m_unlock_time = pd.m_tx.unlock_time; - tx->m_is_unlocked = false; + tx->m_is_locked = true; tx->m_fee = pd.m_amount_in - pd.m_amount_out; tx->m_note = m_w2.get_tx_note(txid); if (tx->m_note->empty()) tx->m_note = boost::none; // clear empty note @@ -335,7 +335,7 @@ namespace monero { tx->m_in_tx_pool = false; tx->m_do_not_relay = false; tx->m_is_double_spend_seen = false; - tx->m_is_unlocked = m_w2.is_transfer_unlocked(td); + tx->m_is_locked = !m_w2.is_transfer_unlocked(td); // construct vout shared_ptr vout = make_shared(); @@ -346,7 +346,7 @@ namespace monero { vout->m_account_index = td.m_subaddr_index.major; vout->m_subaddress_index = td.m_subaddr_index.minor; vout->m_is_spent = td.m_spent; - vout->m_is_unlocked = m_w2.is_transfer_unlocked(td); // TODO: this is redundant with tx + vout->m_is_locked = !m_w2.is_transfer_unlocked(td); // TODO: this is redundant with tx vout->m_is_frozen = td.m_frozen; if (td.m_key_image_known) { vout->m_key_image = make_shared(); @@ -1982,7 +1982,7 @@ namespace monero { tx->m_num_confirmations = 0; tx->m_mixin = request.m_mixin; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); - tx->m_is_unlocked = false; + tx->m_is_locked = true; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 out_transfer->m_account_index = request.m_account_index; if (request.m_subaddress_indices.size() == 1) out_transfer->m_subaddress_indices.push_back(request.m_subaddress_indices[0]); // subaddress index is known iff 1 requested // TODO: get all known subaddress indices here @@ -2137,7 +2137,7 @@ namespace monero { shared_ptr tx = make_shared(); txs.push_back(tx); tx->m_id = *tx_ids_iter; - tx->m_is_unlocked = false; + tx->m_is_locked = true; tx->m_is_outgoing = true; tx->m_key = *tx_keys_iter; tx->m_fee = *tx_fees_iter; @@ -2276,7 +2276,7 @@ namespace monero { tx->m_num_confirmations = 0; tx->m_mixin = request.m_mixin; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); - tx->m_is_unlocked = false; + tx->m_is_locked = true; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 out_transfer->m_account_index = request.m_account_index; if (request.m_subaddress_indices.size() == 1) out_transfer->m_subaddress_indices.push_back(request.m_subaddress_indices[0]); // subaddress index is known iff 1 requested // TODO: get all known subaddress indices here diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index e61c636..e9e284e 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -136,7 +136,7 @@ namespace monero { tgt->m_outgoing_transfer = transferCopy; } tgt->m_note = src->m_note; - tgt->m_is_unlocked = src->m_is_unlocked; + tgt->m_is_locked = src->m_is_locked; tgt->m_input_sum = src->m_input_sum; tgt->m_output_sum = src->m_output_sum; tgt->m_change_address = src->m_change_address; @@ -154,7 +154,7 @@ namespace monero { if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); if (m_note != boost::none) node.put("note", *m_note); - if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); + if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); @@ -194,7 +194,7 @@ namespace monero { m_is_incoming = gen_utils::reconcile(m_is_incoming, other->m_is_incoming); m_is_outgoing = gen_utils::reconcile(m_is_outgoing, other->m_is_outgoing); m_note = gen_utils::reconcile(m_note, other->m_note); - m_is_unlocked = gen_utils::reconcile(m_is_unlocked, other->m_is_unlocked); + m_is_locked = gen_utils::reconcile(m_is_locked, other->m_is_locked); m_input_sum = gen_utils::reconcile(m_input_sum, other->m_input_sum); m_output_sum = gen_utils::reconcile(m_output_sum, other->m_output_sum); m_change_address = gen_utils::reconcile(m_change_address, other->m_change_address); @@ -261,7 +261,7 @@ namespace monero { if (m_do_not_relay != boost::none && m_do_not_relay != tx->m_do_not_relay) return false; if (m_is_failed != boost::none && m_is_failed != tx->m_is_failed) return false; if (m_is_miner_tx != boost::none && m_is_miner_tx != tx->m_is_miner_tx) return false; - if (m_is_unlocked != boost::none && m_is_unlocked != tx->m_is_unlocked) return false; + if (m_is_locked != boost::none && m_is_locked != tx->m_is_locked) return false; // at least one transfer must meet transfer query if defined if (m_transfer_query != boost::none) { @@ -582,7 +582,7 @@ namespace monero { tgt->m_account_index = src->m_account_index; tgt->m_subaddress_index = src->m_subaddress_index; tgt->m_is_spent = src->m_is_spent; - tgt->m_is_unlocked = src->m_is_unlocked; + tgt->m_is_locked = src->m_is_locked; tgt->m_is_frozen = src->m_is_frozen; return tgt; }; @@ -592,7 +592,7 @@ namespace monero { if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); - if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); + if (m_is_locked != boost::none) node.put("isUnlocked", *m_is_locked); if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); return node; } @@ -656,7 +656,7 @@ namespace monero { if (m_subaddress_index != boost::none && (output->m_subaddress_index == boost::none || *m_subaddress_index != *output->m_subaddress_index)) return false; if (m_amount != boost::none && (output->m_amount == boost::none || *m_amount != *output->m_amount)) return false; if (m_is_spent != boost::none && (output->m_is_spent == boost::none || *m_is_spent != *output->m_is_spent)) return false; - if (m_is_unlocked != boost::none && (output->m_is_unlocked == boost::none || *m_is_unlocked != *output->m_is_unlocked)) return false; + if (m_is_locked != boost::none && (output->m_is_locked == boost::none || *m_is_locked != *output->m_is_locked)) return false; // filter on output key image if (m_key_image != boost::none) { diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index c388c23..6626820 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -221,7 +221,7 @@ namespace monero { boost::optional m_account_index; boost::optional m_subaddress_index; boost::optional m_is_spent; - boost::optional m_is_unlocked; + boost::optional m_is_locked; boost::optional m_is_frozen; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -263,7 +263,7 @@ namespace monero { vector> m_incoming_transfers; boost::optional> m_outgoing_transfer; boost::optional m_note; - boost::optional m_is_unlocked; + boost::optional m_is_locked; boost::optional m_input_sum; boost::optional m_output_sum; boost::optional m_change_address; From ef0fa66180cb57ce7e758de7f5eb0ab63dc8b0f7 Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 09:45:58 -0500 Subject: [PATCH 23/34] fix isLocked key --- src/wallet/monero_wallet_model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index e9e284e..7aa89e8 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -592,7 +592,7 @@ namespace monero { if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); - if (m_is_locked != boost::none) node.put("isUnlocked", *m_is_locked); + if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); return node; } From cad7a3156716097cbbf47a6212070682b010793a Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 11:23:10 -0500 Subject: [PATCH 24/34] replace output is_locked with tx wallet is_locked --- src/utils/monero_utils.cpp | 4 +++- src/wallet/monero_wallet.cpp | 1 - src/wallet/monero_wallet_model.cpp | 4 +--- src/wallet/monero_wallet_model.h | 1 - 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index f33087b..a8d22d6 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -117,6 +117,7 @@ void node_to_output(const boost::property_tree::ptree& node, shared_ptrm_index = it->second.get_value(); else if (key == string("ringOutputIndices")) throw runtime_error("node_to_tx() deserialize ringOutputIndices not implemented"); else if (key == string("stealthPublicKey")) throw runtime_error("node_to_tx() deserialize stealthPublicKey not implemented"); + else cout << "WARNING: unrecognized field deserializing node to output: " << key << endl; } } @@ -127,8 +128,8 @@ void node_to_output_wallet(const boost::property_tree::ptree& node, shared_ptrm_account_index = it->second.get_value(); else if (key == string("subaddressIndex")) output_wallet->m_subaddress_index = it->second.get_value(); else if (key == string("isSpent")) output_wallet->m_is_spent = it->second.get_value(); - else if (key == string("isLocked")) output_wallet->m_is_locked = it->second.get_value(); else if (key == string("isFrozen")) output_wallet->m_is_frozen = it->second.get_value(); + else cout << "WARNING: unrecognized field deserializing node to output wallet: " << key << endl; } } @@ -141,6 +142,7 @@ shared_ptr node_to_output_query(const boost::property_tree: string key = it->first; if (key == string("subaddressIndices")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) m_output_query->m_subaddress_indices.push_back(it2->second.get_value()); else if (key == string("txQuery")) {} // ignored + else cout << "WARNING: unrecognized field deserializing node to output query: " << key << endl; } return m_output_query; diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index b2549f8..6548064 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -346,7 +346,6 @@ namespace monero { vout->m_account_index = td.m_subaddr_index.major; vout->m_subaddress_index = td.m_subaddr_index.minor; vout->m_is_spent = td.m_spent; - vout->m_is_locked = !m_w2.is_transfer_unlocked(td); // TODO: this is redundant with tx vout->m_is_frozen = td.m_frozen; if (td.m_key_image_known) { vout->m_key_image = make_shared(); diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 7aa89e8..b60c461 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -582,7 +582,6 @@ namespace monero { tgt->m_account_index = src->m_account_index; tgt->m_subaddress_index = src->m_subaddress_index; tgt->m_is_spent = src->m_is_spent; - tgt->m_is_locked = src->m_is_locked; tgt->m_is_frozen = src->m_is_frozen; return tgt; }; @@ -592,7 +591,6 @@ namespace monero { if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); - if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); return node; } @@ -613,6 +611,7 @@ namespace monero { m_account_index = gen_utils::reconcile(m_account_index, other->m_account_index); m_subaddress_index = gen_utils::reconcile(m_subaddress_index, other->m_subaddress_index); m_is_spent = gen_utils::reconcile(m_is_spent, other->m_is_spent); + m_is_frozen = gen_utils::reconcile(m_is_frozen, other->m_is_frozen); } // ------------------------ MONERO OUTPUT REQUEST --------------------------- @@ -656,7 +655,6 @@ namespace monero { if (m_subaddress_index != boost::none && (output->m_subaddress_index == boost::none || *m_subaddress_index != *output->m_subaddress_index)) return false; if (m_amount != boost::none && (output->m_amount == boost::none || *m_amount != *output->m_amount)) return false; if (m_is_spent != boost::none && (output->m_is_spent == boost::none || *m_is_spent != *output->m_is_spent)) return false; - if (m_is_locked != boost::none && (output->m_is_locked == boost::none || *m_is_locked != *output->m_is_locked)) return false; // filter on output key image if (m_key_image != boost::none) { diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 6626820..7152f4d 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -221,7 +221,6 @@ namespace monero { boost::optional m_account_index; boost::optional m_subaddress_index; boost::optional m_is_spent; - boost::optional m_is_locked; boost::optional m_is_frozen; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; From 8a807753447fa62bcff2374e2ca1146e355e0acc Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 11:42:32 -0500 Subject: [PATCH 25/34] replace mixin with ring size --- src/daemon/monero_daemon_model.cpp | 6 +++--- src/daemon/monero_daemon_model.h | 2 +- src/utils/monero_utils.cpp | 1 - src/wallet/monero_wallet.cpp | 20 ++++++++++---------- src/wallet/monero_wallet_model.cpp | 2 -- src/wallet/monero_wallet_model.h | 1 - 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index cf5ca15..4d565d6 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -192,7 +192,7 @@ namespace monero { tgt->m_is_miner_tx = src->m_is_miner_tx; tgt->m_payment_id = src->m_payment_id; tgt->m_fee = src->m_fee; - tgt->m_mixin = src->m_mixin; + tgt->m_ring_size = src->m_ring_size; tgt->m_do_not_relay = src->m_do_not_relay; tgt->m_is_relayed = src->m_is_relayed; tgt->m_is_confirmed = src->m_is_confirmed; @@ -248,7 +248,7 @@ namespace monero { if (m_is_miner_tx != boost::none) node.put("isMinerTx", *m_is_miner_tx); if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); if (m_fee != boost::none) node.put("fee", *m_fee); - if (m_mixin != boost::none) node.put("mixin", *m_mixin); + if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); if (m_is_relayed != boost::none) node.put("isRelayed", *m_is_relayed); if (m_is_confirmed != boost::none) node.put("isConfirmed", *m_is_confirmed); @@ -313,7 +313,7 @@ namespace monero { m_version = gen_utils::reconcile(m_version, other->m_version); m_payment_id = gen_utils::reconcile(m_payment_id, other->m_payment_id); m_fee = gen_utils::reconcile(m_fee, other->m_fee, "tx fee"); - m_mixin = gen_utils::reconcile(m_mixin, other->m_mixin, "tx m_mixin"); + m_ring_size = gen_utils::reconcile(m_ring_size, other->m_ring_size, "tx m_ring_size"); m_is_confirmed = gen_utils::reconcile(m_is_confirmed, other->m_is_confirmed); m_do_not_relay = gen_utils::reconcile(m_do_not_relay, other->m_do_not_relay); m_is_relayed = gen_utils::reconcile(m_is_relayed, other->m_is_relayed); diff --git a/src/daemon/monero_daemon_model.h b/src/daemon/monero_daemon_model.h index 60a2ad0..391d132 100644 --- a/src/daemon/monero_daemon_model.h +++ b/src/daemon/monero_daemon_model.h @@ -170,7 +170,7 @@ namespace monero { boost::optional m_is_miner_tx; boost::optional m_payment_id; boost::optional m_fee; - boost::optional m_mixin; + boost::optional m_ring_size; boost::optional m_do_not_relay; boost::optional m_is_relayed; boost::optional m_is_confirmed; diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index a8d22d6..ca0f94f 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -435,7 +435,6 @@ shared_ptr monero_utils::deserialize_send_request(const str } else if (key == string("paymentId")) send_request->m_payment_id = it->second.data(); else if (key == string("priority")) throw runtime_error("deserialize_send_request() priority not implemented"); - else if (key == string("mixin")) send_request->m_mixin = it->second.get_value(); else if (key == string("ringSize")) send_request->m_ring_size = it->second.get_value(); else if (key == string("fee")) send_request->m_fee = it->second.get_value(); else if (key == string("accountIndex")) send_request->m_account_index = it->second.get_value(); diff --git a/src/wallet/monero_wallet.cpp b/src/wallet/monero_wallet.cpp index 6548064..5727928 100644 --- a/src/wallet/monero_wallet.cpp +++ b/src/wallet/monero_wallet.cpp @@ -1979,7 +1979,7 @@ namespace monero { tx->m_in_tx_pool = !tx->m_do_not_relay.get(); if (!tx->m_is_failed.get() && tx->m_is_relayed.get()) tx->m_is_double_spend_seen = false; // TODO: test and handle if true tx->m_num_confirmations = 0; - tx->m_mixin = request.m_mixin; + tx->m_ring_size = request.m_ring_size; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); tx->m_is_locked = true; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 @@ -2158,7 +2158,7 @@ namespace monero { tx->m_in_tx_pool = !do_not_relay; if (!tx->m_is_failed.get() && tx->m_is_relayed.get()) tx->m_is_double_spend_seen = false; // TODO: test and handle if true tx->m_num_confirmations = 0; - tx->m_mixin = request.m_mixin; + tx->m_ring_size = request.m_ring_size; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 out_transfer->m_account_index = request.m_account_index; @@ -2210,10 +2210,10 @@ namespace monero { } // create transaction - uint64_t m_mixin = m_w2->adjust_mixin(request.m_ring_size == boost::none ? 0 : request.m_ring_size.get() - 1); + uint64_t mixin = m_w2->adjust_mixin(request.m_ring_size == boost::none ? 0 : request.m_ring_size.get() - 1); uint32_t priority = m_w2->adjust_priority(request.m_priority == boost::none ? 0 : request.m_priority.get()); - uint64_t m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); - std::vector ptx_vector = m_w2->create_transactions_single(ki, dsts[0].addr, dsts[0].is_subaddress, 1, m_mixin, m_unlock_time, priority, extra); + uint64_t unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); + std::vector ptx_vector = m_w2->create_transactions_single(ki, dsts[0].addr, dsts[0].is_subaddress, 1, mixin, unlock_time, priority, extra); // validate created transaction if (ptx_vector.empty()) throw runtime_error("No outputs found"); @@ -2273,7 +2273,7 @@ namespace monero { tx->m_in_tx_pool = !tx->m_do_not_relay.get(); if (!tx->m_is_failed.get() && tx->m_is_relayed.get()) tx->m_is_double_spend_seen = false; // TODO: test and handle if true tx->m_num_confirmations = 0; - tx->m_mixin = request.m_mixin; + tx->m_ring_size = request.m_ring_size; tx->m_unlock_time = request.m_unlock_time == boost::none ? 0 : request.m_unlock_time.get(); tx->m_is_locked = true; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 @@ -2359,7 +2359,7 @@ namespace monero { tx->m_in_tx_pool = !tx->m_do_not_relay.get(); if (!tx->m_is_failed.get() && tx->m_is_relayed.get()) tx->m_is_double_spend_seen = false; // TODO: test and handle if true tx->m_num_confirmations = 0; - //tx->m_mixin = request.m_mixin; // TODO: how to get? + //tx->m_ring_size = request.m_ring_size; // TODO: how to get? tx->m_unlock_time = 0; if (tx->m_is_relayed.get()) tx->m_last_relayed_timestamp = static_cast(time(NULL)); // set last relayed timestamp to current time iff relayed // TODO monero core: this should be encapsulated in wallet2 out_transfer->m_destinations[0]->m_amount = *tx_amounts_iter; @@ -2439,7 +2439,7 @@ namespace monero { tx->m_output_sum = 0; tx->m_change_amount = 0; tx->m_num_dummy_outputs = 0; - tx->m_mixin = std::numeric_limits::max() - 1; // smaller ring sizes will overwrite // TODO: remove - 1 when switched to ring size + tx->m_ring_size = std::numeric_limits::max(); // smaller ring sizes will overwrite const tools::wallet2::tx_construction_data &cd = tx_constructions[n]; std::vector tx_extra_fields; @@ -2470,8 +2470,8 @@ namespace monero { { tx->m_input_sum = tx->m_input_sum.get() + cd.sources[s].amount; size_t ring_size = cd.sources[s].outputs.size(); - if (ring_size < tx->m_mixin.get() + 1) - tx->m_mixin = ring_size - 1; // TODO: switch to m_ring_size + if (ring_size < tx->m_ring_size.get()) + tx->m_ring_size = ring_size; } for (size_t d = 0; d < cd.splitted_dsts.size(); ++d) { diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index b60c461..61ebcf1 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -683,7 +683,6 @@ namespace monero { } m_payment_id = request.m_payment_id; m_priority = request.m_priority; - m_mixin = request.m_mixin; m_ring_size = request.m_ring_size; m_fee = request.m_fee; m_account_index = request.m_account_index; @@ -707,7 +706,6 @@ namespace monero { if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); if (m_priority != boost::none) node.put("priority", *m_priority); - if (m_mixin != boost::none) node.put("mixin", *m_mixin); if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 7152f4d..513ad44 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -348,7 +348,6 @@ namespace monero { vector> m_destinations; boost::optional m_payment_id; boost::optional m_priority; - boost::optional m_mixin; boost::optional m_ring_size; boost::optional m_fee; boost::optional m_account_index; From 2aef5a65f407b392b2c29aed5c84ee0c627d2be9 Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 16:21:34 -0500 Subject: [PATCH 26/34] merge updates from latest wasm branch, mostly serializing using rapidjson instead of boost::property_tree --- CMakeLists.txt | 13 +- src/daemon/monero_daemon_model.cpp | 392 ++++++++++++---- src/daemon/monero_daemon_model.h | 36 +- src/utils/monero_utils.cpp | 182 ++++++-- src/utils/monero_utils.h | 108 +++-- src/wallet/monero_wallet_model.cpp | 697 ++++++++++++++++++++++------- src/wallet/monero_wallet_model.h | 103 +++-- todo.txt | 1 + 8 files changed, 1145 insertions(+), 387 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52e5063..427f6fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,18 +8,19 @@ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11 -F/Library/Frameworks - project(MoneroCppLibrary) -############# -# System -############# +################### +# monero-project +################### set(MONERO_CORE "external/monero-core") set(MONERO_CORE_SRC "${MONERO_CORE}/src") # header includes include_directories(src/) -include_directories(${MONERO_CORE}/contrib/epee/include) -include_directories(${MONERO_CORE}/external/) -include_directories(${MONERO_CORE}/external/easylogging++) +include_directories("${MONERO_CORE}/contrib/epee/include") +include_directories("${MONERO_CORE}/external/") +include_directories("${MONERO_CORE}/external/easylogging++") +include_directories("${MONERO_CORE}/external/rapidjson/include") include_directories("${MONERO_CORE_SRC}/") include_directories("${MONERO_CORE_SRC}/wallet") include_directories("${MONERO_CORE_SRC}/wallet/api") diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index 4d565d6..f16cc1e 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -1,3 +1,55 @@ +//SERIALIZATION TEMPLATE +// // create root +// rapidjson::Value root(rapidjson::kObjectType); + +// // serialize root from superclass +// rapidjson::Value root = superclass::to_json_val(allocator); +// +// // set num values +// rapidjson::Value value_num(rapidjson::kNumberType); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); +// +// // set string values +// rapidjson::Value value_str(rapidjson::kStringType); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); +// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); +// +// // set bool values +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); +// +// // set sub-arrays +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); +// +// // set sub-objects +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// +// // return root +// return root; + + /** * Copyright (c) 2017-2019 woodser * @@ -81,41 +133,96 @@ namespace monero { // ------------------------- SERIALIZABLE STRUCT ---------------------------- string serializable_struct::serialize() const { - return monero_utils::serialize(to_property_tree()); + rapidjson::Document doc; + doc.SetObject(); + rapidjson::Value val = to_json_val(doc.GetAllocator()); + val.Swap(doc); + return monero_utils::serialize(doc); } // ----------------------------- MONERO VERSION ----------------------------- - boost::property_tree::ptree monero_version::to_property_tree() const { - boost::property_tree::ptree node; - if (m_version_number != boost::none) node.put("versionNumber", *m_version_number); - if (m_is_release != boost::none) node.put("isRelease", *m_is_release); - return node; +// boost::property_tree::ptree monero_version::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_version_number != boost::none) node.put("versionNumber", *m_version_number); +// if (m_is_release != boost::none) node.put("isRelease", *m_is_release); +// return node; +// } + + rapidjson::Value monero_version::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_version_number != boost::none) monero_utils::addJsonMember("versionNumber", m_version_number.get(), allocator, root, value_num); + + // set bool values + if (m_is_release != boost::none) monero_utils::addJsonMember("isRelease", m_is_release.get(), allocator, root); + + // return root + return root; } // ------------------------- MONERO BLOCK HEADER ---------------------------- - boost::property_tree::ptree monero_block_header::to_property_tree() const { - boost::property_tree::ptree node; - if (m_id != boost::none) node.put("id", *m_id); - if (m_height != boost::none) node.put("height", *m_height); - if (m_timestamp != boost::none) node.put("timestamp", *m_timestamp); - if (m_size != boost::none) node.put("size", *m_size); - if (m_weight != boost::none) node.put("weight", *m_weight); - if (m_long_term_weight != boost::none) node.put("longTermWeight", *m_long_term_weight); - if (m_depth != boost::none) node.put("depth", *m_depth); - if (m_difficulty != boost::none) node.put("difficulty", *m_difficulty); - if (m_cumulative_difficulty != boost::none) node.put("cumulativeDifficulty", *m_cumulative_difficulty); - if (m_major_version != boost::none) node.put("majorVersion", *m_major_version); - if (m_minor_version != boost::none) node.put("minorVersion", *m_minor_version); - if (m_nonce != boost::none) node.put("m_nonce", *m_nonce); - if (m_miner_tx_id != boost::none) node.put("minerTxId", *m_miner_tx_id); - if (m_num_txs != boost::none) node.put("numTxs", *m_num_txs); - if (m_orphan_status != boost::none) node.put("orphanStatus", *m_orphan_status); - if (m_prev_id != boost::none) node.put("prevId", *m_prev_id); - if (m_reward != boost::none) node.put("m_reward", *m_reward); - if (m_pow_hash != boost::none) node.put("powHash", *m_pow_hash); - return node; +// boost::property_tree::ptree monero_block_header::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_id != boost::none) node.put("id", *m_id); +// if (m_height != boost::none) node.put("height", *m_height); +// if (m_timestamp != boost::none) node.put("timestamp", *m_timestamp); +// if (m_size != boost::none) node.put("size", *m_size); +// if (m_weight != boost::none) node.put("weight", *m_weight); +// if (m_long_term_weight != boost::none) node.put("longTermWeight", *m_long_term_weight); +// if (m_depth != boost::none) node.put("depth", *m_depth); +// if (m_difficulty != boost::none) node.put("difficulty", *m_difficulty); +// if (m_cumulative_difficulty != boost::none) node.put("cumulativeDifficulty", *m_cumulative_difficulty); +// if (m_major_version != boost::none) node.put("majorVersion", *m_major_version); +// if (m_minor_version != boost::none) node.put("minorVersion", *m_minor_version); +// if (m_nonce != boost::none) node.put("m_nonce", *m_nonce); +// if (m_miner_tx_id != boost::none) node.put("minerTxId", *m_miner_tx_id); +// if (m_num_txs != boost::none) node.put("numTxs", *m_num_txs); +// if (m_orphan_status != boost::none) node.put("orphanStatus", *m_orphan_status); +// if (m_prev_id != boost::none) node.put("prevId", *m_prev_id); +// if (m_reward != boost::none) node.put("m_reward", *m_reward); +// if (m_pow_hash != boost::none) node.put("powHash", *m_pow_hash); +// return node; +// } + + rapidjson::Value monero_block_header::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_height != boost::none) monero_utils::addJsonMember("height", m_height.get(), allocator, root, value_num); + if (m_timestamp != boost::none) monero_utils::addJsonMember("timestamp", m_timestamp.get(), allocator, root, value_num); + if (m_size != boost::none) monero_utils::addJsonMember("size", m_size.get(), allocator, root, value_num); + if (m_weight != boost::none) monero_utils::addJsonMember("weight", m_weight.get(), allocator, root, value_num); + if (m_long_term_weight != boost::none) monero_utils::addJsonMember("longTermWeight", m_long_term_weight.get(), allocator, root, value_num); + if (m_depth != boost::none) monero_utils::addJsonMember("depth", m_depth.get(), allocator, root, value_num); + if (m_difficulty != boost::none) monero_utils::addJsonMember("difficulty", m_difficulty.get(), allocator, root, value_num); + if (m_cumulative_difficulty != boost::none) monero_utils::addJsonMember("cumulativeDifficulty", m_cumulative_difficulty.get(), allocator, root, value_num); + if (m_major_version != boost::none) monero_utils::addJsonMember("majorVersion", m_major_version.get(), allocator, root, value_num); + if (m_minor_version != boost::none) monero_utils::addJsonMember("minorVersion", m_minor_version.get(), allocator, root, value_num); + if (m_nonce != boost::none) monero_utils::addJsonMember("nonce", m_nonce.get(), allocator, root, value_num); + if (m_miner_tx_id != boost::none) monero_utils::addJsonMember("minerTxId", m_miner_tx_id.get(), allocator, root, value_num); + if (m_num_txs != boost::none) monero_utils::addJsonMember("numTxs", m_num_txs.get(), allocator, root, value_num); + if (m_reward != boost::none) monero_utils::addJsonMember("reward", m_reward.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_id != boost::none) monero_utils::addJsonMember("id", m_id.get(), allocator, root, value_str); + if (m_prev_id != boost::none) monero_utils::addJsonMember("prevId", m_prev_id.get(), allocator, root, value_str); + if (m_pow_hash != boost::none) monero_utils::addJsonMember("powHash", m_pow_hash.get(), allocator, root, value_str); + + // set bool values + if (m_orphan_status != boost::none) monero_utils::addJsonMember("orphanStatus", m_orphan_status.get(), allocator, root); + + // return root + return root; } void monero_block_header::merge(const shared_ptr& self, const shared_ptr& other) { @@ -143,13 +250,33 @@ namespace monero { // ----------------------------- MONERO BLOCK ------------------------------- - boost::property_tree::ptree monero_block::to_property_tree() const { - boost::property_tree::ptree node = monero_block_header::to_property_tree(); - if (m_hex != boost::none) node.put("hex", *m_hex); - if (m_miner_tx != boost::none) node.add_child("minerTx", (*m_miner_tx)->to_property_tree()); - if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); - if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); - return node; +// boost::property_tree::ptree monero_block::to_property_tree() const { +// boost::property_tree::ptree node = monero_block_header::to_property_tree(); +// if (m_hex != boost::none) node.put("hex", *m_hex); +// if (m_miner_tx != boost::none) node.add_child("minerTx", (*m_miner_tx)->to_property_tree()); +// if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); +// if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); +// return node; +// } + + rapidjson::Value monero_block::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_block_header::to_json_val(allocator); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_hex != boost::none) monero_utils::addJsonMember("hex", m_hex.get(), allocator, root, value_str); + + // set sub-arrays + if (!m_txs.empty()) root.AddMember("txs", monero_utils::to_json_val(allocator, m_txs), allocator); + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); + + // set sub-objects + if (m_miner_tx != boost::none) root.AddMember("minerTx", m_miner_tx.get()->to_json_val(allocator), allocator); + + // return root + return root; } void monero_block::merge(const shared_ptr& self, const shared_ptr& other) { @@ -241,46 +368,102 @@ namespace monero { return tgt; } - boost::property_tree::ptree monero_tx::to_property_tree() const { - boost::property_tree::ptree node; - if (m_id != boost::none) node.put("id", *m_id); - if (m_version != boost::none) node.put("version", *m_version); - if (m_is_miner_tx != boost::none) node.put("isMinerTx", *m_is_miner_tx); - if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); - if (m_fee != boost::none) node.put("fee", *m_fee); - if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); - if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); - if (m_is_relayed != boost::none) node.put("isRelayed", *m_is_relayed); - if (m_is_confirmed != boost::none) node.put("isConfirmed", *m_is_confirmed); - if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); - if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); - if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); - if (m_last_relayed_timestamp != boost::none) node.put("lastRelayedTimestamp", *m_last_relayed_timestamp); - if (m_received_timestamp != boost::none) node.put("receivedTimestamp", *m_received_timestamp); - if (m_is_double_spend_seen != boost::none) node.put("isDoubleSpendSeen", *m_is_double_spend_seen); - if (m_key != boost::none) node.put("key", *m_key); - if (m_full_hex != boost::none) node.put("fullHex", *m_full_hex); - if (m_pruned_hex != boost::none) node.put("prunedHex", *m_pruned_hex); - if (m_prunable_hex != boost::none) node.put("prunableHex", *m_prunable_hex); - if (m_prunable_hash != boost::none) node.put("prunableHash", *m_prunable_hash); - if (m_size != boost::none) node.put("size", *m_size); - if (m_weight != boost::none) node.put("weight", *m_weight); - if (!m_vins.empty()) node.add_child("vins", monero_utils::to_property_tree(m_vins)); - if (!m_vouts.empty()) node.add_child("vouts", monero_utils::to_property_tree(m_vouts)); - if (!m_output_indices.empty()) throw runtime_error("m_output_indices not implemented"); - if (m_metadata != boost::none) node.put("metadata", *m_metadata); - if (m_common_tx_sets != boost::none) throw runtime_error("m_common_tx_sets not implemented"); - if (!m_extra.empty()) node.add_child("extra", monero_utils::to_property_tree(m_extra)); - if (m_rct_signatures != boost::none) throw runtime_error("m_rct_signatures not implemented"); - if (m_rct_sig_prunable != boost::none) throw runtime_error("m_rct_sig_prunable not implemented"); - if (m_is_kept_by_block != boost::none) node.put("isKeptByBlock", *m_is_kept_by_block); - if (m_is_failed != boost::none) node.put("isFailed", *m_is_failed); - if (m_last_failed_height != boost::none) node.put("lastFailedHeight", *m_last_failed_height); - if (m_last_failed_id != boost::none) node.put("lastFailedId", *m_last_failed_id); - if (m_max_used_block_height != boost::none) node.put("maxUsedBlockHeight", *m_max_used_block_height); - if (m_max_used_block_id != boost::none) node.put("maxUsedBlockId", *m_max_used_block_id); - if (!m_signatures.empty()) throw runtime_error("m_signatures not implemented"); - return node; +// boost::property_tree::ptree monero_tx::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_id != boost::none) node.put("id", *m_id); +// if (m_version != boost::none) node.put("version", *m_version); +// if (m_is_miner_tx != boost::none) node.put("isMinerTx", *m_is_miner_tx); +// if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); +// if (m_fee != boost::none) node.put("fee", *m_fee); +// if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); +// if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); +// if (m_is_relayed != boost::none) node.put("isRelayed", *m_is_relayed); +// if (m_is_confirmed != boost::none) node.put("isConfirmed", *m_is_confirmed); +// if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); +// if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); +// if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); +// if (m_last_relayed_timestamp != boost::none) node.put("lastRelayedTimestamp", *m_last_relayed_timestamp); +// if (m_received_timestamp != boost::none) node.put("receivedTimestamp", *m_received_timestamp); +// if (m_is_double_spend_seen != boost::none) node.put("isDoubleSpendSeen", *m_is_double_spend_seen); +// if (m_key != boost::none) node.put("key", *m_key); +// if (m_full_hex != boost::none) node.put("fullHex", *m_full_hex); +// if (m_pruned_hex != boost::none) node.put("prunedHex", *m_pruned_hex); +// if (m_prunable_hex != boost::none) node.put("prunableHex", *m_prunable_hex); +// if (m_prunable_hash != boost::none) node.put("prunableHash", *m_prunable_hash); +// if (m_size != boost::none) node.put("size", *m_size); +// if (m_weight != boost::none) node.put("weight", *m_weight); +// if (!m_vins.empty()) node.add_child("vins", monero_utils::to_property_tree(m_vins)); +// if (!m_vouts.empty()) node.add_child("vouts", monero_utils::to_property_tree(m_vouts)); +// if (!m_output_indices.empty()) throw runtime_error("m_output_indices not implemented"); +// if (m_metadata != boost::none) node.put("metadata", *m_metadata); +// if (m_common_tx_sets != boost::none) throw runtime_error("m_common_tx_sets not implemented"); +// if (!m_extra.empty()) node.add_child("extra", monero_utils::to_property_tree(m_extra)); +// if (m_rct_signatures != boost::none) throw runtime_error("m_rct_signatures not implemented"); +// if (m_rct_sig_prunable != boost::none) throw runtime_error("m_rct_sig_prunable not implemented"); +// if (m_is_kept_by_block != boost::none) node.put("isKeptByBlock", *m_is_kept_by_block); +// if (m_is_failed != boost::none) node.put("isFailed", *m_is_failed); +// if (m_last_failed_height != boost::none) node.put("lastFailedHeight", *m_last_failed_height); +// if (m_last_failed_id != boost::none) node.put("lastFailedId", *m_last_failed_id); +// if (m_max_used_block_height != boost::none) node.put("maxUsedBlockHeight", *m_max_used_block_height); +// if (m_max_used_block_id != boost::none) node.put("maxUsedBlockId", *m_max_used_block_id); +// if (!m_signatures.empty()) throw runtime_error("m_signatures not implemented"); +// return node; +// } + + rapidjson::Value monero_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_version != boost::none) monero_utils::addJsonMember("version", m_version.get(), allocator, root, value_num); + if (m_fee != boost::none) monero_utils::addJsonMember("fee", m_fee.get(), allocator, root, value_num); + if (m_ring_size != boost::none) monero_utils::addJsonMember("ringSize", m_ring_size.get(), allocator, root, value_num); + if (m_num_confirmations != boost::none) monero_utils::addJsonMember("numConfirmations", m_num_confirmations.get(), allocator, root, value_num); + if (m_unlock_time != boost::none) monero_utils::addJsonMember("unlockTime", m_unlock_time.get(), allocator, root, value_num); + if (m_last_relayed_timestamp != boost::none) monero_utils::addJsonMember("lastRelayedTimestamp", m_last_relayed_timestamp.get(), allocator, root, value_num); + if (m_received_timestamp != boost::none) monero_utils::addJsonMember("receivedTimestamp", m_received_timestamp.get(), allocator, root, value_num); + if (m_size != boost::none) monero_utils::addJsonMember("size", m_size.get(), allocator, root, value_num); + if (m_weight != boost::none) monero_utils::addJsonMember("weight", m_weight.get(), allocator, root, value_num); + if (m_last_failed_height != boost::none) monero_utils::addJsonMember("lastFailedHeight", m_last_failed_height.get(), allocator, root, value_num); + if (m_max_used_block_height != boost::none) monero_utils::addJsonMember("maxUsedBlockHeight", m_max_used_block_height.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_id != boost::none) monero_utils::addJsonMember("id", m_id.get(), allocator, root, value_str); + if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); + if (m_key != boost::none) monero_utils::addJsonMember("key", m_key.get(), allocator, root, value_str); + if (m_full_hex != boost::none) monero_utils::addJsonMember("fullHex", m_full_hex.get(), allocator, root, value_str); + if (m_pruned_hex != boost::none) monero_utils::addJsonMember("prunedHex", m_pruned_hex.get(), allocator, root, value_str); + if (m_prunable_hex != boost::none) monero_utils::addJsonMember("prunableHex", m_prunable_hex.get(), allocator, root, value_str); + if (m_prunable_hash != boost::none) monero_utils::addJsonMember("prunableHash", m_prunable_hash.get(), allocator, root, value_str); + if (m_metadata != boost::none) monero_utils::addJsonMember("metadata", m_metadata.get(), allocator, root, value_str); + if (m_common_tx_sets != boost::none) monero_utils::addJsonMember("commonTxSets", m_common_tx_sets.get(), allocator, root, value_str); + if (m_rct_signatures != boost::none) monero_utils::addJsonMember("rctSignatures", m_rct_signatures.get(), allocator, root, value_str); + if (m_rct_sig_prunable != boost::none) monero_utils::addJsonMember("rctSigPrunable", m_rct_sig_prunable.get(), allocator, root, value_str); + if (m_last_failed_id != boost::none) monero_utils::addJsonMember("lastFailedId", m_last_failed_id.get(), allocator, root, value_str); + if (m_max_used_block_id != boost::none) monero_utils::addJsonMember("maxUsedBlockId", m_max_used_block_id.get(), allocator, root, value_str); + + // set bool values + if (m_is_miner_tx != boost::none) monero_utils::addJsonMember("isMinerTx", m_is_miner_tx.get(), allocator, root); + if (m_do_not_relay != boost::none) monero_utils::addJsonMember("doNotRelay", m_do_not_relay.get(), allocator, root); + if (m_is_relayed != boost::none) monero_utils::addJsonMember("isRelayed", m_is_relayed.get(), allocator, root); + if (m_is_confirmed != boost::none) monero_utils::addJsonMember("isConfirmed", m_is_confirmed.get(), allocator, root); + if (m_in_tx_pool != boost::none) monero_utils::addJsonMember("inTxPool", m_in_tx_pool.get(), allocator, root); + if (m_is_double_spend_seen != boost::none) monero_utils::addJsonMember("isDoubleSpendSeen", m_is_double_spend_seen.get(), allocator, root); + if (m_is_kept_by_block != boost::none) monero_utils::addJsonMember("isKeptByBlock", m_is_kept_by_block.get(), allocator, root); + if (m_is_failed != boost::none) monero_utils::addJsonMember("isFailed", m_is_failed.get(), allocator, root); + + // set sub-arrays + if (!m_vins.empty()) root.AddMember("vins", monero_utils::to_json_val(allocator, m_vins), allocator); + if (!m_vouts.empty()) root.AddMember("vouts", monero_utils::to_json_val(allocator, m_vouts), allocator); + if (!m_output_indices.empty()) root.AddMember("outputIndices", monero_utils::to_json_val(allocator, m_output_indices), allocator); + if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_json_val(allocator, m_extra), allocator); // TODO + if (!m_signatures.empty()) root.AddMember("signatures", monero_utils::to_json_val(allocator, m_signatures), allocator); + + // return root + return root; } boost::optional monero_tx::get_height() const { @@ -451,11 +634,25 @@ namespace monero { return tgt; } - boost::property_tree::ptree monero_key_image::to_property_tree() const { - boost::property_tree::ptree node; - if (m_hex != boost::none) node.put("hex", *m_hex); - if (m_signature != boost::none) node.put("signature", *m_signature); - return node; +// boost::property_tree::ptree monero_key_image::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_hex != boost::none) node.put("hex", *m_hex); +// if (m_signature != boost::none) node.put("signature", *m_signature); +// return node; +// } + + rapidjson::Value monero_key_image::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_hex != boost::none) monero_utils::addJsonMember("hex", m_hex.get(), allocator, root, value_str); + if (m_signature != boost::none) monero_utils::addJsonMember("signature", m_signature.get(), allocator, root, value_str); + + // return root + return root; } void monero_key_image::merge(const shared_ptr& self, const shared_ptr& other) { @@ -475,14 +672,35 @@ namespace monero { return tgt; } - boost::property_tree::ptree monero_output::to_property_tree() const { - boost::property_tree::ptree node; - if (m_key_image != boost::none) node.add_child("keyImage", (*m_key_image)->to_property_tree()); - if (m_amount != boost::none) node.put("amount", *m_amount); - if (m_index != boost::none) node.put("index", *m_index); - if (!m_ring_output_indices.empty()) node.add_child("ringOutputIndices", monero_utils::to_property_tree(m_ring_output_indices)); - if (m_stealth_public_key != boost::none) node.put("stealthPublicKey", *m_stealth_public_key); - return node; +// boost::property_tree::ptree monero_output::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_key_image != boost::none) node.add_child("keyImage", (*m_key_image)->to_property_tree()); +// if (m_amount != boost::none) node.put("amount", *m_amount); +// if (m_index != boost::none) node.put("index", *m_index); +// if (!m_ring_output_indices.empty()) node.add_child("ringOutputIndices", monero_utils::to_property_tree(m_ring_output_indices)); +// if (m_stealth_public_key != boost::none) node.put("stealthPublicKey", *m_stealth_public_key); +// return node; +// } + + rapidjson::Value monero_output::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_amount != boost::none) monero_utils::addJsonMember("amount", m_amount.get(), allocator, root, value_num); + if (m_index != boost::none) monero_utils::addJsonMember("index", m_index.get(), allocator, root, value_num); + if (m_stealth_public_key != boost::none) monero_utils::addJsonMember("stealthPublicKey", m_stealth_public_key.get(), allocator, root, value_num); + + // set sub-arrays + if (!m_ring_output_indices.empty()) root.AddMember("ringOutputIndices", monero_utils::to_json_val(allocator, m_ring_output_indices), allocator); + + // set sub-objects + if (m_key_image != boost::none) root.AddMember("keyImage", m_key_image.get()->to_json_val(allocator), allocator); + + // return root + return root; } void monero_output::merge(const shared_ptr& self, const shared_ptr& other) { diff --git a/src/daemon/monero_daemon_model.h b/src/daemon/monero_daemon_model.h index 391d132..9d5c56c 100644 --- a/src/daemon/monero_daemon_model.h +++ b/src/daemon/monero_daemon_model.h @@ -54,6 +54,9 @@ #include #include +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" using namespace std; @@ -74,12 +77,20 @@ namespace monero { */ string serialize() const; +// /** +// * Convert the struct to a property tree. +// * +// * @return the converted property tree +// */ +// virtual boost::property_tree::ptree to_property_tree() const = 0; + /** - * Convert the struct to a property tree. + * Converts the struct to a rapidjson Value. * - * @return the converted property tree + * @param allocator is the rapidjson document allocator + * @return the struct as a rapidjson Value */ - virtual boost::property_tree::ptree to_property_tree() const = 0; + virtual rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const = 0; }; /** @@ -97,7 +108,9 @@ namespace monero { struct monero_version : public serializable_struct { boost::optional m_version_number; boost::optional m_is_release; - boost::property_tree::ptree to_property_tree() const; + + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -141,7 +154,8 @@ namespace monero { boost::optional m_reward; boost::optional m_pow_hash; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -154,7 +168,8 @@ namespace monero { vector> m_txs; vector m_tx_ids; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -204,7 +219,8 @@ namespace monero { vector m_signatures; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); boost::optional get_height() const; }; @@ -217,7 +233,8 @@ namespace monero { boost::optional m_signature; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -233,7 +250,8 @@ namespace monero { boost::optional m_stealth_public_key; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); }; } diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index ca0f94f..40d7d95 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -54,6 +54,7 @@ #include "rpc/core_rpc_server_commands_defs.h" #include "storages/portable_storage_template_helper.h" #include "cryptonote_basic/cryptonote_format_utils.h" +#include "string_tools.h" using namespace std; using namespace cryptonote; @@ -148,6 +149,7 @@ shared_ptr node_to_output_query(const boost::property_tree: return m_output_query; } +// TODO: finish deserialization implementation, uses tests void node_to_tx(const boost::property_tree::ptree& node, shared_ptr tx) { // initialize tx from node @@ -156,7 +158,7 @@ void node_to_tx(const boost::property_tree::ptree& node, shared_ptr t if (key == string("id")) tx->m_id = it->second.data(); else if (key == string("version")) throw runtime_error("version deserializationn not implemented"); else if (key == string("isMinerTx")) tx->m_is_miner_tx = it->second.get_value(); - else if (key == string("paymentId")) throw runtime_error("paymentId deserializationn not implemented"); + else if (key == string("paymentId")) tx->m_payment_id = it->second.data(); // TODO: this threw runtime_error, how is "Can get transactions by payment ids" test passing in Java? else if (key == string("fee")) tx->m_fee = it->second.get_value(); else if (key == string("mixin")) throw runtime_error("mixin deserialization not implemented"); else if (key == string("doNotRelay")) tx->m_do_not_relay = it->second.get_value(); @@ -252,7 +254,7 @@ shared_ptr node_to_destination(const boost::property_tree::p return destination; } -// ------------------------- PUBLIC STATIC UTILITIES -------------------------- +// -------------------------- BINARY SERIALIZATION ---------------------------- void monero_utils::json_to_binary(const std::string &json, std::string &bin) { epee::serialization::portable_storage ps; @@ -345,6 +347,93 @@ monero_tx_set monero_utils::deserialize_tx_set(const string& tx_set_str) { return tx_set; } +// ------------------------------- RAPIDJSON ---------------------------------- + +string monero_utils::serialize(const rapidjson::Document& doc) { + rapidjson::StringBuffer buffer; + rapidjson::Writer writer(buffer); + doc.Accept(writer); + return buffer.GetString(); +} + +void monero_utils::addJsonMember(string key, uint8_t val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field) { + rapidjson::Value field_key(key.c_str(), key.size(), allocator); + field.SetInt(val); + root.AddMember(field_key, field, allocator); +} + +void monero_utils::addJsonMember(string key, uint32_t val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field) { + rapidjson::Value field_key(key.c_str(), key.size(), allocator); + field.SetUint64(val); + root.AddMember(field_key, field, allocator); +} + +void monero_utils::addJsonMember(string key, uint64_t val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field) { + rapidjson::Value field_key(key.c_str(), key.size(), allocator); + field.SetUint64(val); + root.AddMember(field_key, field, allocator); +} + +void monero_utils::addJsonMember(string key, string val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field) { + rapidjson::Value field_key(key.c_str(), key.size(), allocator); + field.SetString(val.c_str(), val.size(), allocator); + root.AddMember(field_key, field, allocator); +} + +void monero_utils::addJsonMember(string key, bool val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root) { + rapidjson::Value field_key(key.c_str(), key.size(), allocator); + if (val) { + rapidjson::Value field_val(rapidjson::kTrueType); + root.AddMember(field_key, field_val, allocator); + } else { + rapidjson::Value field_val(rapidjson::kFalseType); + root.AddMember(field_key, field_val, allocator); + } +} + +rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& strs) { + rapidjson::Value value_arr(rapidjson::kArrayType); + rapidjson::Value value_str(rapidjson::kStringType); + for (const string& str : strs) { + value_str.SetString(str.c_str(), str.size(), allocator); + value_arr.PushBack(value_str, allocator); + } + return value_arr; +} + +rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { + rapidjson::Value value_arr(rapidjson::kArrayType); + rapidjson::Value value_num(rapidjson::kNumberType); + for (const auto& num : nums) { + value_num.SetInt(num); + value_arr.PushBack(value_num, allocator); + } + return value_arr; +} + +// TODO: remove these redundant implementations for different sizes? +rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { + rapidjson::Value value_arr(rapidjson::kArrayType); + rapidjson::Value value_num(rapidjson::kNumberType); + for (const auto& num : nums) { + value_num.SetUint64(num); + value_arr.PushBack(value_num, allocator); + } + return value_arr; +} + +rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { + rapidjson::Value value_arr(rapidjson::kArrayType); + rapidjson::Value value_num(rapidjson::kNumberType); + for (const auto& num : nums) { + value_num.SetUint64(num); + value_arr.PushBack(value_num, allocator); + } + return value_arr; +} + +// -------------------------- MODEL DESERIALIZATION --------------------------- + shared_ptr monero_utils::deserialize_tx_query(const string& tx_query_str) { // deserialize tx query string to property rooted at block @@ -473,6 +562,10 @@ vector> monero_utils::deserialize_key_images(const return key_images; } +// ------------------------ PROPERTY TREES --------------------------- + +// TODO: fully switch to rapidjson + string monero_utils::serialize(const boost::property_tree::ptree& node) { std::stringstream ss; boost::property_tree::write_json(ss, node, false); @@ -480,47 +573,60 @@ string monero_utils::serialize(const boost::property_tree::ptree& node) { return str.substr(0, str.size() - 1); // strip newline } -boost::property_tree::ptree monero_utils::to_property_tree(const vector& strs) { - boost::property_tree::ptree strsNode; - for (const auto& str : strs) { - boost::property_tree::ptree strNode; - strNode.put("", str); - strsNode.push_back(std::make_pair("", strNode)); +// TODO: switch deserializes in this utils class to use this deserialize util +void monero_utils::deserialize(const string& json, boost::property_tree::ptree& root) { + std::istringstream iss = json.empty() ? std::istringstream() : std::istringstream(json); + try { + boost::property_tree::read_json(iss, root); + } catch (std::exception const& e) { + throw runtime_error("Invalid JSON"); } - return strsNode; } -boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { - boost::property_tree::ptree numsNode; - for (const auto& num : nums) { - boost::property_tree::ptree numNode; - numNode.put("", num); - numsNode.push_back(std::make_pair("", numNode)); - } - return numsNode; -} +//boost::property_tree::ptree monero_utils::to_property_tree(const vector& strs) { +// boost::property_tree::ptree strsNode; +// for (const auto& str : strs) { +// boost::property_tree::ptree strNode; +// strNode.put("", str); +// strsNode.push_back(std::make_pair("", strNode)); +// } +// return strsNode; +//} +// +//boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { +// boost::property_tree::ptree numsNode; +// for (const auto& num : nums) { +// boost::property_tree::ptree numNode; +// numNode.put("", num); +// numsNode.push_back(std::make_pair("", numNode)); +// } +// return numsNode; +//} +// +//// TODO: remove these redundant implementations for different sizes? +//boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { +// boost::property_tree::ptree numsNode; +// for (const auto& num : nums) { +// boost::property_tree::ptree numNode; +// numNode.put("", num); +// numsNode.push_back(std::make_pair("", numNode)); +// } +// return numsNode; +//} +// +//boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { +// boost::property_tree::ptree numsNode; +// for (const auto& num : nums) { +// boost::property_tree::ptree numNode; +// numNode.put("", num); +// numsNode.push_back(std::make_pair("", numNode)); +// } +// return numsNode; +//} -// TODO: remove these redundant implementations for different sizes? -boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { - boost::property_tree::ptree numsNode; - for (const auto& num : nums) { - boost::property_tree::ptree numNode; - numNode.put("", num); - numsNode.push_back(std::make_pair("", numNode)); - } - return numsNode; -} - -boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { - boost::property_tree::ptree numsNode; - for (const auto& num : nums) { - boost::property_tree::ptree numNode; - numNode.put("", num); - numsNode.push_back(std::make_pair("", numNode)); - } - return numsNode; -} +// ---------------------------------------------------------------------------- +// TODO: is this unused? shared_ptr monero_utils::cn_block_to_block(const cryptonote::block& cn_block) { cryptonote::block temp = cn_block; cout << cryptonote::obj_to_json_str(temp) << endl; diff --git a/src/utils/monero_utils.h b/src/utils/monero_utils.h index a9250b0..827de55 100644 --- a/src/utils/monero_utils.h +++ b/src/utils/monero_utils.h @@ -53,38 +53,103 @@ #ifndef monero_utils_h #define monero_utils_h -#include "wallet/monero_wallet.h" +#include "wallet/monero_wallet_model.h" #include "cryptonote_basic/cryptonote_basic.h" #include "serialization/keyvalue_serialization.h" // TODO: consolidate with other binary deps? #include "storages/portable_storage.h" /** - * Collection of utilities for working with Monero's binary portable storage format. + * Collection of utilities for the Monero library. */ namespace monero_utils { using namespace std; using namespace cryptonote; + void dummy_method(const string& str); // TODO: remove this + + // ------------------------ BINARY SERIALIZATION ---------------------------- + void json_to_binary(const std::string &json, std::string &bin); - void binary_to_json(const std::string &bin, std::string &json); - void binary_blocks_to_json(const std::string &bin, std::string &json); - monero_tx_set deserialize_tx_set(const string& tx_set_str); + // ------------------------------ RAPIDJSON --------------------------------- + + string serialize(const rapidjson::Document& doc); + + void addJsonMember(string key, uint8_t val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field); + void addJsonMember(string key, uint32_t val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field); + void addJsonMember(string key, uint64_t val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field); + void addJsonMember(string key, string val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root, rapidjson::Value& field); + void addJsonMember(string key, bool val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root); + + // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation + template rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector>& vals) { + rapidjson::Value value_arr(rapidjson::kArrayType); + for (const auto& val : vals) { + value_arr.PushBack(val->to_json_val(allocator), allocator); + } + return value_arr; + } + + // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation + template rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& vals) { + rapidjson::Value value_arr(rapidjson::kArrayType); + for (const auto& val : vals) { + value_arr.PushBack(val.to_json_val(allocator), allocator); + } + return value_arr; + } + + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& strs); + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); + + // ------------------------ MODEL DESERIALIZATION --------------------------- + + // TODO: move deserialization to static utilities on class shared_ptr deserialize_tx_query(const string& txQueryStr); - shared_ptr deserialize_transfer_query(const string& transfer_query_str); - shared_ptr deserialize_output_query(const string& output_query_str); - shared_ptr deserialize_send_request(const string& send_request_str); - vector> deserialize_key_images(const string& key_images_json); + monero_tx_set deserialize_tx_set(const string& tx_set_str); + + // ------------------------ PROPERTY TREES --------------------------- + + // TODO: fully switch from property trees to rapidjson string serialize(const boost::property_tree::ptree& node); + void deserialize(const string& json, boost::property_tree::ptree& root); + + // + // // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation + // template boost::property_tree::ptree to_property_tree(const vector>& types) { + // boost::property_tree::ptree typeNodes; + // for (const auto& type : types) { + // typeNodes.push_back(std::make_pair("", type->to_property_tree())); + // } + // return typeNodes; + // } + // + // // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation + // template boost::property_tree::ptree to_property_tree(const vector& types) { + // boost::property_tree::ptree typeNodes; + // for (const auto& type : types) { + // typeNodes.push_back(std::make_pair("", type.to_property_tree())); + // } + // return typeNodes; + // } + // + // boost::property_tree::ptree to_property_tree(const vector& strs); + // boost::property_tree::ptree to_property_tree(const vector& nums); + // boost::property_tree::ptree to_property_tree(const vector& nums); + // boost::property_tree::ptree to_property_tree(const vector& nums); + + // -------------------------------------------------------------------------- /** * Convert a Monero Core cryptonote::block to a block in this library's native model. @@ -116,30 +181,5 @@ namespace monero_utils CHECK_AND_ASSERT_MES(r, std::string(), "Failed to serialize rct signatures base"); return ss.str(); } - - // ----------------------------- PROPERTY TREE ------------------------------ - - // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation - template boost::property_tree::ptree to_property_tree(const vector>& types) { - boost::property_tree::ptree typeNodes; - for (const auto& type : types) { - typeNodes.push_back(std::make_pair("", type->to_property_tree())); - } - return typeNodes; - } - - // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation - template boost::property_tree::ptree to_property_tree(const vector& types) { - boost::property_tree::ptree typeNodes; - for (const auto& type : types) { - typeNodes.push_back(std::make_pair("", type.to_property_tree())); - } - return typeNodes; - } - - boost::property_tree::ptree to_property_tree(const vector& strs); - boost::property_tree::ptree to_property_tree(const vector& nums); - boost::property_tree::ptree to_property_tree(const vector& nums); - boost::property_tree::ptree to_property_tree(const vector& nums); } #endif /* monero_utils_h */ diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 61ebcf1..fa96c41 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -50,7 +50,7 @@ * Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers */ -#include "monero_wallet.h" +#include "monero_wallet_model.h" #include "utils/gen_utils.h" #include "utils/monero_utils.h" @@ -76,32 +76,99 @@ namespace monero { transfers.push_back(transfer); } - // ---------------------------- MONERO ACCOUNT ------------------------------ + // -------------------------- MONERO SYNC RESULT ---------------------------- - boost::property_tree::ptree monero_account::to_property_tree() const { - boost::property_tree::ptree node; - if (m_index != boost::none) node.put("index", *m_index); - if (m_primary_address != boost::none) node.put("primaryAddress", *m_primary_address); - if (m_balance != boost::none) node.put("balance", *m_balance); - if (m_unlocked_balance != boost::none) node.put("unlockedBalance", *m_unlocked_balance); - if (!m_subaddresses.empty()) node.add_child("subaddresses", monero_utils::to_property_tree(m_subaddresses)); - return node; + rapidjson::Value monero_sync_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + monero_utils::addJsonMember("numBlocksFetched", m_num_blocks_fetched, allocator, root, value_num); + + // set bool values + monero_utils::addJsonMember("receivedMoney", m_received_money, allocator, root); + + // return root + return root; + } + + // -------------------------- MONERO ACCOUNT ----------------------------- + + // boost::property_tree::ptree monero_account::to_property_tree() const { + // boost::property_tree::ptree node; + // if (m_index != boost::none) node.put("index", *m_index); + // if (m_primary_address != boost::none) node.put("primaryAddress", *m_primary_address); + // if (m_balance != boost::none) node.put("balance", *m_balance); + // if (m_unlocked_balance != boost::none) node.put("unlockedBalance", *m_unlocked_balance); + // if (!m_subaddresses.empty()) node.add_child("subaddresses", monero_utils::to_property_tree(m_subaddresses)); + // return node; + // } + + rapidjson::Value monero_account::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_index != boost::none) monero_utils::addJsonMember("index", m_index.get(), allocator, root, value_num); + if (m_balance != boost::none) monero_utils::addJsonMember("balance", m_balance.get(), allocator, root, value_num); + if (m_unlocked_balance != boost::none) monero_utils::addJsonMember("unlockedBalance", m_unlocked_balance.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_primary_address != boost::none) monero_utils::addJsonMember("primaryAddress", m_primary_address.get(), allocator, root, value_str); + if (m_tag != boost::none) monero_utils::addJsonMember("tag", m_tag.get(), allocator, root, value_str); + + // set subaddresses + if (!m_subaddresses.empty()) root.AddMember("subaddresses", monero_utils::to_json_val(allocator, m_subaddresses), allocator); + + // return root + return root; } // -------------------------- MONERO SUBADDRESS ----------------------------- - boost::property_tree::ptree monero_subaddress::to_property_tree() const { - boost::property_tree::ptree node; - if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - if (m_index != boost::none) node.put("index", *m_index); - if (m_address != boost::none) node.put("address", *m_address); - if (m_label != boost::none) node.put("label", *m_label); - if (m_balance != boost::none) node.put("balance", *m_balance); - if (m_unlocked_balance != boost::none) node.put("unlockedBalance", *m_unlocked_balance); - if (m_num_unspent_outputs != boost::none) node.put("numUnspentOutputs", *m_num_unspent_outputs); - if (m_is_used != boost::none) node.put("isUsed", *m_is_used); - if (m_num_blocks_to_unlock != boost::none) node.put("numBlocksToUnlock", *m_num_blocks_to_unlock); - return node; +// boost::property_tree::ptree monero_subaddress::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); +// if (m_index != boost::none) node.put("index", *m_index); +// if (m_address != boost::none) node.put("address", *m_address); +// if (m_label != boost::none) node.put("label", *m_label); +// if (m_balance != boost::none) node.put("balance", *m_balance); +// if (m_unlocked_balance != boost::none) node.put("unlockedBalance", *m_unlocked_balance); +// if (m_num_unspent_outputs != boost::none) node.put("numUnspentOutputs", *m_num_unspent_outputs); +// if (m_is_used != boost::none) node.put("isUsed", *m_is_used); +// if (m_num_blocks_to_unlock != boost::none) node.put("numBlocksToUnlock", *m_num_blocks_to_unlock); +// return node; +// } + + rapidjson::Value monero_subaddress::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_account_index != boost::none) monero_utils::addJsonMember("accountIndex", m_account_index.get(), allocator, root, value_num); + if (m_index != boost::none) monero_utils::addJsonMember("index", m_index.get(), allocator, root, value_num); + if (m_balance != boost::none) monero_utils::addJsonMember("balance", m_balance.get(), allocator, root, value_num); + if (m_unlocked_balance != boost::none) monero_utils::addJsonMember("unlockedBalance", m_unlocked_balance.get(), allocator, root, value_num); + if (m_num_unspent_outputs != boost::none) monero_utils::addJsonMember("numUnspentOutputs", m_num_unspent_outputs.get(), allocator, root, value_num); + if (m_num_blocks_to_unlock) monero_utils::addJsonMember("numBlocksToUnlock", m_num_blocks_to_unlock.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + if (m_label != boost::none) monero_utils::addJsonMember("label", m_label.get(), allocator, root, value_str); + + // set bool values + if (m_is_used != boost::none) monero_utils::addJsonMember("isUsed", m_is_used.get(), allocator, root); + + // return root + return root; } // --------------------------- MONERO TX WALLET ----------------------------- @@ -147,21 +214,54 @@ namespace monero { return tgt; }; - boost::property_tree::ptree monero_tx_wallet::to_property_tree() const { - boost::property_tree::ptree node = monero_tx::to_property_tree(); - if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); - if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); - if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); - if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); - if (m_note != boost::none) node.put("note", *m_note); - if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); - if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); - if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); - if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); - if (m_change_amount != boost::none) node.put("changeAmount", *m_change_amount); - if (m_num_dummy_outputs != boost::none) node.put("numDummyOutputs", *m_num_dummy_outputs); - if (m_extra_hex != boost::none) node.put("extraHex", *m_extra_hex); - return node; +// boost::property_tree::ptree monero_tx_wallet::to_property_tree() const { +// boost::property_tree::ptree node = monero_tx::to_property_tree(); +// if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); +// if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); +// if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); +// if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); +// if (m_note != boost::none) node.put("note", *m_note); +// if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); +// if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); +// if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); +// if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); +// if (m_change_amount != boost::none) node.put("changeAmount", *m_change_amount); +// if (m_num_dummy_outputs != boost::none) node.put("numDummyOutputs", *m_num_dummy_outputs); +// if (m_extra_hex != boost::none) node.put("extraHex", *m_extra_hex); +// return node; +// } + + rapidjson::Value monero_tx_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_tx::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_input_sum != boost::none) monero_utils::addJsonMember("inputSum", m_input_sum.get(), allocator, root, value_num); + if (m_output_sum != boost::none) monero_utils::addJsonMember("outputSum", m_output_sum.get(), allocator, root, value_num); + if (m_change_amount != boost::none) monero_utils::addJsonMember("changeAmount", m_change_amount.get(), allocator, root, value_num); + if (m_num_dummy_outputs != boost::none) monero_utils::addJsonMember("numDummyOutputs", m_num_dummy_outputs.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_note != boost::none) monero_utils::addJsonMember("note", m_note.get(), allocator, root, value_str); + if (m_change_address != boost::none) monero_utils::addJsonMember("changeAddress", m_change_address.get(), allocator, root, value_str); + if (m_extra_hex != boost::none) monero_utils::addJsonMember("extraHex", m_extra_hex.get(), allocator, root, value_str); + + // set bool values + if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); + if (m_is_outgoing != boost::none) monero_utils::addJsonMember("isOutgoing", m_is_outgoing.get(), allocator, root); + if (m_is_locked != boost::none) monero_utils::addJsonMember("isLocked", m_is_locked.get(), allocator, root); + + // set sub-arrays + if (!m_incoming_transfers.empty()) root.AddMember("incomingTransfers", monero_utils::to_json_val(allocator, m_incoming_transfers), allocator); + + // set sub-objects + if (m_outgoing_transfer != boost::none) root.AddMember("outgoingTransfer", m_outgoing_transfer.get()->to_json_val(allocator), allocator); + + // return root + return root; } void monero_tx_wallet::merge(const shared_ptr& self, const shared_ptr& other) { @@ -235,19 +335,47 @@ namespace monero { return tgt; }; - boost::property_tree::ptree monero_tx_query::to_property_tree() const { - boost::property_tree::ptree node = monero_tx_wallet::to_property_tree(); - if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); - if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); - if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); - if (m_has_payment_id != boost::none) node.put("hasPaymentId", *m_has_payment_id); - if (!m_payment_ids.empty()) node.add_child("paymentIds", monero_utils::to_property_tree(m_payment_ids)); - if (m_height != boost::none) node.put("height", *m_height); - if (m_min_height != boost::none) node.put("minHeight", *m_min_height); - if (m_max_height != boost::none) node.put("maxHeight", *m_max_height); - if (m_include_outputs != boost::none) node.put("includeOutputs", *m_include_outputs); - if (m_transfer_query != boost::none) node.add_child("transferQuery", (*m_transfer_query)->to_property_tree()); - return node; +// boost::property_tree::ptree monero_tx_query::to_property_tree() const { +// boost::property_tree::ptree node = monero_tx_wallet::to_property_tree(); +// if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); +// if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); +// if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); +// if (m_has_payment_id != boost::none) node.put("hasPaymentId", *m_has_payment_id); +// if (!m_payment_ids.empty()) node.add_child("paymentIds", monero_utils::to_property_tree(m_payment_ids)); +// if (m_height != boost::none) node.put("height", *m_height); +// if (m_min_height != boost::none) node.put("minHeight", *m_min_height); +// if (m_max_height != boost::none) node.put("maxHeight", *m_max_height); +// if (m_include_outputs != boost::none) node.put("includeOutputs", *m_include_outputs); +// if (m_transfer_query != boost::none) node.add_child("transferQuery", (*m_transfer_query)->to_property_tree()); +// return node; +// } + + rapidjson::Value monero_tx_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_tx_wallet::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_height != boost::none) monero_utils::addJsonMember("height", m_height.get(), allocator, root, value_num); + if (m_min_height != boost::none) monero_utils::addJsonMember("minHeight", m_min_height.get(), allocator, root, value_num); + if (m_max_height != boost::none) monero_utils::addJsonMember("maxHeight", m_max_height.get(), allocator, root, value_num); + + // set bool values + if (m_is_outgoing != boost::none) monero_utils::addJsonMember("isOutgoing", m_is_outgoing.get(), allocator, root); + if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); + if (m_has_payment_id != boost::none) monero_utils::addJsonMember("hasPaymentId", m_has_payment_id.get(), allocator, root); + if (m_include_outputs != boost::none) monero_utils::addJsonMember("includeOutputs", m_include_outputs.get(), allocator, root); + + // set sub-arrays + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); + if (!m_payment_ids.empty()) root.AddMember("paymentIds", monero_utils::to_json_val(allocator, m_payment_ids), allocator); + + // set sub-objects + if (m_transfer_query != boost::none) root.AddMember("transferQuery", m_transfer_query.get()->to_json_val(allocator), allocator); + + // return root + return root; } bool monero_tx_query::meets_criteria(monero_tx_wallet* tx) const { @@ -326,22 +454,57 @@ namespace monero { return tgt; }; - boost::property_tree::ptree monero_destination::to_property_tree() const { - boost::property_tree::ptree node; - if (m_address != boost::none) node.put("address", *m_address); - if (m_amount != boost::none) node.put("amount", *m_amount); - return node; +// boost::property_tree::ptree monero_destination::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_address != boost::none) node.put("address", *m_address); +// if (m_amount != boost::none) node.put("amount", *m_amount); +// return node; +// } + + rapidjson::Value monero_destination::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_amount != boost::none) monero_utils::addJsonMember("amount", m_amount.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + + // return root + return root; } // ----------------------------- MONERO TX SET ------------------------------ - boost::property_tree::ptree monero_tx_set::to_property_tree() const { - boost::property_tree::ptree node; - if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); - if (m_multisig_tx_hex != boost::none) node.put("multisigTxHex", *m_multisig_tx_hex); - if (m_unsigned_tx_hex != boost::none) node.put("unsignedTxHex", *m_unsigned_tx_hex); - if (m_signed_tx_hex != boost::none) node.put("signedTxHex", *m_signed_tx_hex); - return node; +// boost::property_tree::ptree monero_tx_set::to_property_tree() const { +// boost::property_tree::ptree node; +// if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); +// if (m_multisig_tx_hex != boost::none) node.put("multisigTxHex", *m_multisig_tx_hex); +// if (m_unsigned_tx_hex != boost::none) node.put("unsignedTxHex", *m_unsigned_tx_hex); +// if (m_signed_tx_hex != boost::none) node.put("signedTxHex", *m_signed_tx_hex); +// return node; +// } + + rapidjson::Value monero_tx_set::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_multisig_tx_hex != boost::none) monero_utils::addJsonMember("multisigTxHex", m_multisig_tx_hex.get(), allocator, root, value_str); + if (m_unsigned_tx_hex != boost::none) monero_utils::addJsonMember("unsignedTxHex", m_unsigned_tx_hex.get(), allocator, root, value_str); + if (m_signed_tx_hex != boost::none) monero_utils::addJsonMember("signedTxHex", m_signed_tx_hex.get(), allocator, root, value_str); + + // set sub-arrays + if (!m_txs.empty()) root.AddMember("txs", monero_utils::to_json_val(allocator, m_txs), allocator); + + // return root + return root; } // ---------------------------- MONERO TRANSFER ----------------------------- @@ -355,12 +518,27 @@ namespace monero { return tgt; } - boost::property_tree::ptree monero_transfer::to_property_tree() const { - boost::property_tree::ptree node; - if (m_amount != boost::none) node.put("amount", *m_amount); - if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - if (m_num_suggested_confirmations != boost::none) node.put("numSuggestedConfirmations", *m_num_suggested_confirmations); - return node; +// boost::property_tree::ptree monero_transfer::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_amount != boost::none) node.put("amount", *m_amount); +// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); +// if (m_num_suggested_confirmations != boost::none) node.put("numSuggestedConfirmations", *m_num_suggested_confirmations); +// return node; +// } + + rapidjson::Value monero_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_amount != boost::none) monero_utils::addJsonMember("amount", m_amount.get(), allocator, root, value_num); + if (m_account_index != boost::none) monero_utils::addJsonMember("accountIndex", m_account_index.get(), allocator, root, value_num); + if (m_num_suggested_confirmations != boost::none) monero_utils::addJsonMember("numSuggestedConfirmations", m_num_suggested_confirmations.get(), allocator, root, value_num); + + // return root + return root; } void monero_transfer::merge(const shared_ptr& self, const shared_ptr& other) { @@ -394,16 +572,34 @@ namespace monero { } shared_ptr monero_incoming_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + cout << "monero_incoming_transfer::copy()" << endl; throw runtime_error("monero_incoming_transfer::copy(inTransfer) not implemented"); }; boost::optional monero_incoming_transfer::is_incoming() const { return true; } - boost::property_tree::ptree monero_incoming_transfer::to_property_tree() const { - boost::property_tree::ptree node = monero_transfer::to_property_tree(); - if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); - if (m_address != boost::none) node.put("address", *m_address); - return node; +// boost::property_tree::ptree monero_incoming_transfer::to_property_tree() const { +// boost::property_tree::ptree node = monero_transfer::to_property_tree(); +// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); +// if (m_address != boost::none) node.put("address", *m_address); +// return node; +// } + + rapidjson::Value monero_incoming_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_transfer::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + + // return root + return root; } void monero_incoming_transfer::merge(const shared_ptr& self, const shared_ptr& other) { @@ -424,17 +620,32 @@ namespace monero { }; shared_ptr monero_outgoing_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + cout << "monero_outgoing_transfer::copy()" << endl; throw runtime_error("monero_outgoing_transfer::copy(out_transfer) not implemented"); }; boost::optional monero_outgoing_transfer::is_incoming() const { return false; } - boost::property_tree::ptree monero_outgoing_transfer::to_property_tree() const { - boost::property_tree::ptree node = monero_transfer::to_property_tree(); - if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); - if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); - if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); - return node; +// boost::property_tree::ptree monero_outgoing_transfer::to_property_tree() const { +// boost::property_tree::ptree node = monero_transfer::to_property_tree(); +// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); +// if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); +// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); +// return node; +// } + + rapidjson::Value monero_outgoing_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_transfer::to_json_val(allocator); + + // set sub-arrays + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_json_val(allocator, m_addresses), allocator); + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); + + // return root + return root; } void monero_outgoing_transfer::merge(const shared_ptr& self, const shared_ptr& other) { @@ -480,16 +691,42 @@ namespace monero { boost::optional monero_transfer_query::is_incoming() const { return m_is_incoming; } - boost::property_tree::ptree monero_transfer_query::to_property_tree() const { - boost::property_tree::ptree node = monero_transfer::to_property_tree(); - if (is_incoming() != boost::none) node.put("isIncoming", *is_incoming()); - if (m_address != boost::none) node.put("address", *m_address); - if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); - if (m_has_destinations != boost::none) node.put("hasDestinations", *m_has_destinations); - if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); - if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); - if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); - return node; +// boost::property_tree::ptree monero_transfer_query::to_property_tree() const { +// boost::property_tree::ptree node = monero_transfer::to_property_tree(); +// if (is_incoming() != boost::none) node.put("isIncoming", *is_incoming()); +// if (m_address != boost::none) node.put("address", *m_address); +// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); +// if (m_has_destinations != boost::none) node.put("hasDestinations", *m_has_destinations); +// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); +// if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); +// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); +// return node; +// } + + rapidjson::Value monero_transfer_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_transfer::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); + + // set bool values + if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); + if (m_has_destinations != boost::none) monero_utils::addJsonMember("hasDestinations", m_has_destinations.get(), allocator, root); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + + // set sub-arrays + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_json_val(allocator, m_addresses), allocator); + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); + + // return root + return root; } bool monero_transfer_query::meets_criteria(monero_transfer* transfer) const { @@ -586,13 +823,32 @@ namespace monero { return tgt; }; - boost::property_tree::ptree monero_output_wallet::to_property_tree() const { - boost::property_tree::ptree node = monero_output::to_property_tree(); - if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); - if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); - if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); - return node; +// boost::property_tree::ptree monero_output_wallet::to_property_tree() const { +// boost::property_tree::ptree node = monero_output::to_property_tree(); +// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); +// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); +// if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); +// if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); +// if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); +// return node; +// } + + rapidjson::Value monero_output_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_output::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_account_index != boost::none) monero_utils::addJsonMember("accountIndex", m_account_index.get(), allocator, root, value_num); + if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); + + // set bool values + if (m_is_spent != boost::none) monero_utils::addJsonMember("isSpent", m_is_spent.get(), allocator, root); + if (m_is_frozen != boost::none) monero_utils::addJsonMember("isFrozen", m_is_frozen.get(), allocator, root); + + // return root + return root; } void monero_output_wallet::merge(const shared_ptr& self, const shared_ptr& other) { @@ -642,10 +898,22 @@ namespace monero { return tgt; }; - boost::property_tree::ptree monero_output_query::to_property_tree() const { - boost::property_tree::ptree node = monero_output_wallet::to_property_tree(); - if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); - return node; +// boost::property_tree::ptree monero_output_query::to_property_tree() const { +// boost::property_tree::ptree node = monero_output_wallet::to_property_tree(); +// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); +// return node; +// } + + rapidjson::Value monero_output_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_output_wallet::to_json_val(allocator); + + // set sub-arrays + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + + // return root + return root; } bool monero_output_query::meets_criteria(monero_output_wallet* output) const { @@ -701,105 +969,198 @@ namespace monero { return monero_send_request(*this); } - boost::property_tree::ptree monero_send_request::to_property_tree() const { - boost::property_tree::ptree node; - if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); - if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); - if (m_priority != boost::none) node.put("priority", *m_priority); - if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); - if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); - if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); - if (m_can_split != boost::none) node.put("canSplit", *m_can_split); - if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); - if (m_note != boost::none) node.put("note", *m_note); - if (m_recipient_name != boost::none) node.put("recipientName", *m_recipient_name); - if (m_below_amount != boost::none) node.put("belowAmount", *m_below_amount); - if (m_sweep_each_subaddress != boost::none) node.put("sweepEachSubaddress", *m_sweep_each_subaddress); - if (m_key_image != boost::none) node.put("keyImage", *m_key_image); - return node; +// boost::property_tree::ptree monero_send_request::to_property_tree() const { +// boost::property_tree::ptree node; +// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); +// if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); +// if (m_priority != boost::none) node.put("priority", *m_priority); +// if (m_mixin != boost::none) node.put("mixin", *m_mixin); +// if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); +// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); +// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); +// if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); +// if (m_can_split != boost::none) node.put("canSplit", *m_can_split); +// if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); +// if (m_note != boost::none) node.put("note", *m_note); +// if (m_recipient_name != boost::none) node.put("recipientName", *m_recipient_name); +// if (m_below_amount != boost::none) node.put("belowAmount", *m_below_amount); +// if (m_sweep_each_subaddress != boost::none) node.put("sweepEachSubaddress", *m_sweep_each_subaddress); +// if (m_key_image != boost::none) node.put("keyImage", *m_key_image); +// return node; +// } + + rapidjson::Value monero_send_request::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_priority != boost::none) monero_utils::addJsonMember("priority", m_priority.get(), allocator, root, value_num); + if (m_ring_size != boost::none) monero_utils::addJsonMember("ringSize", m_ring_size.get(), allocator, root, value_num); + if (m_account_index != boost::none) monero_utils::addJsonMember("accountIndex", m_account_index.get(), allocator, root, value_num); + if (m_unlock_time != boost::none) monero_utils::addJsonMember("unlockTime", m_unlock_time.get(), allocator, root, value_num); + if (m_below_amount != boost::none) monero_utils::addJsonMember("belowAmount", m_below_amount.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); + if (m_note != boost::none) monero_utils::addJsonMember("note", m_note.get(), allocator, root, value_str); + if (m_recipient_name != boost::none) monero_utils::addJsonMember("recipientName", m_recipient_name.get(), allocator, root, value_str); + if (m_key_image != boost::none) monero_utils::addJsonMember("keyImage", m_key_image.get(), allocator, root, value_str); + + // set bool values + if (m_can_split != boost::none) monero_utils::addJsonMember("canSplit", m_can_split.get(), allocator, root); + if (m_do_not_relay != boost::none) monero_utils::addJsonMember("doNotRelay", m_do_not_relay.get(), allocator, root); + if (m_sweep_each_subaddress != boost::none) monero_utils::addJsonMember("sweepEachSubaddress", m_sweep_each_subaddress.get(), allocator, root); + + // set sub-arrays + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + + // return root + return root; } // ---------------------- MONERO INTEGRATED ADDRESS ------------------------- - boost::property_tree::ptree monero_integrated_address::to_property_tree() const { - boost::property_tree::ptree node; - node.put("standardAddress", m_standard_address); - node.put("paymentId", m_payment_id); - node.put("integratedAddress", m_integrated_address); - return node; +// boost::property_tree::ptree monero_integrated_address::to_property_tree() const { +// boost::property_tree::ptree node; +// node.put("standardAddress", m_standard_address); +// node.put("paymentId", m_payment_id); +// node.put("integratedAddress", m_integrated_address); +// return node; +// } + + rapidjson::Value monero_integrated_address::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_integrated_address::to_json_val()" << endl; + throw runtime_error("monero_integrated_address::to_json_val() not implemented"); } // -------------------- MONERO KEY IMAGE IMPORT RESULT ---------------------- - boost::property_tree::ptree monero_key_image_import_result::to_property_tree() const { - boost::property_tree::ptree node; - if (m_height != boost::none) node.put("height", *m_height); - if (m_spent_amount != boost::none) node.put("spentAmount", *m_spent_amount); - if (m_unspent_amount != boost::none) node.put("unspentAmount", *m_unspent_amount); - return node; +// boost::property_tree::ptree monero_key_image_import_result::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_height != boost::none) node.put("height", *m_height); +// if (m_spent_amount != boost::none) node.put("spentAmount", *m_spent_amount); +// if (m_unspent_amount != boost::none) node.put("unspentAmount", *m_unspent_amount); +// return node; +// } + + rapidjson::Value monero_key_image_import_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_key_image_import_result::to_json_val()" << endl; + throw runtime_error("monero_key_image_import_result::to_json_val() not implemented"); } // ----------------------------- MONERO CHECK ------------------------------- - boost::property_tree::ptree monero_check::to_property_tree() const { - boost::property_tree::ptree node; - node.put("isGood", m_is_good); - return node; +// boost::property_tree::ptree monero_check::to_property_tree() const { +// boost::property_tree::ptree node; +// node.put("isGood", m_is_good); +// return node; +// } + + rapidjson::Value monero_check::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_check::to_json_val()" << endl; + throw runtime_error("monero_check::to_json_val() not implemented"); } // --------------------------- MONERO CHECK TX ------------------------------ - boost::property_tree::ptree monero_check_tx::to_property_tree() const { - boost::property_tree::ptree node = monero_check::to_property_tree();; - if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); - if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); - if (m_received_amount != boost::none) node.put("receivedAmount", *m_received_amount); - return node; +// boost::property_tree::ptree monero_check_tx::to_property_tree() const { +// boost::property_tree::ptree node = monero_check::to_property_tree();; +// if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); +// if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); +// if (m_received_amount != boost::none) node.put("receivedAmount", *m_received_amount); +// return node; +// } + + rapidjson::Value monero_check_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_check_tx::to_json_val()" << endl; + throw runtime_error("monero_check_tx::to_json_val() not implemented"); } // ------------------------ MONERO CHECK RESERVE ---------------------------- - boost::property_tree::ptree monero_check_reserve::to_property_tree() const { - boost::property_tree::ptree node = monero_check::to_property_tree(); - if (m_total_amount != boost::none) node.put("totalAmount", *m_total_amount); - if (m_unconfirmed_spent_amount != boost::none) node.put("unconfirmedSpentAmount", *m_unconfirmed_spent_amount); - return node; +// boost::property_tree::ptree monero_check_reserve::to_property_tree() const { +// boost::property_tree::ptree node = monero_check::to_property_tree(); +// if (m_total_amount != boost::none) node.put("totalAmount", *m_total_amount); +// if (m_unconfirmed_spent_amount != boost::none) node.put("unconfirmedSpentAmount", *m_unconfirmed_spent_amount); +// return node; +// } + + rapidjson::Value monero_check_reserve::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_check_reserve::to_json_val()" << endl; + throw runtime_error("monero_check_reserve::to_json_val() not implemented"); } // --------------------------- MONERO MULTISIG ------------------------------ - boost::property_tree::ptree monero_multisig_info::to_property_tree() const { - boost::property_tree::ptree node; - node.put("isMultisig", m_is_multisig); - node.put("isReady", m_is_ready); - node.put("threshold", m_threshold); - node.put("numParticipants", m_num_participants); - return node; +// boost::property_tree::ptree monero_multisig_info::to_property_tree() const { +// boost::property_tree::ptree node; +// node.put("isMultisig", m_is_multisig); +// node.put("isReady", m_is_ready); +// node.put("threshold", m_threshold); +// node.put("numParticipants", m_num_participants); +// return node; +// } + + rapidjson::Value monero_multisig_info::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_multisig_info::to_json_val()" << endl; + throw runtime_error("monero_multisig_info::to_json_val() not implemented"); } - boost::property_tree::ptree monero_multisig_init_result::to_property_tree() const { - boost::property_tree::ptree node; - if (m_address != boost::none) node.put("address", *m_address); - if (m_multisig_hex != boost::none) node.put("multisigHex", *m_multisig_hex); - return node; +// boost::property_tree::ptree monero_multisig_init_result::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_address != boost::none) node.put("address", *m_address); +// if (m_multisig_hex != boost::none) node.put("multisigHex", *m_multisig_hex); +// return node; +// } + + rapidjson::Value monero_multisig_init_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_multisig_init_result::to_json_val()" << endl; + throw runtime_error("monero_multisig_init_result::to_json_val() not implemented"); } - boost::property_tree::ptree monero_multisig_sign_result::to_property_tree() const { - boost::property_tree::ptree node; - if (m_signed_multisig_tx_hex != boost::none) node.put("signedMultisigTxHex", *m_signed_multisig_tx_hex); - if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); - return node; +// boost::property_tree::ptree monero_multisig_sign_result::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_signed_multisig_tx_hex != boost::none) node.put("signedMultisigTxHex", *m_signed_multisig_tx_hex); +// if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); +// return node; +// } + + rapidjson::Value monero_multisig_sign_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + cout << "monero_multisig_sign_result::to_json_val()" << endl; + throw runtime_error("monero_multisig_sign_result::to_json_val() not implemented"); } // -------------------------- MONERO ADDRESS BOOK --------------------------- - boost::property_tree::ptree monero_address_book_entry::to_property_tree() const { - boost::property_tree::ptree node; - if (m_index != boost::none) node.put("index", *m_index); - if (m_address != boost::none) node.put("address", *m_address); - if (m_description != boost::none) node.put("description", *m_description); - if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); - return node; +// boost::property_tree::ptree monero_address_book_entry::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_index != boost::none) node.put("index", *m_index); +// if (m_address != boost::none) node.put("address", *m_address); +// if (m_description != boost::none) node.put("description", *m_description); +// if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); +// return node; +// } + + rapidjson::Value monero_address_book_entry::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_index != boost::none) monero_utils::addJsonMember("index", m_index.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + if (m_description != boost::none) monero_utils::addJsonMember("description", m_description.get(), allocator, root, value_str); + if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); + + // return root + return root; } } diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 513ad44..82a3a40 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -65,11 +65,13 @@ namespace monero { /** * Models a result of syncing a wallet. */ - struct monero_sync_result { + struct monero_sync_result : public serializable_struct { uint64_t m_num_blocks_fetched; bool m_received_money; monero_sync_result() {} monero_sync_result(const uint64_t num_blocks_fetched, const bool received_money) : m_num_blocks_fetched(num_blocks_fetched), m_received_money(received_money) {} + + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -85,20 +87,9 @@ namespace monero { boost::optional m_num_unspent_outputs; boost::optional m_is_used; boost::optional m_num_blocks_to_unlock; -// BEGIN_KV_SERIALIZE_MAP() -// KV_SERIALIZE(m_account_index) -// KV_SERIALIZE(index) -// KV_SERIALIZE(address) -// KV_SERIALIZE(label) -// KV_SERIALIZE(balance) -// KV_SERIALIZE(m_unlocked_balance) -// KV_SERIALIZE(m_num_unspent_outputs) -// KV_SERIALIZE(m_is_used) -// KV_SERIALIZE(m_num_blocks_to_unlock) -// END_KV_SERIALIZE_MAP() - boost::property_tree::ptree to_property_tree() const; - //void merge(const shared_ptr& self, const shared_ptr& other); + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -111,17 +102,19 @@ namespace monero { boost::optional m_unlocked_balance; boost::optional m_tag; vector m_subaddresses; -// BEGIN_KV_SERIALIZE_MAP() -// KV_SERIALIZE(index) -// KV_SERIALIZE(m_primary_address) -// KV_SERIALIZE(label) -// KV_SERIALIZE(balance) -// KV_SERIALIZE(m_unlocked_balance) -// KV_SERIALIZE(tag) -// KV_SERIALIZE(subaddresses) -// END_KV_SERIALIZE_MAP() - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + + string serialize_doc() const; + rapidjson::Document to_json_doc() const { + rapidjson::Document doc; + doc.SetObject(); + rapidjson::Value val = to_json_val(doc); + val.Swap(doc); + return doc; + } + rapidjson::Value to_json_val(rapidjson::Document& doc) const; }; /** @@ -134,7 +127,8 @@ namespace monero { monero_destination() {} monero_destination(const string& address, uint64_t amount) : m_address(address), m_amount(amount) {} shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; // forward declarations @@ -157,7 +151,8 @@ namespace monero { if (is_incoming() == boost::none) return boost::none; return !(*is_incoming()); } - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -171,7 +166,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -187,7 +183,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -210,7 +207,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; bool meets_criteria(monero_transfer* transfer) const; }; @@ -225,7 +223,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -245,7 +244,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; bool meets_criteria(monero_output_wallet* output) const; private: @@ -272,7 +272,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -299,7 +300,8 @@ namespace monero { shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; bool meets_criteria(monero_tx_wallet* tx) const; }; @@ -311,13 +313,14 @@ namespace monero { * hex string which is needed in order to sign and submit the multisig * transactions. */ - struct monero_tx_set : serializable_struct { + struct monero_tx_set : public serializable_struct { vector> m_txs; boost::optional m_signed_tx_hex; boost::optional m_unsigned_tx_hex; boost::optional m_multisig_tx_hex; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -328,7 +331,8 @@ namespace monero { string m_payment_id; string m_integrated_address; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -364,7 +368,8 @@ namespace monero { monero_send_request() {} monero_send_request(const monero_send_request& request); monero_send_request copy() const; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -375,7 +380,8 @@ namespace monero { boost::optional m_spent_amount; boost::optional m_unspent_amount; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -384,7 +390,8 @@ namespace monero { struct monero_check : public serializable_struct { bool m_is_good; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -395,7 +402,8 @@ namespace monero { boost::optional m_num_confirmations; boost::optional m_received_amount; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -405,7 +413,8 @@ namespace monero { boost::optional m_total_amount; boost::optional m_unconfirmed_spent_amount; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -417,7 +426,8 @@ namespace monero { uint32_t m_threshold; uint32_t m_num_participants; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -429,7 +439,8 @@ namespace monero { boost::optional m_address; boost::optional m_multisig_hex; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -439,7 +450,8 @@ namespace monero { boost::optional m_signed_multisig_tx_hex; vector m_tx_ids; - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -453,6 +465,7 @@ namespace monero { monero_address_book_entry() {} monero_address_book_entry(uint64_t index, const string& address, const string& description, const string& payment_id) : m_index(index), m_address(address), m_description(description), m_payment_id(payment_id) {} - boost::property_tree::ptree to_property_tree() const; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; }; } diff --git a/todo.txt b/todo.txt index 57b0e1b..3e0a1a0 100644 --- a/todo.txt +++ b/todo.txt @@ -1,4 +1,5 @@ TODO +monero_wallet.h request -> query preserve rpc error codes, just throwing runtime_error now gen_utils.h and monero_utils.h should not depend on monero_wallet.h add to ecosystem? From 0eba80e7f5d7be9836750504bc2a3f4cd12cbbb2 Mon Sep 17 00:00:00 2001 From: woodser Date: Fri, 29 Nov 2019 17:40:43 -0500 Subject: [PATCH 27/34] to_json_val implementations --- src/wallet/monero_wallet_model.cpp | 112 ++++++++++++++++++++++++----- 1 file changed, 96 insertions(+), 16 deletions(-) diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index fa96c41..b69aed2 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -1033,8 +1033,18 @@ namespace monero { // } rapidjson::Value monero_integrated_address::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_integrated_address::to_json_val()" << endl; - throw runtime_error("monero_integrated_address::to_json_val() not implemented"); + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + monero_utils::addJsonMember("standardAddress", m_standard_address, allocator, root, value_str); + monero_utils::addJsonMember("paymentId", m_payment_id, allocator, root, value_str); + monero_utils::addJsonMember("integratedAddress", m_integrated_address, allocator, root, value_str); + + // return root + return root; } // -------------------- MONERO KEY IMAGE IMPORT RESULT ---------------------- @@ -1048,8 +1058,18 @@ namespace monero { // } rapidjson::Value monero_key_image_import_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_key_image_import_result::to_json_val()" << endl; - throw runtime_error("monero_key_image_import_result::to_json_val() not implemented"); + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_height != boost::none) monero_utils::addJsonMember("height", m_height.get(), allocator, root, value_num); + if (m_spent_amount != boost::none) monero_utils::addJsonMember("spentAmount", m_spent_amount.get(), allocator, root, value_num); + if (m_unspent_amount != boost::none) monero_utils::addJsonMember("unspentAmount", m_unspent_amount.get(), allocator, root, value_num); + + // return root + return root; } // ----------------------------- MONERO CHECK ------------------------------- @@ -1061,8 +1081,15 @@ namespace monero { // } rapidjson::Value monero_check::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_check::to_json_val()" << endl; - throw runtime_error("monero_check::to_json_val() not implemented"); + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set bool values + monero_utils::addJsonMember("isGood", m_is_good, allocator, root); + + // return root + return root; } // --------------------------- MONERO CHECK TX ------------------------------ @@ -1076,8 +1103,20 @@ namespace monero { // } rapidjson::Value monero_check_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_check_tx::to_json_val()" << endl; - throw runtime_error("monero_check_tx::to_json_val() not implemented"); + + // serialize root from superclass + rapidjson::Value root = monero_check::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_num_confirmations != boost::none) monero_utils::addJsonMember("numConfirmations", m_num_confirmations.get(), allocator, root, value_num); + if (m_received_amount != boost::none) monero_utils::addJsonMember("receivedAmount", m_received_amount.get(), allocator, root, value_num); + + // set bool values + if (m_in_tx_pool != boost::none) monero_utils::addJsonMember("inTxPool", m_in_tx_pool.get(), allocator, root); + + // return root + return root; } // ------------------------ MONERO CHECK RESERVE ---------------------------- @@ -1090,8 +1129,17 @@ namespace monero { // } rapidjson::Value monero_check_reserve::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_check_reserve::to_json_val()" << endl; - throw runtime_error("monero_check_reserve::to_json_val() not implemented"); + + // serialize root from superclass + rapidjson::Value root = monero_check::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_total_amount != boost::none) monero_utils::addJsonMember("totalAmount", m_total_amount.get(), allocator, root, value_num); + if (m_unconfirmed_spent_amount != boost::none) monero_utils::addJsonMember("unconfirmedSpentAmount", m_unconfirmed_spent_amount.get(), allocator, root, value_num); + + // return root + return root; } // --------------------------- MONERO MULTISIG ------------------------------ @@ -1106,8 +1154,21 @@ namespace monero { // } rapidjson::Value monero_multisig_info::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_multisig_info::to_json_val()" << endl; - throw runtime_error("monero_multisig_info::to_json_val() not implemented"); + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + monero_utils::addJsonMember("threshold", m_threshold, allocator, root, value_num); + monero_utils::addJsonMember("numParticipants", m_num_participants, allocator, root, value_num); + + // set bool values + monero_utils::addJsonMember("isMultisig", m_is_multisig, allocator, root); + monero_utils::addJsonMember("isReady", m_is_ready, allocator, root); + + // return root + return root; } // boost::property_tree::ptree monero_multisig_init_result::to_property_tree() const { @@ -1118,8 +1179,17 @@ namespace monero { // } rapidjson::Value monero_multisig_init_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_multisig_init_result::to_json_val()" << endl; - throw runtime_error("monero_multisig_init_result::to_json_val() not implemented"); + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + if (m_multisig_hex != boost::none) monero_utils::addJsonMember("multisigHex", m_multisig_hex.get(), allocator, root, value_str); + + // return root + return root; } // boost::property_tree::ptree monero_multisig_sign_result::to_property_tree() const { @@ -1130,8 +1200,18 @@ namespace monero { // } rapidjson::Value monero_multisig_sign_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - cout << "monero_multisig_sign_result::to_json_val()" << endl; - throw runtime_error("monero_multisig_sign_result::to_json_val() not implemented"); + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_signed_multisig_tx_hex != boost::none) monero_utils::addJsonMember("signedMultisigTxHex", m_signed_multisig_tx_hex.get(), allocator, root, value_str); + + // set sub-arrays + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); + + // return root + return root; } // -------------------------- MONERO ADDRESS BOOK --------------------------- From c3bc05d9795f1eccdeb73ee2546fa92e19f269b9 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 17:13:29 -0500 Subject: [PATCH 28/34] move deserialization utils from monero_utils to model methods --- src/daemon/monero_daemon_model.cpp | 359 ++++++++----- src/daemon/monero_daemon_model.h | 11 +- src/utils/monero_utils.cpp | 351 ------------- src/utils/monero_utils.h | 11 - src/wallet/monero_wallet_model.cpp | 786 +++++++++++++++++++---------- src/wallet/monero_wallet_model.h | 66 +-- 6 files changed, 787 insertions(+), 797 deletions(-) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index f16cc1e..385124e 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -312,6 +312,149 @@ namespace monero { // ------------------------------- MONERO TX -------------------------------- + // boost::property_tree::ptree monero_tx::to_property_tree() const { + // boost::property_tree::ptree node; + // if (m_id != boost::none) node.put("id", *m_id); + // if (m_version != boost::none) node.put("version", *m_version); + // if (m_is_miner_tx != boost::none) node.put("isMinerTx", *m_is_miner_tx); + // if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); + // if (m_fee != boost::none) node.put("fee", *m_fee); + // if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); + // if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); + // if (m_is_relayed != boost::none) node.put("isRelayed", *m_is_relayed); + // if (m_is_confirmed != boost::none) node.put("isConfirmed", *m_is_confirmed); + // if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); + // if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); + // if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); + // if (m_last_relayed_timestamp != boost::none) node.put("lastRelayedTimestamp", *m_last_relayed_timestamp); + // if (m_received_timestamp != boost::none) node.put("receivedTimestamp", *m_received_timestamp); + // if (m_is_double_spend_seen != boost::none) node.put("isDoubleSpendSeen", *m_is_double_spend_seen); + // if (m_key != boost::none) node.put("key", *m_key); + // if (m_full_hex != boost::none) node.put("fullHex", *m_full_hex); + // if (m_pruned_hex != boost::none) node.put("prunedHex", *m_pruned_hex); + // if (m_prunable_hex != boost::none) node.put("prunableHex", *m_prunable_hex); + // if (m_prunable_hash != boost::none) node.put("prunableHash", *m_prunable_hash); + // if (m_size != boost::none) node.put("size", *m_size); + // if (m_weight != boost::none) node.put("weight", *m_weight); + // if (!m_vins.empty()) node.add_child("vins", monero_utils::to_property_tree(m_vins)); + // if (!m_vouts.empty()) node.add_child("vouts", monero_utils::to_property_tree(m_vouts)); + // if (!m_output_indices.empty()) throw runtime_error("m_output_indices not implemented"); + // if (m_metadata != boost::none) node.put("metadata", *m_metadata); + // if (m_common_tx_sets != boost::none) throw runtime_error("m_common_tx_sets not implemented"); + // if (!m_extra.empty()) node.add_child("extra", monero_utils::to_property_tree(m_extra)); + // if (m_rct_signatures != boost::none) throw runtime_error("m_rct_signatures not implemented"); + // if (m_rct_sig_prunable != boost::none) throw runtime_error("m_rct_sig_prunable not implemented"); + // if (m_is_kept_by_block != boost::none) node.put("isKeptByBlock", *m_is_kept_by_block); + // if (m_is_failed != boost::none) node.put("isFailed", *m_is_failed); + // if (m_last_failed_height != boost::none) node.put("lastFailedHeight", *m_last_failed_height); + // if (m_last_failed_id != boost::none) node.put("lastFailedId", *m_last_failed_id); + // if (m_max_used_block_height != boost::none) node.put("maxUsedBlockHeight", *m_max_used_block_height); + // if (m_max_used_block_id != boost::none) node.put("maxUsedBlockId", *m_max_used_block_id); + // if (!m_signatures.empty()) throw runtime_error("m_signatures not implemented"); + // return node; + // } + + rapidjson::Value monero_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // create root + rapidjson::Value root(rapidjson::kObjectType); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_version != boost::none) monero_utils::addJsonMember("version", m_version.get(), allocator, root, value_num); + if (m_fee != boost::none) monero_utils::addJsonMember("fee", m_fee.get(), allocator, root, value_num); + if (m_ring_size != boost::none) monero_utils::addJsonMember("ringSize", m_ring_size.get(), allocator, root, value_num); + if (m_num_confirmations != boost::none) monero_utils::addJsonMember("numConfirmations", m_num_confirmations.get(), allocator, root, value_num); + if (m_unlock_time != boost::none) monero_utils::addJsonMember("unlockTime", m_unlock_time.get(), allocator, root, value_num); + if (m_last_relayed_timestamp != boost::none) monero_utils::addJsonMember("lastRelayedTimestamp", m_last_relayed_timestamp.get(), allocator, root, value_num); + if (m_received_timestamp != boost::none) monero_utils::addJsonMember("receivedTimestamp", m_received_timestamp.get(), allocator, root, value_num); + if (m_size != boost::none) monero_utils::addJsonMember("size", m_size.get(), allocator, root, value_num); + if (m_weight != boost::none) monero_utils::addJsonMember("weight", m_weight.get(), allocator, root, value_num); + if (m_last_failed_height != boost::none) monero_utils::addJsonMember("lastFailedHeight", m_last_failed_height.get(), allocator, root, value_num); + if (m_max_used_block_height != boost::none) monero_utils::addJsonMember("maxUsedBlockHeight", m_max_used_block_height.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_id != boost::none) monero_utils::addJsonMember("id", m_id.get(), allocator, root, value_str); + if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); + if (m_key != boost::none) monero_utils::addJsonMember("key", m_key.get(), allocator, root, value_str); + if (m_full_hex != boost::none) monero_utils::addJsonMember("fullHex", m_full_hex.get(), allocator, root, value_str); + if (m_pruned_hex != boost::none) monero_utils::addJsonMember("prunedHex", m_pruned_hex.get(), allocator, root, value_str); + if (m_prunable_hex != boost::none) monero_utils::addJsonMember("prunableHex", m_prunable_hex.get(), allocator, root, value_str); + if (m_prunable_hash != boost::none) monero_utils::addJsonMember("prunableHash", m_prunable_hash.get(), allocator, root, value_str); + if (m_metadata != boost::none) monero_utils::addJsonMember("metadata", m_metadata.get(), allocator, root, value_str); + if (m_common_tx_sets != boost::none) monero_utils::addJsonMember("commonTxSets", m_common_tx_sets.get(), allocator, root, value_str); + if (m_rct_signatures != boost::none) monero_utils::addJsonMember("rctSignatures", m_rct_signatures.get(), allocator, root, value_str); + if (m_rct_sig_prunable != boost::none) monero_utils::addJsonMember("rctSigPrunable", m_rct_sig_prunable.get(), allocator, root, value_str); + if (m_last_failed_id != boost::none) monero_utils::addJsonMember("lastFailedId", m_last_failed_id.get(), allocator, root, value_str); + if (m_max_used_block_id != boost::none) monero_utils::addJsonMember("maxUsedBlockId", m_max_used_block_id.get(), allocator, root, value_str); + + // set bool values + if (m_is_miner_tx != boost::none) monero_utils::addJsonMember("isMinerTx", m_is_miner_tx.get(), allocator, root); + if (m_do_not_relay != boost::none) monero_utils::addJsonMember("doNotRelay", m_do_not_relay.get(), allocator, root); + if (m_is_relayed != boost::none) monero_utils::addJsonMember("isRelayed", m_is_relayed.get(), allocator, root); + if (m_is_confirmed != boost::none) monero_utils::addJsonMember("isConfirmed", m_is_confirmed.get(), allocator, root); + if (m_in_tx_pool != boost::none) monero_utils::addJsonMember("inTxPool", m_in_tx_pool.get(), allocator, root); + if (m_is_double_spend_seen != boost::none) monero_utils::addJsonMember("isDoubleSpendSeen", m_is_double_spend_seen.get(), allocator, root); + if (m_is_kept_by_block != boost::none) monero_utils::addJsonMember("isKeptByBlock", m_is_kept_by_block.get(), allocator, root); + if (m_is_failed != boost::none) monero_utils::addJsonMember("isFailed", m_is_failed.get(), allocator, root); + + // set sub-arrays + if (!m_vins.empty()) root.AddMember("vins", monero_utils::to_json_val(allocator, m_vins), allocator); + if (!m_vouts.empty()) root.AddMember("vouts", monero_utils::to_json_val(allocator, m_vouts), allocator); + if (!m_output_indices.empty()) root.AddMember("outputIndices", monero_utils::to_json_val(allocator, m_output_indices), allocator); + if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_json_val(allocator, m_extra), allocator); // TODO + if (!m_signatures.empty()) root.AddMember("signatures", monero_utils::to_json_val(allocator, m_signatures), allocator); + + // return root + return root; + } + + void monero_tx::from_property_tree(const boost::property_tree::ptree& node, shared_ptr tx) { + + // initialize tx from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("id")) tx->m_id = it->second.data(); + else if (key == string("version")) throw runtime_error("version deserializationn not implemented"); + else if (key == string("isMinerTx")) tx->m_is_miner_tx = it->second.get_value(); + else if (key == string("paymentId")) tx->m_payment_id = it->second.data(); // TODO: this threw runtime_error, how is "Can get transactions by payment ids" test passing in Java? + else if (key == string("fee")) tx->m_fee = it->second.get_value(); + else if (key == string("mixin")) throw runtime_error("mixin deserialization not implemented"); + else if (key == string("doNotRelay")) tx->m_do_not_relay = it->second.get_value(); + else if (key == string("isRelayed")) tx->m_is_relayed = it->second.get_value(); + else if (key == string("isConfirmed")) tx->m_is_confirmed = it->second.get_value(); + else if (key == string("inTxPool")) tx->m_in_tx_pool = it->second.get_value(); + else if (key == string("numConfirmations")) tx->m_num_confirmations = it->second.get_value(); + else if (key == string("unlockTime")) tx->m_unlock_time = it->second.get_value(); + else if (key == string("lastRelayedTimestamp")) tx->m_last_relayed_timestamp = it->second.get_value(); + else if (key == string("receivedTimestamp")) tx->m_received_timestamp = it->second.get_value(); + else if (key == string("isDoubleSpendSeen")) tx->m_is_double_spend_seen = it->second.get_value(); + else if (key == string("key")) tx->m_key = it->second.data(); + else if (key == string("fullHex")) tx->m_full_hex = it->second.data(); + else if (key == string("prunedHex")) tx->m_pruned_hex = it->second.data(); + else if (key == string("prunableHex")) tx->m_prunable_hex = it->second.data(); + else if (key == string("prunableHash")) tx->m_prunable_hash = it->second.data(); + else if (key == string("size")) throw runtime_error("size deserialization not implemented"); + else if (key == string("weight")) throw runtime_error("weight deserialization not implemented"); + else if (key == string("vins")) throw runtime_error("vins deserializationn not implemented"); + else if (key == string("vouts")) throw runtime_error("vouts deserializationn not implemented"); + else if (key == string("outputIndices")) throw runtime_error("m_output_indices deserialization not implemented"); + else if (key == string("metadata")) tx->m_metadata = it->second.data(); + else if (key == string("commonTxSets")) throw runtime_error("commonTxSets deserialization not implemented"); + else if (key == string("extra")) throw runtime_error("extra deserialization not implemented"); + else if (key == string("rctSignatures")) throw runtime_error("rctSignatures deserialization not implemented"); + else if (key == string("rctSigPrunable")) throw runtime_error("rctSigPrunable deserialization not implemented"); + else if (key == string("isKeptByBlock")) tx->m_is_kept_by_block = it->second.get_value(); + else if (key == string("isFailed")) tx->m_is_failed = it->second.get_value(); + else if (key == string("lastFailedHeight")) throw runtime_error("lastFailedHeight deserialization not implemented"); + else if (key == string("lastFailedId")) tx->m_last_failed_id = it->second.data(); + else if (key == string("maxUsedBlockHeight")) throw runtime_error("maxUsedBlockHeight deserialization not implemented"); + else if (key == string("maxUsedBlockId")) tx->m_max_used_block_id = it->second.data(); + else if (key == string("signatures")) throw runtime_error("signatures deserialization not implemented"); + } + } + shared_ptr monero_tx::copy(const shared_ptr& src, const shared_ptr& tgt) const { MTRACE("monero_tx::copy(const shared_ptr& src, const shared_ptr& tgt)"); tgt->m_id = src->m_id; @@ -368,104 +511,6 @@ namespace monero { return tgt; } -// boost::property_tree::ptree monero_tx::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_id != boost::none) node.put("id", *m_id); -// if (m_version != boost::none) node.put("version", *m_version); -// if (m_is_miner_tx != boost::none) node.put("isMinerTx", *m_is_miner_tx); -// if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); -// if (m_fee != boost::none) node.put("fee", *m_fee); -// if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); -// if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); -// if (m_is_relayed != boost::none) node.put("isRelayed", *m_is_relayed); -// if (m_is_confirmed != boost::none) node.put("isConfirmed", *m_is_confirmed); -// if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); -// if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); -// if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); -// if (m_last_relayed_timestamp != boost::none) node.put("lastRelayedTimestamp", *m_last_relayed_timestamp); -// if (m_received_timestamp != boost::none) node.put("receivedTimestamp", *m_received_timestamp); -// if (m_is_double_spend_seen != boost::none) node.put("isDoubleSpendSeen", *m_is_double_spend_seen); -// if (m_key != boost::none) node.put("key", *m_key); -// if (m_full_hex != boost::none) node.put("fullHex", *m_full_hex); -// if (m_pruned_hex != boost::none) node.put("prunedHex", *m_pruned_hex); -// if (m_prunable_hex != boost::none) node.put("prunableHex", *m_prunable_hex); -// if (m_prunable_hash != boost::none) node.put("prunableHash", *m_prunable_hash); -// if (m_size != boost::none) node.put("size", *m_size); -// if (m_weight != boost::none) node.put("weight", *m_weight); -// if (!m_vins.empty()) node.add_child("vins", monero_utils::to_property_tree(m_vins)); -// if (!m_vouts.empty()) node.add_child("vouts", monero_utils::to_property_tree(m_vouts)); -// if (!m_output_indices.empty()) throw runtime_error("m_output_indices not implemented"); -// if (m_metadata != boost::none) node.put("metadata", *m_metadata); -// if (m_common_tx_sets != boost::none) throw runtime_error("m_common_tx_sets not implemented"); -// if (!m_extra.empty()) node.add_child("extra", monero_utils::to_property_tree(m_extra)); -// if (m_rct_signatures != boost::none) throw runtime_error("m_rct_signatures not implemented"); -// if (m_rct_sig_prunable != boost::none) throw runtime_error("m_rct_sig_prunable not implemented"); -// if (m_is_kept_by_block != boost::none) node.put("isKeptByBlock", *m_is_kept_by_block); -// if (m_is_failed != boost::none) node.put("isFailed", *m_is_failed); -// if (m_last_failed_height != boost::none) node.put("lastFailedHeight", *m_last_failed_height); -// if (m_last_failed_id != boost::none) node.put("lastFailedId", *m_last_failed_id); -// if (m_max_used_block_height != boost::none) node.put("maxUsedBlockHeight", *m_max_used_block_height); -// if (m_max_used_block_id != boost::none) node.put("maxUsedBlockId", *m_max_used_block_id); -// if (!m_signatures.empty()) throw runtime_error("m_signatures not implemented"); -// return node; -// } - - rapidjson::Value monero_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - - // create root - rapidjson::Value root(rapidjson::kObjectType); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_version != boost::none) monero_utils::addJsonMember("version", m_version.get(), allocator, root, value_num); - if (m_fee != boost::none) monero_utils::addJsonMember("fee", m_fee.get(), allocator, root, value_num); - if (m_ring_size != boost::none) monero_utils::addJsonMember("ringSize", m_ring_size.get(), allocator, root, value_num); - if (m_num_confirmations != boost::none) monero_utils::addJsonMember("numConfirmations", m_num_confirmations.get(), allocator, root, value_num); - if (m_unlock_time != boost::none) monero_utils::addJsonMember("unlockTime", m_unlock_time.get(), allocator, root, value_num); - if (m_last_relayed_timestamp != boost::none) monero_utils::addJsonMember("lastRelayedTimestamp", m_last_relayed_timestamp.get(), allocator, root, value_num); - if (m_received_timestamp != boost::none) monero_utils::addJsonMember("receivedTimestamp", m_received_timestamp.get(), allocator, root, value_num); - if (m_size != boost::none) monero_utils::addJsonMember("size", m_size.get(), allocator, root, value_num); - if (m_weight != boost::none) monero_utils::addJsonMember("weight", m_weight.get(), allocator, root, value_num); - if (m_last_failed_height != boost::none) monero_utils::addJsonMember("lastFailedHeight", m_last_failed_height.get(), allocator, root, value_num); - if (m_max_used_block_height != boost::none) monero_utils::addJsonMember("maxUsedBlockHeight", m_max_used_block_height.get(), allocator, root, value_num); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_id != boost::none) monero_utils::addJsonMember("id", m_id.get(), allocator, root, value_str); - if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); - if (m_key != boost::none) monero_utils::addJsonMember("key", m_key.get(), allocator, root, value_str); - if (m_full_hex != boost::none) monero_utils::addJsonMember("fullHex", m_full_hex.get(), allocator, root, value_str); - if (m_pruned_hex != boost::none) monero_utils::addJsonMember("prunedHex", m_pruned_hex.get(), allocator, root, value_str); - if (m_prunable_hex != boost::none) monero_utils::addJsonMember("prunableHex", m_prunable_hex.get(), allocator, root, value_str); - if (m_prunable_hash != boost::none) monero_utils::addJsonMember("prunableHash", m_prunable_hash.get(), allocator, root, value_str); - if (m_metadata != boost::none) monero_utils::addJsonMember("metadata", m_metadata.get(), allocator, root, value_str); - if (m_common_tx_sets != boost::none) monero_utils::addJsonMember("commonTxSets", m_common_tx_sets.get(), allocator, root, value_str); - if (m_rct_signatures != boost::none) monero_utils::addJsonMember("rctSignatures", m_rct_signatures.get(), allocator, root, value_str); - if (m_rct_sig_prunable != boost::none) monero_utils::addJsonMember("rctSigPrunable", m_rct_sig_prunable.get(), allocator, root, value_str); - if (m_last_failed_id != boost::none) monero_utils::addJsonMember("lastFailedId", m_last_failed_id.get(), allocator, root, value_str); - if (m_max_used_block_id != boost::none) monero_utils::addJsonMember("maxUsedBlockId", m_max_used_block_id.get(), allocator, root, value_str); - - // set bool values - if (m_is_miner_tx != boost::none) monero_utils::addJsonMember("isMinerTx", m_is_miner_tx.get(), allocator, root); - if (m_do_not_relay != boost::none) monero_utils::addJsonMember("doNotRelay", m_do_not_relay.get(), allocator, root); - if (m_is_relayed != boost::none) monero_utils::addJsonMember("isRelayed", m_is_relayed.get(), allocator, root); - if (m_is_confirmed != boost::none) monero_utils::addJsonMember("isConfirmed", m_is_confirmed.get(), allocator, root); - if (m_in_tx_pool != boost::none) monero_utils::addJsonMember("inTxPool", m_in_tx_pool.get(), allocator, root); - if (m_is_double_spend_seen != boost::none) monero_utils::addJsonMember("isDoubleSpendSeen", m_is_double_spend_seen.get(), allocator, root); - if (m_is_kept_by_block != boost::none) monero_utils::addJsonMember("isKeptByBlock", m_is_kept_by_block.get(), allocator, root); - if (m_is_failed != boost::none) monero_utils::addJsonMember("isFailed", m_is_failed.get(), allocator, root); - - // set sub-arrays - if (!m_vins.empty()) root.AddMember("vins", monero_utils::to_json_val(allocator, m_vins), allocator); - if (!m_vouts.empty()) root.AddMember("vouts", monero_utils::to_json_val(allocator, m_vouts), allocator); - if (!m_output_indices.empty()) root.AddMember("outputIndices", monero_utils::to_json_val(allocator, m_output_indices), allocator); - if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_json_val(allocator, m_extra), allocator); // TODO - if (!m_signatures.empty()) root.AddMember("signatures", monero_utils::to_json_val(allocator, m_signatures), allocator); - - // return root - return root; - } - boost::optional monero_tx::get_height() const { if (m_block == boost::none) return boost::none; return *((*m_block)->m_height); @@ -627,19 +672,12 @@ namespace monero { // --------------------------- MONERO KEY IMAGE ----------------------------- - shared_ptr monero_key_image::copy(const shared_ptr& src, const shared_ptr& tgt) const { - if (this != src.get()) throw runtime_error("this != src"); - tgt->m_hex = src->m_hex; - tgt->m_signature = src->m_signature; - return tgt; - } - -// boost::property_tree::ptree monero_key_image::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_hex != boost::none) node.put("hex", *m_hex); -// if (m_signature != boost::none) node.put("signature", *m_signature); -// return node; -// } + // boost::property_tree::ptree monero_key_image::to_property_tree() const { + // boost::property_tree::ptree node; + // if (m_hex != boost::none) node.put("hex", *m_hex); + // if (m_signature != boost::none) node.put("signature", *m_signature); + // return node; + // } rapidjson::Value monero_key_image::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -655,33 +693,52 @@ namespace monero { return root; } + void monero_key_image::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& key_image) { + + // initialize key image from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("hex")) key_image->m_hex = it->second.data(); + else if (key == string("signature")) key_image->m_signature = it->second.data(); + } + } + + vector> monero_key_image::deserialize_key_images(const string& key_images_json) { + + // deserialize json to property node + std::istringstream iss = key_images_json.empty() ? std::istringstream() : std::istringstream(key_images_json); + boost::property_tree::ptree node; + boost::property_tree::read_json(iss, node); + + // convert property tree to key images + vector> key_images; + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("keyImages")) { + for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { + shared_ptr key_image = make_shared(); + monero_key_image::from_property_tree(it2->second, key_image); + key_images.push_back(key_image); + } + } + else MWARNING("WARNING MoneroWalletJni::deserialize_key_images() unrecognized key: " << key); + } + return key_images; + } + + shared_ptr monero_key_image::copy(const shared_ptr& src, const shared_ptr& tgt) const { + if (this != src.get()) throw runtime_error("this != src"); + tgt->m_hex = src->m_hex; + tgt->m_signature = src->m_signature; + return tgt; + } + void monero_key_image::merge(const shared_ptr& self, const shared_ptr& other) { throw runtime_error("Not implemented"); } // ------------------------------ MONERO OUTPUT ----------------------------- - shared_ptr monero_output::copy(const shared_ptr& src, const shared_ptr& tgt) const { - if (this != src.get()) throw runtime_error("this != src"); - tgt->m_tx = src->m_tx; // reference same parent tx by default - if (src->m_key_image != boost::none) tgt->m_key_image = src->m_key_image.get()->copy(src->m_key_image.get(), make_shared()); - tgt->m_amount = src->m_amount; - tgt->m_index = src->m_index; - if (!src->m_ring_output_indices.empty()) tgt->m_ring_output_indices = vector(src->m_ring_output_indices); - tgt->m_stealth_public_key = src->m_stealth_public_key; - return tgt; - } - -// boost::property_tree::ptree monero_output::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_key_image != boost::none) node.add_child("keyImage", (*m_key_image)->to_property_tree()); -// if (m_amount != boost::none) node.put("amount", *m_amount); -// if (m_index != boost::none) node.put("index", *m_index); -// if (!m_ring_output_indices.empty()) node.add_child("ringOutputIndices", monero_utils::to_property_tree(m_ring_output_indices)); -// if (m_stealth_public_key != boost::none) node.put("stealthPublicKey", *m_stealth_public_key); -// return node; -// } - rapidjson::Value monero_output::to_json_val(rapidjson::Document::AllocatorType& allocator) const { // create root @@ -703,6 +760,44 @@ namespace monero { return root; } + void monero_output::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output) { + + // initialize output from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("keyImage")) { + output->m_key_image = make_shared(); + monero_key_image::from_property_tree(it->second, output->m_key_image.get()); + } + else if (key == string("amount")) output->m_amount = it->second.get_value(); + else if (key == string("index")) output->m_index = it->second.get_value(); + else if (key == string("ringOutputIndices")) throw runtime_error("node_to_tx() deserialize ringOutputIndices not implemented"); + else if (key == string("stealthPublicKey")) throw runtime_error("node_to_tx() deserialize stealthPublicKey not implemented"); + else cout << "WARNING: unrecognized field deserializing node to output: " << key << endl; + } + } + + shared_ptr monero_output::copy(const shared_ptr& src, const shared_ptr& tgt) const { + if (this != src.get()) throw runtime_error("this != src"); + tgt->m_tx = src->m_tx; // reference same parent tx by default + if (src->m_key_image != boost::none) tgt->m_key_image = src->m_key_image.get()->copy(src->m_key_image.get(), make_shared()); + tgt->m_amount = src->m_amount; + tgt->m_index = src->m_index; + if (!src->m_ring_output_indices.empty()) tgt->m_ring_output_indices = vector(src->m_ring_output_indices); + tgt->m_stealth_public_key = src->m_stealth_public_key; + return tgt; + } + +// boost::property_tree::ptree monero_output::to_property_tree() const { +// boost::property_tree::ptree node; +// if (m_key_image != boost::none) node.add_child("keyImage", (*m_key_image)->to_property_tree()); +// if (m_amount != boost::none) node.put("amount", *m_amount); +// if (m_index != boost::none) node.put("index", *m_index); +// if (!m_ring_output_indices.empty()) node.add_child("ringOutputIndices", monero_utils::to_property_tree(m_ring_output_indices)); +// if (m_stealth_public_key != boost::none) node.put("stealthPublicKey", *m_stealth_public_key); +// return node; +// } + void monero_output::merge(const shared_ptr& self, const shared_ptr& other) { if (this != self.get()) throw runtime_error("this != self"); if (self == other) return; diff --git a/src/daemon/monero_daemon_model.h b/src/daemon/monero_daemon_model.h index 9d5c56c..f87094d 100644 --- a/src/daemon/monero_daemon_model.h +++ b/src/daemon/monero_daemon_model.h @@ -170,6 +170,7 @@ namespace monero { //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -218,9 +219,10 @@ namespace monero { boost::optional m_max_used_block_id; vector m_signatures; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, shared_ptr tx); + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); boost::optional get_height() const; }; @@ -232,9 +234,11 @@ namespace monero { boost::optional m_hex; boost::optional m_signature; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& key_image); + static vector> deserialize_key_images(const string& key_images_json); // TODO: remove this specialty util used once + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -249,9 +253,10 @@ namespace monero { vector m_ring_output_indices; boost::optional m_stealth_public_key; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output); + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); }; } diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index 40d7d95..5ba3d26 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -60,200 +60,6 @@ using namespace std; using namespace cryptonote; using namespace monero_utils; -// ------------------------------- INNER HELPERS ------------------------------ - -void node_to_transfer(const boost::property_tree::ptree& node, shared_ptr transfer) { - - // initialize transfer from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("accountIndex")) transfer->m_account_index = it->second.get_value(); - } -} - -shared_ptr node_to_transfer_query(const boost::property_tree::ptree& node) { - shared_ptr m_transfer_query = make_shared(); - node_to_transfer(node, m_transfer_query); - - // initialize query from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("isIncoming")) m_transfer_query->m_is_incoming = it->second.get_value(); - else if (key == string("address")) m_transfer_query->m_address = it->second.data(); - else if (key == string("addresses")) throw runtime_error("addresses not implemented"); - else if (key == string("subaddressIndex")) m_transfer_query->m_subaddress_index = it->second.get_value(); - else if (key == string("subaddressIndices")) { - vector m_subaddress_indices; - for (const auto& child : it->second) m_subaddress_indices.push_back(child.second.get_value()); - m_transfer_query->m_subaddress_indices = m_subaddress_indices; - } - else if (key == string("destinations")) throw runtime_error("destinations not implemented"); - else if (key == string("hasDestinations")) m_transfer_query->m_has_destinations = it->second.get_value(); - else if (key == string("txQuery")) throw runtime_error("txQuery not implemented"); - } - - return m_transfer_query; -} - -shared_ptr node_to_key_image(const boost::property_tree::ptree& node) { - - // initialize key image from node - shared_ptr m_key_image = make_shared(); - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("hex")) m_key_image->m_hex = it->second.data(); - else if (key == string("signature")) m_key_image->m_signature = it->second.data(); - } - - return m_key_image; -} - -void node_to_output(const boost::property_tree::ptree& node, shared_ptr output) { - - // initialize output from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("keyImage")) output->m_key_image = node_to_key_image(it->second); - else if (key == string("amount")) output->m_amount = it->second.get_value(); - else if (key == string("index")) output->m_index = it->second.get_value(); - else if (key == string("ringOutputIndices")) throw runtime_error("node_to_tx() deserialize ringOutputIndices not implemented"); - else if (key == string("stealthPublicKey")) throw runtime_error("node_to_tx() deserialize stealthPublicKey not implemented"); - else cout << "WARNING: unrecognized field deserializing node to output: " << key << endl; - } -} - -void node_to_output_wallet(const boost::property_tree::ptree& node, shared_ptr output_wallet) { - node_to_output(node, output_wallet); - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("accountIndex")) output_wallet->m_account_index = it->second.get_value(); - else if (key == string("subaddressIndex")) output_wallet->m_subaddress_index = it->second.get_value(); - else if (key == string("isSpent")) output_wallet->m_is_spent = it->second.get_value(); - else if (key == string("isFrozen")) output_wallet->m_is_frozen = it->second.get_value(); - else cout << "WARNING: unrecognized field deserializing node to output wallet: " << key << endl; - } -} - -shared_ptr node_to_output_query(const boost::property_tree::ptree& node) { - shared_ptr m_output_query = make_shared(); - node_to_output_wallet(node, m_output_query); - - // initialize query from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("subaddressIndices")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) m_output_query->m_subaddress_indices.push_back(it2->second.get_value()); - else if (key == string("txQuery")) {} // ignored - else cout << "WARNING: unrecognized field deserializing node to output query: " << key << endl; - } - - return m_output_query; -} - -// TODO: finish deserialization implementation, uses tests -void node_to_tx(const boost::property_tree::ptree& node, shared_ptr tx) { - - // initialize tx from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("id")) tx->m_id = it->second.data(); - else if (key == string("version")) throw runtime_error("version deserializationn not implemented"); - else if (key == string("isMinerTx")) tx->m_is_miner_tx = it->second.get_value(); - else if (key == string("paymentId")) tx->m_payment_id = it->second.data(); // TODO: this threw runtime_error, how is "Can get transactions by payment ids" test passing in Java? - else if (key == string("fee")) tx->m_fee = it->second.get_value(); - else if (key == string("mixin")) throw runtime_error("mixin deserialization not implemented"); - else if (key == string("doNotRelay")) tx->m_do_not_relay = it->second.get_value(); - else if (key == string("isRelayed")) tx->m_is_relayed = it->second.get_value(); - else if (key == string("isConfirmed")) tx->m_is_confirmed = it->second.get_value(); - else if (key == string("inTxPool")) tx->m_in_tx_pool = it->second.get_value(); - else if (key == string("numConfirmations")) tx->m_num_confirmations = it->second.get_value(); - else if (key == string("unlockTime")) tx->m_unlock_time = it->second.get_value(); - else if (key == string("lastRelayedTimestamp")) tx->m_last_relayed_timestamp = it->second.get_value(); - else if (key == string("receivedTimestamp")) tx->m_received_timestamp = it->second.get_value(); - else if (key == string("isDoubleSpendSeen")) tx->m_is_double_spend_seen = it->second.get_value(); - else if (key == string("key")) tx->m_key = it->second.data(); - else if (key == string("fullHex")) tx->m_full_hex = it->second.data(); - else if (key == string("prunedHex")) tx->m_pruned_hex = it->second.data(); - else if (key == string("prunableHex")) tx->m_prunable_hex = it->second.data(); - else if (key == string("prunableHash")) tx->m_prunable_hash = it->second.data(); - else if (key == string("size")) throw runtime_error("size deserialization not implemented"); - else if (key == string("weight")) throw runtime_error("weight deserialization not implemented"); - else if (key == string("vins")) throw runtime_error("vins deserializationn not implemented"); - else if (key == string("vouts")) throw runtime_error("vouts deserializationn not implemented"); - else if (key == string("outputIndices")) throw runtime_error("m_output_indices deserialization not implemented"); - else if (key == string("metadata")) tx->m_metadata = it->second.data(); - else if (key == string("commonTxSets")) throw runtime_error("commonTxSets deserialization not implemented"); - else if (key == string("extra")) throw runtime_error("extra deserialization not implemented"); - else if (key == string("rctSignatures")) throw runtime_error("rctSignatures deserialization not implemented"); - else if (key == string("rctSigPrunable")) throw runtime_error("rctSigPrunable deserialization not implemented"); - else if (key == string("isKeptByBlock")) tx->m_is_kept_by_block = it->second.get_value(); - else if (key == string("isFailed")) tx->m_is_failed = it->second.get_value(); - else if (key == string("lastFailedHeight")) throw runtime_error("lastFailedHeight deserialization not implemented"); - else if (key == string("lastFailedId")) tx->m_last_failed_id = it->second.data(); - else if (key == string("maxUsedBlockHeight")) throw runtime_error("maxUsedBlockHeight deserialization not implemented"); - else if (key == string("maxUsedBlockId")) tx->m_max_used_block_id = it->second.data(); - else if (key == string("signatures")) throw runtime_error("signatures deserialization not implemented"); - } -} - -// TODO: fill this out -void node_to_tx_wallet(const boost::property_tree::ptree& node, shared_ptr tx_wallet) { - node_to_tx(node, tx_wallet); - - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - //if (key == string("id")) tx->m_id = it->second.data(); - if (key == string("isLocked")) tx_wallet->m_is_locked = it->second.get_value(); - // TODO: deserialize other fields - } -} - -shared_ptr node_to_tx_query(const boost::property_tree::ptree& node) { - shared_ptr tx_query = make_shared(); - node_to_tx_wallet(node, tx_query); - - // initialize query from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("isOutgoing")) tx_query->m_is_outgoing = it->second.get_value(); - else if (key == string("isIncoming")) tx_query->m_is_incoming = it->second.get_value(); - else if (key == string("txIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) tx_query->m_tx_ids.push_back(it2->second.data()); - else if (key == string("hasPaymentId")) tx_query->m_has_payment_id = it->second.get_value(); - else if (key == string("paymentIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) tx_query->m_payment_ids.push_back(it2->second.data()); - else if (key == string("height")) tx_query->m_height = it->second.get_value(); - else if (key == string("minHeight")) tx_query->m_min_height = it->second.get_value(); - else if (key == string("maxHeight")) tx_query->m_max_height = it->second.get_value(); - else if (key == string("includeOutputs")) tx_query->m_include_outputs = it->second.get_value(); - else if (key == string("transferQuery")) tx_query->m_transfer_query = node_to_transfer_query(it->second); - else if (key == string("outputQuery")) tx_query->m_output_query = node_to_output_query(it->second); - } - - return tx_query; -} - -shared_ptr node_to_block_query(const boost::property_tree::ptree& node) { - shared_ptr block = make_shared(); - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("txs")) { - boost::property_tree::ptree txs_node = it->second; - for (boost::property_tree::ptree::const_iterator it2 = txs_node.begin(); it2 != txs_node.end(); ++it2) { - block->m_txs.push_back(node_to_tx_query(it2->second)); - } - } - } - return block; -} - -shared_ptr node_to_destination(const boost::property_tree::ptree& node) { - shared_ptr destination = make_shared(); - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("address")) destination->m_address = it->second.data(); - else if (key == string("amount")) destination->m_amount = it->second.get_value(); - } - return destination; -} - // -------------------------- BINARY SERIALIZATION ---------------------------- void monero_utils::json_to_binary(const std::string &json, std::string &bin) { @@ -320,33 +126,6 @@ void monero_utils::binary_blocks_to_json(const std::string &bin, std::string &js json = ss.str(); } -monero_tx_set monero_utils::deserialize_tx_set(const string& tx_set_str) { - - // deserialize tx set to property - std::istringstream iss = tx_set_str.empty() ? std::istringstream() : std::istringstream(tx_set_str); - boost::property_tree::ptree tx_set_node; - boost::property_tree::read_json(iss, tx_set_node); - - // initialize tx_set from property node - monero_tx_set tx_set; - for (boost::property_tree::ptree::const_iterator it = tx_set_node.begin(); it != tx_set_node.end(); ++it) { - string key = it->first; - if (key == string("unsignedTxHex")) tx_set.m_unsigned_tx_hex = it->second.data(); - else if (key == string("multisigTxHex")) tx_set.m_multisig_tx_hex = it->second.data(); - else if (key == string("txs")) { - boost::property_tree::ptree txs_node = it->second; - for (boost::property_tree::ptree::const_iterator it2 = txs_node.begin(); it2 != txs_node.end(); ++it2) { - shared_ptr tx_wallet = make_shared(); - node_to_tx_wallet(it2->second, tx_wallet); - tx_set.m_txs.push_back(tx_wallet); - } - } - else throw runtime_error("monero_utils::deserialize_tx_set() field '" + key + "' not supported"); - } - - return tx_set; -} - // ------------------------------- RAPIDJSON ---------------------------------- string monero_utils::serialize(const rapidjson::Document& doc) { @@ -432,136 +211,6 @@ rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& a return value_arr; } -// -------------------------- MODEL DESERIALIZATION --------------------------- - -shared_ptr monero_utils::deserialize_tx_query(const string& tx_query_str) { - - // deserialize tx query string to property rooted at block - std::istringstream iss = tx_query_str.empty() ? std::istringstream() : std::istringstream(tx_query_str); - boost::property_tree::ptree block_node; - boost::property_tree::read_json(iss, block_node); - - // convert query property tree to block - shared_ptr block = node_to_block_query(block_node); - - // get tx query - shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); - - // return deserialized query - return tx_query; -} - -shared_ptr monero_utils::deserialize_transfer_query(const string& transfer_query_str) { - - // deserialize transfer query string to property rooted at block - std::istringstream iss = transfer_query_str.empty() ? std::istringstream() : std::istringstream(transfer_query_str); - boost::property_tree::ptree blockNode; - boost::property_tree::read_json(iss, blockNode); - - // convert query property tree to block - shared_ptr block = node_to_block_query(blockNode); - - // return empty query if no txs - if (block->m_txs.empty()) return make_shared(); - - // get tx query - shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); - - // get / create transfer query - shared_ptr transfer_query = tx_query->m_transfer_query == boost::none ? make_shared() : *tx_query->m_transfer_query; - - // transfer query references tx query but not the other way around to avoid circular loop // TODO: could add check within meetsCriterias() - transfer_query->m_tx_query = tx_query; - tx_query->m_transfer_query = boost::none; - - // return deserialized query - return transfer_query; -} - -shared_ptr monero_utils::deserialize_output_query(const string& output_query_str) { - - // deserialize output query string to property rooted at block - std::istringstream iss = output_query_str.empty() ? std::istringstream() : std::istringstream(output_query_str); - boost::property_tree::ptree blockNode; - boost::property_tree::read_json(iss, blockNode); - - // convert query property tree to block - shared_ptr block = node_to_block_query(blockNode); - - // empty query if no txs - if (block->m_txs.empty()) return make_shared(); - - // get tx query - shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); - - // get / create output query - shared_ptr output_query = tx_query->m_output_query == boost::none ? make_shared() : *tx_query->m_output_query; - - // output query references tx query but not the other way around to avoid circular loop // TODO: could add check within meetsCriterias(), TODO: move this temp hack to the caller - output_query->m_tx_query = tx_query; - tx_query->m_output_query = boost::none; - - // return deserialized query - return output_query; -} - -shared_ptr monero_utils::deserialize_send_request(const string& send_request_str) { - - // deserialize send request json to property node - std::istringstream iss = send_request_str.empty() ? std::istringstream() : std::istringstream(send_request_str); - boost::property_tree::ptree node; - boost::property_tree::read_json(iss, node); - - // convert request property tree to monero_send_request - shared_ptr send_request = make_shared(); - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("destinations")) { - boost::property_tree::ptree destinationsNode = it->second; - for (boost::property_tree::ptree::const_iterator it2 = destinationsNode.begin(); it2 != destinationsNode.end(); ++it2) { - send_request->m_destinations.push_back(node_to_destination(it2->second)); - } - } - else if (key == string("paymentId")) send_request->m_payment_id = it->second.data(); - else if (key == string("priority")) throw runtime_error("deserialize_send_request() priority not implemented"); - else if (key == string("ringSize")) send_request->m_ring_size = it->second.get_value(); - else if (key == string("fee")) send_request->m_fee = it->second.get_value(); - else if (key == string("accountIndex")) send_request->m_account_index = it->second.get_value(); - else if (key == string("subaddressIndices")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) send_request->m_subaddress_indices.push_back(it2->second.get_value()); - else if (key == string("unlockTime")) send_request->m_unlock_time = it->second.get_value(); - else if (key == string("canSplit")) send_request->m_can_split = it->second.get_value(); - else if (key == string("doNotRelay")) send_request->m_do_not_relay = it->second.get_value(); - else if (key == string("note")) send_request->m_note = it->second.data(); - else if (key == string("recipientName")) send_request->m_recipient_name = it->second.data(); - else if (key == string("belowAmount")) send_request->m_below_amount = it->second.get_value(); - else if (key == string("sweepEachSubaddress")) send_request->m_sweep_each_subaddress = it->second.get_value(); - else if (key == string("keyImage")) send_request->m_key_image = it->second.data(); - } - - return send_request; -} - -vector> monero_utils::deserialize_key_images(const string& key_images_json) { - - // deserialize json to property node - std::istringstream iss = key_images_json.empty() ? std::istringstream() : std::istringstream(key_images_json); - boost::property_tree::ptree node; - boost::property_tree::read_json(iss, node); - - // convert property tree to key images - vector> key_images; - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("keyImages")) { - for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) { - key_images.push_back(node_to_key_image(it2->second)); - } - } - else MWARNING("WARNING MoneroWalletJni::deserialize_key_images() unrecognized key: " << key); - } - return key_images; -} - // ------------------------ PROPERTY TREES --------------------------- // TODO: fully switch to rapidjson diff --git a/src/utils/monero_utils.h b/src/utils/monero_utils.h index 827de55..8394e82 100644 --- a/src/utils/monero_utils.h +++ b/src/utils/monero_utils.h @@ -107,17 +107,6 @@ namespace monero_utils rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); - // ------------------------ MODEL DESERIALIZATION --------------------------- - - // TODO: move deserialization to static utilities on class - - shared_ptr deserialize_tx_query(const string& txQueryStr); - shared_ptr deserialize_transfer_query(const string& transfer_query_str); - shared_ptr deserialize_output_query(const string& output_query_str); - shared_ptr deserialize_send_request(const string& send_request_str); - vector> deserialize_key_images(const string& key_images_json); - monero_tx_set deserialize_tx_set(const string& tx_set_str); - // ------------------------ PROPERTY TREES --------------------------- // TODO: fully switch from property trees to rapidjson diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index b69aed2..1ea3b02 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -76,6 +76,22 @@ namespace monero { transfers.push_back(transfer); } + shared_ptr node_to_block_query(const boost::property_tree::ptree& node) { + shared_ptr block = make_shared(); + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("txs")) { + boost::property_tree::ptree txs_node = it->second; + for (boost::property_tree::ptree::const_iterator it2 = txs_node.begin(); it2 != txs_node.end(); ++it2) { + shared_ptr tx_query = make_shared(); + monero_tx_query::from_property_tree(it2->second, tx_query); + block->m_txs.push_back(tx_query); + } + } + } + return block; + } + // -------------------------- MONERO SYNC RESULT ---------------------------- rapidjson::Value monero_sync_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -173,6 +189,67 @@ namespace monero { // --------------------------- MONERO TX WALLET ----------------------------- + // boost::property_tree::ptree monero_tx_wallet::to_property_tree() const { + // boost::property_tree::ptree node = monero_tx::to_property_tree(); + // if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); + // if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); + // if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); + // if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); + // if (m_note != boost::none) node.put("note", *m_note); + // if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); + // if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); + // if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); + // if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); + // if (m_change_amount != boost::none) node.put("changeAmount", *m_change_amount); + // if (m_num_dummy_outputs != boost::none) node.put("numDummyOutputs", *m_num_dummy_outputs); + // if (m_extra_hex != boost::none) node.put("extraHex", *m_extra_hex); + // return node; + // } + + rapidjson::Value monero_tx_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_tx::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_input_sum != boost::none) monero_utils::addJsonMember("inputSum", m_input_sum.get(), allocator, root, value_num); + if (m_output_sum != boost::none) monero_utils::addJsonMember("outputSum", m_output_sum.get(), allocator, root, value_num); + if (m_change_amount != boost::none) monero_utils::addJsonMember("changeAmount", m_change_amount.get(), allocator, root, value_num); + if (m_num_dummy_outputs != boost::none) monero_utils::addJsonMember("numDummyOutputs", m_num_dummy_outputs.get(), allocator, root, value_num); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_note != boost::none) monero_utils::addJsonMember("note", m_note.get(), allocator, root, value_str); + if (m_change_address != boost::none) monero_utils::addJsonMember("changeAddress", m_change_address.get(), allocator, root, value_str); + if (m_extra_hex != boost::none) monero_utils::addJsonMember("extraHex", m_extra_hex.get(), allocator, root, value_str); + + // set bool values + if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); + if (m_is_outgoing != boost::none) monero_utils::addJsonMember("isOutgoing", m_is_outgoing.get(), allocator, root); + if (m_is_locked != boost::none) monero_utils::addJsonMember("isLocked", m_is_locked.get(), allocator, root); + + // set sub-arrays + if (!m_incoming_transfers.empty()) root.AddMember("incomingTransfers", monero_utils::to_json_val(allocator, m_incoming_transfers), allocator); + + // set sub-objects + if (m_outgoing_transfer != boost::none) root.AddMember("outgoingTransfer", m_outgoing_transfer.get()->to_json_val(allocator), allocator); + + // return root + return root; + } + + void monero_tx_wallet::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_wallet) { + monero_tx::from_property_tree(node, tx_wallet); + + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + //if (key == string("id")) tx->m_id = it->second.data(); + if (key == string("isLocked")) tx_wallet->m_is_locked = it->second.get_value(); + // TODO: deserialize other fields + } + } + shared_ptr monero_tx_wallet::copy(const shared_ptr& src, const shared_ptr& tgt) const { MTRACE("monero_tx_wallet::copy(const shared_ptr& src, const shared_ptr& tgt)"); return monero_tx_wallet::copy(static_pointer_cast(src), static_pointer_cast(tgt)); @@ -214,56 +291,6 @@ namespace monero { return tgt; }; -// boost::property_tree::ptree monero_tx_wallet::to_property_tree() const { -// boost::property_tree::ptree node = monero_tx::to_property_tree(); -// if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); -// if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); -// if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); -// if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); -// if (m_note != boost::none) node.put("note", *m_note); -// if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); -// if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); -// if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); -// if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); -// if (m_change_amount != boost::none) node.put("changeAmount", *m_change_amount); -// if (m_num_dummy_outputs != boost::none) node.put("numDummyOutputs", *m_num_dummy_outputs); -// if (m_extra_hex != boost::none) node.put("extraHex", *m_extra_hex); -// return node; -// } - - rapidjson::Value monero_tx_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - - // serialize root from superclass - rapidjson::Value root = monero_tx::to_json_val(allocator); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_input_sum != boost::none) monero_utils::addJsonMember("inputSum", m_input_sum.get(), allocator, root, value_num); - if (m_output_sum != boost::none) monero_utils::addJsonMember("outputSum", m_output_sum.get(), allocator, root, value_num); - if (m_change_amount != boost::none) monero_utils::addJsonMember("changeAmount", m_change_amount.get(), allocator, root, value_num); - if (m_num_dummy_outputs != boost::none) monero_utils::addJsonMember("numDummyOutputs", m_num_dummy_outputs.get(), allocator, root, value_num); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_note != boost::none) monero_utils::addJsonMember("note", m_note.get(), allocator, root, value_str); - if (m_change_address != boost::none) monero_utils::addJsonMember("changeAddress", m_change_address.get(), allocator, root, value_str); - if (m_extra_hex != boost::none) monero_utils::addJsonMember("extraHex", m_extra_hex.get(), allocator, root, value_str); - - // set bool values - if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); - if (m_is_outgoing != boost::none) monero_utils::addJsonMember("isOutgoing", m_is_outgoing.get(), allocator, root); - if (m_is_locked != boost::none) monero_utils::addJsonMember("isLocked", m_is_locked.get(), allocator, root); - - // set sub-arrays - if (!m_incoming_transfers.empty()) root.AddMember("incomingTransfers", monero_utils::to_json_val(allocator, m_incoming_transfers), allocator); - - // set sub-objects - if (m_outgoing_transfer != boost::none) root.AddMember("outgoingTransfer", m_outgoing_transfer.get()->to_json_val(allocator), allocator); - - // return root - return root; - } - void monero_tx_wallet::merge(const shared_ptr& self, const shared_ptr& other) { merge(static_pointer_cast(self), static_pointer_cast(other)); } @@ -303,7 +330,93 @@ namespace monero { m_extra_hex = gen_utils::reconcile(m_extra_hex, other->m_extra_hex); } - // -------------------------- MONERO TX REQUEST ----------------------------- + // -------------------------- MONERO TX QUERY ----------------------------- + + // boost::property_tree::ptree monero_tx_query::to_property_tree() const { + // boost::property_tree::ptree node = monero_tx_wallet::to_property_tree(); + // if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); + // if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); + // if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); + // if (m_has_payment_id != boost::none) node.put("hasPaymentId", *m_has_payment_id); + // if (!m_payment_ids.empty()) node.add_child("paymentIds", monero_utils::to_property_tree(m_payment_ids)); + // if (m_height != boost::none) node.put("height", *m_height); + // if (m_min_height != boost::none) node.put("minHeight", *m_min_height); + // if (m_max_height != boost::none) node.put("maxHeight", *m_max_height); + // if (m_include_outputs != boost::none) node.put("includeOutputs", *m_include_outputs); + // if (m_transfer_query != boost::none) node.add_child("transferQuery", (*m_transfer_query)->to_property_tree()); + // return node; + // } + + rapidjson::Value monero_tx_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_tx_wallet::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_height != boost::none) monero_utils::addJsonMember("height", m_height.get(), allocator, root, value_num); + if (m_min_height != boost::none) monero_utils::addJsonMember("minHeight", m_min_height.get(), allocator, root, value_num); + if (m_max_height != boost::none) monero_utils::addJsonMember("maxHeight", m_max_height.get(), allocator, root, value_num); + + // set bool values + if (m_is_outgoing != boost::none) monero_utils::addJsonMember("isOutgoing", m_is_outgoing.get(), allocator, root); + if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); + if (m_has_payment_id != boost::none) monero_utils::addJsonMember("hasPaymentId", m_has_payment_id.get(), allocator, root); + if (m_include_outputs != boost::none) monero_utils::addJsonMember("includeOutputs", m_include_outputs.get(), allocator, root); + + // set sub-arrays + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); + if (!m_payment_ids.empty()) root.AddMember("paymentIds", monero_utils::to_json_val(allocator, m_payment_ids), allocator); + + // set sub-objects + if (m_transfer_query != boost::none) root.AddMember("transferQuery", m_transfer_query.get()->to_json_val(allocator), allocator); + + // return root + return root; + } + + void monero_tx_query::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_query) { + monero_tx_wallet::from_property_tree(node, tx_query); + + // initialize query from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("isOutgoing")) tx_query->m_is_outgoing = it->second.get_value(); + else if (key == string("isIncoming")) tx_query->m_is_incoming = it->second.get_value(); + else if (key == string("txIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) tx_query->m_tx_ids.push_back(it2->second.data()); + else if (key == string("hasPaymentId")) tx_query->m_has_payment_id = it->second.get_value(); + else if (key == string("paymentIds")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) tx_query->m_payment_ids.push_back(it2->second.data()); + else if (key == string("height")) tx_query->m_height = it->second.get_value(); + else if (key == string("minHeight")) tx_query->m_min_height = it->second.get_value(); + else if (key == string("maxHeight")) tx_query->m_max_height = it->second.get_value(); + else if (key == string("includeOutputs")) tx_query->m_include_outputs = it->second.get_value(); + else if (key == string("transferQuery")) { + tx_query->m_transfer_query = make_shared(); + monero_transfer_query::from_property_tree(it->second, tx_query->m_transfer_query.get()); + } + else if (key == string("outputQuery")) { + tx_query->m_output_query = make_shared(); + monero_output_query::from_property_tree(it->second, tx_query->m_output_query.get()); + } + } + } + + shared_ptr monero_tx_query::deserialize(const string& tx_query_json) { + + // deserialize tx query string to property rooted at block + std::istringstream iss = tx_query_json.empty() ? std::istringstream() : std::istringstream(tx_query_json); + boost::property_tree::ptree block_node; + boost::property_tree::read_json(iss, block_node); + + // convert query property tree to block + shared_ptr block = node_to_block_query(block_node); + + // get tx query + shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); + + // return deserialized query + return tx_query; + } shared_ptr monero_tx_query::copy(const shared_ptr& src, const shared_ptr& tgt) const { return copy(static_pointer_cast(src), static_pointer_cast(tgt)); @@ -335,49 +448,6 @@ namespace monero { return tgt; }; -// boost::property_tree::ptree monero_tx_query::to_property_tree() const { -// boost::property_tree::ptree node = monero_tx_wallet::to_property_tree(); -// if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); -// if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); -// if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); -// if (m_has_payment_id != boost::none) node.put("hasPaymentId", *m_has_payment_id); -// if (!m_payment_ids.empty()) node.add_child("paymentIds", monero_utils::to_property_tree(m_payment_ids)); -// if (m_height != boost::none) node.put("height", *m_height); -// if (m_min_height != boost::none) node.put("minHeight", *m_min_height); -// if (m_max_height != boost::none) node.put("maxHeight", *m_max_height); -// if (m_include_outputs != boost::none) node.put("includeOutputs", *m_include_outputs); -// if (m_transfer_query != boost::none) node.add_child("transferQuery", (*m_transfer_query)->to_property_tree()); -// return node; -// } - - rapidjson::Value monero_tx_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - - // serialize root from superclass - rapidjson::Value root = monero_tx_wallet::to_json_val(allocator); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_height != boost::none) monero_utils::addJsonMember("height", m_height.get(), allocator, root, value_num); - if (m_min_height != boost::none) monero_utils::addJsonMember("minHeight", m_min_height.get(), allocator, root, value_num); - if (m_max_height != boost::none) monero_utils::addJsonMember("maxHeight", m_max_height.get(), allocator, root, value_num); - - // set bool values - if (m_is_outgoing != boost::none) monero_utils::addJsonMember("isOutgoing", m_is_outgoing.get(), allocator, root); - if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); - if (m_has_payment_id != boost::none) monero_utils::addJsonMember("hasPaymentId", m_has_payment_id.get(), allocator, root); - if (m_include_outputs != boost::none) monero_utils::addJsonMember("includeOutputs", m_include_outputs.get(), allocator, root); - - // set sub-arrays - if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); - if (!m_payment_ids.empty()) root.AddMember("paymentIds", monero_utils::to_json_val(allocator, m_payment_ids), allocator); - - // set sub-objects - if (m_transfer_query != boost::none) root.AddMember("transferQuery", m_transfer_query.get()->to_json_val(allocator), allocator); - - // return root - return root; - } - bool monero_tx_query::meets_criteria(monero_tx_wallet* tx) const { if (tx == nullptr) return false; @@ -446,20 +516,12 @@ namespace monero { // -------------------------- MONERO DESTINATION ---------------------------- - shared_ptr monero_destination::copy(const shared_ptr& src, const shared_ptr& tgt) const { - MTRACE("monero_destination::copy(const shared_ptr& src, const shared_ptr& tgt)"); - if (this != src.get()) throw runtime_error("this != src"); - tgt->m_address = src->m_address; - tgt->m_amount = src->m_amount; - return tgt; - }; - -// boost::property_tree::ptree monero_destination::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_address != boost::none) node.put("address", *m_address); -// if (m_amount != boost::none) node.put("amount", *m_amount); -// return node; -// } + // boost::property_tree::ptree monero_destination::to_property_tree() const { + // boost::property_tree::ptree node; + // if (m_address != boost::none) node.put("address", *m_address); + // if (m_amount != boost::none) node.put("amount", *m_amount); + // return node; + // } rapidjson::Value monero_destination::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -478,6 +540,22 @@ namespace monero { return root; } + void monero_destination::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& destination) { + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("address")) destination->m_address = it->second.data(); + else if (key == string("amount")) destination->m_amount = it->second.get_value(); + } + } + + shared_ptr monero_destination::copy(const shared_ptr& src, const shared_ptr& tgt) const { + MTRACE("monero_destination::copy(const shared_ptr& src, const shared_ptr& tgt)"); + if (this != src.get()) throw runtime_error("this != src"); + tgt->m_address = src->m_address; + tgt->m_amount = src->m_amount; + return tgt; + }; + // ----------------------------- MONERO TX SET ------------------------------ // boost::property_tree::ptree monero_tx_set::to_property_tree() const { @@ -507,24 +585,43 @@ namespace monero { return root; } - // ---------------------------- MONERO TRANSFER ----------------------------- + monero_tx_set monero_tx_set::deserialize(const string& tx_set_json) { - shared_ptr monero_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { - MTRACE("monero_transfer::copy(const shared_ptr& src, const shared_ptr& tgt)"); - tgt->m_tx = src->m_tx; // reference parent tx by default - tgt->m_amount = src->m_amount; - tgt->m_account_index = src->m_account_index; - tgt->m_num_suggested_confirmations = src->m_num_suggested_confirmations; - return tgt; + // deserialize tx set to property + std::istringstream iss = tx_set_json.empty() ? std::istringstream() : std::istringstream(tx_set_json); + boost::property_tree::ptree tx_set_node; + boost::property_tree::read_json(iss, tx_set_node); + + // initialize tx_set from property node + monero_tx_set tx_set; + for (boost::property_tree::ptree::const_iterator it = tx_set_node.begin(); it != tx_set_node.end(); ++it) { + string key = it->first; + if (key == string("unsignedTxHex")) tx_set.m_unsigned_tx_hex = it->second.data(); + else if (key == string("multisigTxHex")) tx_set.m_multisig_tx_hex = it->second.data(); + else if (key == string("txs")) { + boost::property_tree::ptree txs_node = it->second; + for (boost::property_tree::ptree::const_iterator it2 = txs_node.begin(); it2 != txs_node.end(); ++it2) { + shared_ptr tx_wallet = make_shared(); + monero_tx_wallet::from_property_tree(it2->second, tx_wallet); + tx_set.m_txs.push_back(tx_wallet); + } + } + else throw runtime_error("monero_utils::deserialize_tx_set() field '" + key + "' not supported"); + } + + return tx_set; } -// boost::property_tree::ptree monero_transfer::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_amount != boost::none) node.put("amount", *m_amount); -// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); -// if (m_num_suggested_confirmations != boost::none) node.put("numSuggestedConfirmations", *m_num_suggested_confirmations); -// return node; -// } + // ---------------------------- MONERO TRANSFER ----------------------------- + + + // boost::property_tree::ptree monero_transfer::to_property_tree() const { + // boost::property_tree::ptree node; + // if (m_amount != boost::none) node.put("amount", *m_amount); + // if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); + // if (m_num_suggested_confirmations != boost::none) node.put("numSuggestedConfirmations", *m_num_suggested_confirmations); + // return node; + // } rapidjson::Value monero_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -541,6 +638,24 @@ namespace monero { return root; } + void monero_transfer::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer) { + + // initialize transfer from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("accountIndex")) transfer->m_account_index = it->second.get_value(); + } + } + + shared_ptr monero_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + MTRACE("monero_transfer::copy(const shared_ptr& src, const shared_ptr& tgt)"); + tgt->m_tx = src->m_tx; // reference parent tx by default + tgt->m_amount = src->m_amount; + tgt->m_account_index = src->m_account_index; + tgt->m_num_suggested_confirmations = src->m_num_suggested_confirmations; + return tgt; + } + void monero_transfer::merge(const shared_ptr& self, const shared_ptr& other) { if (this != self.get()) throw runtime_error("this != self"); if (self == other) return; @@ -567,23 +682,12 @@ namespace monero { // ----------------------- MONERO INCOMING TRANSFER ------------------------- - shared_ptr monero_incoming_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { - return copy(static_pointer_cast(src), static_pointer_cast(tgt)); - } - - shared_ptr monero_incoming_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { - cout << "monero_incoming_transfer::copy()" << endl; - throw runtime_error("monero_incoming_transfer::copy(inTransfer) not implemented"); - }; - - boost::optional monero_incoming_transfer::is_incoming() const { return true; } - -// boost::property_tree::ptree monero_incoming_transfer::to_property_tree() const { -// boost::property_tree::ptree node = monero_transfer::to_property_tree(); -// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); -// if (m_address != boost::none) node.put("address", *m_address); -// return node; -// } + // boost::property_tree::ptree monero_incoming_transfer::to_property_tree() const { + // boost::property_tree::ptree node = monero_transfer::to_property_tree(); + // if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); + // if (m_address != boost::none) node.put("address", *m_address); + // return node; + // } rapidjson::Value monero_incoming_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -602,6 +706,17 @@ namespace monero { return root; } + shared_ptr monero_incoming_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + return copy(static_pointer_cast(src), static_pointer_cast(tgt)); + } + + shared_ptr monero_incoming_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + cout << "monero_incoming_transfer::copy()" << endl; + throw runtime_error("monero_incoming_transfer::copy(inTransfer) not implemented"); + }; + + boost::optional monero_incoming_transfer::is_incoming() const { return true; } + void monero_incoming_transfer::merge(const shared_ptr& self, const shared_ptr& other) { merge(static_pointer_cast(self), static_pointer_cast(other)); } @@ -615,24 +730,13 @@ namespace monero { // ----------------------- MONERO OUTGOING TRANSFER ------------------------- - shared_ptr monero_outgoing_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { - return copy(static_pointer_cast(src), static_pointer_cast(tgt)); - }; - - shared_ptr monero_outgoing_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { - cout << "monero_outgoing_transfer::copy()" << endl; - throw runtime_error("monero_outgoing_transfer::copy(out_transfer) not implemented"); - }; - - boost::optional monero_outgoing_transfer::is_incoming() const { return false; } - -// boost::property_tree::ptree monero_outgoing_transfer::to_property_tree() const { -// boost::property_tree::ptree node = monero_transfer::to_property_tree(); -// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); -// if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); -// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); -// return node; -// } + // boost::property_tree::ptree monero_outgoing_transfer::to_property_tree() const { + // boost::property_tree::ptree node = monero_transfer::to_property_tree(); + // if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); + // if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); + // if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); + // return node; + // } rapidjson::Value monero_outgoing_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -648,6 +752,17 @@ namespace monero { return root; } + shared_ptr monero_outgoing_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + return copy(static_pointer_cast(src), static_pointer_cast(tgt)); + }; + + shared_ptr monero_outgoing_transfer::copy(const shared_ptr& src, const shared_ptr& tgt) const { + cout << "monero_outgoing_transfer::copy()" << endl; + throw runtime_error("monero_outgoing_transfer::copy(out_transfer) not implemented"); + }; + + boost::optional monero_outgoing_transfer::is_incoming() const { return false; } + void monero_outgoing_transfer::merge(const shared_ptr& self, const shared_ptr& other) { merge(static_pointer_cast(self), static_pointer_cast(other)); } @@ -662,6 +777,80 @@ namespace monero { // ----------------------- MONERO TRANSFER REQUEST -------------------------- + rapidjson::Value monero_transfer_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_transfer::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); + + // set bool values + if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); + if (m_has_destinations != boost::none) monero_utils::addJsonMember("hasDestinations", m_has_destinations.get(), allocator, root); + + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); + + // set sub-arrays + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_json_val(allocator, m_addresses), allocator); + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); + + // return root + return root; + } + + void monero_transfer_query::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer_query) { + monero_transfer::from_property_tree(node, transfer_query); + + // initialize query from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("isIncoming")) transfer_query->m_is_incoming = it->second.get_value(); + else if (key == string("address")) transfer_query->m_address = it->second.data(); + else if (key == string("addresses")) throw runtime_error("addresses not implemented"); + else if (key == string("subaddressIndex")) transfer_query->m_subaddress_index = it->second.get_value(); + else if (key == string("subaddressIndices")) { + vector m_subaddress_indices; + for (const auto& child : it->second) m_subaddress_indices.push_back(child.second.get_value()); + transfer_query->m_subaddress_indices = m_subaddress_indices; + } + else if (key == string("destinations")) throw runtime_error("destinations not implemented"); + else if (key == string("hasDestinations")) transfer_query->m_has_destinations = it->second.get_value(); + else if (key == string("txQuery")) throw runtime_error("txQuery not implemented"); + } + } + + shared_ptr monero_transfer_query::deserialize(const string& transfer_query_json) { + + // deserialize transfer query string to property rooted at block + std::istringstream iss = transfer_query_json.empty() ? std::istringstream() : std::istringstream(transfer_query_json); + boost::property_tree::ptree blockNode; + boost::property_tree::read_json(iss, blockNode); + + // convert query property tree to block + shared_ptr block = node_to_block_query(blockNode); + + // return empty query if no txs + if (block->m_txs.empty()) return make_shared(); + + // get tx query + shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); + + // get / create transfer query + shared_ptr transfer_query = tx_query->m_transfer_query == boost::none ? make_shared() : *tx_query->m_transfer_query; + + // transfer query references tx query but not the other way around to avoid circular loop // TODO: could add check within meetsCriterias() + transfer_query->m_tx_query = tx_query; + tx_query->m_transfer_query = boost::none; + + // return deserialized query + return transfer_query; + } + shared_ptr monero_transfer_query::copy(const shared_ptr& src, const shared_ptr& tgt) const { return copy(static_pointer_cast(src), static_pointer_cast(tgt)); }; @@ -689,46 +878,6 @@ namespace monero { return tgt; }; - boost::optional monero_transfer_query::is_incoming() const { return m_is_incoming; } - -// boost::property_tree::ptree monero_transfer_query::to_property_tree() const { -// boost::property_tree::ptree node = monero_transfer::to_property_tree(); -// if (is_incoming() != boost::none) node.put("isIncoming", *is_incoming()); -// if (m_address != boost::none) node.put("address", *m_address); -// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); -// if (m_has_destinations != boost::none) node.put("hasDestinations", *m_has_destinations); -// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); -// if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); -// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); -// return node; -// } - - rapidjson::Value monero_transfer_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - - // serialize root from superclass - rapidjson::Value root = monero_transfer::to_json_val(allocator); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); - - // set bool values - if (m_is_incoming != boost::none) monero_utils::addJsonMember("isIncoming", m_is_incoming.get(), allocator, root); - if (m_has_destinations != boost::none) monero_utils::addJsonMember("hasDestinations", m_has_destinations.get(), allocator, root); - - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); - - // set sub-arrays - if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); - if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_json_val(allocator, m_addresses), allocator); - if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); - - // return root - return root; - } - bool monero_transfer_query::meets_criteria(monero_transfer* transfer) const { if (transfer == nullptr) throw runtime_error("transfer is null"); if (m_tx_query != boost::none && (*m_tx_query)->m_transfer_query != boost::none) throw runtime_error("Transfer query's tx query cannot have a circular transfer query"); // TODO: could auto detect and handle this. port to java/js @@ -801,8 +950,62 @@ namespace monero { return true; } + boost::optional monero_transfer_query::is_incoming() const { return m_is_incoming; } + +// boost::property_tree::ptree monero_transfer_query::to_property_tree() const { +// boost::property_tree::ptree node = monero_transfer::to_property_tree(); +// if (is_incoming() != boost::none) node.put("isIncoming", *is_incoming()); +// if (m_address != boost::none) node.put("address", *m_address); +// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); +// if (m_has_destinations != boost::none) node.put("hasDestinations", *m_has_destinations); +// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); +// if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); +// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); +// return node; +// } + // ------------------------- MONERO OUTPUT WALLET --------------------------- + // boost::property_tree::ptree monero_output_wallet::to_property_tree() const { + // boost::property_tree::ptree node = monero_output::to_property_tree(); + // if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); + // if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); + // if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); + // if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); + // if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); + // return node; + // } + + rapidjson::Value monero_output_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_output::to_json_val(allocator); + + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_account_index != boost::none) monero_utils::addJsonMember("accountIndex", m_account_index.get(), allocator, root, value_num); + if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); + + // set bool values + if (m_is_spent != boost::none) monero_utils::addJsonMember("isSpent", m_is_spent.get(), allocator, root); + if (m_is_frozen != boost::none) monero_utils::addJsonMember("isFrozen", m_is_frozen.get(), allocator, root); + + // return root + return root; + } + + void monero_output_wallet::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_wallet) { + monero_output::from_property_tree(node, output_wallet); + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("accountIndex")) output_wallet->m_account_index = it->second.get_value(); + else if (key == string("subaddressIndex")) output_wallet->m_subaddress_index = it->second.get_value(); + else if (key == string("isSpent")) output_wallet->m_is_spent = it->second.get_value(); + else if (key == string("isFrozen")) output_wallet->m_is_frozen = it->second.get_value(); + else cout << "WARNING: unrecognized field deserializing node to output wallet: " << key << endl; + } + } + shared_ptr monero_output_wallet::copy(const shared_ptr& src, const shared_ptr& tgt) const { MTRACE("monero_output_wallet::copy(output)"); return monero_output_wallet::copy(static_pointer_cast(src), static_pointer_cast(tgt)); @@ -823,34 +1026,6 @@ namespace monero { return tgt; }; -// boost::property_tree::ptree monero_output_wallet::to_property_tree() const { -// boost::property_tree::ptree node = monero_output::to_property_tree(); -// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); -// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); -// if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); -// if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); -// if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); -// return node; -// } - - rapidjson::Value monero_output_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - - // serialize root from superclass - rapidjson::Value root = monero_output::to_json_val(allocator); - - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_account_index != boost::none) monero_utils::addJsonMember("accountIndex", m_account_index.get(), allocator, root, value_num); - if (m_subaddress_index != boost::none) monero_utils::addJsonMember("subaddressIndex", m_subaddress_index.get(), allocator, root, value_num); - - // set bool values - if (m_is_spent != boost::none) monero_utils::addJsonMember("isSpent", m_is_spent.get(), allocator, root); - if (m_is_frozen != boost::none) monero_utils::addJsonMember("isFrozen", m_is_frozen.get(), allocator, root); - - // return root - return root; - } - void monero_output_wallet::merge(const shared_ptr& self, const shared_ptr& other) { merge(static_pointer_cast(self), static_pointer_cast(other)); } @@ -872,6 +1047,57 @@ namespace monero { // ------------------------ MONERO OUTPUT REQUEST --------------------------- + rapidjson::Value monero_output_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + + // serialize root from superclass + rapidjson::Value root = monero_output_wallet::to_json_val(allocator); + + // set sub-arrays + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + + // return root + return root; + } + + void monero_output_query::from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_query) { + monero_output_wallet::from_property_tree(node, output_query); + + // initialize query from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("subaddressIndices")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) output_query->m_subaddress_indices.push_back(it2->second.get_value()); + else if (key == string("txQuery")) {} // ignored + else cout << "WARNING: unrecognized field deserializing node to output query: " << key << endl; + } + } + + shared_ptr monero_output_query::deserialize(const string& output_query_json) { + + // deserialize output query string to property rooted at block + std::istringstream iss = output_query_json.empty() ? std::istringstream() : std::istringstream(output_query_json); + boost::property_tree::ptree blockNode; + boost::property_tree::read_json(iss, blockNode); + + // convert query property tree to block + shared_ptr block = node_to_block_query(blockNode); + + // empty query if no txs + if (block->m_txs.empty()) return make_shared(); + + // get tx query + shared_ptr tx_query = static_pointer_cast(block->m_txs[0]); + + // get / create output query + shared_ptr output_query = tx_query->m_output_query == boost::none ? make_shared() : *tx_query->m_output_query; + + // output query references tx query but not the other way around to avoid circular loop // TODO: could add check within meetsCriterias(), TODO: move this temp hack to the caller + output_query->m_tx_query = tx_query; + tx_query->m_output_query = boost::none; + + // return deserialized query + return output_query; + } + // initialize static empty output for is_default() check const unique_ptr monero_output_query::M_EMPTY_OUTPUT = unique_ptr(new monero_output_wallet()); bool monero_output_query::is_default() const { @@ -898,24 +1124,6 @@ namespace monero { return tgt; }; -// boost::property_tree::ptree monero_output_query::to_property_tree() const { -// boost::property_tree::ptree node = monero_output_wallet::to_property_tree(); -// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); -// return node; -// } - - rapidjson::Value monero_output_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { - - // serialize root from superclass - rapidjson::Value root = monero_output_wallet::to_json_val(allocator); - - // set sub-arrays - if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); - - // return root - return root; - } - bool monero_output_query::meets_criteria(monero_output_wallet* output) const { // filter on output @@ -941,6 +1149,12 @@ namespace monero { return true; } +// boost::property_tree::ptree monero_output_query::to_property_tree() const { +// boost::property_tree::ptree node = monero_output_wallet::to_property_tree(); +// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); +// return node; +// } + // ------------------------- MONERO SEND REQUEST ---------------------------- monero_send_request::monero_send_request(const monero_send_request& request) { @@ -965,29 +1179,25 @@ namespace monero { m_key_image = request.m_key_image; } - monero_send_request monero_send_request::copy() const { - return monero_send_request(*this); - } - -// boost::property_tree::ptree monero_send_request::to_property_tree() const { -// boost::property_tree::ptree node; -// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); -// if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); -// if (m_priority != boost::none) node.put("priority", *m_priority); -// if (m_mixin != boost::none) node.put("mixin", *m_mixin); -// if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); -// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); -// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); -// if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); -// if (m_can_split != boost::none) node.put("canSplit", *m_can_split); -// if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); -// if (m_note != boost::none) node.put("note", *m_note); -// if (m_recipient_name != boost::none) node.put("recipientName", *m_recipient_name); -// if (m_below_amount != boost::none) node.put("belowAmount", *m_below_amount); -// if (m_sweep_each_subaddress != boost::none) node.put("sweepEachSubaddress", *m_sweep_each_subaddress); -// if (m_key_image != boost::none) node.put("keyImage", *m_key_image); -// return node; -// } + // boost::property_tree::ptree monero_send_request::to_property_tree() const { + // boost::property_tree::ptree node; + // if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); + // if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); + // if (m_priority != boost::none) node.put("priority", *m_priority); + // if (m_mixin != boost::none) node.put("mixin", *m_mixin); + // if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); + // if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); + // if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); + // if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); + // if (m_can_split != boost::none) node.put("canSplit", *m_can_split); + // if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); + // if (m_note != boost::none) node.put("note", *m_note); + // if (m_recipient_name != boost::none) node.put("recipientName", *m_recipient_name); + // if (m_below_amount != boost::none) node.put("belowAmount", *m_below_amount); + // if (m_sweep_each_subaddress != boost::none) node.put("sweepEachSubaddress", *m_sweep_each_subaddress); + // if (m_key_image != boost::none) node.put("keyImage", *m_key_image); + // return node; + // } rapidjson::Value monero_send_request::to_json_val(rapidjson::Document::AllocatorType& allocator) const { @@ -1022,6 +1232,48 @@ namespace monero { return root; } + shared_ptr monero_send_request::deserialize(const string& send_request_json) { + + // deserialize send request json to property node + std::istringstream iss = send_request_json.empty() ? std::istringstream() : std::istringstream(send_request_json); + boost::property_tree::ptree node; + boost::property_tree::read_json(iss, node); + + // convert request property tree to monero_send_request + shared_ptr send_request = make_shared(); + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("destinations")) { + boost::property_tree::ptree destinationsNode = it->second; + for (boost::property_tree::ptree::const_iterator it2 = destinationsNode.begin(); it2 != destinationsNode.end(); ++it2) { + shared_ptr destination = make_shared(); + monero_destination::from_property_tree(it2->second, destination); + send_request->m_destinations.push_back(destination); + } + } + else if (key == string("paymentId")) send_request->m_payment_id = it->second.data(); + else if (key == string("priority")) throw runtime_error("deserialize_send_request() priority not implemented"); + else if (key == string("ringSize")) send_request->m_ring_size = it->second.get_value(); + else if (key == string("fee")) send_request->m_fee = it->second.get_value(); + else if (key == string("accountIndex")) send_request->m_account_index = it->second.get_value(); + else if (key == string("subaddressIndices")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) send_request->m_subaddress_indices.push_back(it2->second.get_value()); + else if (key == string("unlockTime")) send_request->m_unlock_time = it->second.get_value(); + else if (key == string("canSplit")) send_request->m_can_split = it->second.get_value(); + else if (key == string("doNotRelay")) send_request->m_do_not_relay = it->second.get_value(); + else if (key == string("note")) send_request->m_note = it->second.data(); + else if (key == string("recipientName")) send_request->m_recipient_name = it->second.data(); + else if (key == string("belowAmount")) send_request->m_below_amount = it->second.get_value(); + else if (key == string("sweepEachSubaddress")) send_request->m_sweep_each_subaddress = it->second.get_value(); + else if (key == string("keyImage")) send_request->m_key_image = it->second.data(); + } + + return send_request; + } + + monero_send_request monero_send_request::copy() const { + return monero_send_request(*this); + } + // ---------------------- MONERO INTEGRATED ADDRESS ------------------------- // boost::property_tree::ptree monero_integrated_address::to_property_tree() const { diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 82a3a40..f0aaeeb 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -105,16 +105,6 @@ namespace monero { //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; - - string serialize_doc() const; - rapidjson::Document to_json_doc() const { - rapidjson::Document doc; - doc.SetObject(); - rapidjson::Value val = to_json_val(doc); - val.Swap(doc); - return doc; - } - rapidjson::Value to_json_val(rapidjson::Document& doc) const; }; /** @@ -126,9 +116,10 @@ namespace monero { monero_destination() {} monero_destination(const string& address, uint64_t amount) : m_address(address), m_amount(amount) {} - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& destination); + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; }; // forward declarations @@ -145,14 +136,15 @@ namespace monero { boost::optional m_account_index; boost::optional m_num_suggested_confirmations; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer); virtual boost::optional is_incoming() const = 0; // derived class must implement shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_outgoing() const { if (is_incoming() == boost::none) return boost::none; return !(*is_incoming()); } - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -163,11 +155,11 @@ namespace monero { boost::optional m_subaddress_index; boost::optional m_address; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -180,11 +172,11 @@ namespace monero { vector m_addresses; vector> m_destinations; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -204,11 +196,13 @@ namespace monero { boost::optional m_has_destinations; boost::optional> m_tx_query; + //boost::property_tree::ptree to_property_tree() const; + rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer_query); + static shared_ptr deserialize(const string& transfer_query_json); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; bool meets_criteria(monero_transfer* transfer) const; }; @@ -221,10 +215,11 @@ namespace monero { boost::optional m_is_spent; boost::optional m_is_frozen; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_wallet); + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -239,13 +234,14 @@ namespace monero { vector m_subaddress_indices; boost::optional> m_tx_query; - // TODO: necessary to override all super classes? - bool is_default() const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_query); + static shared_ptr deserialize(const string& output_query_json); + bool is_default() const; + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; // TODO: necessary to override all super classes? + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; bool meets_criteria(monero_output_wallet* output) const; private: @@ -270,10 +266,11 @@ namespace monero { boost::optional m_num_dummy_outputs; boost::optional m_extra_hex; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_wallet); + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -296,12 +293,13 @@ namespace monero { boost::optional> m_transfer_query; boost::optional> m_output_query; - // TODO: necessary to override all super classes? - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; - shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_query); + static shared_ptr deserialize(const string& tx_query_json); + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; // TODO: necessary to override all super classes? + shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; bool meets_criteria(monero_tx_wallet* tx) const; }; @@ -321,6 +319,7 @@ namespace monero { //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static monero_tx_set deserialize(const string& tx_set_json); }; /** @@ -367,9 +366,10 @@ namespace monero { monero_send_request() {} monero_send_request(const monero_send_request& request); - monero_send_request copy() const; //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + static shared_ptr deserialize(const string& send_request_json); + monero_send_request copy() const; }; /** From 2db2b209f5ba500b4b89435e6858ec4b08ad1414 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 17:24:11 -0500 Subject: [PATCH 29/34] remove old property tree serialization code; rename to_json_val -> to_rapidjson_val --- src/daemon/monero_daemon_model.cpp | 328 ++++++++++------------------- src/daemon/monero_daemon_model.h | 28 +-- src/utils/monero_utils.cpp | 55 +---- src/utils/monero_utils.h | 42 +--- src/wallet/monero_wallet_model.cpp | 311 +++++---------------------- src/wallet/monero_wallet_model.h | 66 ++---- 6 files changed, 209 insertions(+), 621 deletions(-) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index 385124e..b3925c3 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -3,7 +3,7 @@ // rapidjson::Value root(rapidjson::kObjectType); // // serialize root from superclass -// rapidjson::Value root = superclass::to_json_val(allocator); +// rapidjson::Value root = superclass::to_rapidjson_val(allocator); // // // set num values // rapidjson::Value value_num(rapidjson::kNumberType); @@ -32,19 +32,19 @@ // if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); // // // set sub-arrays -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_json_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); +// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); // // // set sub-objects -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_json_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); +// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); // // // return root // return root; @@ -135,21 +135,14 @@ namespace monero { string serializable_struct::serialize() const { rapidjson::Document doc; doc.SetObject(); - rapidjson::Value val = to_json_val(doc.GetAllocator()); + rapidjson::Value val = to_rapidjson_val(doc.GetAllocator()); val.Swap(doc); return monero_utils::serialize(doc); } // ----------------------------- MONERO VERSION ----------------------------- -// boost::property_tree::ptree monero_version::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_version_number != boost::none) node.put("versionNumber", *m_version_number); -// if (m_is_release != boost::none) node.put("isRelease", *m_is_release); -// return node; -// } - - rapidjson::Value monero_version::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_version::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -167,30 +160,7 @@ namespace monero { // ------------------------- MONERO BLOCK HEADER ---------------------------- -// boost::property_tree::ptree monero_block_header::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_id != boost::none) node.put("id", *m_id); -// if (m_height != boost::none) node.put("height", *m_height); -// if (m_timestamp != boost::none) node.put("timestamp", *m_timestamp); -// if (m_size != boost::none) node.put("size", *m_size); -// if (m_weight != boost::none) node.put("weight", *m_weight); -// if (m_long_term_weight != boost::none) node.put("longTermWeight", *m_long_term_weight); -// if (m_depth != boost::none) node.put("depth", *m_depth); -// if (m_difficulty != boost::none) node.put("difficulty", *m_difficulty); -// if (m_cumulative_difficulty != boost::none) node.put("cumulativeDifficulty", *m_cumulative_difficulty); -// if (m_major_version != boost::none) node.put("majorVersion", *m_major_version); -// if (m_minor_version != boost::none) node.put("minorVersion", *m_minor_version); -// if (m_nonce != boost::none) node.put("m_nonce", *m_nonce); -// if (m_miner_tx_id != boost::none) node.put("minerTxId", *m_miner_tx_id); -// if (m_num_txs != boost::none) node.put("numTxs", *m_num_txs); -// if (m_orphan_status != boost::none) node.put("orphanStatus", *m_orphan_status); -// if (m_prev_id != boost::none) node.put("prevId", *m_prev_id); -// if (m_reward != boost::none) node.put("m_reward", *m_reward); -// if (m_pow_hash != boost::none) node.put("powHash", *m_pow_hash); -// return node; -// } - - rapidjson::Value monero_block_header::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_block_header::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -250,30 +220,21 @@ namespace monero { // ----------------------------- MONERO BLOCK ------------------------------- -// boost::property_tree::ptree monero_block::to_property_tree() const { -// boost::property_tree::ptree node = monero_block_header::to_property_tree(); -// if (m_hex != boost::none) node.put("hex", *m_hex); -// if (m_miner_tx != boost::none) node.add_child("minerTx", (*m_miner_tx)->to_property_tree()); -// if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); -// if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); -// return node; -// } - - rapidjson::Value monero_block::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_block::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_block_header::to_json_val(allocator); + rapidjson::Value root = monero_block_header::to_rapidjson_val(allocator); // set string values rapidjson::Value value_str(rapidjson::kStringType); if (m_hex != boost::none) monero_utils::addJsonMember("hex", m_hex.get(), allocator, root, value_str); // set sub-arrays - if (!m_txs.empty()) root.AddMember("txs", monero_utils::to_json_val(allocator, m_txs), allocator); - if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); + if (!m_txs.empty()) root.AddMember("txs", monero_utils::to_rapidjson_val(allocator, m_txs), allocator); + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_rapidjson_val(allocator, m_tx_ids), allocator); // set sub-objects - if (m_miner_tx != boost::none) root.AddMember("minerTx", m_miner_tx.get()->to_json_val(allocator), allocator); + if (m_miner_tx != boost::none) root.AddMember("minerTx", m_miner_tx.get()->to_rapidjson_val(allocator), allocator); // return root return root; @@ -312,147 +273,105 @@ namespace monero { // ------------------------------- MONERO TX -------------------------------- - // boost::property_tree::ptree monero_tx::to_property_tree() const { - // boost::property_tree::ptree node; - // if (m_id != boost::none) node.put("id", *m_id); - // if (m_version != boost::none) node.put("version", *m_version); - // if (m_is_miner_tx != boost::none) node.put("isMinerTx", *m_is_miner_tx); - // if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); - // if (m_fee != boost::none) node.put("fee", *m_fee); - // if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); - // if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); - // if (m_is_relayed != boost::none) node.put("isRelayed", *m_is_relayed); - // if (m_is_confirmed != boost::none) node.put("isConfirmed", *m_is_confirmed); - // if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); - // if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); - // if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); - // if (m_last_relayed_timestamp != boost::none) node.put("lastRelayedTimestamp", *m_last_relayed_timestamp); - // if (m_received_timestamp != boost::none) node.put("receivedTimestamp", *m_received_timestamp); - // if (m_is_double_spend_seen != boost::none) node.put("isDoubleSpendSeen", *m_is_double_spend_seen); - // if (m_key != boost::none) node.put("key", *m_key); - // if (m_full_hex != boost::none) node.put("fullHex", *m_full_hex); - // if (m_pruned_hex != boost::none) node.put("prunedHex", *m_pruned_hex); - // if (m_prunable_hex != boost::none) node.put("prunableHex", *m_prunable_hex); - // if (m_prunable_hash != boost::none) node.put("prunableHash", *m_prunable_hash); - // if (m_size != boost::none) node.put("size", *m_size); - // if (m_weight != boost::none) node.put("weight", *m_weight); - // if (!m_vins.empty()) node.add_child("vins", monero_utils::to_property_tree(m_vins)); - // if (!m_vouts.empty()) node.add_child("vouts", monero_utils::to_property_tree(m_vouts)); - // if (!m_output_indices.empty()) throw runtime_error("m_output_indices not implemented"); - // if (m_metadata != boost::none) node.put("metadata", *m_metadata); - // if (m_common_tx_sets != boost::none) throw runtime_error("m_common_tx_sets not implemented"); - // if (!m_extra.empty()) node.add_child("extra", monero_utils::to_property_tree(m_extra)); - // if (m_rct_signatures != boost::none) throw runtime_error("m_rct_signatures not implemented"); - // if (m_rct_sig_prunable != boost::none) throw runtime_error("m_rct_sig_prunable not implemented"); - // if (m_is_kept_by_block != boost::none) node.put("isKeptByBlock", *m_is_kept_by_block); - // if (m_is_failed != boost::none) node.put("isFailed", *m_is_failed); - // if (m_last_failed_height != boost::none) node.put("lastFailedHeight", *m_last_failed_height); - // if (m_last_failed_id != boost::none) node.put("lastFailedId", *m_last_failed_id); - // if (m_max_used_block_height != boost::none) node.put("maxUsedBlockHeight", *m_max_used_block_height); - // if (m_max_used_block_id != boost::none) node.put("maxUsedBlockId", *m_max_used_block_id); - // if (!m_signatures.empty()) throw runtime_error("m_signatures not implemented"); - // return node; - // } + rapidjson::Value monero_tx::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { - rapidjson::Value monero_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + // create root + rapidjson::Value root(rapidjson::kObjectType); - // create root - rapidjson::Value root(rapidjson::kObjectType); + // set num values + rapidjson::Value value_num(rapidjson::kNumberType); + if (m_version != boost::none) monero_utils::addJsonMember("version", m_version.get(), allocator, root, value_num); + if (m_fee != boost::none) monero_utils::addJsonMember("fee", m_fee.get(), allocator, root, value_num); + if (m_ring_size != boost::none) monero_utils::addJsonMember("ringSize", m_ring_size.get(), allocator, root, value_num); + if (m_num_confirmations != boost::none) monero_utils::addJsonMember("numConfirmations", m_num_confirmations.get(), allocator, root, value_num); + if (m_unlock_time != boost::none) monero_utils::addJsonMember("unlockTime", m_unlock_time.get(), allocator, root, value_num); + if (m_last_relayed_timestamp != boost::none) monero_utils::addJsonMember("lastRelayedTimestamp", m_last_relayed_timestamp.get(), allocator, root, value_num); + if (m_received_timestamp != boost::none) monero_utils::addJsonMember("receivedTimestamp", m_received_timestamp.get(), allocator, root, value_num); + if (m_size != boost::none) monero_utils::addJsonMember("size", m_size.get(), allocator, root, value_num); + if (m_weight != boost::none) monero_utils::addJsonMember("weight", m_weight.get(), allocator, root, value_num); + if (m_last_failed_height != boost::none) monero_utils::addJsonMember("lastFailedHeight", m_last_failed_height.get(), allocator, root, value_num); + if (m_max_used_block_height != boost::none) monero_utils::addJsonMember("maxUsedBlockHeight", m_max_used_block_height.get(), allocator, root, value_num); - // set num values - rapidjson::Value value_num(rapidjson::kNumberType); - if (m_version != boost::none) monero_utils::addJsonMember("version", m_version.get(), allocator, root, value_num); - if (m_fee != boost::none) monero_utils::addJsonMember("fee", m_fee.get(), allocator, root, value_num); - if (m_ring_size != boost::none) monero_utils::addJsonMember("ringSize", m_ring_size.get(), allocator, root, value_num); - if (m_num_confirmations != boost::none) monero_utils::addJsonMember("numConfirmations", m_num_confirmations.get(), allocator, root, value_num); - if (m_unlock_time != boost::none) monero_utils::addJsonMember("unlockTime", m_unlock_time.get(), allocator, root, value_num); - if (m_last_relayed_timestamp != boost::none) monero_utils::addJsonMember("lastRelayedTimestamp", m_last_relayed_timestamp.get(), allocator, root, value_num); - if (m_received_timestamp != boost::none) monero_utils::addJsonMember("receivedTimestamp", m_received_timestamp.get(), allocator, root, value_num); - if (m_size != boost::none) monero_utils::addJsonMember("size", m_size.get(), allocator, root, value_num); - if (m_weight != boost::none) monero_utils::addJsonMember("weight", m_weight.get(), allocator, root, value_num); - if (m_last_failed_height != boost::none) monero_utils::addJsonMember("lastFailedHeight", m_last_failed_height.get(), allocator, root, value_num); - if (m_max_used_block_height != boost::none) monero_utils::addJsonMember("maxUsedBlockHeight", m_max_used_block_height.get(), allocator, root, value_num); + // set string values + rapidjson::Value value_str(rapidjson::kStringType); + if (m_id != boost::none) monero_utils::addJsonMember("id", m_id.get(), allocator, root, value_str); + if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); + if (m_key != boost::none) monero_utils::addJsonMember("key", m_key.get(), allocator, root, value_str); + if (m_full_hex != boost::none) monero_utils::addJsonMember("fullHex", m_full_hex.get(), allocator, root, value_str); + if (m_pruned_hex != boost::none) monero_utils::addJsonMember("prunedHex", m_pruned_hex.get(), allocator, root, value_str); + if (m_prunable_hex != boost::none) monero_utils::addJsonMember("prunableHex", m_prunable_hex.get(), allocator, root, value_str); + if (m_prunable_hash != boost::none) monero_utils::addJsonMember("prunableHash", m_prunable_hash.get(), allocator, root, value_str); + if (m_metadata != boost::none) monero_utils::addJsonMember("metadata", m_metadata.get(), allocator, root, value_str); + if (m_common_tx_sets != boost::none) monero_utils::addJsonMember("commonTxSets", m_common_tx_sets.get(), allocator, root, value_str); + if (m_rct_signatures != boost::none) monero_utils::addJsonMember("rctSignatures", m_rct_signatures.get(), allocator, root, value_str); + if (m_rct_sig_prunable != boost::none) monero_utils::addJsonMember("rctSigPrunable", m_rct_sig_prunable.get(), allocator, root, value_str); + if (m_last_failed_id != boost::none) monero_utils::addJsonMember("lastFailedId", m_last_failed_id.get(), allocator, root, value_str); + if (m_max_used_block_id != boost::none) monero_utils::addJsonMember("maxUsedBlockId", m_max_used_block_id.get(), allocator, root, value_str); - // set string values - rapidjson::Value value_str(rapidjson::kStringType); - if (m_id != boost::none) monero_utils::addJsonMember("id", m_id.get(), allocator, root, value_str); - if (m_payment_id != boost::none) monero_utils::addJsonMember("paymentId", m_payment_id.get(), allocator, root, value_str); - if (m_key != boost::none) monero_utils::addJsonMember("key", m_key.get(), allocator, root, value_str); - if (m_full_hex != boost::none) monero_utils::addJsonMember("fullHex", m_full_hex.get(), allocator, root, value_str); - if (m_pruned_hex != boost::none) monero_utils::addJsonMember("prunedHex", m_pruned_hex.get(), allocator, root, value_str); - if (m_prunable_hex != boost::none) monero_utils::addJsonMember("prunableHex", m_prunable_hex.get(), allocator, root, value_str); - if (m_prunable_hash != boost::none) monero_utils::addJsonMember("prunableHash", m_prunable_hash.get(), allocator, root, value_str); - if (m_metadata != boost::none) monero_utils::addJsonMember("metadata", m_metadata.get(), allocator, root, value_str); - if (m_common_tx_sets != boost::none) monero_utils::addJsonMember("commonTxSets", m_common_tx_sets.get(), allocator, root, value_str); - if (m_rct_signatures != boost::none) monero_utils::addJsonMember("rctSignatures", m_rct_signatures.get(), allocator, root, value_str); - if (m_rct_sig_prunable != boost::none) monero_utils::addJsonMember("rctSigPrunable", m_rct_sig_prunable.get(), allocator, root, value_str); - if (m_last_failed_id != boost::none) monero_utils::addJsonMember("lastFailedId", m_last_failed_id.get(), allocator, root, value_str); - if (m_max_used_block_id != boost::none) monero_utils::addJsonMember("maxUsedBlockId", m_max_used_block_id.get(), allocator, root, value_str); + // set bool values + if (m_is_miner_tx != boost::none) monero_utils::addJsonMember("isMinerTx", m_is_miner_tx.get(), allocator, root); + if (m_do_not_relay != boost::none) monero_utils::addJsonMember("doNotRelay", m_do_not_relay.get(), allocator, root); + if (m_is_relayed != boost::none) monero_utils::addJsonMember("isRelayed", m_is_relayed.get(), allocator, root); + if (m_is_confirmed != boost::none) monero_utils::addJsonMember("isConfirmed", m_is_confirmed.get(), allocator, root); + if (m_in_tx_pool != boost::none) monero_utils::addJsonMember("inTxPool", m_in_tx_pool.get(), allocator, root); + if (m_is_double_spend_seen != boost::none) monero_utils::addJsonMember("isDoubleSpendSeen", m_is_double_spend_seen.get(), allocator, root); + if (m_is_kept_by_block != boost::none) monero_utils::addJsonMember("isKeptByBlock", m_is_kept_by_block.get(), allocator, root); + if (m_is_failed != boost::none) monero_utils::addJsonMember("isFailed", m_is_failed.get(), allocator, root); - // set bool values - if (m_is_miner_tx != boost::none) monero_utils::addJsonMember("isMinerTx", m_is_miner_tx.get(), allocator, root); - if (m_do_not_relay != boost::none) monero_utils::addJsonMember("doNotRelay", m_do_not_relay.get(), allocator, root); - if (m_is_relayed != boost::none) monero_utils::addJsonMember("isRelayed", m_is_relayed.get(), allocator, root); - if (m_is_confirmed != boost::none) monero_utils::addJsonMember("isConfirmed", m_is_confirmed.get(), allocator, root); - if (m_in_tx_pool != boost::none) monero_utils::addJsonMember("inTxPool", m_in_tx_pool.get(), allocator, root); - if (m_is_double_spend_seen != boost::none) monero_utils::addJsonMember("isDoubleSpendSeen", m_is_double_spend_seen.get(), allocator, root); - if (m_is_kept_by_block != boost::none) monero_utils::addJsonMember("isKeptByBlock", m_is_kept_by_block.get(), allocator, root); - if (m_is_failed != boost::none) monero_utils::addJsonMember("isFailed", m_is_failed.get(), allocator, root); + // set sub-arrays + if (!m_vins.empty()) root.AddMember("vins", monero_utils::to_rapidjson_val(allocator, m_vins), allocator); + if (!m_vouts.empty()) root.AddMember("vouts", monero_utils::to_rapidjson_val(allocator, m_vouts), allocator); + if (!m_output_indices.empty()) root.AddMember("outputIndices", monero_utils::to_rapidjson_val(allocator, m_output_indices), allocator); + if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_rapidjson_val(allocator, m_extra), allocator); // TODO + if (!m_signatures.empty()) root.AddMember("signatures", monero_utils::to_rapidjson_val(allocator, m_signatures), allocator); - // set sub-arrays - if (!m_vins.empty()) root.AddMember("vins", monero_utils::to_json_val(allocator, m_vins), allocator); - if (!m_vouts.empty()) root.AddMember("vouts", monero_utils::to_json_val(allocator, m_vouts), allocator); - if (!m_output_indices.empty()) root.AddMember("outputIndices", monero_utils::to_json_val(allocator, m_output_indices), allocator); - if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_json_val(allocator, m_extra), allocator); // TODO - if (!m_signatures.empty()) root.AddMember("signatures", monero_utils::to_json_val(allocator, m_signatures), allocator); + // return root + return root; + } - // return root - return root; + void monero_tx::from_property_tree(const boost::property_tree::ptree& node, shared_ptr tx) { + + // initialize tx from node + for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { + string key = it->first; + if (key == string("id")) tx->m_id = it->second.data(); + else if (key == string("version")) throw runtime_error("version deserializationn not implemented"); + else if (key == string("isMinerTx")) tx->m_is_miner_tx = it->second.get_value(); + else if (key == string("paymentId")) tx->m_payment_id = it->second.data(); // TODO: this threw runtime_error, how is "Can get transactions by payment ids" test passing in Java? + else if (key == string("fee")) tx->m_fee = it->second.get_value(); + else if (key == string("mixin")) throw runtime_error("mixin deserialization not implemented"); + else if (key == string("doNotRelay")) tx->m_do_not_relay = it->second.get_value(); + else if (key == string("isRelayed")) tx->m_is_relayed = it->second.get_value(); + else if (key == string("isConfirmed")) tx->m_is_confirmed = it->second.get_value(); + else if (key == string("inTxPool")) tx->m_in_tx_pool = it->second.get_value(); + else if (key == string("numConfirmations")) tx->m_num_confirmations = it->second.get_value(); + else if (key == string("unlockTime")) tx->m_unlock_time = it->second.get_value(); + else if (key == string("lastRelayedTimestamp")) tx->m_last_relayed_timestamp = it->second.get_value(); + else if (key == string("receivedTimestamp")) tx->m_received_timestamp = it->second.get_value(); + else if (key == string("isDoubleSpendSeen")) tx->m_is_double_spend_seen = it->second.get_value(); + else if (key == string("key")) tx->m_key = it->second.data(); + else if (key == string("fullHex")) tx->m_full_hex = it->second.data(); + else if (key == string("prunedHex")) tx->m_pruned_hex = it->second.data(); + else if (key == string("prunableHex")) tx->m_prunable_hex = it->second.data(); + else if (key == string("prunableHash")) tx->m_prunable_hash = it->second.data(); + else if (key == string("size")) throw runtime_error("size deserialization not implemented"); + else if (key == string("weight")) throw runtime_error("weight deserialization not implemented"); + else if (key == string("vins")) throw runtime_error("vins deserializationn not implemented"); + else if (key == string("vouts")) throw runtime_error("vouts deserializationn not implemented"); + else if (key == string("outputIndices")) throw runtime_error("m_output_indices deserialization not implemented"); + else if (key == string("metadata")) tx->m_metadata = it->second.data(); + else if (key == string("commonTxSets")) throw runtime_error("commonTxSets deserialization not implemented"); + else if (key == string("extra")) throw runtime_error("extra deserialization not implemented"); + else if (key == string("rctSignatures")) throw runtime_error("rctSignatures deserialization not implemented"); + else if (key == string("rctSigPrunable")) throw runtime_error("rctSigPrunable deserialization not implemented"); + else if (key == string("isKeptByBlock")) tx->m_is_kept_by_block = it->second.get_value(); + else if (key == string("isFailed")) tx->m_is_failed = it->second.get_value(); + else if (key == string("lastFailedHeight")) throw runtime_error("lastFailedHeight deserialization not implemented"); + else if (key == string("lastFailedId")) tx->m_last_failed_id = it->second.data(); + else if (key == string("maxUsedBlockHeight")) throw runtime_error("maxUsedBlockHeight deserialization not implemented"); + else if (key == string("maxUsedBlockId")) tx->m_max_used_block_id = it->second.data(); + else if (key == string("signatures")) throw runtime_error("signatures deserialization not implemented"); } - - void monero_tx::from_property_tree(const boost::property_tree::ptree& node, shared_ptr tx) { - - // initialize tx from node - for (boost::property_tree::ptree::const_iterator it = node.begin(); it != node.end(); ++it) { - string key = it->first; - if (key == string("id")) tx->m_id = it->second.data(); - else if (key == string("version")) throw runtime_error("version deserializationn not implemented"); - else if (key == string("isMinerTx")) tx->m_is_miner_tx = it->second.get_value(); - else if (key == string("paymentId")) tx->m_payment_id = it->second.data(); // TODO: this threw runtime_error, how is "Can get transactions by payment ids" test passing in Java? - else if (key == string("fee")) tx->m_fee = it->second.get_value(); - else if (key == string("mixin")) throw runtime_error("mixin deserialization not implemented"); - else if (key == string("doNotRelay")) tx->m_do_not_relay = it->second.get_value(); - else if (key == string("isRelayed")) tx->m_is_relayed = it->second.get_value(); - else if (key == string("isConfirmed")) tx->m_is_confirmed = it->second.get_value(); - else if (key == string("inTxPool")) tx->m_in_tx_pool = it->second.get_value(); - else if (key == string("numConfirmations")) tx->m_num_confirmations = it->second.get_value(); - else if (key == string("unlockTime")) tx->m_unlock_time = it->second.get_value(); - else if (key == string("lastRelayedTimestamp")) tx->m_last_relayed_timestamp = it->second.get_value(); - else if (key == string("receivedTimestamp")) tx->m_received_timestamp = it->second.get_value(); - else if (key == string("isDoubleSpendSeen")) tx->m_is_double_spend_seen = it->second.get_value(); - else if (key == string("key")) tx->m_key = it->second.data(); - else if (key == string("fullHex")) tx->m_full_hex = it->second.data(); - else if (key == string("prunedHex")) tx->m_pruned_hex = it->second.data(); - else if (key == string("prunableHex")) tx->m_prunable_hex = it->second.data(); - else if (key == string("prunableHash")) tx->m_prunable_hash = it->second.data(); - else if (key == string("size")) throw runtime_error("size deserialization not implemented"); - else if (key == string("weight")) throw runtime_error("weight deserialization not implemented"); - else if (key == string("vins")) throw runtime_error("vins deserializationn not implemented"); - else if (key == string("vouts")) throw runtime_error("vouts deserializationn not implemented"); - else if (key == string("outputIndices")) throw runtime_error("m_output_indices deserialization not implemented"); - else if (key == string("metadata")) tx->m_metadata = it->second.data(); - else if (key == string("commonTxSets")) throw runtime_error("commonTxSets deserialization not implemented"); - else if (key == string("extra")) throw runtime_error("extra deserialization not implemented"); - else if (key == string("rctSignatures")) throw runtime_error("rctSignatures deserialization not implemented"); - else if (key == string("rctSigPrunable")) throw runtime_error("rctSigPrunable deserialization not implemented"); - else if (key == string("isKeptByBlock")) tx->m_is_kept_by_block = it->second.get_value(); - else if (key == string("isFailed")) tx->m_is_failed = it->second.get_value(); - else if (key == string("lastFailedHeight")) throw runtime_error("lastFailedHeight deserialization not implemented"); - else if (key == string("lastFailedId")) tx->m_last_failed_id = it->second.data(); - else if (key == string("maxUsedBlockHeight")) throw runtime_error("maxUsedBlockHeight deserialization not implemented"); - else if (key == string("maxUsedBlockId")) tx->m_max_used_block_id = it->second.data(); - else if (key == string("signatures")) throw runtime_error("signatures deserialization not implemented"); - } } shared_ptr monero_tx::copy(const shared_ptr& src, const shared_ptr& tgt) const { @@ -672,14 +591,7 @@ namespace monero { // --------------------------- MONERO KEY IMAGE ----------------------------- - // boost::property_tree::ptree monero_key_image::to_property_tree() const { - // boost::property_tree::ptree node; - // if (m_hex != boost::none) node.put("hex", *m_hex); - // if (m_signature != boost::none) node.put("signature", *m_signature); - // return node; - // } - - rapidjson::Value monero_key_image::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_key_image::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -739,7 +651,7 @@ namespace monero { // ------------------------------ MONERO OUTPUT ----------------------------- - rapidjson::Value monero_output::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_output::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -751,10 +663,10 @@ namespace monero { if (m_stealth_public_key != boost::none) monero_utils::addJsonMember("stealthPublicKey", m_stealth_public_key.get(), allocator, root, value_num); // set sub-arrays - if (!m_ring_output_indices.empty()) root.AddMember("ringOutputIndices", monero_utils::to_json_val(allocator, m_ring_output_indices), allocator); + if (!m_ring_output_indices.empty()) root.AddMember("ringOutputIndices", monero_utils::to_rapidjson_val(allocator, m_ring_output_indices), allocator); // set sub-objects - if (m_key_image != boost::none) root.AddMember("keyImage", m_key_image.get()->to_json_val(allocator), allocator); + if (m_key_image != boost::none) root.AddMember("keyImage", m_key_image.get()->to_rapidjson_val(allocator), allocator); // return root return root; @@ -788,16 +700,6 @@ namespace monero { return tgt; } -// boost::property_tree::ptree monero_output::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_key_image != boost::none) node.add_child("keyImage", (*m_key_image)->to_property_tree()); -// if (m_amount != boost::none) node.put("amount", *m_amount); -// if (m_index != boost::none) node.put("index", *m_index); -// if (!m_ring_output_indices.empty()) node.add_child("ringOutputIndices", monero_utils::to_property_tree(m_ring_output_indices)); -// if (m_stealth_public_key != boost::none) node.put("stealthPublicKey", *m_stealth_public_key); -// return node; -// } - void monero_output::merge(const shared_ptr& self, const shared_ptr& other) { if (this != self.get()) throw runtime_error("this != self"); if (self == other) return; diff --git a/src/daemon/monero_daemon_model.h b/src/daemon/monero_daemon_model.h index f87094d..e766a27 100644 --- a/src/daemon/monero_daemon_model.h +++ b/src/daemon/monero_daemon_model.h @@ -77,20 +77,13 @@ namespace monero { */ string serialize() const; -// /** -// * Convert the struct to a property tree. -// * -// * @return the converted property tree -// */ -// virtual boost::property_tree::ptree to_property_tree() const = 0; - /** * Converts the struct to a rapidjson Value. * * @param allocator is the rapidjson document allocator * @return the struct as a rapidjson Value */ - virtual rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const = 0; + virtual rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const = 0; }; /** @@ -109,8 +102,7 @@ namespace monero { boost::optional m_version_number; boost::optional m_is_release; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -154,8 +146,7 @@ namespace monero { boost::optional m_reward; boost::optional m_pow_hash; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -168,9 +159,7 @@ namespace monero { vector> m_txs; vector m_tx_ids; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; - + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; void merge(const shared_ptr& self, const shared_ptr& other); void merge(const shared_ptr& self, const shared_ptr& other); }; @@ -219,8 +208,7 @@ namespace monero { boost::optional m_max_used_block_id; vector m_signatures; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, shared_ptr tx); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); @@ -234,8 +222,7 @@ namespace monero { boost::optional m_hex; boost::optional m_signature; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& key_image); static vector> deserialize_key_images(const string& key_images_json); // TODO: remove this specialty util used once shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -253,8 +240,7 @@ namespace monero { vector m_ring_output_indices; boost::optional m_stealth_public_key; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; virtual void merge(const shared_ptr& self, const shared_ptr& other); diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index 5ba3d26..a56d6bf 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -170,7 +170,7 @@ void monero_utils::addJsonMember(string key, bool val, rapidjson::Document::Allo } } -rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& strs) { +rapidjson::Value monero_utils::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& strs) { rapidjson::Value value_arr(rapidjson::kArrayType); rapidjson::Value value_str(rapidjson::kStringType); for (const string& str : strs) { @@ -180,7 +180,7 @@ rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& a return value_arr; } -rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { +rapidjson::Value monero_utils::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { rapidjson::Value value_arr(rapidjson::kArrayType); rapidjson::Value value_num(rapidjson::kNumberType); for (const auto& num : nums) { @@ -191,7 +191,7 @@ rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& a } // TODO: remove these redundant implementations for different sizes? -rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { +rapidjson::Value monero_utils::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { rapidjson::Value value_arr(rapidjson::kArrayType); rapidjson::Value value_num(rapidjson::kNumberType); for (const auto& num : nums) { @@ -201,7 +201,7 @@ rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& a return value_arr; } -rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { +rapidjson::Value monero_utils::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& nums) { rapidjson::Value value_arr(rapidjson::kArrayType); rapidjson::Value value_num(rapidjson::kNumberType); for (const auto& num : nums) { @@ -213,7 +213,7 @@ rapidjson::Value monero_utils::to_json_val(rapidjson::Document::AllocatorType& a // ------------------------ PROPERTY TREES --------------------------- -// TODO: fully switch to rapidjson +// TODO: switch to rapidjson string monero_utils::serialize(const boost::property_tree::ptree& node) { std::stringstream ss; @@ -222,7 +222,6 @@ string monero_utils::serialize(const boost::property_tree::ptree& node) { return str.substr(0, str.size() - 1); // strip newline } -// TODO: switch deserializes in this utils class to use this deserialize util void monero_utils::deserialize(const string& json, boost::property_tree::ptree& root) { std::istringstream iss = json.empty() ? std::istringstream() : std::istringstream(json); try { @@ -232,50 +231,10 @@ void monero_utils::deserialize(const string& json, boost::property_tree::ptree& } } -//boost::property_tree::ptree monero_utils::to_property_tree(const vector& strs) { -// boost::property_tree::ptree strsNode; -// for (const auto& str : strs) { -// boost::property_tree::ptree strNode; -// strNode.put("", str); -// strsNode.push_back(std::make_pair("", strNode)); -// } -// return strsNode; -//} -// -//boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { -// boost::property_tree::ptree numsNode; -// for (const auto& num : nums) { -// boost::property_tree::ptree numNode; -// numNode.put("", num); -// numsNode.push_back(std::make_pair("", numNode)); -// } -// return numsNode; -//} -// -//// TODO: remove these redundant implementations for different sizes? -//boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { -// boost::property_tree::ptree numsNode; -// for (const auto& num : nums) { -// boost::property_tree::ptree numNode; -// numNode.put("", num); -// numsNode.push_back(std::make_pair("", numNode)); -// } -// return numsNode; -//} -// -//boost::property_tree::ptree monero_utils::to_property_tree(const vector& nums) { -// boost::property_tree::ptree numsNode; -// for (const auto& num : nums) { -// boost::property_tree::ptree numNode; -// numNode.put("", num); -// numsNode.push_back(std::make_pair("", numNode)); -// } -// return numsNode; -//} - // ---------------------------------------------------------------------------- -// TODO: is this unused? +// TODO: this is unused + shared_ptr monero_utils::cn_block_to_block(const cryptonote::block& cn_block) { cryptonote::block temp = cn_block; cout << cryptonote::obj_to_json_str(temp) << endl; diff --git a/src/utils/monero_utils.h b/src/utils/monero_utils.h index 8394e82..38bfdc7 100644 --- a/src/utils/monero_utils.h +++ b/src/utils/monero_utils.h @@ -66,8 +66,6 @@ namespace monero_utils using namespace std; using namespace cryptonote; - void dummy_method(const string& str); // TODO: remove this - // ------------------------ BINARY SERIALIZATION ---------------------------- void json_to_binary(const std::string &json, std::string &bin); @@ -85,27 +83,27 @@ namespace monero_utils void addJsonMember(string key, bool val, rapidjson::Document::AllocatorType& allocator, rapidjson::Value& root); // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation - template rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector>& vals) { + template rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector>& vals) { rapidjson::Value value_arr(rapidjson::kArrayType); for (const auto& val : vals) { - value_arr.PushBack(val->to_json_val(allocator), allocator); + value_arr.PushBack(val->to_rapidjson_val(allocator), allocator); } return value_arr; } // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation - template rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& vals) { + template rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& vals) { rapidjson::Value value_arr(rapidjson::kArrayType); for (const auto& val : vals) { - value_arr.PushBack(val.to_json_val(allocator), allocator); + value_arr.PushBack(val.to_rapidjson_val(allocator), allocator); } return value_arr; } - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& strs); - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& strs); + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator, const vector& nums); // ------------------------ PROPERTY TREES --------------------------- @@ -114,30 +112,6 @@ namespace monero_utils string serialize(const boost::property_tree::ptree& node); void deserialize(const string& json, boost::property_tree::ptree& root); - // - // // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation - // template boost::property_tree::ptree to_property_tree(const vector>& types) { - // boost::property_tree::ptree typeNodes; - // for (const auto& type : types) { - // typeNodes.push_back(std::make_pair("", type->to_property_tree())); - // } - // return typeNodes; - // } - // - // // TODO: template implementation here, could move to monero_utils.hpp per https://stackoverflow.com/questions/3040480/c-template-function-compiles-in-header-but-not-implementation - // template boost::property_tree::ptree to_property_tree(const vector& types) { - // boost::property_tree::ptree typeNodes; - // for (const auto& type : types) { - // typeNodes.push_back(std::make_pair("", type.to_property_tree())); - // } - // return typeNodes; - // } - // - // boost::property_tree::ptree to_property_tree(const vector& strs); - // boost::property_tree::ptree to_property_tree(const vector& nums); - // boost::property_tree::ptree to_property_tree(const vector& nums); - // boost::property_tree::ptree to_property_tree(const vector& nums); - // -------------------------------------------------------------------------- /** diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index 1ea3b02..cf1b550 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -94,7 +94,7 @@ namespace monero { // -------------------------- MONERO SYNC RESULT ---------------------------- - rapidjson::Value monero_sync_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_sync_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -112,17 +112,7 @@ namespace monero { // -------------------------- MONERO ACCOUNT ----------------------------- - // boost::property_tree::ptree monero_account::to_property_tree() const { - // boost::property_tree::ptree node; - // if (m_index != boost::none) node.put("index", *m_index); - // if (m_primary_address != boost::none) node.put("primaryAddress", *m_primary_address); - // if (m_balance != boost::none) node.put("balance", *m_balance); - // if (m_unlocked_balance != boost::none) node.put("unlockedBalance", *m_unlocked_balance); - // if (!m_subaddresses.empty()) node.add_child("subaddresses", monero_utils::to_property_tree(m_subaddresses)); - // return node; - // } - - rapidjson::Value monero_account::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_account::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -139,7 +129,7 @@ namespace monero { if (m_tag != boost::none) monero_utils::addJsonMember("tag", m_tag.get(), allocator, root, value_str); // set subaddresses - if (!m_subaddresses.empty()) root.AddMember("subaddresses", monero_utils::to_json_val(allocator, m_subaddresses), allocator); + if (!m_subaddresses.empty()) root.AddMember("subaddresses", monero_utils::to_rapidjson_val(allocator, m_subaddresses), allocator); // return root return root; @@ -147,21 +137,7 @@ namespace monero { // -------------------------- MONERO SUBADDRESS ----------------------------- -// boost::property_tree::ptree monero_subaddress::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); -// if (m_index != boost::none) node.put("index", *m_index); -// if (m_address != boost::none) node.put("address", *m_address); -// if (m_label != boost::none) node.put("label", *m_label); -// if (m_balance != boost::none) node.put("balance", *m_balance); -// if (m_unlocked_balance != boost::none) node.put("unlockedBalance", *m_unlocked_balance); -// if (m_num_unspent_outputs != boost::none) node.put("numUnspentOutputs", *m_num_unspent_outputs); -// if (m_is_used != boost::none) node.put("isUsed", *m_is_used); -// if (m_num_blocks_to_unlock != boost::none) node.put("numBlocksToUnlock", *m_num_blocks_to_unlock); -// return node; -// } - - rapidjson::Value monero_subaddress::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_subaddress::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -189,27 +165,10 @@ namespace monero { // --------------------------- MONERO TX WALLET ----------------------------- - // boost::property_tree::ptree monero_tx_wallet::to_property_tree() const { - // boost::property_tree::ptree node = monero_tx::to_property_tree(); - // if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); - // if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); - // if (!m_incoming_transfers.empty()) node.add_child("incomingTransfers", monero_utils::to_property_tree(m_incoming_transfers)); - // if (m_outgoing_transfer != boost::none) node.add_child("outgoingTransfer", (*m_outgoing_transfer)->to_property_tree()); - // if (m_note != boost::none) node.put("note", *m_note); - // if (m_is_locked != boost::none) node.put("isLocked", *m_is_locked); - // if (m_input_sum != boost::none) node.put("inputSum", *m_input_sum); - // if (m_output_sum != boost::none) node.put("outputSum", *m_output_sum); - // if (m_change_address != boost::none) node.put("changeAddress", *m_change_address); - // if (m_change_amount != boost::none) node.put("changeAmount", *m_change_amount); - // if (m_num_dummy_outputs != boost::none) node.put("numDummyOutputs", *m_num_dummy_outputs); - // if (m_extra_hex != boost::none) node.put("extraHex", *m_extra_hex); - // return node; - // } - - rapidjson::Value monero_tx_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_tx_wallet::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_tx::to_json_val(allocator); + rapidjson::Value root = monero_tx::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -230,10 +189,10 @@ namespace monero { if (m_is_locked != boost::none) monero_utils::addJsonMember("isLocked", m_is_locked.get(), allocator, root); // set sub-arrays - if (!m_incoming_transfers.empty()) root.AddMember("incomingTransfers", monero_utils::to_json_val(allocator, m_incoming_transfers), allocator); + if (!m_incoming_transfers.empty()) root.AddMember("incomingTransfers", monero_utils::to_rapidjson_val(allocator, m_incoming_transfers), allocator); // set sub-objects - if (m_outgoing_transfer != boost::none) root.AddMember("outgoingTransfer", m_outgoing_transfer.get()->to_json_val(allocator), allocator); + if (m_outgoing_transfer != boost::none) root.AddMember("outgoingTransfer", m_outgoing_transfer.get()->to_rapidjson_val(allocator), allocator); // return root return root; @@ -332,25 +291,10 @@ namespace monero { // -------------------------- MONERO TX QUERY ----------------------------- - // boost::property_tree::ptree monero_tx_query::to_property_tree() const { - // boost::property_tree::ptree node = monero_tx_wallet::to_property_tree(); - // if (m_is_outgoing != boost::none) node.put("isOutgoing", *m_is_outgoing); - // if (m_is_incoming != boost::none) node.put("isIncoming", *m_is_incoming); - // if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); - // if (m_has_payment_id != boost::none) node.put("hasPaymentId", *m_has_payment_id); - // if (!m_payment_ids.empty()) node.add_child("paymentIds", monero_utils::to_property_tree(m_payment_ids)); - // if (m_height != boost::none) node.put("height", *m_height); - // if (m_min_height != boost::none) node.put("minHeight", *m_min_height); - // if (m_max_height != boost::none) node.put("maxHeight", *m_max_height); - // if (m_include_outputs != boost::none) node.put("includeOutputs", *m_include_outputs); - // if (m_transfer_query != boost::none) node.add_child("transferQuery", (*m_transfer_query)->to_property_tree()); - // return node; - // } - - rapidjson::Value monero_tx_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_tx_query::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_tx_wallet::to_json_val(allocator); + rapidjson::Value root = monero_tx_wallet::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -365,11 +309,11 @@ namespace monero { if (m_include_outputs != boost::none) monero_utils::addJsonMember("includeOutputs", m_include_outputs.get(), allocator, root); // set sub-arrays - if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); - if (!m_payment_ids.empty()) root.AddMember("paymentIds", monero_utils::to_json_val(allocator, m_payment_ids), allocator); + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_rapidjson_val(allocator, m_tx_ids), allocator); + if (!m_payment_ids.empty()) root.AddMember("paymentIds", monero_utils::to_rapidjson_val(allocator, m_payment_ids), allocator); // set sub-objects - if (m_transfer_query != boost::none) root.AddMember("transferQuery", m_transfer_query.get()->to_json_val(allocator), allocator); + if (m_transfer_query != boost::none) root.AddMember("transferQuery", m_transfer_query.get()->to_rapidjson_val(allocator), allocator); // return root return root; @@ -516,14 +460,7 @@ namespace monero { // -------------------------- MONERO DESTINATION ---------------------------- - // boost::property_tree::ptree monero_destination::to_property_tree() const { - // boost::property_tree::ptree node; - // if (m_address != boost::none) node.put("address", *m_address); - // if (m_amount != boost::none) node.put("amount", *m_amount); - // return node; - // } - - rapidjson::Value monero_destination::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_destination::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -558,16 +495,7 @@ namespace monero { // ----------------------------- MONERO TX SET ------------------------------ -// boost::property_tree::ptree monero_tx_set::to_property_tree() const { -// boost::property_tree::ptree node; -// if (!m_txs.empty()) node.add_child("txs", monero_utils::to_property_tree(m_txs)); -// if (m_multisig_tx_hex != boost::none) node.put("multisigTxHex", *m_multisig_tx_hex); -// if (m_unsigned_tx_hex != boost::none) node.put("unsignedTxHex", *m_unsigned_tx_hex); -// if (m_signed_tx_hex != boost::none) node.put("signedTxHex", *m_signed_tx_hex); -// return node; -// } - - rapidjson::Value monero_tx_set::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_tx_set::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -579,7 +507,7 @@ namespace monero { if (m_signed_tx_hex != boost::none) monero_utils::addJsonMember("signedTxHex", m_signed_tx_hex.get(), allocator, root, value_str); // set sub-arrays - if (!m_txs.empty()) root.AddMember("txs", monero_utils::to_json_val(allocator, m_txs), allocator); + if (!m_txs.empty()) root.AddMember("txs", monero_utils::to_rapidjson_val(allocator, m_txs), allocator); // return root return root; @@ -614,16 +542,7 @@ namespace monero { // ---------------------------- MONERO TRANSFER ----------------------------- - - // boost::property_tree::ptree monero_transfer::to_property_tree() const { - // boost::property_tree::ptree node; - // if (m_amount != boost::none) node.put("amount", *m_amount); - // if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - // if (m_num_suggested_confirmations != boost::none) node.put("numSuggestedConfirmations", *m_num_suggested_confirmations); - // return node; - // } - - rapidjson::Value monero_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_transfer::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -682,17 +601,10 @@ namespace monero { // ----------------------- MONERO INCOMING TRANSFER ------------------------- - // boost::property_tree::ptree monero_incoming_transfer::to_property_tree() const { - // boost::property_tree::ptree node = monero_transfer::to_property_tree(); - // if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); - // if (m_address != boost::none) node.put("address", *m_address); - // return node; - // } - - rapidjson::Value monero_incoming_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_incoming_transfer::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_transfer::to_json_val(allocator); + rapidjson::Value root = monero_transfer::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -730,23 +642,15 @@ namespace monero { // ----------------------- MONERO OUTGOING TRANSFER ------------------------- - // boost::property_tree::ptree monero_outgoing_transfer::to_property_tree() const { - // boost::property_tree::ptree node = monero_transfer::to_property_tree(); - // if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); - // if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); - // if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); - // return node; - // } - - rapidjson::Value monero_outgoing_transfer::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_outgoing_transfer::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_transfer::to_json_val(allocator); + rapidjson::Value root = monero_transfer::to_rapidjson_val(allocator); // set sub-arrays - if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); - if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_json_val(allocator, m_addresses), allocator); - if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); + if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_rapidjson_val(allocator, m_addresses), allocator); + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_rapidjson_val(allocator, m_destinations), allocator); // return root return root; @@ -777,10 +681,10 @@ namespace monero { // ----------------------- MONERO TRANSFER REQUEST -------------------------- - rapidjson::Value monero_transfer_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_transfer_query::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_transfer::to_json_val(allocator); + rapidjson::Value root = monero_transfer::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -795,9 +699,9 @@ namespace monero { if (m_address != boost::none) monero_utils::addJsonMember("address", m_address.get(), allocator, root, value_str); // set sub-arrays - if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); - if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_json_val(allocator, m_addresses), allocator); - if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); + if (!m_addresses.empty()) root.AddMember("addresses", monero_utils::to_rapidjson_val(allocator, m_addresses), allocator); + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_rapidjson_val(allocator, m_destinations), allocator); // return root return root; @@ -952,34 +856,12 @@ namespace monero { boost::optional monero_transfer_query::is_incoming() const { return m_is_incoming; } -// boost::property_tree::ptree monero_transfer_query::to_property_tree() const { -// boost::property_tree::ptree node = monero_transfer::to_property_tree(); -// if (is_incoming() != boost::none) node.put("isIncoming", *is_incoming()); -// if (m_address != boost::none) node.put("address", *m_address); -// if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); -// if (m_has_destinations != boost::none) node.put("hasDestinations", *m_has_destinations); -// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); -// if (!m_addresses.empty()) node.add_child("addresses", monero_utils::to_property_tree(m_addresses)); -// if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); -// return node; -// } - // ------------------------- MONERO OUTPUT WALLET --------------------------- - // boost::property_tree::ptree monero_output_wallet::to_property_tree() const { - // boost::property_tree::ptree node = monero_output::to_property_tree(); - // if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - // if (m_subaddress_index != boost::none) node.put("subaddressIndex", *m_subaddress_index); - // if (m_is_spent != boost::none) node.put("isSpent", *m_is_spent); - // if (m_is_unlocked != boost::none) node.put("isUnlocked", *m_is_unlocked); - // if (m_is_frozen != boost::none) node.put("isFrozen", *m_is_frozen); - // return node; - // } - - rapidjson::Value monero_output_wallet::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_output_wallet::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_output::to_json_val(allocator); + rapidjson::Value root = monero_output::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -1047,13 +929,13 @@ namespace monero { // ------------------------ MONERO OUTPUT REQUEST --------------------------- - rapidjson::Value monero_output_query::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_output_query::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_output_wallet::to_json_val(allocator); + rapidjson::Value root = monero_output_wallet::to_rapidjson_val(allocator); // set sub-arrays - if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); // return root return root; @@ -1149,12 +1031,6 @@ namespace monero { return true; } -// boost::property_tree::ptree monero_output_query::to_property_tree() const { -// boost::property_tree::ptree node = monero_output_wallet::to_property_tree(); -// if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); -// return node; -// } - // ------------------------- MONERO SEND REQUEST ---------------------------- monero_send_request::monero_send_request(const monero_send_request& request) { @@ -1179,27 +1055,7 @@ namespace monero { m_key_image = request.m_key_image; } - // boost::property_tree::ptree monero_send_request::to_property_tree() const { - // boost::property_tree::ptree node; - // if (!m_destinations.empty()) node.add_child("destinations", monero_utils::to_property_tree(m_destinations)); - // if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); - // if (m_priority != boost::none) node.put("priority", *m_priority); - // if (m_mixin != boost::none) node.put("mixin", *m_mixin); - // if (m_ring_size != boost::none) node.put("ringSize", *m_ring_size); - // if (m_account_index != boost::none) node.put("accountIndex", *m_account_index); - // if (!m_subaddress_indices.empty()) node.add_child("subaddressIndices", monero_utils::to_property_tree(m_subaddress_indices)); - // if (m_unlock_time != boost::none) node.put("unlockTime", *m_unlock_time); - // if (m_can_split != boost::none) node.put("canSplit", *m_can_split); - // if (m_do_not_relay != boost::none) node.put("doNotRelay", *m_do_not_relay); - // if (m_note != boost::none) node.put("note", *m_note); - // if (m_recipient_name != boost::none) node.put("recipientName", *m_recipient_name); - // if (m_below_amount != boost::none) node.put("belowAmount", *m_below_amount); - // if (m_sweep_each_subaddress != boost::none) node.put("sweepEachSubaddress", *m_sweep_each_subaddress); - // if (m_key_image != boost::none) node.put("keyImage", *m_key_image); - // return node; - // } - - rapidjson::Value monero_send_request::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_send_request::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1225,8 +1081,8 @@ namespace monero { if (m_sweep_each_subaddress != boost::none) monero_utils::addJsonMember("sweepEachSubaddress", m_sweep_each_subaddress.get(), allocator, root); // set sub-arrays - if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_json_val(allocator, m_destinations), allocator); - if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_json_val(allocator, m_subaddress_indices), allocator); + if (!m_destinations.empty()) root.AddMember("destinations", monero_utils::to_rapidjson_val(allocator, m_destinations), allocator); + if (!m_subaddress_indices.empty()) root.AddMember("subaddressIndices", monero_utils::to_rapidjson_val(allocator, m_subaddress_indices), allocator); // return root return root; @@ -1276,15 +1132,7 @@ namespace monero { // ---------------------- MONERO INTEGRATED ADDRESS ------------------------- -// boost::property_tree::ptree monero_integrated_address::to_property_tree() const { -// boost::property_tree::ptree node; -// node.put("standardAddress", m_standard_address); -// node.put("paymentId", m_payment_id); -// node.put("integratedAddress", m_integrated_address); -// return node; -// } - - rapidjson::Value monero_integrated_address::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_integrated_address::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1301,15 +1149,7 @@ namespace monero { // -------------------- MONERO KEY IMAGE IMPORT RESULT ---------------------- -// boost::property_tree::ptree monero_key_image_import_result::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_height != boost::none) node.put("height", *m_height); -// if (m_spent_amount != boost::none) node.put("spentAmount", *m_spent_amount); -// if (m_unspent_amount != boost::none) node.put("unspentAmount", *m_unspent_amount); -// return node; -// } - - rapidjson::Value monero_key_image_import_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_key_image_import_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1326,13 +1166,7 @@ namespace monero { // ----------------------------- MONERO CHECK ------------------------------- -// boost::property_tree::ptree monero_check::to_property_tree() const { -// boost::property_tree::ptree node; -// node.put("isGood", m_is_good); -// return node; -// } - - rapidjson::Value monero_check::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_check::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1346,18 +1180,10 @@ namespace monero { // --------------------------- MONERO CHECK TX ------------------------------ -// boost::property_tree::ptree monero_check_tx::to_property_tree() const { -// boost::property_tree::ptree node = monero_check::to_property_tree();; -// if (m_in_tx_pool != boost::none) node.put("inTxPool", *m_in_tx_pool); -// if (m_num_confirmations != boost::none) node.put("numConfirmations", *m_num_confirmations); -// if (m_received_amount != boost::none) node.put("receivedAmount", *m_received_amount); -// return node; -// } - - rapidjson::Value monero_check_tx::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_check_tx::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_check::to_json_val(allocator); + rapidjson::Value root = monero_check::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -1373,17 +1199,10 @@ namespace monero { // ------------------------ MONERO CHECK RESERVE ---------------------------- -// boost::property_tree::ptree monero_check_reserve::to_property_tree() const { -// boost::property_tree::ptree node = monero_check::to_property_tree(); -// if (m_total_amount != boost::none) node.put("totalAmount", *m_total_amount); -// if (m_unconfirmed_spent_amount != boost::none) node.put("unconfirmedSpentAmount", *m_unconfirmed_spent_amount); -// return node; -// } - - rapidjson::Value monero_check_reserve::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_check_reserve::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // serialize root from superclass - rapidjson::Value root = monero_check::to_json_val(allocator); + rapidjson::Value root = monero_check::to_rapidjson_val(allocator); // set num values rapidjson::Value value_num(rapidjson::kNumberType); @@ -1396,16 +1215,7 @@ namespace monero { // --------------------------- MONERO MULTISIG ------------------------------ -// boost::property_tree::ptree monero_multisig_info::to_property_tree() const { -// boost::property_tree::ptree node; -// node.put("isMultisig", m_is_multisig); -// node.put("isReady", m_is_ready); -// node.put("threshold", m_threshold); -// node.put("numParticipants", m_num_participants); -// return node; -// } - - rapidjson::Value monero_multisig_info::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_multisig_info::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1423,14 +1233,7 @@ namespace monero { return root; } -// boost::property_tree::ptree monero_multisig_init_result::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_address != boost::none) node.put("address", *m_address); -// if (m_multisig_hex != boost::none) node.put("multisigHex", *m_multisig_hex); -// return node; -// } - - rapidjson::Value monero_multisig_init_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_multisig_init_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1444,14 +1247,7 @@ namespace monero { return root; } -// boost::property_tree::ptree monero_multisig_sign_result::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_signed_multisig_tx_hex != boost::none) node.put("signedMultisigTxHex", *m_signed_multisig_tx_hex); -// if (!m_tx_ids.empty()) node.add_child("txIds", monero_utils::to_property_tree(m_tx_ids)); -// return node; -// } - - rapidjson::Value monero_multisig_sign_result::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_multisig_sign_result::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); @@ -1460,7 +1256,7 @@ namespace monero { if (m_signed_multisig_tx_hex != boost::none) monero_utils::addJsonMember("signedMultisigTxHex", m_signed_multisig_tx_hex.get(), allocator, root, value_str); // set sub-arrays - if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_json_val(allocator, m_tx_ids), allocator); + if (!m_tx_ids.empty()) root.AddMember("txIds", monero_utils::to_rapidjson_val(allocator, m_tx_ids), allocator); // return root return root; @@ -1468,16 +1264,7 @@ namespace monero { // -------------------------- MONERO ADDRESS BOOK --------------------------- -// boost::property_tree::ptree monero_address_book_entry::to_property_tree() const { -// boost::property_tree::ptree node; -// if (m_index != boost::none) node.put("index", *m_index); -// if (m_address != boost::none) node.put("address", *m_address); -// if (m_description != boost::none) node.put("description", *m_description); -// if (m_payment_id != boost::none) node.put("paymentId", *m_payment_id); -// return node; -// } - - rapidjson::Value monero_address_book_entry::to_json_val(rapidjson::Document::AllocatorType& allocator) const { + rapidjson::Value monero_address_book_entry::to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const { // create root rapidjson::Value root(rapidjson::kObjectType); diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index f0aaeeb..8563b64 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -71,7 +71,7 @@ namespace monero { monero_sync_result() {} monero_sync_result(const uint64_t num_blocks_fetched, const bool received_money) : m_num_blocks_fetched(num_blocks_fetched), m_received_money(received_money) {} - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -88,8 +88,7 @@ namespace monero { boost::optional m_is_used; boost::optional m_num_blocks_to_unlock; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -103,8 +102,7 @@ namespace monero { boost::optional m_tag; vector m_subaddresses; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -116,8 +114,7 @@ namespace monero { monero_destination() {} monero_destination(const string& address, uint64_t amount) : m_address(address), m_amount(amount) {} - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& destination); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; }; @@ -136,8 +133,7 @@ namespace monero { boost::optional m_account_index; boost::optional m_num_suggested_confirmations; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer); virtual boost::optional is_incoming() const = 0; // derived class must implement shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -155,8 +151,7 @@ namespace monero { boost::optional m_subaddress_index; boost::optional m_address; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; @@ -172,8 +167,7 @@ namespace monero { vector m_addresses; vector> m_destinations; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; @@ -196,8 +190,7 @@ namespace monero { boost::optional m_has_destinations; boost::optional> m_tx_query; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer_query); static shared_ptr deserialize(const string& transfer_query_json); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -215,8 +208,7 @@ namespace monero { boost::optional m_is_spent; boost::optional m_is_frozen; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_wallet); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -235,7 +227,7 @@ namespace monero { boost::optional> m_tx_query; //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_query); static shared_ptr deserialize(const string& output_query_json); bool is_default() const; @@ -266,8 +258,7 @@ namespace monero { boost::optional m_num_dummy_outputs; boost::optional m_extra_hex; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_wallet); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -293,8 +284,7 @@ namespace monero { boost::optional> m_transfer_query; boost::optional> m_output_query; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_query); static shared_ptr deserialize(const string& tx_query_json); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; @@ -318,7 +308,7 @@ namespace monero { boost::optional m_multisig_tx_hex; //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static monero_tx_set deserialize(const string& tx_set_json); }; @@ -330,8 +320,7 @@ namespace monero { string m_payment_id; string m_integrated_address; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -366,8 +355,7 @@ namespace monero { monero_send_request() {} monero_send_request(const monero_send_request& request); - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static shared_ptr deserialize(const string& send_request_json); monero_send_request copy() const; }; @@ -380,8 +368,7 @@ namespace monero { boost::optional m_spent_amount; boost::optional m_unspent_amount; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -390,8 +377,7 @@ namespace monero { struct monero_check : public serializable_struct { bool m_is_good; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -402,8 +388,7 @@ namespace monero { boost::optional m_num_confirmations; boost::optional m_received_amount; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -413,8 +398,7 @@ namespace monero { boost::optional m_total_amount; boost::optional m_unconfirmed_spent_amount; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -426,8 +410,7 @@ namespace monero { uint32_t m_threshold; uint32_t m_num_participants; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -439,8 +422,7 @@ namespace monero { boost::optional m_address; boost::optional m_multisig_hex; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -450,8 +432,7 @@ namespace monero { boost::optional m_signed_multisig_tx_hex; vector m_tx_ids; - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; /** @@ -465,7 +446,6 @@ namespace monero { monero_address_book_entry() {} monero_address_book_entry(uint64_t index, const string& address, const string& description, const string& payment_id) : m_index(index), m_address(address), m_description(description), m_payment_id(payment_id) {} - //boost::property_tree::ptree to_property_tree() const; - rapidjson::Value to_json_val(rapidjson::Document::AllocatorType& allocator) const; + rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; }; } From f9dc90cb178daf2f1c2a1459178ca4f6245e5ed3 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 17:31:32 -0500 Subject: [PATCH 30/34] remove unrecognized field warnings which are incorrect because superclasses handle some fields --- src/utils/monero_utils.cpp | 2 -- src/wallet/monero_wallet_model.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/utils/monero_utils.cpp b/src/utils/monero_utils.cpp index a56d6bf..d2268a4 100644 --- a/src/utils/monero_utils.cpp +++ b/src/utils/monero_utils.cpp @@ -213,8 +213,6 @@ rapidjson::Value monero_utils::to_rapidjson_val(rapidjson::Document::AllocatorTy // ------------------------ PROPERTY TREES --------------------------- -// TODO: switch to rapidjson - string monero_utils::serialize(const boost::property_tree::ptree& node) { std::stringstream ss; boost::property_tree::write_json(ss, node, false); diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index cf1b550..e6e0513 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -884,7 +884,6 @@ namespace monero { else if (key == string("subaddressIndex")) output_wallet->m_subaddress_index = it->second.get_value(); else if (key == string("isSpent")) output_wallet->m_is_spent = it->second.get_value(); else if (key == string("isFrozen")) output_wallet->m_is_frozen = it->second.get_value(); - else cout << "WARNING: unrecognized field deserializing node to output wallet: " << key << endl; } } @@ -949,7 +948,6 @@ namespace monero { string key = it->first; if (key == string("subaddressIndices")) for (boost::property_tree::ptree::const_iterator it2 = it->second.begin(); it2 != it->second.end(); ++it2) output_query->m_subaddress_indices.push_back(it2->second.get_value()); else if (key == string("txQuery")) {} // ignored - else cout << "WARNING: unrecognized field deserializing node to output query: " << key << endl; } } From 78e8f60e60e928210ee358517caa99ba794a2875 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 17:33:56 -0500 Subject: [PATCH 31/34] remove rapidjson serialization template --- src/daemon/monero_daemon_model.cpp | 52 ------------------------------ 1 file changed, 52 deletions(-) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index b3925c3..d0500f1 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -1,55 +1,3 @@ -//SERIALIZATION TEMPLATE -// // create root -// rapidjson::Value root(rapidjson::kObjectType); - -// // serialize root from superclass -// rapidjson::Value root = superclass::to_rapidjson_val(allocator); -// -// // set num values -// rapidjson::Value value_num(rapidjson::kNumberType); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_num); -// -// // set string values -// rapidjson::Value value_str(rapidjson::kStringType); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); -// if (m_todo != boost::none) monero_utils::addJsonMember("todo", m_todo.get(), allocator, root, value_str); -// -// // set bool values -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// if (m_todo != boost::none) monero_utils::addJsonMember("m_todo", m_todo.get(), allocator, root); -// -// // set sub-arrays -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); -// if (!m_todos.empty()) root.AddMember("todos", monero_utils::to_rapidjson_val(allocator, m_todos), allocator); -// -// // set sub-objects -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); -// if (m_todo != boost::none) root.AddMember("todo", m_todo.get()->to_rapidjson_val(allocator), allocator); -// -// // return root -// return root; - - /** * Copyright (c) 2017-2019 woodser * From eafd073093e27d6db0d466fd7a3f588a43657e15 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 17:48:09 -0500 Subject: [PATCH 32/34] rename tx, transfer, output query deserialize() -> deserialize_from_block() because json str is rooted at block --- src/wallet/monero_wallet_model.cpp | 6 +++--- src/wallet/monero_wallet_model.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/wallet/monero_wallet_model.cpp b/src/wallet/monero_wallet_model.cpp index e6e0513..80575ed 100644 --- a/src/wallet/monero_wallet_model.cpp +++ b/src/wallet/monero_wallet_model.cpp @@ -345,7 +345,7 @@ namespace monero { } } - shared_ptr monero_tx_query::deserialize(const string& tx_query_json) { + shared_ptr monero_tx_query::deserialize_from_block(const string& tx_query_json) { // deserialize tx query string to property rooted at block std::istringstream iss = tx_query_json.empty() ? std::istringstream() : std::istringstream(tx_query_json); @@ -728,7 +728,7 @@ namespace monero { } } - shared_ptr monero_transfer_query::deserialize(const string& transfer_query_json) { + shared_ptr monero_transfer_query::deserialize_from_block(const string& transfer_query_json) { // deserialize transfer query string to property rooted at block std::istringstream iss = transfer_query_json.empty() ? std::istringstream() : std::istringstream(transfer_query_json); @@ -951,7 +951,7 @@ namespace monero { } } - shared_ptr monero_output_query::deserialize(const string& output_query_json) { + shared_ptr monero_output_query::deserialize_from_block(const string& output_query_json) { // deserialize output query string to property rooted at block std::istringstream iss = output_query_json.empty() ? std::istringstream() : std::istringstream(output_query_json); diff --git a/src/wallet/monero_wallet_model.h b/src/wallet/monero_wallet_model.h index 8563b64..7c4fcc3 100644 --- a/src/wallet/monero_wallet_model.h +++ b/src/wallet/monero_wallet_model.h @@ -192,7 +192,7 @@ namespace monero { rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& transfer_query); - static shared_ptr deserialize(const string& transfer_query_json); + static shared_ptr deserialize_from_block(const string& transfer_query_json); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; boost::optional is_incoming() const; @@ -229,7 +229,7 @@ namespace monero { //boost::property_tree::ptree to_property_tree() const; rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& output_query); - static shared_ptr deserialize(const string& output_query_json); + static shared_ptr deserialize_from_block(const string& output_query_json); bool is_default() const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; // TODO: necessary to override all super classes? @@ -286,7 +286,7 @@ namespace monero { rapidjson::Value to_rapidjson_val(rapidjson::Document::AllocatorType& allocator) const; static void from_property_tree(const boost::property_tree::ptree& node, const shared_ptr& tx_query); - static shared_ptr deserialize(const string& tx_query_json); + static shared_ptr deserialize_from_block(const string& tx_query_json); shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; // TODO: necessary to override all super classes? shared_ptr copy(const shared_ptr& src, const shared_ptr& tgt) const; From 3c4f68911e9c80fb7fbd0b4761372aa3b4f1dca5 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 18:06:35 -0500 Subject: [PATCH 33/34] cleanup --- src/daemon/monero_daemon_model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/daemon/monero_daemon_model.cpp b/src/daemon/monero_daemon_model.cpp index d0500f1..0759d73 100644 --- a/src/daemon/monero_daemon_model.cpp +++ b/src/daemon/monero_daemon_model.cpp @@ -270,7 +270,7 @@ namespace monero { if (!m_vins.empty()) root.AddMember("vins", monero_utils::to_rapidjson_val(allocator, m_vins), allocator); if (!m_vouts.empty()) root.AddMember("vouts", monero_utils::to_rapidjson_val(allocator, m_vouts), allocator); if (!m_output_indices.empty()) root.AddMember("outputIndices", monero_utils::to_rapidjson_val(allocator, m_output_indices), allocator); - if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_rapidjson_val(allocator, m_extra), allocator); // TODO + if (!m_extra.empty()) root.AddMember("extra", monero_utils::to_rapidjson_val(allocator, m_extra), allocator); if (!m_signatures.empty()) root.AddMember("signatures", monero_utils::to_rapidjson_val(allocator, m_signatures), allocator); // return root From f6d7d47d2c073e8b8dfb7fbf0ccd75ae1a82c251 Mon Sep 17 00:00:00 2001 From: woodser Date: Sun, 1 Dec 2019 08:41:53 -0500 Subject: [PATCH 34/34] monero_wallet.h request -> query terminology --- src/wallet/monero_wallet.h | 26 +++++++++++++------------- todo.txt | 5 +---- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/wallet/monero_wallet.h b/src/wallet/monero_wallet.h index 40df6c0..8ecae28 100644 --- a/src/wallet/monero_wallet.h +++ b/src/wallet/monero_wallet.h @@ -655,15 +655,15 @@ namespace monero { * Get wallet transactions. Wallet transactions contain one or more * transfers that are either incoming or outgoing to the wallet. * - * Query results can be filtered by passing in a transaction request. - * Transactions must meet every criteria defined in the request in order to + * Query results can be filtered by passing in a transaction query. + * Transactions must meet every criteria defined in the query in order to * be returned. All filtering is optional and no filtering is applied when * not defined. * - * @param request filters query results (optional) - * @return wallet transactions per the request + * @param query filters query results (optional) + * @return wallet transactions per the query */ - vector> get_txs(const monero_tx_query& request) const; + vector> get_txs(const monero_tx_query& query) const; // /** // * Get all incoming and outgoing transfers to and from this wallet. An @@ -713,14 +713,14 @@ namespace monero { * are stored on the blockchain. * * Query results can be filtered by passing in a monero_transfer_query. - * Transfers must meet every criteria defined in the request in order to be + * Transfers must meet every criteria defined in the query in order to be * returned. All filtering is optional and no filtering is applied when not * defined. * - * @param request filters query results (optional) - * @return wallet transfers per the request + * @param query filters query results (optional) + * @return wallet transfers per the query */ - vector> get_transfers(const monero_transfer_query& request) const; + vector> get_transfers(const monero_transfer_query& query) const; // /** // * Get outputs created from previous transactions that belong to the wallet @@ -737,13 +737,13 @@ namespace monero { * transactions which are stored in blocks on the blockchain. * * Results can be configured by passing a monero_output_query. Outputs must - * meet every criteria defined in the request in order to be returned. All + * meet every criteria defined in the query in order to be returned. All * filtering is optional and no filtering is applied when not defined. * - * @param request specifies request options (optional) - * @return List are wallet outputs per the request + * @param query specifies query options (optional) + * @return wallet outputs per the query */ - vector> get_outputs(const monero_output_query& request) const; + vector> get_outputs(const monero_output_query& query) const; /** * Export all outputs in hex format. diff --git a/todo.txt b/todo.txt index 3e0a1a0..84c2816 100644 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,7 @@ TODO -monero_wallet.h request -> query preserve rpc error codes, just throwing runtime_error now -gen_utils.h and monero_utils.h should not depend on monero_wallet.h -add to ecosystem? monero_wallet.cpp move utilities in monero_namespace to be private -polish model: no boost::optional? no boost::optional? etc +polish model: remove all boost::optional from model to be consistent with core? ensure model toPropertyTrees(), etc are not unecessarily copying return objects monero_wallet_listener should be a class? way to use copy constructors instead of query copy(sp, sp) methods?