aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptonote_basic/miner.cpp112
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp19
-rw-r--r--src/cryptonote_core/cryptonote_core.h15
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h14
-rw-r--r--src/mnemonics/electrum-words.cpp77
-rw-r--r--src/mnemonics/electrum-words.h22
-rw-r--r--src/rpc/core_rpc_server.cpp2
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h2
-rw-r--r--src/serialization/serialization.h3
-rw-r--r--src/serialization/set.h127
-rw-r--r--src/simplewallet/simplewallet.cpp18
-rw-r--r--src/wallet/api/wallet.cpp4
-rw-r--r--src/wallet/api/wallet.h2
-rw-r--r--src/wallet/wallet2.cpp15
-rw-r--r--src/wallet/wallet2.h29
-rw-r--r--src/wallet/wallet2_api.h2
-rw-r--r--src/wallet/wallet_rpc_server.cpp90
-rw-r--r--src/wallet/wallet_rpc_server.h2
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h47
-rw-r--r--src/wallet/wallet_rpc_server_error_codes.h2
20 files changed, 541 insertions, 63 deletions
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
index 0aafe24e1..c90ab0f03 100644
--- a/src/cryptonote_basic/miner.cpp
+++ b/src/cryptonote_basic/miner.cpp
@@ -53,6 +53,19 @@
#include <TargetConditionals.h>
#endif
+#ifdef __FreeBSD__
+#include <devstat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <machine/apm_bios.h>
+#include <stdio.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <sys/times.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "miner"
@@ -735,8 +748,6 @@ namespace cryptonote
#elif defined(__linux__)
- const std::string STR_CPU("cpu");
- const std::size_t STR_CPU_LEN = STR_CPU.size();
const std::string STAT_FILE_PATH = "/proc/stat";
if( !epee::file_io_utils::is_file_exist(STAT_FILE_PATH) )
@@ -785,9 +796,36 @@ namespace cryptonote
return true;
+ #elif defined(__FreeBSD__)
+
+ struct statinfo s;
+ size_t n = sizeof(s.cp_time);
+ if( sysctlbyname("kern.cp_time", s.cp_time, &n, NULL, 0) == -1 )
+ {
+ LOG_ERROR("sysctlbyname(\"kern.cp_time\"): " << strerror(errno));
+ return false;
+ }
+ if( n != sizeof(s.cp_time) )
+ {
+ LOG_ERROR("sysctlbyname(\"kern.cp_time\") output is unexpectedly "
+ << n << " bytes instead of the expected " << sizeof(s.cp_time)
+ << " bytes.");
+ return false;
+ }
+
+ idle_time = s.cp_time[CP_IDLE];
+ total_time =
+ s.cp_time[CP_USER] +
+ s.cp_time[CP_NICE] +
+ s.cp_time[CP_SYS] +
+ s.cp_time[CP_INTR] +
+ s.cp_time[CP_IDLE];
+
+ return true;
+
#endif
- return false; // unsupported systemm..
+ return false; // unsupported system
}
//-----------------------------------------------------------------------------------------------------
bool miner::get_process_time(uint64_t& total_time)
@@ -807,7 +845,7 @@ namespace cryptonote
return true;
}
- #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__)
+ #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) || defined(__FreeBSD__)
struct tms tms;
if ( times(&tms) != (clock_t)-1 )
@@ -818,7 +856,7 @@ namespace cryptonote
#endif
- return false; // unsupported system..
+ return false; // unsupported system
}
//-----------------------------------------------------------------------------------------------------
uint8_t miner::get_percent_of_total(uint64_t other, uint64_t total)
@@ -929,6 +967,70 @@ namespace cryptonote
}
return on_battery;
+ #elif defined(__FreeBSD__)
+ int ac;
+ size_t n = sizeof(ac);
+ if( sysctlbyname("hw.acpi.acline", &ac, &n, NULL, 0) == -1 )
+ {
+ if( errno != ENOENT )
+ {
+ LOG_ERROR("Cannot query battery status: "
+ << "sysctlbyname(\"hw.acpi.acline\"): " << strerror(errno));
+ return boost::logic::tribool(boost::logic::indeterminate);
+ }
+
+ // If sysctl fails with ENOENT, then try querying /dev/apm.
+
+ static const char* dev_apm = "/dev/apm";
+ const int fd = open(dev_apm, O_RDONLY);
+ if( fd == -1 ) {
+ LOG_ERROR("Cannot query battery status: "
+ << "open(): " << dev_apm << ": " << strerror(errno));
+ return boost::logic::tribool(boost::logic::indeterminate);
+ }
+
+ apm_info info;
+ if( ioctl(fd, APMIO_GETINFO, &info) == -1 ) {
+ close(fd);
+ LOG_ERROR("Cannot query battery status: "
+ << "ioctl(" << dev_apm << ", APMIO_GETINFO): " << strerror(errno));
+ return boost::logic::tribool(boost::logic::indeterminate);
+ }
+
+ close(fd);
+
+ // See apm(8).
+ switch( info.ai_acline )
+ {
+ case 0: // off-line
+ case 2: // backup power
+ return boost::logic::tribool(true);
+ case 1: // on-line
+ return boost::logic::tribool(false);
+ }
+ switch( info.ai_batt_stat )
+ {
+ case 0: // high
+ case 1: // low
+ case 2: // critical
+ return boost::logic::tribool(true);
+ case 3: // charging
+ return boost::logic::tribool(false);
+ }
+
+ LOG_ERROR("Cannot query battery status: "
+ << "sysctl hw.acpi.acline is not available and /dev/apm returns "
+ << "unexpected ac-line status (" << info.ai_acline << ") and "
+ << "battery status (" << info.ai_batt_stat << ").");
+ return boost::logic::tribool(boost::logic::indeterminate);
+ }
+ if( n != sizeof(ac) )
+ {
+ LOG_ERROR("sysctlbyname(\"hw.acpi.acline\") output is unexpectedly "
+ << n << " bytes instead of the expected " << sizeof(ac) << " bytes.");
+ return boost::logic::tribool(boost::logic::indeterminate);
+ }
+ return boost::logic::tribool(ac == 0);
#endif
LOG_ERROR("couldn't query power status");
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index acc76a8d6..5c181208f 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1336,6 +1336,7 @@ namespace cryptonote
m_fork_moaner.do_call(boost::bind(&core::check_fork_time, this));
m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this));
m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
+ m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
m_miner.on_idle();
m_mempool.on_idle();
return true;
@@ -1467,6 +1468,17 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
+ bool core::check_disk_space()
+ {
+ uint64_t free_space = get_free_space();
+ if (free_space < 1ull * 1024 * 1024 * 1024) // 1 GB
+ {
+ const el::Level level = el::Level::Warning;
+ MCLOG_RED(level, "global", "Free space is below 1 GB on " << m_config_folder);
+ }
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------
void core::set_target_blockchain_height(uint64_t target_blockchain_height)
{
m_target_blockchain_height = target_blockchain_height;
@@ -1482,6 +1494,13 @@ namespace cryptonote
return get_blockchain_storage().prevalidate_block_hashes(height, hashes);
}
//-----------------------------------------------------------------------------------------------
+ uint64_t core::get_free_space() const
+ {
+ boost::filesystem::path path(m_config_folder);
+ boost::filesystem::space_info si = boost::filesystem::space(path);
+ return si.available;
+ }
+ //-----------------------------------------------------------------------------------------------
std::time_t core::get_start_time() const
{
return start_time;
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index dc014206d..905e67f6d 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -766,6 +766,13 @@ namespace cryptonote
*/
uint64_t prevalidate_block_hashes(uint64_t height, const std::list<crypto::hash> &hashes);
+ /**
+ * @brief get free disk space on the blockchain partition
+ *
+ * @return free space in bytes
+ */
+ uint64_t get_free_space() const;
+
private:
/**
@@ -925,6 +932,13 @@ namespace cryptonote
*/
bool check_updates();
+ /**
+ * @brief checks free disk space
+ *
+ * @return true on success, false otherwise
+ */
+ bool check_disk_space();
+
bool m_test_drop_download = true; //!< whether or not to drop incoming blocks (for testing)
uint64_t m_test_drop_download_height = 0; //!< height under which to drop incoming blocks, if doing so
@@ -948,6 +962,7 @@ namespace cryptonote
epee::math_helper::once_a_time_seconds<60*60*2, true> m_fork_moaner; //!< interval for checking HardFork status
epee::math_helper::once_a_time_seconds<60*2, false> m_txpool_auto_relayer; //!< interval for checking re-relaying txpool transactions
epee::math_helper::once_a_time_seconds<60*60*12, true> m_check_updates_interval; //!< interval for checking for new versions
+ epee::math_helper::once_a_time_seconds<60*10, true> m_check_disk_space_interval; //!< interval for checking for disk space
std::atomic<bool> m_starter_message_showed; //!< has the "daemon will sync now" message been shown?
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
index 9a3b2484d..8d9a1e332 100644
--- a/src/cryptonote_core/cryptonote_tx_utils.h
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -53,6 +53,20 @@ namespace cryptonote
rct::key mask; //ringct amount mask
void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(outputs)
+ FIELD(real_output)
+ FIELD(real_out_tx_key)
+ FIELD(real_out_additional_tx_keys)
+ FIELD(real_output_in_tx_index)
+ FIELD(amount)
+ FIELD(rct)
+ FIELD(mask)
+
+ if (real_output >= outputs.size())
+ return false;
+ END_SERIALIZE()
};
struct tx_destination_entry
diff --git a/src/mnemonics/electrum-words.cpp b/src/mnemonics/electrum-words.cpp
index 6ae33a743..1b14905f6 100644
--- a/src/mnemonics/electrum-words.cpp
+++ b/src/mnemonics/electrum-words.cpp
@@ -236,11 +236,13 @@ namespace crypto
/*!
* \brief Converts seed words to bytes (secret key).
* \param words String containing the words separated by spaces.
- * \param dst To put the secret key restored from the words.
+ * \param dst To put the secret data restored from the words.
+ * \param len The number of bytes to expect, 0 if unknown
+ * \param duplicate If true and len is not zero, we accept half the data, and duplicate it
* \param language_name Language of the seed as found gets written here.
* \return false if not a multiple of 3 words, or if word is not in the words list
*/
- bool words_to_bytes(std::string words, crypto::secret_key& dst,
+ bool words_to_bytes(std::string words, std::string& dst, size_t len, bool duplicate,
std::string &language_name)
{
std::vector<std::string> seed;
@@ -248,15 +250,23 @@ namespace crypto
boost::algorithm::trim(words);
boost::split(seed, words, boost::is_any_of(" "), boost::token_compress_on);
- // error on non-compliant word list
- if (seed.size() != seed_length/2 && seed.size() != seed_length &&
- seed.size() != seed_length + 1)
- {
+ if (len % 4)
return false;
- }
- // If it is seed with a checksum.
- bool has_checksum = seed.size() == (seed_length + 1);
+ bool has_checksum = true;
+ if (len)
+ {
+ // error on non-compliant word list
+ const size_t expected = len * 8 * 3 / 32;
+ if (seed.size() != expected/2 && seed.size() != expected &&
+ seed.size() != expected + 1)
+ {
+ return false;
+ }
+
+ // If it is seed with a checksum.
+ has_checksum = seed.size() == (expected + 1);
+ }
std::vector<uint32_t> matched_indices;
Language::Base *language;
@@ -290,32 +300,55 @@ namespace crypto
if (!(val % word_list_length == w1)) return false;
- memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position
+ dst.append((const char*)&val, 4); // copy 4 bytes to position
}
- std::string wlist_copy = words;
- if (seed.size() == seed_length/2)
+ if (len > 0 && duplicate)
{
- memcpy(dst.data+16, dst.data, 16); // if electrum 12-word seed, duplicate
- wlist_copy += ' ';
- wlist_copy += words;
+ const size_t expected = len * 3 / 32;
+ std::string wlist_copy = words;
+ if (seed.size() == expected/2)
+ {
+ dst.append(dst); // if electrum 12-word seed, duplicate
+ wlist_copy += ' ';
+ wlist_copy += words;
+ }
}
return true;
}
/*!
+ * \brief Converts seed words to bytes (secret key).
+ * \param words String containing the words separated by spaces.
+ * \param dst To put the secret key restored from the words.
+ * \param language_name Language of the seed as found gets written here.
+ * \return false if not a multiple of 3 words, or if word is not in the words list
+ */
+ bool words_to_bytes(std::string words, crypto::secret_key& dst,
+ std::string &language_name)
+ {
+ std::string s;
+ if (!words_to_bytes(words, s, sizeof(dst), true, language_name))
+ return false;
+ if (s.size() != sizeof(dst))
+ return false;
+ dst = *(const crypto::secret_key*)s.data();
+ return true;
+ }
+
+ /*!
* \brief Converts bytes (secret key) to seed words.
* \param src Secret key
* \param words Space delimited concatenated words get written here.
* \param language_name Seed language name
* \return true if successful false if not. Unsuccessful if wrong key size.
*/
- bool bytes_to_words(const crypto::secret_key& src, std::string& words,
+ bool bytes_to_words(const char *src, size_t len, std::string& words,
const std::string &language_name)
{
- if (sizeof(src.data) % 4 != 0 || sizeof(src.data) == 0) return false;
+ if (len % 4 != 0 || len == 0) return false;
Language::Base *language;
if (language_name == "English")
@@ -376,13 +409,13 @@ namespace crypto
uint32_t word_list_length = word_list.size();
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
- for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
+ for (unsigned int i=0; i < len/4; i++, words += ' ')
{
uint32_t w1, w2, w3;
uint32_t val;
- memcpy(&val, (src.data) + (i * 4), 4);
+ memcpy(&val, src + (i * 4), 4);
w1 = val % word_list_length;
w2 = ((val / word_list_length) + w1) % word_list_length;
@@ -404,6 +437,12 @@ namespace crypto
return true;
}
+ bool bytes_to_words(const crypto::secret_key& src, std::string& words,
+ const std::string &language_name)
+ {
+ return bytes_to_words(src.data, sizeof(src), words, language_name);
+ }
+
/*!
* \brief Gets a list of seed languages that are supported.
* \param languages The vector is set to the list of languages.
diff --git a/src/mnemonics/electrum-words.h b/src/mnemonics/electrum-words.h
index 94ce9c200..941768352 100644
--- a/src/mnemonics/electrum-words.h
+++ b/src/mnemonics/electrum-words.h
@@ -64,6 +64,17 @@ namespace crypto
/*!
* \brief Converts seed words to bytes (secret key).
* \param words String containing the words separated by spaces.
+ * \param dst To put the secret data restored from the words.
+ * \param len The number of bytes to expect, 0 if unknown
+ * \param duplicate If true and len is not zero, we accept half the data, and duplicate it
+ * \param language_name Language of the seed as found gets written here.
+ * \return false if not a multiple of 3 words, or if word is not in the words list
+ */
+ bool words_to_bytes(std::string words, std::string& dst, size_t len, bool duplicate,
+ std::string &language_name);
+ /*!
+ * \brief Converts seed words to bytes (secret key).
+ * \param words String containing the words separated by spaces.
* \param dst To put the secret key restored from the words.
* \param language_name Language of the seed as found gets written here.
* \return false if not a multiple of 3 words, or if word is not in the words list
@@ -72,6 +83,17 @@ namespace crypto
std::string &language_name);
/*!
+ * \brief Converts bytes to seed words.
+ * \param src Secret data
+ * \param len Secret data length in bytes (positive multiples of 4 only)
+ * \param words Space delimited concatenated words get written here.
+ * \param language_name Seed language name
+ * \return true if successful false if not. Unsuccessful if wrong key size.
+ */
+ bool bytes_to_words(const char *src, size_t len, std::string& words,
+ const std::string &language_name);
+
+ /*!
* \brief Converts bytes (secret key) to seed words.
* \param src Secret key
* \param words Space delimited concatenated words get written here.
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 6e7fb7e8e..e9a6a18aa 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -149,6 +149,7 @@ namespace cryptonote
res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit();
res.status = CORE_RPC_STATUS_OK;
res.start_time = (uint64_t)m_core.get_start_time();
+ res.free_space = m_restricted ? std::numeric_limits<uint64_t>::max() : m_core.get_free_space();
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -1328,6 +1329,7 @@ namespace cryptonote
res.block_size_limit = m_core.get_blockchain_storage().get_current_cumulative_blocksize_limit();
res.status = CORE_RPC_STATUS_OK;
res.start_time = (uint64_t)m_core.get_start_time();
+ res.free_space = m_restricted ? std::numeric_limits<uint64_t>::max() : m_core.get_free_space();
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 15b4b503a..d27d5611e 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -927,6 +927,7 @@ namespace cryptonote
uint64_t cumulative_difficulty;
uint64_t block_size_limit;
uint64_t start_time;
+ uint64_t free_space;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -947,6 +948,7 @@ namespace cryptonote
KV_SERIALIZE(cumulative_difficulty)
KV_SERIALIZE(block_size_limit)
KV_SERIALIZE(start_time)
+ KV_SERIALIZE(free_space)
END_KV_SERIALIZE_MAP()
};
};
diff --git a/src/serialization/serialization.h b/src/serialization/serialization.h
index 869f5d10e..9e23f0791 100644
--- a/src/serialization/serialization.h
+++ b/src/serialization/serialization.h
@@ -43,6 +43,8 @@
#include <vector>
#include <deque>
#include <list>
+#include <set>
+#include <unordered_set>
#include <string>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/integral_constant.hpp>
@@ -364,3 +366,4 @@ namespace serialization {
#include "vector.h"
#include "list.h"
#include "pair.h"
+#include "set.h"
diff --git a/src/serialization/set.h b/src/serialization/set.h
new file mode 100644
index 000000000..54b4eb3ab
--- /dev/null
+++ b/src/serialization/set.h
@@ -0,0 +1,127 @@
+// Copyright (c) 2014-2017, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+#include "serialization.h"
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::set<T> &v);
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::set<T> &v);
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v);
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v);
+
+namespace serialization
+{
+ namespace detail
+ {
+ template <typename Archive, class T>
+ bool serialize_set_element(Archive& ar, T& e)
+ {
+ return ::do_serialize(ar, e);
+ }
+
+ template <typename Archive>
+ bool serialize_set_element(Archive& ar, uint32_t& e)
+ {
+ ar.serialize_varint(e);
+ return true;
+ }
+
+ template <typename Archive>
+ bool serialize_set_element(Archive& ar, uint64_t& e)
+ {
+ ar.serialize_varint(e);
+ return true;
+ }
+ }
+}
+
+template <template <bool> class Archive, class T>
+bool do_serialize_set(Archive<false> &ar, T &v)
+{
+ size_t cnt;
+ ar.begin_array(cnt);
+ if (!ar.stream().good())
+ return false;
+ v.clear();
+
+ // very basic sanity check
+ if (ar.remaining_bytes() < cnt) {
+ ar.stream().setstate(std::ios::failbit);
+ return false;
+ }
+
+ for (size_t i = 0; i < cnt; i++) {
+ if (i > 0)
+ ar.delimit_array();
+ typename T::key_type k;
+ if (!::serialization::detail::serialize_set_element(ar, k))
+ return false;
+ v.insert(std::move(k));
+ if (!ar.stream().good())
+ return false;
+ }
+ ar.end_array();
+ return true;
+}
+
+template <template <bool> class Archive, class T>
+bool do_serialize_set(Archive<true> &ar, T &v)
+{
+ size_t cnt = v.size();
+ ar.begin_array(cnt);
+ bool first = true;
+ for (const typename T::key_type &k: v) {
+ if (!ar.stream().good())
+ return false;
+ if (!first)
+ ar.delimit_array();
+ if(!::serialization::detail::serialize_set_element(ar, const_cast<typename T::key_type&>(k)))
+ return false;
+ if (!ar.stream().good())
+ return false;
+ first = false;
+ }
+ ar.end_array();
+ return true;
+}
+
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::set<T> &v) { return do_serialize_set(ar, v); }
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::set<T> &v) { return do_serialize_set(ar, v); }
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<false> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); }
+template <template <bool> class Archive, class T>
+bool do_serialize(Archive<true> &ar, std::unordered_set<T> &v) { return do_serialize_set(ar, v); }
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 6c694d743..068fb7eb3 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -3966,20 +3966,12 @@ bool simple_wallet::get_tx_proof(const std::vector<std::string> &args)
try
{
- std::string error_str;
- std::string sig_str = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, args.size() == 3 ? args[2] : "", error_str);
- if (sig_str.empty())
- {
- fail_msg_writer() << error_str;
- }
+ std::string sig_str = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, args.size() == 3 ? args[2] : "");
+ const std::string filename = "monero_tx_proof";
+ if (epee::file_io_utils::save_string_to_file(filename, sig_str))
+ success_msg_writer() << tr("signature file saved to: ") << filename;
else
- {
- const std::string filename = "monero_tx_proof";
- if (epee::file_io_utils::save_string_to_file(filename, sig_str))
- success_msg_writer() << tr("signature file saved to:") << filename;
- else
- fail_msg_writer() << tr("failed to save signature file");
- }
+ fail_msg_writer() << tr("failed to save signature file");
}
catch (const std::exception &e)
{
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index e0326db84..fd0b65866 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -1467,7 +1467,7 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
}
}
-std::string WalletImpl::getTxProof(const std::string &txid_str, const std::string &address_str, const std::string &message, std::string &error_str) const
+std::string WalletImpl::getTxProof(const std::string &txid_str, const std::string &address_str, const std::string &message) const
{
crypto::hash txid;
if (!epee::string_tools::hex_to_pod(txid_str, txid))
@@ -1488,7 +1488,7 @@ std::string WalletImpl::getTxProof(const std::string &txid_str, const std::strin
try
{
m_status = Status_Ok;
- return m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, message, error_str);
+ return m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, message);
}
catch (const std::exception &e)
{
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 38e167516..8ceabc843 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -138,7 +138,7 @@ public:
virtual std::string getUserNote(const std::string &txid) const;
virtual std::string getTxKey(const std::string &txid) const;
virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
- virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message, std::string &error_str) const;
+ virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const;
virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations);
virtual std::string getSpendProof(const std::string &txid, const std::string &message) const;
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index bfbb653a3..2c8513fa4 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -6536,9 +6536,8 @@ void wallet2::check_tx_key_helper(const crypto::hash &txid, const crypto::key_de
}
}
-std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, std::string &error_str)
+std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message)
{
- error_str = "";
// determine if the address is found in the subaddress hash table (i.e. whether the proof is outbound or inbound)
const bool is_out = m_subaddresses.count(address.m_spend_public_key) == 0;
@@ -6554,11 +6553,7 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac
{
crypto::secret_key tx_key;
std::vector<crypto::secret_key> additional_tx_keys;
- if (!get_tx_key(txid, tx_key, additional_tx_keys))
- {
- error_str = tr("Tx secret key wasn't found in the wallet file.");
- return {};
- }
+ THROW_WALLET_EXCEPTION_IF(!get_tx_key(txid, tx_key, additional_tx_keys), error::wallet_internal_error, "Tx secret key wasn't found in the wallet file.");
const size_t num_sigs = 1 + additional_tx_keys.size();
shared_secret.resize(num_sigs);
@@ -6661,11 +6656,7 @@ std::string wallet2::get_tx_proof(const crypto::hash &txid, const cryptonote::ac
bool in_pool;
uint64_t confirmations;
check_tx_key_helper(txid, derivation, additional_derivations, address, received, in_pool, confirmations);
- if (!received)
- {
- error_str = tr("No funds received in this tx.");
- return {};
- }
+ THROW_WALLET_EXCEPTION_IF(!received, error::wallet_internal_error, tr("No funds received in this tx."));
// concatenate all signature strings
for (size_t i = 0; i < num_sigs; ++i)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 7807f7f33..ce0c67fc3 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -292,6 +292,19 @@ namespace tools
std::vector<cryptonote::tx_destination_entry> dests; // original setup, does not include change
uint32_t subaddr_account; // subaddress account of your wallet to be used in this transfer
std::set<uint32_t> subaddr_indices; // set of address indices used as inputs in this transfer
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(sources)
+ FIELD(change_dts)
+ FIELD(splitted_dsts)
+ FIELD(selected_transfers)
+ FIELD(extra)
+ FIELD(unlock_time)
+ FIELD(use_rct)
+ FIELD(dests)
+ FIELD(subaddr_account)
+ FIELD(subaddr_indices)
+ END_SERIALIZE()
};
typedef std::vector<transfer_details> transfer_container;
@@ -313,6 +326,20 @@ namespace tools
std::vector<cryptonote::tx_destination_entry> dests;
tx_construction_data construction_data;
+
+ BEGIN_SERIALIZE_OBJECT()
+ FIELD(tx)
+ FIELD(dust)
+ FIELD(fee)
+ FIELD(dust_added_to_fee)
+ FIELD(change_dts)
+ FIELD(selected_transfers)
+ FIELD(key_images)
+ FIELD(tx_key)
+ FIELD(additional_tx_keys)
+ FIELD(dests)
+ FIELD(construction_data)
+ END_SERIALIZE()
};
// The term "Unsigned tx" is not really a tx since it's not signed yet.
@@ -686,7 +713,7 @@ namespace tools
bool get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const;
void check_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
void check_tx_key_helper(const crypto::hash &txid, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, const cryptonote::account_public_address &address, uint64_t &received, bool &in_pool, uint64_t &confirmations);
- std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, std::string &error_str);
+ std::string get_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message);
bool check_tx_proof(const crypto::hash &txid, const cryptonote::account_public_address &address, bool is_subaddress, const std::string &message, const std::string &sig_str, uint64_t &received, bool &in_pool, uint64_t &confirmations);
std::string get_spend_proof(const crypto::hash &txid, const std::string &message);
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index 101fceebb..b1f8369a3 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -701,7 +701,7 @@ struct Wallet
virtual std::string getUserNote(const std::string &txid) const = 0;
virtual std::string getTxKey(const std::string &txid) const = 0;
virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) = 0;
- virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message, std::string &error_str) const = 0;
+ virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const = 0;
virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations) = 0;
virtual std::string getSpendProof(const std::string &txid, const std::string &message) const = 0;
virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const = 0;
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index f540ba67a..fe7f51617 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -30,6 +30,7 @@
#include <boost/format.hpp>
#include <boost/asio/ip/address.hpp>
#include <boost/filesystem/operations.hpp>
+#include <boost/algorithm/string.hpp>
#include <cstdint>
#include "include_base_utils.h"
using namespace epee;
@@ -635,6 +636,13 @@ namespace tools
tx_to_blob(ptx_vector.back().tx, blob);
res.tx_blob = epee::string_tools::buff_to_hex_nodelimer(blob);
}
+ if (req.get_tx_metadata)
+ {
+ std::ostringstream oss;
+ binary_archive<true> ar(oss);
+ ::serialization::serialize(ar, ptx_vector.back());
+ res.tx_metadata = epee::string_tools::buff_to_hex_nodelimer(oss.str());
+ }
return true;
}
catch (const std::exception& e)
@@ -682,7 +690,7 @@ namespace tools
}
// populate response with tx hashes
- for (auto & ptx : ptx_vector)
+ for (const auto & ptx : ptx_vector)
{
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
@@ -705,6 +713,13 @@ namespace tools
tx_to_blob(ptx.tx, blob);
res.tx_blob_list.push_back(epee::string_tools::buff_to_hex_nodelimer(blob));
}
+ if (req.get_tx_metadata)
+ {
+ std::ostringstream oss;
+ binary_archive<true> ar(oss);
+ ::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx));
+ res.tx_metadata_list.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
+ }
}
return true;
@@ -735,7 +750,7 @@ namespace tools
m_wallet->commit_tx(ptx_vector);
// populate response with tx hashes
- for (auto & ptx : ptx_vector)
+ for (const auto & ptx : ptx_vector)
{
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
@@ -749,6 +764,13 @@ namespace tools
tx_to_blob(ptx.tx, blob);
res.tx_blob_list.push_back(epee::string_tools::buff_to_hex_nodelimer(blob));
}
+ if (req.get_tx_metadata)
+ {
+ std::ostringstream oss;
+ binary_archive<true> ar(oss);
+ ::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx));
+ res.tx_metadata_list.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
+ }
}
return true;
@@ -793,7 +815,7 @@ namespace tools
m_wallet->commit_tx(ptx_vector);
// populate response with tx hashes
- for (auto & ptx : ptx_vector)
+ for (const auto & ptx : ptx_vector)
{
res.tx_hash_list.push_back(epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx)));
if (req.get_tx_keys)
@@ -806,6 +828,13 @@ namespace tools
tx_to_blob(ptx.tx, blob);
res.tx_blob_list.push_back(epee::string_tools::buff_to_hex_nodelimer(blob));
}
+ if (req.get_tx_metadata)
+ {
+ std::ostringstream oss;
+ binary_archive<true> ar(oss);
+ ::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx));
+ res.tx_metadata_list.push_back(epee::string_tools::buff_to_hex_nodelimer(oss.str()));
+ }
}
return true;
@@ -889,6 +918,13 @@ namespace tools
tx_to_blob(ptx.tx, blob);
res.tx_blob = epee::string_tools::buff_to_hex_nodelimer(blob);
}
+ if (req.get_tx_metadata)
+ {
+ std::ostringstream oss;
+ binary_archive<true> ar(oss);
+ ::serialization::serialize(ar, const_cast<tools::wallet2::pending_tx&>(ptx));
+ res.tx_metadata = epee::string_tools::buff_to_hex_nodelimer(oss.str());
+ }
return true;
}
@@ -913,6 +949,47 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_relay_tx(const wallet_rpc::COMMAND_RPC_RELAY_TX::request& req, wallet_rpc::COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& er)
+ {
+ if (!m_wallet) return not_open(er);
+
+ cryptonote::blobdata blob;
+ if (!epee::string_tools::parse_hexstr_to_binbuff(req.hex, blob))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_BAD_HEX;
+ er.message = "Failed to parse hex.";
+ return false;
+ }
+
+ std::stringstream ss;
+ ss << blob;
+ binary_archive<false> ba(ss);
+
+ tools::wallet2::pending_tx ptx;
+ bool r = ::serialization::serialize(ba, ptx);
+ if (!r)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_BAD_TX_METADATA;
+ er.message = "Failed to parse tx metadata.";
+ return false;
+ }
+
+ try
+ {
+ m_wallet->commit_tx(ptx);
+ }
+ catch(const std::exception &e)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR;
+ er.message = "Failed to commit tx.";
+ return false;
+ }
+
+ res.tx_hash = epee::string_tools::pod_to_hex(cryptonote::get_transaction_hash(ptx.tx));
+
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_make_integrated_address(const wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
@@ -1507,12 +1584,7 @@ namespace tools
try
{
- res.signature = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, req.message, er.message);
- if (res.signature.empty())
- {
- er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
- return false;
- }
+ res.signature = m_wallet->get_tx_proof(txid, info.address, info.is_subaddress, req.message);
}
catch (const std::exception &e)
{
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index beeadba6b..9455c4769 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -80,6 +80,7 @@ namespace tools
MAP_JON_RPC_WE("sweep_dust", on_sweep_dust, wallet_rpc::COMMAND_RPC_SWEEP_DUST)
MAP_JON_RPC_WE("sweep_all", on_sweep_all, wallet_rpc::COMMAND_RPC_SWEEP_ALL)
MAP_JON_RPC_WE("sweep_single", on_sweep_single, wallet_rpc::COMMAND_RPC_SWEEP_SINGLE)
+ MAP_JON_RPC_WE("relay_tx", on_relay_tx, wallet_rpc::COMMAND_RPC_RELAY_TX)
MAP_JON_RPC_WE("store", on_store, wallet_rpc::COMMAND_RPC_STORE)
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_rpc::COMMAND_RPC_GET_PAYMENTS)
MAP_JON_RPC_WE("get_bulk_payments", on_get_bulk_payments, wallet_rpc::COMMAND_RPC_GET_BULK_PAYMENTS)
@@ -134,6 +135,7 @@ namespace tools
bool on_sweep_dust(const wallet_rpc::COMMAND_RPC_SWEEP_DUST::request& req, wallet_rpc::COMMAND_RPC_SWEEP_DUST::response& res, epee::json_rpc::error& er);
bool on_sweep_all(const wallet_rpc::COMMAND_RPC_SWEEP_ALL::request& req, wallet_rpc::COMMAND_RPC_SWEEP_ALL::response& res, epee::json_rpc::error& er);
bool on_sweep_single(const wallet_rpc::COMMAND_RPC_SWEEP_SINGLE::request& req, wallet_rpc::COMMAND_RPC_SWEEP_SINGLE::response& res, epee::json_rpc::error& er);
+ bool on_relay_tx(const wallet_rpc::COMMAND_RPC_RELAY_TX::request& req, wallet_rpc::COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& er);
bool on_make_integrated_address(const wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_MAKE_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er);
bool on_split_integrated_address(const wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_SPLIT_INTEGRATED_ADDRESS::response& res, epee::json_rpc::error& er);
bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 1b15c0a99..e084d9e6d 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -291,6 +291,7 @@ namespace wallet_rpc
bool get_tx_key;
bool do_not_relay;
bool get_tx_hex;
+ bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(destinations)
@@ -303,6 +304,7 @@ namespace wallet_rpc
KV_SERIALIZE(get_tx_key)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
+ KV_SERIALIZE_OPT(get_tx_metadata, false)
END_KV_SERIALIZE_MAP()
};
@@ -313,6 +315,7 @@ namespace wallet_rpc
std::list<std::string> amount_keys;
uint64_t fee;
std::string tx_blob;
+ std::string tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash)
@@ -320,6 +323,7 @@ namespace wallet_rpc
KV_SERIALIZE(amount_keys)
KV_SERIALIZE(fee)
KV_SERIALIZE(tx_blob)
+ KV_SERIALIZE(tx_metadata)
END_KV_SERIALIZE_MAP()
};
};
@@ -338,6 +342,7 @@ namespace wallet_rpc
bool get_tx_keys;
bool do_not_relay;
bool get_tx_hex;
+ bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(destinations)
@@ -350,6 +355,7 @@ namespace wallet_rpc
KV_SERIALIZE(get_tx_keys)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
+ KV_SERIALIZE_OPT(get_tx_metadata, false)
END_KV_SERIALIZE_MAP()
};
@@ -369,6 +375,7 @@ namespace wallet_rpc
std::list<uint64_t> amount_list;
std::list<uint64_t> fee_list;
std::list<std::string> tx_blob_list;
+ std::list<std::string> tx_metadata_list;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
@@ -376,6 +383,7 @@ namespace wallet_rpc
KV_SERIALIZE(amount_list)
KV_SERIALIZE(fee_list)
KV_SERIALIZE(tx_blob_list)
+ KV_SERIALIZE(tx_metadata_list)
END_KV_SERIALIZE_MAP()
};
};
@@ -387,11 +395,13 @@ namespace wallet_rpc
bool get_tx_keys;
bool do_not_relay;
bool get_tx_hex;
+ bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(get_tx_keys)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
+ KV_SERIALIZE_OPT(get_tx_metadata, false)
END_KV_SERIALIZE_MAP()
};
@@ -410,12 +420,14 @@ namespace wallet_rpc
std::list<std::string> tx_key_list;
std::list<uint64_t> fee_list;
std::list<std::string> tx_blob_list;
+ std::list<std::string> tx_metadata_list;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
KV_SERIALIZE(tx_key_list)
KV_SERIALIZE(fee_list)
KV_SERIALIZE(tx_blob_list)
+ KV_SERIALIZE(tx_metadata_list)
END_KV_SERIALIZE_MAP()
};
};
@@ -435,6 +447,7 @@ namespace wallet_rpc
uint64_t below_amount;
bool do_not_relay;
bool get_tx_hex;
+ bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
@@ -448,6 +461,7 @@ namespace wallet_rpc
KV_SERIALIZE(below_amount)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
+ KV_SERIALIZE_OPT(get_tx_metadata, false)
END_KV_SERIALIZE_MAP()
};
@@ -466,12 +480,14 @@ namespace wallet_rpc
std::list<std::string> tx_key_list;
std::list<uint64_t> fee_list;
std::list<std::string> tx_blob_list;
+ std::list<std::string> tx_metadata_list;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(tx_hash_list)
KV_SERIALIZE(tx_key_list)
KV_SERIALIZE(fee_list)
KV_SERIALIZE(tx_blob_list)
+ KV_SERIALIZE(tx_metadata_list)
END_KV_SERIALIZE_MAP()
};
};
@@ -489,6 +505,7 @@ namespace wallet_rpc
std::string key_image;
bool do_not_relay;
bool get_tx_hex;
+ bool get_tx_metadata;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(address)
@@ -500,6 +517,36 @@ namespace wallet_rpc
KV_SERIALIZE(key_image)
KV_SERIALIZE_OPT(do_not_relay, false)
KV_SERIALIZE_OPT(get_tx_hex, false)
+ KV_SERIALIZE_OPT(get_tx_metadata, false)
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ std::string tx_hash;
+ std::string tx_key;
+ uint64_t fee;
+ std::string tx_blob;
+ std::string tx_metadata;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(tx_hash)
+ KV_SERIALIZE(tx_key)
+ KV_SERIALIZE(fee)
+ KV_SERIALIZE(tx_blob)
+ KV_SERIALIZE(tx_metadata)
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
+ struct COMMAND_RPC_RELAY_TX
+ {
+ struct request
+ {
+ std::string hex;
+
+ BEGIN_KV_SERIALIZE_MAP()
+ KV_SERIALIZE(hex)
END_KV_SERIALIZE_MAP()
};
diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h
index 74f2999b6..c3f3e20d1 100644
--- a/src/wallet/wallet_rpc_server_error_codes.h
+++ b/src/wallet/wallet_rpc_server_error_codes.h
@@ -56,3 +56,5 @@
#define WALLET_RPC_ERROR_CODE_NO_WALLET_DIR -23
#define WALLET_RPC_ERROR_CODE_NO_TXKEY -24
#define WALLET_RPC_ERROR_CODE_WRONG_KEY -25
+#define WALLET_RPC_ERROR_CODE_BAD_HEX -26
+#define WALLET_RPC_ERROR_CODE_BAD_TX_METADATA -27