From c3bc05d9795f1eccdeb73ee2546fa92e19f269b9 Mon Sep 17 00:00:00 2001 From: woodser Date: Sat, 30 Nov 2019 17:13:29 -0500 Subject: [PATCH] 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; }; /**